One-line: An MCP server that brokers reckon plan-state writes
over stdio/SSE so any MCP-capable agent can read and update plans directly,
without going through the docs-server HTTP endpoint.
Location: MCP code lives inside the reckon repo at
reckon/mcp.py, reckon/_store.py, reckon/_mcp_tools.py.
The standalone ~/Code/reckon-mcp/ repo has been retired.
_store.py is working code; mcp.py has all tool logic complete
with the mcp SDK wired in via FastMCP.
1. Why MCP?
The existing docs-server (reckon/serve.py, port 8765) serves HTML
to a browser and exposes a POST /state/<project>/<doc> endpoint
for in-page decision capture. Agents can call this endpoint over HTTP, but that
requires:
The docs-server process to be running (tmux, login node).
The agent to know the port and hostname (SSH tunnel from laptop).
An HTTP library call rather than a first-class tool invocation.
An MCP server removes all three constraints. It speaks the Model Context Protocol
natively — Claude Code discovers it via ~/.claude/mcp.json and
presents each state operation as a named tool. The agent calls
reckon.patch_plan the same way it calls any other tool, with no HTTP
machinery in the call chain.
The docs-server stays for the browser UI. The MCP server stays for agent IO.
Both write to the same state files via the same atomic-rename versioning protocol.
Call reckon.read_plan(project, slug) — note the version field.
Call the write tool with expected_version = <that version>.
On conflict (error: "version_conflict"): re-read and retry.
3. State write contract
The version-write contract is identical to POST /state/<project>/<doc>
in reckon/serve.py:
State files: ~/docs-server/state/<project>/<slug>.json
(symlinked from each project repo's docs/state/).
Envelope: { "updated", "project", "doc", "data" }. The data
sub-object is the writeable payload.
data._version is the optimistic-concurrency counter. Reads always
return the current version; writes require the caller to echo it back.
Writes are atomic: the new envelope is written to <file>.json.tmp
and then os.replace()'d to <file>.json.
Conflict: if expected_version != current_version the write is
rejected and the caller receives the current version + data so it can
re-read and retry.
Both the docs-server and the MCP server follow this contract. Concurrent writes from
a browser tab and an agent are safe — one of them will get a conflict and retry.
4. Distribution
The MCP server is part of the reckon package — no separate install.
Development install:
uv pip install -e ~/Code/reckon
Start the MCP server via the unified CLI:
reckon mcp
This runs alongside reckon serve — both commands are part of the same
reckon CLI entry point, backed by the same venv.
Once stable, a PyPI publish of reckon will include the MCP server.