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.
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:
stdiossestreamable-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:
- The MindRoom tool entry that you put in
tools:ismcp_<server_id>. - 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:
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_idandtool_prefixmust use letters, numbers, and underscores.- The final function name
<prefix>_<remote_tool_name>must be 64 characters or fewer.