plan_sprint_report gets that whole apparatus behind one tool call, instead of improvising the same sequence differently every time.
For your agent, graph brings deterministic_-ish_ skills.
Configuring a client
What is loaded, and when
The global layer is anchored to your home directory, so it does not depend on where anything was started. Only the project layer does, which is why only the project layer requires you to name it.
Writes follow the same rule. The authoring tools (
graph_plan_new, graph_plan_draft, graph_plan_set, graph_plan_step_*) write into the first configured plans directory of whichever layer set is active: ~/.config/graph/plans without --dir, and the project’s ./.graph/plans with it. A client’s working directory is never a destination, and no authoring tool takes a path argument — where a plan is written is the user’s decision, expressed with --dir, not the calling agent’s.
[plans].paths replaces the default list rather than adding to it. A project config that pins paths = ["./.graph/plans"] drops ~/.config/graph/plans, and those global plans stop being served.instructions the calling model reads, along with the --dir fix.
When the config is broken
A server that dies before the MCP handshake is the worst failure mode this surface has: the client reports “connection failed”, stderr goes to client logs no model reads, and the agent gets nothing to act on. Sograph mcp serve never exits over a bad config — it serves anyway and puts the why where the agent will see it:
- A missing provider key (
api_key = "${ANTHROPIC_API_KEY}"with the variable unset) doesn’t degrade the server at all. Config loading defers the error to the entry that owns it: authoring tools,graph_plan_list, and plans that run without inference all work, and the calls that do need a model (graph_plan_draft, solver-mode plans) fail naming the variable and the config path that wants it. - A config that cannot load (parse error, missing variable outside
[providers.*]/[mcp.*]) still gets a running server: the load error is appended to the MCPinstructionsat initialize, and every tool call returns it. The config is re-read per request, so fixing the file or the environment heals the server in place — no restart.
env block next to command/args in the server entry.
What gets served
Your plans, as tools
Every plan in the catalog becomesplan_<identifier>, carrying that plan’s own input_schema as the tool’s schema, and its description plus exemplars as the routing signal. The calling agent gets exactly the argument contract graph enforces internally — not a generic “run a plan” tool taking a free-form blob.
requires_servers on this machine is not served, for the same reason it is not offered to graph’s own agent: it cannot run here.
The authoring tools
graph_plan_list, graph_plan_show, graph_plan_validate, graph_plan_new, graph_plan_draft, graph_plan_set, graph_plan_unset, graph_plan_step_add, graph_plan_step_update, graph_plan_step_rename, graph_plan_step_rm, graph_tools_list, graph_tools_show, graph_tools_test.
These give your agent everything it needs to build and check a plan without a shell. Every edit goes through the same validation guard as the command line: an edit that would break the plan is refused, with the problems it would have introduced.
Authoring and calling in one session
The tool list is read fresh on everytools/list, and a successful edit sends notifications/tools/list_changed. So an agent can build a capability and then use it, without a restart:
Cost and latency
graph_plan_draft calls the planner model — roughly 30 seconds, and the only served tool that costs inference. Plans themselves cost whatever their finish mode implies: output-mode plans run with zero inference, solver-mode plans cost one call. Many MCP clients default to a 60-second tool timeout; raise it if your plans are long-running.
Progress and cancellation
Pass aprogressToken with a plan_* call and the server reports each step as it runs — the same information plan run prints to a terminal, including the plan call stack when plans compose. Without a token the run is silent, because MCP only permits notifying against a token the client issued.
Questions back to the client
A plan can contain anask step — a value only a person can supply. Over MCP that becomes an elicitation/create request sent back to your client from inside the tools/call that is running the plan:
elicitation at initialize time is never sent a request — the ask resolves as unavailable immediately and the plan runs its declared when_unanswered path, which is why a plan written for a terminal still works here. A client that advertises support and then errors or times out is treated the same way; an unanswerable question is a plan-declared condition, not a server failure. decline and cancel both come back to the plan as "declined".
The answer schema is a flat object of primitive fields, which is the protocol’s constraint — graph enforces it when the plan is validated, so it fails as a review comment rather than at runtime on one host.