Skip to content

MCP

Model Context Protocol (MCP) is a standard way for AI applications to connect to external tool servers. MindRoom's Phase 1 MCP support acts as an MCP client for tools. It connects to configured servers, discovers their tool catalogs, and exposes those tools to agents. MindRoom does not yet consume MCP resources or prompts.

Configuration Overview

Configure MCP servers in the top-level mcp_servers block in config.yaml. Each key is the server ID. Server IDs must use only letters, numbers, and underscores because MindRoom uses them in tool names.

mcp_servers:
  chrome_devtools:
    transport: stdio
    command: npx
    args:
      - -y
      - chrome-devtools-mcp@latest

Each configured server creates one dynamic MindRoom tool named mcp_<server_id>. Add that tool name to an agent's tools: list to let the agent use the server's discovered MCP tools.

Transport Types

MindRoom supports three MCP transport types:

  • stdio
  • sse
  • streamable-http

stdio

Use stdio when MindRoom should start the MCP server as a subprocess.

mcp_servers:
  echo:
    transport: stdio
    command: python
    args:
      - ./echo_mcp_server.py
    cwd: .
    env:
      ECHO_PREFIX: "echo:"

For stdio servers, command is required. args, cwd, and env are optional. url and headers are not allowed on this transport.

sse

Use sse for MCP servers that expose a Server-Sent Events endpoint.

mcp_servers:
  remote_sse:
    transport: sse
    url: http://127.0.0.1:9000/sse
    headers:
      Authorization: Bearer ${MCP_API_TOKEN}

For sse servers, url is required. headers are optional. command, args, cwd, and env are not allowed on this transport.

streamable-http

Use streamable-http for MCP servers that expose the newer streamable HTTP endpoint.

mcp_servers:
  remote_http:
    transport: streamable-http
    url: http://127.0.0.1:9000/mcp
    headers:
      Authorization: Bearer ${MCP_API_TOKEN}

For streamable-http servers, url is required. headers are optional. command, args, cwd, and env are not allowed on this transport.

env and headers values support ${ENV_VAR} interpolation. MindRoom resolves those placeholders from the current runtime environment when it opens the MCP transport. Static headers are process-global and shared by every requester. Use the OAuth auth block for remote MCP servers that need a different bearer token per requester.

Per-Server Options

Option Type Default Notes
enabled bool true Set to false to disable one server without removing its config
description string null What the server provides; appended to the OAuth bridge tool descriptions shown to the model; requires auth
required bool false Block dependent agent startup while this server is unavailable instead of degrading
transport string required One of stdio, sse, or streamable-http
command string null Required for stdio
args list[string] [] Optional stdio arguments
cwd string null Optional stdio working directory
env map[string,string] {} Optional stdio environment variables; supports ${ENV_VAR} placeholders
url string null Required for sse and streamable-http
headers map[string,string] {} Optional remote transport headers; supports ${ENV_VAR} placeholders
auth object null Optional OAuth configuration for requester-scoped remote MCP access
tool_prefix string server ID Prefix for model-visible function names
include_tools list[string] [] Optional allowlist of remote tool names to expose
exclude_tools list[string] [] Optional denylist of remote tool names to hide
startup_timeout_seconds float 20.0 Maximum time to open the transport, initialize, and discover tools
call_timeout_seconds float 120.0 Default timeout for each tool call
max_concurrent_calls int 1 Maximum concurrent tool calls for that server
auto_reconnect bool true Retry once after connection or timeout failures during a call

tool_prefix must use only letters, numbers, and underscores. include_tools and exclude_tools are matched against the remote MCP tool names, not the MindRoom-prefixed function names. include_tools and exclude_tools cannot overlap.

Agent Access

Each MCP server becomes one MindRoom tool named mcp_<server_id>. Add that name to an agent's tools: list to expose the server's discovered tools.

mcp_servers:
  chrome_devtools:
    transport: stdio
    command: npx
    args:
      - -y
      - chrome-devtools-mcp@latest

agents:
  browser:
    display_name: Browser
    role: Debug and inspect web apps in Chrome
    model: sonnet
    tools:
      - mcp_chrome_devtools

You can also apply per-agent overrides when you assign the MCP tool:

agents:
  browser:
    tools:
      - mcp_chrome_devtools:
          include_tools:
            - new_page
            - navigate_page
            - take_snapshot
          call_timeout_seconds: 180

These per-agent overrides filter the already discovered catalog for that agent assignment. They are useful when one server exposes many tools but one agent should see only a focused subset.

MCP tools are available on every worker scope, including private per-user agents. Non-OAuth mcp_<server_id> tools always execute through the shared MCP server session; requester identity and requester credentials are never passed to the server. OAuth-backed remote MCP servers instead load a scoped OAuth token for the current requester at tool-call time and keep one session per requester scope.

