Skip to main content

Module mcp

Module mcp 

Source
Expand description

P5-2 (COMPOSABLE-HARNESS-DESIGN.md §2 module 15 mcp.client, D7 rows 1-8): full Model Context Protocol client support — stdio (P5-1 baseline, GROWN not rewritten), remote HTTP/SSE transports, resources + templates, prompts-as-commands, server instructions, and elicitation — plus the handle_request / serve_stdio harness-as-MCP-server direction (module 16).

Transport model. McpClient hides three wire shapes behind one request()/list_tools()/call_tool()/… API:

  • McpClient::connect — stdio (newline-delimited JSON-RPC over a spawned child process’s stdin/stdout). Pre-existing (P5-1 baseline).
  • McpClient::connect_http — a single POST per request (“Streamable HTTP”, non-streaming case): the response body is either a bare application/json object or a text/event-stream body carrying the one response event. A Mcp-Session-Id response header, if the server sends one, is captured and replayed on every subsequent request.
  • McpClient::connect_sse — the legacy (2024-11-05) HTTP+SSE transport: a persistent GET stream whose first event names the POST endpoint for client→server messages; a background reader task forwards every subsequent server→client frame into an in-process channel.

Server-initiated requests and notifications. A real MCP session is bidirectional: while a client request is in flight, the server may push a notification (resources/updated, …) or even issue its OWN request back to the client (elicitation/create). McpClient’s read loop (McpClient::handle_incoming_message) recognizes all three shapes on both the stdio and SSE transports (persistent, bidirectional connections) and dispatches server-initiated requests to the installed McpElicitationHandler — see that trait’s doc comment for the HEADLESS-DENY default and the tui-deferred interactive part. The HTTP transport is a single non-streaming request/response cycle with no return channel for a reply; a server-initiated request arriving on it is a documented, tested, fail-CLOSED error (Error::tool("mcp", ...)), never a silent drop or a hang — see McpClient::http_roundtrip’s doc comment.

Security posture (this module’s own scope; see also crate::configfile’s project-sanitization for the config-file side). MCP OAuth tokens are credentials, the same trust class as Config::api_key (§3.2 S13) — crate::mcp_oauth handles only the wire PROTOCOL (device-code grant, refresh); persistence to disk with trust-grade (owner-only, user/global-directory-only) permissions is a CLI-layer concern (crates/cli/src/userconfig.rs’s save_mcp_oauth_tokens/load_mcp_oauth_tokens, mirroring save_api_key’s existing 0600-perms precedent) — this crate never writes a token to disk itself. Remote connects honor an active crate::tools::NetworkPolicy (module 12’s SSRF/domain-allowlist floor) via crate::tools::check_network_policy, the exact function crate::tools::ToolContext::check_network itself calls — one enforcement point, not a second parallel one.

Structs§

ElicitationRequest
P5-2 (§2.1 dep “elicitation → tools.question surface”; §2 module 6’s own row: “⚡ headless print mode (deny-default like OC, oc§1)”): a server→client elicitation/create request, mid-tools/call, asking the user for structured input.
ElicitationResponse
What an McpElicitationHandler returns for one ElicitationRequest.
HeadlessElicitationHandler
The default: every elicitation request is declined. Correct for non-interactive/print-mode runs (the only mode this crate’s CLI embedder — crates/cli — runs in today); a TUI-backed handler is a tui-deferred follow-up, not built here.
McpClient
A client connected to an MCP server over stdio, HTTP, or SSE — see the module doc comment for the transport model.
McpPromptArgDef
One argument a McpPromptDef accepts.
McpPromptDef
A prompt exposed by a remote MCP server (prompts/list).
McpPromptSource
A prompt this crate can render via prompts/get — what McpServerHandle::prompts hands back for a caller to register as a slash-command source (crate::agent::Agent::register_mcp_prompt).
McpResourceDef
A resource exposed by a remote MCP server (resources/list).
McpResourceTemplateDef
A resource TEMPLATE exposed by a remote MCP server (resources/templates/list).
McpServerHandle
P5-2: one connected server, wrapping the Arc<Mutex<McpClient>> every derived Tool/prompt-source shares — the single point that produces tools (McpTool), resource tools, prompt names, and the server’s folded-in instructions, so a caller (crates/cli’s attach_mcp) only has to connect once and ask this handle for everything else.
McpTool
A supercode Tool backed by a remote MCP tool. The name is namespaced mcp__<server>__<tool> to match the convention seen in the corpus.
McpToolDef
A tool exposed by a remote MCP server.
SdkMcpTool
MCP tool projection of the versioned SDK facade. The MCP envelope and tool-call id never enter the SDK request or its canonical session data.

Enums§

ElicitationAction
The outcome an McpElicitationHandler returns — the three actions the MCP elicitation spec defines.
McpConnectParams
How an McpClient was connected — kept on the client so McpClient::reconnect can rebuild an equivalent connection without the caller having to remember its own parameters.

Constants§

DEFAULT_MCP_TIMEOUT
Default per-request timeout (connect handshake + every subsequent request()) for the network transports — stdio has no analogous “hung server” risk distinct from a hung read, so it is NOT subject to this timeout (a misbehaving stdio child can still be killed by the caller; kill_on_drop already covers process cleanup).
MCP_MAX_RESOURCE_BYTES
Hardening cap (same review finding): the maximum joined size of resources/read’s concatenated text contents McpClient::read_resource will return before erroring out instead of buffering an unbounded string.
MCP_MAX_RESPONSE_BYTES
Hardening cap (Fable-5 review, memory-DoS-from-a-hostile-configured- server finding): the maximum size of a single non-streaming HTTP response body (McpClient::http_roundtrip) this client will buffer before erroring out. 16 MiB is generous for real tool-call/initialize responses (the actual payloads this transport carries) while bounding how much memory a misbehaving or malicious configured MCP server can force this process to allocate for one response.
MCP_MAX_SSE_FRAME_BYTES
Hardening cap (same review finding as MCP_MAX_RESPONSE_BYTES): the maximum size a single un-terminated SSE frame may grow to inside SseLineAccumulator before it’s treated as malformed/hostile and the connection is torn down, rather than the accumulator buffer growing without bound while waiting forever for a blank-line terminator that never arrives.

Traits§

McpElicitationHandler
Handles a server-initiated elicitation/create request — the tools.question surface’s PROTOCOL side (§2.1 dep). The real interactive prompt UI is tui’s job (P5 item #4, not yet built); pending that, HeadlessElicitationHandler is the honest default — DENY (decline), matching module 6’s own “headless print mode: deny-default like OC” row rather than hanging the tool call or silently fabricating an answer. An embedder (or a future tui integration) can install a real interactive handler via McpClient::set_elicitation_handler.

Functions§

cache_churn_notice
P5-2 (§2.2 C2 “connect invalidates cache prefix”; §2 module 25 cache is the referee): the churn notice a caller (crates/cli’s attach_mcp) emits when connecting a server under an active CachePlan::ImportedPrefix — a pure, independently-testable function so the wording/threshold logic isn’t buried in CLI plumbing. “At minimum emit the churn signal” (P5-2 build brief) — this is that signal; it does not itself reset any cache bookkeeping (see Agent::register_tool’s own C2 note for the runtime half: any tool registered after the agent’s first turn resets cache_established, MCP-sourced or not).
handle_request
Handle one JSON-RPC request against a ToolRegistry, returning the JSON-RPC response (or None for notifications that need no reply).
register_sdk_tool
Register the SDK adapter alongside ordinary MCP coding tools.
serve_stdio
Run a blocking stdio MCP server exposing registry, reading requests from stdin and writing responses to stdout until EOF.