Skip to content

MCP server

Reference

Serve an agent's skills over MCP

The repo ships an MCP server that exposes any agent.3md's skills to an MCP-capable agent as tools. It speaks newline-delimited JSON-RPC 2.0 over stdio (the MCP stdio convention): only JSON-RPC responses go to stdout, and all logging goes to stderr so the stream stays clean.

bun run mcp agent.3md

On startup it logs the agent name and skill count to stderr, for example [agent-3md mcp] dev: 7 skills from /path/to/agent.3md.

The tools an MCP client sees

The server projects the loader contract into four tools. None of them load skill bodies unless asked, preserving progressive disclosure.

ToolArgumentsWhat it returns
list_skills(none)The body-less skill catalog as JSON: name, z, triggers, cost, tool.
route_skilltext (string, required)The best-matching skills for the request, each as name (score N; matched: ...).
get_skillname (string, required)One skill's full instructions (its plane body). Loads only that plane.
resolve_skillname (string, required)The skill plus its dependency chain, each as ### name followed by its body.

route_skill returns no skill matched when nothing matches; get_skill and resolve_skill return an error result for an unknown skill name.

Point an MCP client at it

Most MCP clients take a command and args pair. Point them at bun running the server with the agent file as its argument:

{ "command": "bun", "args": ["src/mcp.ts", "agent.3md"] }

From an installed clone you can use bun run mcp style invocation, or give an absolute path to the agent file so the client can launch it from any working directory:

{ "command": "bun", "args": ["/abs/path/agent-3md/src/mcp.ts", "/abs/path/agent.3md"] }

The server resolves the path to an absolute one and refuses to load anything that is not a .3md file, and it caps the document and per-line sizes so an untrusted file or client cannot exhaust memory.

A typical client flow

Once connected, an agent uses the tools in the same route then fill then run loop:

  1. Call list_skills once to see the catalog (or keep it resident).
  2. Call route_skill with the user's request to pick the right skill.
  3. Call get_skill (or resolve_skill if the skill has dependencies) to load only that skill's instructions into context.
  4. Fill the skill's inputs and run its bound command with the host's own tools.

Protocol notes

The server answers initialize (protocol version 2024-11-05, server info agent-3md:<name>), ping, tools/list, and tools/call. Notifications (no id) are acknowledged silently, and malformed requests get standard JSON-RPC error codes. You can exercise it end to end with bun run mcp:selftest, which spawns the server and calls each tool.

See also