OAuth-Backed Remote MCP

Use auth.type: oauth for a remote MCP server that requires a requester-owned OAuth bearer token. OAuth-backed MCP requires sse or streamable-http; stdio servers cannot use this mode.

mcp_servers:
  example:
    transport: streamable-http
    url: https://mcp.example.com/mcp
    tool_prefix: example
    description: Example workspace search, documents, and calendar for the signed-in user.
    auth:
      type: oauth
      provider_id: mcp_example
      display_name: Example MCP
      resource: https://mcp.example.com/mcp
      discovery: auto
      token_endpoint_auth_method: none
      pkce_code_challenge_method: S256
      dynamic_client_registration: true
      scopes: []

agents:
  assistant:
    display_name: Assistant
    role: Use requester-scoped MCP tools
    model: sonnet
    worker_scope: user_agent
    tools:
      - mcp_example

MindRoom registers a generated OAuth provider for the server. If provider_id is omitted, the provider ID defaults to mcp_<server_id>. When the provider ID starts with mcp_, OAuth tokens are stored under <provider_id>_oauth, and OAuth client configuration is read from <provider_id>_oauth_client unless you specify client_config_services or shared_client_config_services. When a custom provider ID does not start with mcp_, MindRoom prefixes mcp_ for the generated credential service names so the tokens remain classified as MCP-owned runtime credentials.

OAuth-backed MCP servers always expose a stable bridge surface:

  • <prefix>_connection_status
  • <prefix>_list_tools
  • <prefix>_call_tool

The bridge functions let an agent trigger the normal MindRoom OAuth connect flow before the remote server has revealed a requester-specific tool catalog. When credentials are missing, the bridge returns the same structured OAuth-required payload used by built-in OAuth tools. Until the requester connects, the bridge functions are the only model-visible surface for the server, and their generic descriptions say nothing about what the server offers. Set the per-server description option to tell the model what connecting would unlock; it is appended to all three bridge tool descriptions. After the user connects, list_tools returns the remote catalog and call_tool sends Authorization: Bearer <requester access token> to the MCP server. After MindRoom has a cached requester-specific catalog, the toolkit also exposes typed <prefix>_<remote_tool_name> functions for that requester in addition to the bridge functions.

discovery: auto performs protected-resource metadata discovery from the configured resource or server url, then resolves authorization-server metadata. MindRoom tries /.well-known/oauth-protected-resource at the resource origin and at the resource path. It then reads the advertised authorization server and fetches OAuth authorization-server metadata. The discovered metadata supplies the authorization endpoint, token endpoint, optional registration endpoint, supported token endpoint auth methods, and supported PKCE methods.

If dynamic_client_registration is enabled and no client config has been stored yet, MindRoom registers a public client lazily when the first OAuth flow starts. The generated client registration is stored in the generated OAuth client config service and reused for later users. Public clients using token_endpoint_auth_method: none only need client_id; confidential methods still require client_secret. Use extra_auth_params and extra_token_params when the OAuth server requires additional parameters such as resource during authorization, code exchange, or refresh.

Use discovery: manual when the provider does not publish metadata or when you want to pin endpoints explicitly:

mcp_servers:
  example_manual:
    transport: streamable-http
    url: https://mcp.example.com/mcp
    auth:
      type: oauth
      discovery: manual
      authorization_url: https://mcp.example.com/oauth/authorize
      token_url: https://mcp.example.com/oauth/token
      registration_url: https://mcp.example.com/oauth/register
      token_endpoint_auth_method: none

OAuth discovery requires HTTPS by default and does not follow redirects. For local development, set MINDROOM_MCP_OAUTH_ALLOW_INSECURE_DISCOVERY=1 to allow non-HTTPS discovery URLs, and set MINDROOM_MCP_OAUTH_ALLOW_PRIVATE_DISCOVERY=1 to allow loopback or private-network discovery hosts.

Tool Naming

There are two names to keep in mind:

  1. The MindRoom tool entry that you put in tools: is mcp_<server_id>.
  2. The model-visible function names inside that toolkit are <prefix>_<remote_tool_name>.

If tool_prefix is omitted, MindRoom uses the server ID as the prefix.

For example, this config:

mcp_servers:
  chrome_devtools:
    transport: stdio
    command: npx
    args:
      - -y
      - chrome-devtools-mcp@latest
    tool_prefix: chrome

means a remote MCP tool named navigate_page becomes chrome_navigate_page inside the agent's tool list.

MindRoom rejects duplicate function names after prefixing. That includes collisions inside one server and collisions across different servers. The final function name must also fit within 64 characters.

Example: Echo MCP Server

This is the smallest useful local example. Save it as echo_mcp_server.py:

from mcp.server.fastmcp import FastMCP

server = FastMCP("Echo Server")


