Model Context Protocol
Model Context Protocol (MCP) is an open protocol that lets models safely call tools exposed by external processes or services — for example, reading GitHub issues, querying databases, or operating the local file system. Mirri Code CLI acts as an MCP client to connect these external tools and exposes them to the Agent alongside built-in tools (Read, Bash, Grep, etc.) with no behavioral difference.
Connection Methods
Mirri Code CLI supports three MCP server connection methods:
- stdio: The CLI starts the local MCP server as a child process and communicates via standard input/output. Suitable for local command-line tools.
- HTTP: The CLI connects to an already-running HTTP endpoint. Suitable for remote services or processes that need to run persistently.
- SSE: The CLI connects to a legacy HTTP+SSE endpoint (Server-Sent Events, a streaming HTTP mechanism). Prefer HTTP for new MCP servers, but use
transport: "sse"when a service still exposes only the older SSE transport.
Configuration
MCP server configuration is written in mcp.json, at two levels:
- User level:
~/.mirri-code/mcp.json(or$MIRRICODE_HOME/mcp.json), shared across projects - Project level:
.mirri-code/mcp.jsonin the working directory, effective only for the current repository
Entries with the same name: the project-level entry takes precedence and overrides the user-level entry.
Run /mcp-config in the TUI to interactively add, edit, or delete servers without manually editing the JSON file. Run /mcp to view the connection status of all current servers.
Structure of mcp.json:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"linear": {
"url": "https://mcp.linear.app/mcp"
},
"legacy-events": {
"transport": "sse",
"url": "https://mcp.example.com/sse"
}
}
}Entries with a command field are stdio servers; entries with a url field and no transport are HTTP servers. For legacy SSE servers, set transport to "sse" explicitly.
Optional fields:
| Field | Type | Applies to | Description |
|---|---|---|---|
env | Record<string, string> | stdio | Environment variables injected into the child process |
cwd | string | stdio | Working directory for the child process |
headers | Record<string, string> | HTTP, SSE | Static request headers appended to every request |
bearerTokenEnvVar | string | HTTP, SSE | Name of an environment variable that contains a bearer token |
enabled | boolean | All | Set to false to disable this server |
startupTimeoutMs | number | All | Connection timeout; default 30000 milliseconds |
toolTimeoutMs | number | All | Timeout for a single tool call |
enabledTools | string[] | All | Tool allowlist |
disabledTools | string[] | All | Tool blocklist |
HTTP and SSE servers support providing static credentials via headers or bearerTokenEnvVar. When OAuth is needed, run /mcp-config login <server-name> to complete browser-based authorization.
Environment variable interpolation
Any string value in mcp.json supports environment variable interpolation, so secrets and hostnames no longer need to be hardcoded in the config file. Two syntaxes are supported:
${VAR_NAME}— POSIX-style${env:VAR_NAME}— explicitenv:prefix (compatible with some tools)
At load time, references in strings are replaced with the corresponding environment variable values; an undefined variable resolves to the empty string, and the downstream schema validation catches invalid results (an empty URL or command, for example). Interpolation runs before schema validation, so it applies to every string field: url, command, args, headers, env, and so on.
{
"mcpServers": {
"remote": {
"transport": "http",
"url": "https://${MCP_HOST}:${MCP_PORT}/mcp",
"headers": {
"Authorization": "Bearer ${env:MCP_TOKEN}"
}
},
"local": {
"command": "${env:BIN_DIR}/server",
"args": ["--region", "${AWS_REGION}"],
"env": {
"API_KEY": "${API_KEY}"
}
}
}
}Object keys, numbers, booleans, and null are not interpolated. The existing semantics of bearerTokenEnvVar and the stdio env field are unchanged — they are still treated as literal values; environment variable interpolation is an orthogonal expansion layer.
Plugins can also declare MCP servers in their manifest. Servers declared by a plugin are enabled by default and can be disabled or re-enabled in /plugins, then a new session must be started. See Plugins for details.
Note
stdio entries in a project-level .mirri-code/mcp.json execute local commands when a session starts. Only enable these in repositories you trust.
Tool Naming and Permissions
MCP tools are named in the format mcp__<server>__<tool>, for example mcp__github__create_issue. Permission rules support * and ** wildcards, for example mcp__github__* matches all tools under that server. MCP tool parameters are not included in permission matching.
Calls that do not match any permission rule trigger an approval request. Selecting "Approve for this session" in the approval dialog automatically allows subsequent calls of the same kind within the current session.
You can also pre-configure permanent rules in [[permission.rules]] in config.toml:
[[permission.rules]]
decision = "allow"
pattern = "mcp__github__*"
[[permission.rules]]
decision = "deny"
pattern = "mcp__filesystem__write_file"For the full permission rule syntax, see Configuration files.
Security
When connecting to external MCP servers, be aware of:
- Only connect to servers from trusted sources
- Verify that tool names and parameters look reasonable in approval requests
- Keep manual approval for high-risk tools (file writes, command execution, etc.); avoid using
mcp__*wildcards to allow all tools at once
Note
In YOLO mode, MCP tool calls are automatically approved. Only use this mode when you fully trust the MCP servers you have connected.
Next steps
- Tool Integrations — Declare MCP tool capabilities so the Agent automatically prefers them over built-in equivalents
- Plugins — Declare MCP servers in a plugin manifest to package and distribute them together
- Configuration files — Full field reference for permission rules