Skip to content

MCP Reference

Speccify ships an MCP server over stdio. Every tool is a thin adapter over speccify-core, the same code the CLI runs — so an agent and a human never get different answers.

Terminal window
uv run speccify-mcp --project /path/to/project

This is the path that matters, and it is pinned by a test: an agent that has to guess the order is an agent that gets it wrong halfway through a release.

ToolWhat it doesKey inputs
playbook_listeverything in the library: id, title, summary, step countlibrary_path?
playbook_getone playbook: steps, sources, pitfalls, prerequisitesreference
playbook_stepa single step, with its sources resolvedreference, step_id
playbook_asseta file that ships with the playbookreference, path
playbook_checkstructure plus how old every source isreference, links?

reference is a playbook id (@scope/name) or a git source (git+<url>[#<path>]). Every one of these also takes offline and an optional library_path.

playbook_check is the one to call before following a playbook: it reports sources that have not been re-read in over 180 days. A stale playbook is worse than none, because an agent will follow it confidently.

ToolCLI equivalentEffect
searchspeccify searchread-only, across configured index repos
lockspeccify lockwrites speccify.lock
pullspeccify pullfetches bundles into the local library
verifyspeccify verifyread-only; re-fetches and compares hashes
ToolWhat it does
viewer_selectionwhat the user has selected in the viewer, resolved
playbook_proposepropose a changed playbook; the user sees a diff

viewer_selection returns the step itself — detail, verify line, resolved sources — not just an id, so “why is this necessary?” can be answered without three more calls. It needs the backend running (./scripts/dev-up.sh); if it is not, the tool says so with code=backend_unreachable rather than failing silently.

playbook_propose takes the complete new playbook.yaml. It is validated immediately, so an invalid proposal never becomes a diff the user cannot apply, and it is never written to disk — only a human clicking Apply does that. Playbooks from git sources are refused: changes belong in the source repository, as a commit and a new tag.

Failures come back as structured results — verify returns {ok, problems[]}, search reports code=no_index_configured, viewer_selection reports code=backend_unreachable. An agent can react to those; it cannot react to a transport-level error.

URIContent
speccify://manifestthe project’s speccify.yaml
speccify://lockfilethe project’s speccify.lock

Both say what to run when the file does not exist yet, rather than returning an error.

{
"mcpServers": {
"speccify": {
"command": "uv",
"args": ["run", "speccify-mcp", "--project", "/path/to/project"]
}
}
}