Skip to content
GitHub
Docs / Reference / MCP tools and resources

MCP tools and resources

VERSIONv0.4.1 · SOURCE docs/tools.md

Every server mounted in the default mode exposes the same small surface, no matter how large the underlying state machine is. The action namespace does not inflate the tool list; it lives in step’s action argument and at theodosia://graph.

ToolWhat it does
step(action, inputs)Run one transition. Returns the result, the new state, and valid_next_actions, or a structured refusal.
reset_session()Rebuild this session’s Application from the factory, discarding state and history. Refuses in shared mode.
fork_at(sequence_id)Roll this session back to a prior history entry and continue from there.
fork_from_past(app_id, sequence_id)Resume another session’s state through the persister. Hidden unless a tracker or state_loader is wired.

Two more tools appear when the client cannot read MCP resources directly (FastMCP’s ResourcesAsTools transform): list_resources() returns the theodosia:// catalog and read_resource(uri) returns what a native resources/read would. They route through the same path as the native resources, so a tools-only client reaches everything below.

A step call returns a FastMCP ToolResult with two content blocks plus the structured payload:

  1. A short human headline like Step 3: pay ✓ → fulfill (or Step 3: pay ✗ invalid_transition). Clients that render server-log strings inline (Bob, Claude Code’s streaming output) show this on the timeline.
  2. The JSON body, serialised as a text block.

The same JSON body lives on result.structured_content for capable clients. A programmatic driver should read structured_content, not the second text block. The schema of the JSON body (success vs. each refusal shape) is documented in refusals. Sample shape from fastmcp.Client:

r = await client.call_tool("step", {"action": "pay", "inputs": {"amount": 5.0}})
r.structured_content # the dict you act on
r.content # [TextContent(headline), TextContent(json body)]
URIReturns
theodosia://graphStatic FSM topology: actions, transitions, each action’s required and optional inputs plus their JSON schemas (input_schemas, with full Pydantic model_json_schema() for typed inputs), and the state schema (the Pydantic JSON schema when typed state is used).
theodosia://stateThe current state for this session.
theodosia://nextThe actions reachable from the current state.
theodosia://historyThe per-session attempt timeline, including refusals and forks.
theodosia://subruns, theodosia://subruns/{id}Sub-application index and a sub-run’s full timeline. Appears only when the FSM uses theodosia.spawn_subapp(...).
theodosia://traceBurr’s LocalTrackingClient JSONL, mirrored for the agent.
theodosia://sessionTracker coordinates: project, app_id, app directory, partition key.

A constant tool list keeps the agent’s choice space small and stable across turns: the agent always has the same few verbs, and learns the domain actions from step’s schema and theodosia://graph rather than from a tool list that changes shape as state advances. The discipline lives in the graph, not in the tool catalog. See Architecture for how step drives Burr underneath.

VERSIONv0.4.1 · SOURCE docs/tools.md