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.
| Tool | Arguments | What it returns |
|---|---|---|
list_skills | (none) | The body-less skill catalog as JSON: name, z, triggers, cost, tool. |
route_skill | text (string, required) | The best-matching skills for the request, each as name (score N; matched: ...). |
get_skill | name (string, required) | One skill's full instructions (its plane body). Loads only that plane. |
resolve_skill | name (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:
- Call
list_skillsonce to see the catalog (or keep it resident). - Call
route_skillwith the user's request to pick the right skill. - Call
get_skill(orresolve_skillif the skill has dependencies) to load only that skill's instructions into context. - 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
- Skills and the format: what each catalog field means.
- Loaders: the same contract as a library API.