Skip to main content

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:

SourceDescriptionExample
remoteHTTP-based MCP servers, managed by the platformFigma, Sentry, GitHub
deviceLocal MCP servers running on the agent's machine via @octavus/computerBrowser automation, filesystem
consumerInline 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.

yaml

Fields

FieldRequiredDescription
descriptionYesWhat the MCP server provides
sourceYesremote, device, or consumer (see source types above)
displayNoHow tool calls appear in UI: hidden, name, description (default: description)
connectionNoWhen to connect: eager or lazy (default: lazy). remote only.
executionNoWhere 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:

ModeBehavior
hiddenTool calls run silently
nameShows tool name while executing
descriptionShows tool description while executing

Making MCP Servers Available

Like tools, MCP servers defined in mcpServers: must be referenced in agent.mcpServers to be available:

yaml

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_page
  • browser__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:

text

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:

  1. Add an MCP server to your project (URL + authentication)
  2. The server's slug must match the namespace in your protocol
  3. 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:

ModeBehavior
lazy(default) The agent activates integrations on demand at runtime. The agent starts responding immediately.
eagerThe platform connects and discovers tools before the first LLM request. Tools are guaranteed available from message 1.
yaml

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 TypeDescription
MCP OAuthStandard MCP OAuth flow
API KeyStatic API key sent as a header
BearerBearer token authentication
NoneNo 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.

yaml

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

  • execution is only meaningful for source: remote MCPs that use STDIO transport. HTTP-transport remote MCPs always connect from the platform regardless of the execution setting.
  • execution is invalid on source: device and source: consumer MCPs - they already run outside the platform. Using it produces a validation error.
  • The connection field (eager or lazy) 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:

  1. The consumer creates a Computer with matching namespaces
  2. @octavus/computer discovers tools from each MCP server
  3. Tool schemas are sent to the platform via the server-sdk
  4. 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:

yaml
typescript

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.

yaml

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():

yaml
typescript

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:

yaml

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:

yaml

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:

yaml

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, and contextRetention from the per-source entry in onDemandMcpServers.
  • Scopes decide independently - threads do not inherit onDemandMcpServers from their parent, the same rule as mcpServers:.
  • 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.

yaml

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

yaml

Cloud-Only Agent

Agents that only use remote MCP servers don't need @octavus/computer:

yaml