Skip to main content

Module mcp

Module mcp 

Source
Expand description

Discovery of .mcp.json — the MCP servers a workspace wants connected.

Tools reach the model three ways: mentra’s builtins, skills, and MCP servers. mentra owns the client half — spawning the process, the initialize handshake, bridging every advertised tool into the runtime’s roster. basis owns the convention half: which file names a server, where that file lives, and what its fields mean. Nothing here interprets a server.

§The format is not basis’s

An mcpServers object in a repo-root .mcp.json is what the agents that already read a project-local MCP file write, so basis reads that rather than inventing a spelling for the same idea. The one place basis is stricter: a file that exists but names no mcpServers key is an error, because the alternative is that a typo disables every server and says nothing.

§Three places a server can come from, and no fourth

In precedence order — supplied by the host, then the workspace file, then the global one. “Supplied” is an ACP client’s mcpServers on session/new, or a Rust host’s own list; the client is the most specific authority there is, because it is answering for this session in particular.

There is deliberately no parent walk, which is where this module parts company with context and skills. Those walk from the workspace root outward, and for instructions that is right: a monorepo’s house rules should reach every crate inside it, and the worst case of picking one up is prose the model did not need.

.mcp.json is not prose. It names commands to spawn and credentials to spawn them with — it is in basis’s own .gitignore for that reason, and in most projects’ — so inheriting one from a directory the operator did not point basis at means running a program they never chose, with a token they never offered, because of where they happened to cd. Two roots the operator names explicitly (this workspace, their own config) are the whole set. A server in a parent directory is one cd away from being asked for properly.

Nothing read here is ever repeated back: see McpError.

Names are the identity. mentra namespaces every bridged tool by its server’s name, so two servers sharing a name would collide in the tool roster; a more specific one therefore shadows a weaker one instead of joining it.

§Transports

stdio, the legacy HTTP+SSE transport, and Streamable HTTP — the three mentra has clients for. Streamable HTTP is the transport current MCP servers ship; a server that answers 404 on a legacy /sse path wants McpServer::Http. One deliberate asymmetry survives in .mcp.json: a bare url with no type still means SSE, because files written before the third transport existed keep their meaning.

mentra’s allow_plaintext_credentials override is deliberately not a .mcp.json key. A committed file must not be able to grant its own headers plaintext passage to a non-loopback host — the same line drawn at base_url — so the refusal stays mentra’s, checked at parse, and the override stays with hosts that construct the config in code.

Structs§

McpConfig
Which MCP servers a run gets: where to look for configured ones, and any the host already has in hand.
McpSource
One .mcp.json that exists on disk, and what it configured.

Enums§

McpError
Anything that can go wrong turning configuration into servers.
McpServer
One MCP server, as basis hands it to mentra.

Constants§

DEFAULT_GLOBAL_MCP_FILE
Where basis looks inside the global config directory. Not the dotted name: a hidden file inside a directory that exists to hold configuration would be hiding it from the person who put it there.
DEFAULT_WORKSPACE_MCP_FILE
Where basis looks inside a workspace, relative to its root.

Functions§

discover
Every .mcp.json that exists, most specific first.
servers
Every server a run should connect, strongest source first.