Skip to content

Connect MCP servers

Attach a Model Context Protocol server to a ToolRegistry as an mcp handler. The server announces its tools and the runtime lists them when the agent starts, so you write no tool definition.

  • A ToolRegistry, referenced from the AgentRuntime through toolRegistryRef.
  • An MCP server that speaks SSE or Streamable HTTP and that the agent pod can reach. The runtime refuses an endpoint whose host is a link-local or cloud-metadata address (such as 169.254.169.254), and refuses redirects to another scheme, host or port. In-cluster Service names and private addresses are allowed.
  1. Add an mcp handler to spec.handlers and pick a transport.

    For sse, point endpoint at the SSE URL:

    - name: mcp-server
    type: mcp
    mcpConfig:
    transport: sse
    endpoint: http://mcp-server.tools.svc.cluster.local:8080/sse

    For streamable-http, point endpoint at the HTTP URL:

    - name: mcp-http
    type: mcp
    mcpConfig:
    transport: streamable-http
    endpoint: http://mcp-server.tools.svc.cluster.local:8080/mcp

    The dashboard’s ToolRegistry dialog supports both transports. It sets only transport and endpoint; every other step on this page is YAML.

  2. Optionally narrow the tools the agent can see with toolFilter:

    mcpConfig:
    transport: sse
    endpoint: http://mcp-github.tools.svc.cluster.local:8080/sse
    toolFilter:
    allowlist: [search_issues, get_pull_request] # illustrative tool names

    An allowlist exposes only the names it lists. With no allowlist, every tool is exposed except those in blocklist. When both are set, blocklist is ignored.

  3. Optionally retry failed tool calls:

    mcpConfig:
    retryPolicy:
    maxAttempts: 3 # 1-10; 1 means no retries
    initialBackoff: "100ms"
    backoffMultiplier: "2.0"
    maxBackoff: "30s"

    Without a retryPolicy, each call is attempted once. This policy is separate from session recovery. When the session is lost, the runtime reconnects, lists the tools again and retries the call once, whatever the policy says.

  4. Add authentication if the server needs it. The credential is sent as a header on both transports:

    auth:
    type: bearer
    secretRef:
    name: mcp-credentials
    key: token

    See Authenticate tools for the other auth types.

  5. Declare the tools in the PromptPack. The runtime offers the model only the tools that a prompt lists in tools, so add each MCP tool name to the prompt that should use it and republish the pack. Tool names are one namespace across the registry: if two handlers expose the same name, the first handler (in name order) keeps it. Use toolFilter on either handler to resolve the clash.

There is no stdio transport: every Omnia runtime image is distroless/static, with no shell, npx or uvx to spawn a subprocess. A registry that sets transport: stdio is rejected.

To give an agent local tooling, use a codegen sandbox. Declare a sandbox in spec.sandboxes, then give the mcp handler a sandbox block that names it and the class port to dial. On a sandbox handler, mcpConfig.endpoint is a path on that port, not a URL, and toolFilter.allowlist is required. Set spec.sandbox.enabled on the AgentRuntime:

spec:
sandboxes:
- name: workspace
class:
name: codegen-default
kind: ClusterSandboxClass
handlers:
- name: workspace
type: mcp
sandbox:
name: workspace
port: mcp
mcpConfig:
transport: sse
endpoint: /sse
toolFilter:
allowlist: [Read, Write, Edit, Glob, Grep, Bash]

The operator creates a SandboxClaim from the class for each conversation that uses the handler. The allowlist is required because the sandbox is not dialled at start-up, so it is the only list of the handler’s tools. The handler’s port must be one the class declares. See Sandboxes for the fields and Codegen sandbox isolation for what the sandbox can reach.

To use a third-party server that only speaks stdio, wrap it in a Deployment that bridges stdio to SSE or Streamable HTTP, and point a handler at that Service.

Check the registry and the handler’s placeholder tool:

Terminal window
kubectl -n <namespace> get toolregistry <name> -o yaml

status.discoveredTools holds one placeholder entry per mcp handler, named after the handler. The individual tools are listed by the runtime when the agent starts, so they do not appear there. Available reflects a valid configuration, not reachability, unless you enable spec.probe, which TCP-dials the endpoint.

For a sandbox handler, also check the SandboxesValid condition. It is False when the sandbox names a class that does not exist, or a port the class does not declare.

Then send the agent a message that needs the tool. To see why the model was not offered one, read the runtime container logs: it logs the registry tools that no prompt in the pack declares.

  • The registry rejects the handler with a link-local or metadata message: the endpoint host is such an address. Use the server’s Service name or a private IP.
  • An agent never calls an MCP tool: the pack’s tools list does not name it, or toolFilter removes it.
  • A sandbox handler is rejected: it needs an endpoint that starts with /, and a non-empty toolFilter.allowlist.