MCP tools
Castellan exposes a progressive-disclosure MCP surface: meta-tools for discovery, compact listings in tools/list, and full schemas on demand via castellan_describe_tool.
Registry: crates/castellan-runtime/src/mcp/registry.rs
Stdio server: castellan mcp
Live episodes: castellan run --mcp → CastellanEngine::call_mcp_tool
Discovery flow
flowchart LR
A[Agent starts] --> B[discover / search tools]
B --> C[describe_tool]
C --> D[Invoke tool]
D --> E[Governance + trace]
classDef runtime stroke:#0969da,stroke-width:2px
classDef substrate stroke:#8250df,stroke-width:2px
classDef gate stroke:#1a7f37,stroke-width:2px
class A,B runtime
class C,D substrate
class E gate
- Discover —
castellan_discover_toolsreturns domain-indexed tool cards (no full schemas). - Search —
castellan_search_toolswithquery(and optionaldomain) narrows by intent. Results are BM25-ranked over tool name, summary, description, and domain; when no whole term matches (partial words), substring matching kicks in. The response reports which via"ranking": "bm25" | "substring". - Describe —
castellan_describe_toolwithnamereturns full schema, preconditions, side effects, examples. - Invoke —
tools/callor livemcp_toolsobservation payload.
Meta-tools are always listed with full schemas. Operational tools in tools/list use compact cards (call castellan_describe_tool for parameters).
Meta tools
| Tool | Domain | Purpose |
|---|---|---|
castellan_discover_tools | meta | Browse domains and tool names |
castellan_search_tools | meta | BM25-ranked search over catalog |
castellan_describe_tool | meta | Full ToolSpec for one tool |
Operational tools
| Tool | Domain | Summary | Live (--mcp) | Governance |
|---|---|---|---|---|
castellan_deposit_signal | substrate | Deposit pheromone into zone | Yes | pre/post hooks |
castellan_read_signal | substrate | Read signal strength | Yes | read-only |
castellan_read_blackboard | substrate | Read blackboard slot | Yes | read-only |
castellan_topology_snapshot | substrate | Harness topology JSON | Yes | read-only |
castellan_metrics | substrate | Session counters | Yes | read-only |
castellan_multiplexer_status | multiplexer | Dashboard statusline snapshot | Yes | read-only |
castellan_propose_mutation | evolve | Preview harness mutation (diff + drift); does not apply | Yes | preview-only |
castellan_resolve_mutation | evolve | Accept or reject a persisted proposal | Yes | high-impact gate |
castellan_read_resource | substrate | Resolve typed URI (episode://, genome://, pane://, blackboard://) | Yes | read-only |
castellan_recall | memory | Recall durable memory by key | Yes | read-only |
castellan_remember | memory | Store durable memory entry | Yes | pre/post hooks |
castellan_query_field_history | substrate | Query pressure-field history | Yes | read-only |
All operational tools are in LIVE_TOOL_NAMES for castellan run --mcp.
Start the server
castellan mcp
Wire your MCP client to stdin/stdout JSON-RPC. Cursor config example in Cursor setup.
Example: discovery sequence
{"name": "castellan_search_tools", "arguments": {"query": "deposit", "domain": "substrate"}}
{"name": "castellan_describe_tool", "arguments": {"name": "castellan_deposit_signal"}}
{"name": "castellan_deposit_signal", "arguments": {"zone": "grid", "signal": "coordination", "amount": 2.0}}
Example: live episode
Observation payload for castellan run --goal "..." --plugin gridworld --mcp:
{
"mcp_tools": [
{
"tool": "castellan_deposit_signal",
"args": { "zone": "grid", "signal": "coordination", "amount": 2.0 }
}
]
}
Trace JSONL emits mcp_discovery for meta-tools and mcp_tool for operational calls. Governance pre/post hooks apply on the hot path.
Design principles
| Principle | Implementation |
|---|---|
| Progressive discovery | Meta-tools before full schemas |
| Context efficiency | Compact tools/list for operational tools |
| Live parity | Same registry for castellan mcp and castellan run --mcp |
| Description quality | Summary + preconditions + side effects per tool |
Adding a tool
- Add
ToolSpecinregistry.rsand register inall_tool_specs(). - Add handler in
handlers.rsand route incall_tool_with_registry. - Add name to
LIVE_TOOL_NAMESif live episodes should expose it. - Update this page and run
cargo test -p castellan-runtime.
See also MCP overview and Agent guide.