Expand description
Model Context Protocol (MCP) server for grr.
Hand-rolled JSON-RPC 2.0 over stdio — no SDK crate: a tool-only server needs four RPCs. Newline-delimited requests in, one response line per request out, logs to stderr ONLY (stdout is the MCP stream, the same discipline as the rest of grr).
server/discover— the stateless revision’s discovery RPC: revisions served, capabilities, identity, and it needs no prior calltools/list— every method in the Discovery index as a tooltools/call— one method invocation through the shared call path
2026-07-28 is the newest revision served, so the handshake is gone from
the happy path — but initialize is answered with a minimal legacy
handshake (server/discover remains the discovery RPC), because the
deployed client ecosystem still opens with it. ping and
logging/setLevel answer with a JSON-RPC error naming the revision to
speak instead. Notifications (notifications/initialized, whatever the
revision) carry no id, so they are never answered at all.
Tool names are the dotted method ids grr api call takes
(gmail.users.messages.list), so an agent reaches every method Google
publishes through the same resolution the CLI uses. Errors never kill
the server: a tool failure is an isError result (MCP’s tool-error
contract), a protocol failure a JSON-RPC error object.
{"jsonrpc":"2.0","id":1,"method":"server/discover"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"gmail.users.messages.list","arguments":{"userId":"me","dry_run":true}}}Structs§
- McpServer
- One server instance: one credential, one safety profile, every tool.
The stdio loop is single-tasked, so no
Arcis needed.
Functions§
- serve
- The stdio loop: newline-delimited JSON-RPC in, one response line per request out. Generic over the reader/writer so tests can run the whole handshake in-process. EOF on stdin (the client closed the session) is a clean shutdown.