MCP Server
Serve agentty's native tools over the Model Context Protocol, and consume other MCP servers from inside agentty.
agentty speaks the Model Context Protocol both ways: it can serve its native tools to any MCP client, and consume tools from other MCP servers inside a thread.
ℹNoteJust want to add a tool (a browser driver, a database client)? See Plugins for the practical mcp.json / agentty plugin add guide. This page is the full protocol reference.
Serving agentty's tools (mcp-serve)
agentty mcp-serve runs headless — no terminal UI — and exposes agentty's native toolset over MCP on stdio. An external MCP client (Claude Desktop, an IDE, another agent) drives tools/list and tools/call over stdin/stdout; diagnostics go to stderr.
agentty mcp-serve
The served tools are the same native tools the TUI uses: file read/write/edit/move/remove, shell bash, long-running process_* sessions, focused test, code search (grep/glob/find_definition/search_structural/repo_map), web fetch/search, diagnostics, and the git_* family including git_show and git_blame. Filesystem tools stay sandboxed to the workspace boundary and shell/process calls run inside the OS sandbox, exactly as they do interactively.
mcp-serve is deliberately native-only. A configured external MCP server is never re-exported implicitly, preventing credential leaks and recursive MCP proxy loops.
Point a client at it
Any MCP client can launch agentty as a stdio server. For a client that reads a JSON config (Claude Desktop shown here):
{
"mcpServers": {
"agentty": {
"command": "agentty",
"args": ["mcp-serve"]
}
}
}
Consuming other MCP servers
The reverse of serving is consuming — agentty adds tools to a thread by connecting to external MCP servers listed in an mcp.json, which is exactly what a plugin is. See that page for the practical how-to (agentty plugin add, the Plugins picker, project vs user scope, and the trust gate on repo-shipped servers). The rest of this section is the protocol-level behaviour:
- Provenance naming. External tools get stable, namespaced names such as
mcp__playwright__browser_click; they can never collide with or impersonate native tools. - Live catalog.
tools/list_changedis honoured live, including removals and schema replacements. - Tool budget / brokering. To keep provider requests fast and tool choice accurate, agentty sends all native and pinned tools plus at most 16 MCP tools ranked for the current request. The always-available
mcp_search_toolsandmcp_callbroker exposes the long tail without injecting hundreds of schemas into every turn.
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@playwright/mcp"]
}
}
}
Per-server policy is explicit:
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["-y", "@playwright/mcp"],
"timeoutMs": 30000,
"connectTimeoutMs": 10000,
"maxOutputChars": 30000,
"trustAnnotations": false,
"tools": {
"include": ["browser_click", "browser_snapshot", "browser_navigate"],
"exclude": ["browser_install"],
"pin": ["browser_snapshot"]
}
}
}
}
disabled:truekeeps a configured server off without deleting it.trustAnnotationsdefaults tofalse: remote read-only hints cannot silently weaken permission checks. Enable it only for a server you trust.include/excludefilter the advertised surface;pinkeeps important tools in every turn.- Stdio and HTTP servers receive the workspace through MCP roots.
- Calls stream MCP progress into the live tool card, propagate Esc cancellation, and reconnect a poisoned/crashed server on its next call.
- Independent servers execute concurrently; each individual transport retains its own serialization.
ℹNoteMCP consumption is lazy and opt-in — with no .agentty/mcp.json present, startup is a single stat() that returns nothing, so there is zero overhead when you aren't using it.
Authorizing an OAuth-gated server
Some hosted MCP servers require OAuth (MCP spec 2026-07-28 authorization). When you run agentty against one, an unauthorized call returns an actionable error instead of hanging. Authorize once with:
agentty mcp-login <server>
This runs the full OAuth 2.1 + PKCE flow: agentty discovers the authorization server from the endpoint's protected-resource metadata (RFC 9728), dynamically registers itself (application_type=native, so the loopback redirect is accepted), opens your browser to authorize, catches the redirect on a local loopback port, and validates the response — including the RFC 9207 iss check that blocks authorization-server mix-up attacks before the code is exchanged.
When the server doesn't support Dynamic Client Registration
Some authorization servers don't offer a registration endpoint. Give agentty a client_id instead — an https:// value is used as a CIMD (Client ID Metadata Document) URL, the 2026-07-28 preferred path where the URL is the client identity; anything else is treated as a pre-registered public client. In precedence order:
agentty mcp-login acme --client-id https://agentty.example/client.json # CIMD URL
agentty mcp-login acme --client-id my-registered-client-id # pre-registered id
…or set it per-server in mcp.json ("client_id") or globally via AGENTTY_MCP_CLIENT_ID:
{ "mcpServers": { "acme": { "url": "https://mcp.acme.dev/mcp",
"client_id": "https://agentty.example/client.json" } } }
If the discovery probe can't find the metadata URL from the 401 challenge, pass it explicitly with --metadata <url>.
The resulting token is issuer-bound (it will never be replayed to a different authorization server), stored encrypted at rest (~/.agentty/mcp_tokens/<server>.json, chmod 600), attached automatically to every request to that server, and refreshed transparently when it expires. Manage tokens with:
agentty mcp-status # list servers and which are authorized
agentty mcp-logout <server> # forget a stored token
A statically-configured Authorization header in mcp.json still wins, so you can also just paste a bearer token if you have one:
{ "mcpServers": { "acme": { "url": "https://mcp.acme.dev/mcp",
"headers": { "Authorization": "Bearer sk-..." } } } }
External ACP agents
When an external ACP agent is selected, trusted servers from the same MCP configuration are passed through session/new.mcpServers. The delegated agent owns those calls and agentty renders their ACP tool updates as observed activity; it does not execute them a second time. Workspace-local MCP servers are passed through only once trusted — per-server content-hash approval or the blanket AGENTTY_MCP_ALLOW_PROJECT=1.
Agentty does not silently inject a nested unrestricted agentty mcp-serve into delegated agents. That would duplicate built-ins, bypass clear execution ownership, and make recursive task flows possible.
Searching an MCP server's resources
Beyond tools, an MCP server can expose resources (resources/*) — documents, wiki pages, reference material. agentty can fold those into its retrieval engine so search_docs searches them alongside your local docs, skills, and memory, all fused into one ranked, source-tagged result set. It's off by default; enable with AGENTTY_RAG_MCP=1 (requires an MCP config to be present). From the model's view a docs folder and an MCP server are the same thing — a knowledge source behind one interface.