@server.tool()
def echo(text: str) -> str:
    return f"echo:{text}"


if __name__ == "__main__":
    server.run()

Then point MindRoom at it:

mcp_servers:
  echo:
    transport: stdio
    command: ./.venv/bin/python
    args:
      - ./echo_mcp_server.py

agents:
  code:
    display_name: Code
    role: Test MCP tools
    model: sonnet
    tools:
      - mcp_echo

With that setup, the remote echo tool is exposed to the model as echo_echo. If you prefer a shorter function name, set tool_prefix to something else. Use whatever Python interpreter has the mcp package installed. Inside this repository, ./.venv/bin/python is usually the right choice.

The same server can also be run over HTTP transports. If you change the script to server.run(transport="sse"), the default FastMCP endpoint is /sse. If you change it to server.run(transport="streamable-http"), the default FastMCP endpoint is /mcp.

Example: Chrome DevTools MCP

Chrome DevTools MCP is a good fit for browser debugging, page inspection, performance work, and interactive web automation.

mcp_servers:
  chrome_devtools:
    transport: stdio
    command: npx
    args:
      - -y
      - chrome-devtools-mcp@latest
    tool_prefix: chrome
    startup_timeout_seconds: 20

agents:
  browser:
    display_name: Browser
    role: Debug web apps with Chrome DevTools
    model: sonnet
    tools:
      - mcp_chrome_devtools

This exposes Chrome DevTools functions with names like chrome_<tool_name>. By default, chrome-devtools-mcp starts its own Chrome instance with a dedicated profile.

To attach to an already running debuggable Chrome instance instead, add --browser-url=http://127.0.0.1:9222:

mcp_servers:
  chrome_devtools:
    transport: stdio
    command: npx
    args:
      - -y
      - chrome-devtools-mcp@latest
      - --browser-url=http://127.0.0.1:9222
    tool_prefix: chrome

If Chrome startup is slow on your machine, increase startup_timeout_seconds. If individual browser operations can take a while, increase call_timeout_seconds.

Example: MemPalace AI Memory

MemPalace is a local AI memory system that stores conversations in ChromaDB, organized as a navigable "palace" with wings, rooms, and halls. It exposes 19 MCP tools for search, knowledge graph operations, agent diaries, and more — all without API keys.

Using uvx keeps MemPalace in an isolated virtual environment, avoiding dependency conflicts with MindRoom's own ChromaDB version:

mcp_servers:
  mempalace:
    transport: stdio
    command: uvx
    args:
      - --from
      - mempalace
      - python
      - -m
      - mempalace.mcp_server
      - --palace
      - /path/to/.mempalace/palace
    startup_timeout_seconds: 30
    call_timeout_seconds: 60

agents:
  assistant:
    display_name: Assistant
    role: General assistant with persistent memory
    model: sonnet
    tools:
      - mcp_mempalace

Before the MCP server can return results, initialize and seed the palace:

uvx mempalace init /path/to/content
uvx mempalace mine /path/to/content

Agents can also add memories on the fly via the mempalace_add_drawer tool. The palace enforces deduplication at a 0.9 similarity threshold.

Error Handling

MindRoom connects to MCP servers during startup and whenever config.yaml changes. If a server fails to start, initialize, or publish a valid tool catalog, MindRoom marks that server as failed and logs a warning.

By default a failed server degrades gracefully: agents and teams that reference mcp_<server_id> still start, with that server's tools omitted from their tool schema. MindRoom keeps retrying failed MCP discovery in the background with exponential backoff, and restarts the affected agents and teams once the server recovers so they pick up its tools. Set required: true on a server to restore hard-fail behavior, where dependent agents and teams stay blocked from starting until the server is available.

During tool execution, explicit MCP tool failures are surfaced as tool errors. Those explicit server-side errors are not retried automatically.

Connection drops and timeouts are treated differently. When auto_reconnect: true, MindRoom refreshes the server connection and retries the tool call once. If reconnect also fails, the error is surfaced to the caller.

If an MCP server sends a tools/list_changed notification, MindRoom refreshes that server's catalog. If the catalog changed, MindRoom restarts the agents and teams that reference that server so they pick up the updated tool list.

Limitations

  • Phase 1 supports MCP tools only.
  • MCP resources and prompts are not exposed in MindRoom yet.
  • Non-OAuth MCP integrations always use the shared server session, even on isolating worker scopes; per-requester isolation requires an OAuth-backed server.
  • OAuth-backed remote MCP integrations use requester-scoped OAuth credentials and sessions.
  • OAuth-backed remote MCP typed functions appear only after MindRoom has cached a requester-specific remote catalog.
  • server_id and tool_prefix must use letters, numbers, and underscores.
  • The final function name <prefix>_<remote_tool_name> must be 64 characters or fewer.