Skip to content
brain.GitHub
Developer docs OPEN SOURCE
Tools

MCP tools

Connect tools from a remote MCP server, with the same tenant checks, validation, and limits as HTTP tools.

The Model Context Protocol (MCP) is an open protocol for serving tools to AI applications. Brain connects to remote MCP servers over Streamable HTTP with the official MCP Go SDK (pinned in go.mod), so you can give sessions tools from an MCP server you already run. MCP tools go through the same tenant allowlist, input validation, timeout, and output limits as HTTP tools.

What Brain supports

  • Transport: Remote MCP servers over Streamable HTTP, or installed stdio commands through the Go application SDK.
  • Authentication: API keys sent as bearer tokens from the environment variable named in token_env.
  • Results: Tool calls that return text, images, or structured content.
  • Progress: Progress notifications streamed during a call as tool.progress events.

Discover tools

Run cmd/mcp-tools to turn tools from an MCP server into Brain tool bindings:

go run ./cmd/mcp-tools -url https://YOUR_SERVER/mcp -token-env MCP_API_KEY -tenant local -tools search,fetch
FlagDescription
-urlThe server's Streamable HTTP endpoint.
-token-envThe environment variable that holds the server's API key. The command uses it to connect, and the bindings tell Brain to send it as a bearer token.
-tenantThe tenant allowed to use the tools.
-toolsA comma-separated list of 1 to 128 remote tool names to include.

The command connects to the server, reads its tool list, and prints a JSON array with one binding for each named tool. It fails if a named tool doesn't exist or if discovery takes longer than 30 seconds. The output looks like this:

[
  {
    "name": "search",
    "description": "Search the knowledge base.",
    "input_schema": { "type": "object", "properties": { "query": { "type": "string" } }, "required": ["query"] },
    "url": "https://YOUR_SERVER/mcp",
    "mcp_tool": "search",
    "token_env": "MCP_API_KEY",
    "tenants": ["local"],
    "timeout_seconds": 300,
    "max_output_bytes": 1048576
  }
]

Review the descriptions and schemas, then copy the bindings into the tools array of your host config. Bindings are static: a tool's description and schema change only when you edit the config and restart Brain, and discovery never changes the tools of a running session.

Configure an MCP binding

An MCP binding is a regular tool binding with one extra field, mcp_tool:

  • name is the name the model sees. Rename tools to avoid collisions, for example docs_search for a search tool.
  • mcp_tool is the tool's name on the MCP server.
  • url is the server's MCP endpoint.
  • token_env names the environment variable with the server's API key. Brain sends it as a bearer token on every request to the server.

tenants, timeout_seconds, max_output_bytes, and output_schema work as they do for HTTP tools. inspect_session applies to HTTP and SSE tools; Brain rejects a host config that sets it on an MCP binding.

How Brain calls an MCP tool

  1. Check the call. Brain confirms that the tool is allowed for the session's tenant and validates the arguments against input_schema.
  2. Open an MCP session. Brain starts a new MCP session with the server for this call, over pooled HTTP connections. A separate MCP session per call keeps server-side session state from crossing tenants or calls, at the cost of one initialization round trip per call.
  3. Call the tool. Brain sends the arguments and puts the session's identity in _meta["brain.dev/scope"] as tenant_id, session_id, and call_id. The call ID is also the progress token.
  4. Stream progress. Each progress notification from the server becomes a live-only tool.progress event.
  5. Return the result. Brain converts the result into a tool.result event, returns it to the harness, and closes the MCP session.

Scope metadata is for attribution

The _meta["brain.dev/scope"] values tell your server which tenant and session a call belongs to. Your server must still authenticate Brain's API key and enforce access to its own resources. Brain never sends session inspection tokens to MCP servers.

Results and errors

Brain converts MCP results into Brain content blocks:

MCP resultBrain result
Text contentA text block.
Image contentAn image block with base64 data and mime_type.
Structured contentstructured_content plus a text block containing the JSON. Successful output schemas validate the structured value.
isError: trueis_error: true. The model sees the error as a tool result.
Any other content typeThe call fails.

When a call fails, the tool.result has is_error: true:

What happenedunknown_outcome
Brain refused the call or couldn't connect to the server, so the tool was never calledNo
The call failed after Brain sent it: the connection dropped, the call timed out, or the server returned a protocol errorYes
The server asked for user inputYes. Handle approval inside the tool instead.
The result had an unsupported content type, exceeded max_output_bytes, or didn't match output_schemaYes

Brain sends each MCP call at most once. With an unknown outcome, the model can use another tool to check the resource. Interrupting the session or reaching the timeout cancels the request; whether the work stops on the server depends on the server.

Next steps

On this page