Skip to content

Connect MCP servers ​

Give an agent the tools of any MCP (Model Context Protocol) server — an external stdio or HTTP server connected per turn, or your own @tool functions bundled into an in-process server.

External serverIn-process server
Configured onHostConfig.mcp_server_resolverOptions.mcp_servers
Enabledper turn, by alias (enabled_mcp=)always, for that agent
Tool names the model seesmcp__{alias}__{tool}the bare @tool names
Runs ina subprocess, or over HTTPyour process

Connect an external server ​

Hand the host a resolver (alias -> spec | None), then name the aliases to connect on each turn:

python
from noeta.sdk import Client, HostConfig, McpHttpServerSpec, McpServerSpec, Options
from noeta.sdk.providers import AnthropicProvider

SERVERS = {
    "fs": McpServerSpec(
        alias="fs",
        argv=("npx", "-y", "@modelcontextprotocol/server-filesystem", "/data"),
        tool_subset=("read_file", "list_directory"),   # None = every tool
    ),
    "search": McpHttpServerSpec(
        alias="search",
        url="https://mcp.example.com/rpc",
        headers=(("Authorization", "Bearer …"),),
    ),
}

client = Client(
    Options(system_prompt="You are a helpful assistant.", name="my-agent"),
    provider=AnthropicProvider(),
    model="claude-sonnet-5",
    host_config=HostConfig(mcp_server_resolver=SERVERS.get),
)

outcome = client.start(goal="List the data directory.", enabled_mcp=("fs",))

The model now sees mcp__fs__read_file and mcp__fs__list_directory.

  • enabled_mcp is per turn and not stored with the task's configuration. start, send_goal, seed_start and seed_send_goal all take it. query() does not — external MCP needs a Client.
  • Credentials (headers, env) live only in the spec you build. They never reach the event log or the model.
  • MCP tools are ordinary tools: guards, permission modes and approvals apply to them unchanged.

Spec fields ​

SpecFieldNotes
bothaliasmust match ^[a-z0-9_-]{1,32}$
bothtool_subsetraw tool names to keep; None keeps every advertised tool
McpServerSpecargvlaunch command, run directly (never through a shell)
McpServerSpecenvextra environment for the process, as (("KEY", "value"), …)
McpHttpServerSpecurlthe single JSON-RPC endpoint
McpHttpServerSpecheadersstatic headers sent on every request, as (("Name", "value"), …)

HTTP servers that assign an Mcp-Session-Id (Streamable HTTP) get it echoed on every later request. To use your own HTTP transport, set HostConfig.mcp_http_post.

When a server fails or changes ​

  • A server that cannot connect at turn start is dropped, an McpServerSkipped event is recorded, and the turn continues with the other servers. A duplicate alias raises McpConfigError.
  • A tool name longer than 64 characters or colliding with another fails fast; it is never truncated silently.
  • Connections are pooled per host and shared across tasks. Idle ones close after HostConfig.mcp_idle_ttl (default 1800 s). Call client.reconnect_mcp("fs") (or reconnect_mcp() for all) after you change a server's config.
  • Serving several tenants? Set HostConfig.mcp_scope_resolver so a stateful server is never shared between them — see Per-tenant memory.

Share servers with subagents ​

A subagent inherits the turn's enabled servers only if its definition activates mcp:

python
AgentDefinition(description="…", prompt="…", plugins=("mcp",))

Bundle your own tools in-process ​

python
from noeta.sdk import Options, ToolContext, ToolResult, create_sdk_mcp_server, tool

@tool(
    name="echo",
    version="1",
    description="Return the given text unchanged.",
    input_schema={
        "type": "object",
        "properties": {"text": {"type": "string"}},
        "required": ["text"],
        "additionalProperties": False,
    },
)
def echo(arguments: dict, ctx: ToolContext) -> ToolResult:
    return ToolResult(success=True, output=arguments["text"])

my_mcp = create_sdk_mcp_server(name="my-tools", version="1.0.0", tools=(echo,))

options = Options(system_prompt="…", name="my-agent", mcp_servers=(my_mcp,))

The tools run in your process with no subprocess or network hop, and keep their bare names — the model sees echo, not mcp__my-tools__echo. Pick names that don't collide with a built-in tool. examples/mcp_server.py is a runnable version.

Next ​

Released under the Apache License 2.0.