MCP Servers
MCP servers extend your agent with tools from external services. Define them in your protocol, and agents automatically discover and use their tools at runtime.
There are three types of MCP servers:
| Source | Description | Example |
|---|---|---|
remote | HTTP-based MCP servers, managed by the platform | Figma, Sentry, GitHub |
device | Local MCP servers running on the agent's machine via @octavus/computer | Browser automation, filesystem |
consumer | Inline MCP servers defined in your server-sdk process via createInlineMcpServer() | Custom integrations, third-party APIs |
Defining MCP Servers
MCP servers are defined in the mcpServers: section. The key becomes the namespace for all tools from that server.
Fields
| Field | Required | Description |
|---|---|---|
description | Yes | What the MCP server provides |
source | Yes | remote, device, or consumer (see source types above) |
display | No | How tool calls appear in UI: hidden, name, description (default: description) |
connection | No | When to connect: eager or lazy (default: lazy). remote only. |
execution | No | Where the MCP process runs: sandbox (default) or device. remote only. See Device Execution. |
Display Modes
Display modes control visibility of all tool calls from the MCP server, using the same modes as regular tools:
| Mode | Behavior |
|---|---|
hidden | Tool calls run silently |
name | Shows tool name while executing |
description | Shows tool description while executing |
Making MCP Servers Available
Like tools, MCP servers defined in mcpServers: must be referenced in agent.mcpServers to be available:
Tool Namespacing
All MCP tools are automatically namespaced using __ (double underscore) as a separator. The namespace comes from the mcpServers key.
For example, a server defined as browser: that exposes navigate_page and click produces:
browser__navigate_pagebrowser__click
A server defined as figma: that exposes get_design_context produces:
figma__get_design_context
The namespace is stripped before calling the MCP server - the server receives the original tool name. This convention matches Anthropic's MCP integration in Claude Desktop and ensures tool names stay unique across servers.
What the LLM Sees
When an agent has both regular tools and MCP servers configured, the LLM sees all tools combined:
You don't define individual MCP tool schemas in the protocol - remote and device tools are auto-discovered from each MCP server at runtime, and consumer tools are supplied by the server-sdk.
Remote MCP Servers
Remote MCP servers (source: remote) connect to HTTP-based MCP endpoints. The platform manages the connection, authentication, and tool discovery.
Configuration happens in the Octavus platform UI:
- Add an MCP server to your project (URL + authentication)
- The server's slug must match the namespace in your protocol
- The platform connects, discovers tools, and makes them available to the agent
Connection Modes
The connection field controls when the platform connects to a remote MCP server:
| Mode | Behavior |
|---|---|
lazy | (default) The agent activates integrations on demand at runtime. The agent starts responding immediately. |
eager | The platform connects and discovers tools before the first LLM request. Tools are guaranteed available from message 1. |
With lazy connection (the default), the agent receives two built-in tools - one for listing available integrations and one for activating them. The agent decides which integrations it needs based on the conversation and activates them on demand. This avoids paying connection latency for integrations the agent doesn't end up using.
With eager connection, the platform connects to the MCP server before the first LLM request, exactly like a declared tool. Use this when the agent needs the MCP's tools from the very first message.
The connection field is only valid on source: remote - device MCPs (source: device) have their own connection mechanism through the server-sdk. The connection field is respected for remote MCPs with execution: device the same way as sandbox MCPs.
Authentication
Remote MCP servers support multiple authentication methods:
| Auth Type | Description |
|---|---|
| MCP OAuth | Standard MCP OAuth flow |
| API Key | Static API key sent as a header |
| Bearer | Bearer token authentication |
| None | No authentication required |
Authentication is configured per-project - different projects can connect to the same MCP server with different credentials.
Device Execution
The execution field controls where a remote MCP server's STDIO process runs. By default (execution: sandbox), the process runs in the platform's sandbox. When set to execution: device, the STDIO process runs on the agent's computer (VM or desktop) instead.
When to Use
Use execution: device when the MCP server needs access to the agent's local environment - for example, tools that read from the local filesystem, interact with running processes, or need CLIs installed on the device.
Rules
executionis only meaningful forsource: remoteMCPs that use STDIO transport. HTTP-transport remote MCPs always connect from the platform regardless of theexecutionsetting.executionis invalid onsource: deviceandsource: consumerMCPs - they already run outside the platform. Using it produces a validation error.- The
connectionfield (eagerorlazy) is respected for device-executed MCPs the same way as sandbox-executed MCPs.
Device MCP Servers
Device MCP servers (source: device) run on the consumer's machine. The consumer provides the MCP tools via the @octavus/computer package (or any ToolProvider implementation) through the server-sdk.
When an agent has device MCP servers:
- The consumer creates a
Computerwith matching namespaces @octavus/computerdiscovers tools from each MCP server- Tool schemas are sent to the platform via the server-sdk
- Tool calls flow back to the consumer for execution
See @octavus/computer for the full integration guide.
Namespace Matching
The mcpServers keys in the protocol must match the keys in the consumer's Computer configuration:
If the consumer provides a namespace not declared in the protocol, the platform rejects it.
Consumer MCP Servers
Consumer MCP servers (source: consumer) are defined inline in your server-sdk process. Tool schemas and handlers live in your code; the platform learns the namespace from the protocol and routes tool calls to your process via the same dynamicToolSchemas channel that device MCPs use.
The protocol declaration is intentionally minimal - the SDK supplies tool names and JSON schemas at runtime, so adding or evolving tools doesn't require a protocol change.
Use consumer MCPs when:
- The integration's credentials should never reach the platform (OAuth tokens, customer API keys).
- You want to group an integration's tools (
github__list-prs,github__get-issue) without enumerating each one in YAML. - You want type-safe handler arguments via Zod schemas.
See createInlineMcpServer in the server-sdk reference for the full implementation guide.
Namespace Matching
The protocol namespace must match the namespace passed to createInlineMcpServer():
If the SDK provides a namespace not declared in the protocol, those tools are filtered out at the runtime boundary and the LLM never sees them.
Thread-Level Scoping
Threads can scope which MCP servers are available, the same way they scope tools:
This thread can use Figma and browser tools, but not sentry or filesystem - even if those are available on the main agent.
On-Demand MCP Servers
By default, an agent can only call MCP tools whose namespace is listed in mcpServers. With onDemandMcpServers, a scope can opt into every connected MCP of a given source at runtime, without enumerating each one in the protocol.
Remote MCPs are connected at the project level from the Octavus dashboard. Normally, each connected MCP that the agent should be able to use has to be declared in the protocol - connecting a new MCP means editing the protocol and redeploying. onDemandMcpServers removes that round-trip: once a source is opted in, any MCP connected to the project under that source becomes available to the agent immediately.
Currently supported for source: remote.
Protocol-level declaration
Add an onDemandMcpServers: section alongside mcpServers:, keyed by source. Each entry configures how the matched MCPs appear in tool lists:
On-demand MCP definitions also support the execution field. When set, all MCPs matched by that on-demand source inherit the execution mode.
Scope-level opt-in
The agent and individual start-thread blocks each choose whether to pick up on-demand MCPs, by listing the sources they want:
Rules
- A scope's tool list includes every connected MCP of any referenced source, whether or not any protocol declares that slug.
- Undeclared namespaces inherit
description,display, andcontextRetentionfrom the per-source entry inonDemandMcpServers. - Scopes decide independently - threads do not inherit
onDemandMcpServersfrom their parent, the same rule asmcpServers:. - Tool namespaces are always the connector's slug (for example
notion__search,linear__create_issue). Source keys are never namespaces.
Workers opt into on-demand MCPs the same way: through start-thread blocks inside steps. A worker without a start-thread that lists a source won't see on-demand MCPs of that source.
Workers
Workers can declare and use MCP servers using the same mcpServers: syntax. Workers resolve their own MCP connections independently - they don't inherit from a parent interactive agent.
Since workers don't have a global agent: section, MCP servers are scoped per-thread via start-thread - the same way tools and skills work in workers. Remote MCP connections are project-scoped, so workers in the same project share the same OAuth connections.
See Workers for the full worker protocol reference.
Full Example
Cloud-Only Agent
Agents that only use remote MCP servers don't need @octavus/computer: