Four servers,
registered on install.
Coordination needs no separate download. Three of these servers are pulled from npm the first time they launch, and the one the baseline ships runs from the overlay. When the baseline renames a server of its own, your .mcp.json drops the stale entry instead of carrying it for good.
The servers
The coordination channel behind org mode. Backed by a file-locked directory under .claude/state/sprint/<channel_id>/, which is why every session in a pod must sit on one machine and in one checkout.
Current documentation for third-party libraries. Article VI.5 requires a third-party API to be checked against current docs before code is written against it, and this is the shipped default for satisfying that. Which server plays this role is named in .claude/docs-provider.json, so a project can swap in its own — self-hosted or otherwise — by editing that pointer and the matching .mcp.json entry.
Renders the PlantUML diagrams a spec declares. Pairs with the jar fetched to .claude/bin/plantuml.jar at install time and with the plantuml_syntax_guard hook, which validates diagram source at the write boundary.
Drives a real browser for cross-engine smoke checks. Wired with --browser chrome --isolated so a run leaves no profile state behind.
Launch commands
Each entry's command, exactly as registered. The Claude Code client is what starts these servers, and they run on your own machine with the project directory as their working directory (nothing is dialled out to a hosted endpoint).
baseline node .claude/mcp/baseline/server.mjs gitmcp plantuml npx -y plantuml-mcp-server playwright npx -y @playwright/mcp@latest --browser chrome --isolated
The three npx entries pull from npm the first time they launch, whereas baseline runs from the overlay itself. That is why org mode needs no extra install, and also why every session in a pod must share a single checkout. To find its store the channel asks git rev-parse --git-common-dir. A linked worktree and the tree it came from therefore reach one directory instead of each opening its own.
Channel tools
Eighteen calls, on the one server that ships inside the overlay.
To join a pod a session calls register_peer, and it leaves with leave_peer. Peers talk through send_message and broadcast. The lane board is enqueue_task, claim_task, update_task, cancel_task, list_tasks, release_task and signal_done.
When a peer cannot settle something itself, it raises it rather than guessing. raise_conflict reports a write-set collision. yield_fork hands back a decision bound to one task. ask_lead and answer_peer carry a free-form question, which the lead may pass on to the human.
Where a pushed notification can go missing, sprint_status cannot. It returns the whole channel: tasks, peers, messages and yields. Its all_done flag is true exactly when every enqueued lane has drained, so a lost message can never strand a pod.
Every call accepts sprint_id and every call may omit it. An omitted id resolves to default, one channel per repository, so the board works for a single session with org mode switched off. Name the id when you want a channel of your own.
acquire_lead and release_lead hold one lead per channel. A second session that asks for a channel someone already leads is refused, and the refusal names the holder, so it knows who to escalate to.
Merge behaviour
An upgrade refreshes what the baseline owns and leaves what you added exactly as it was.
If you already have a .mcp.json, install and upgrade will merge into it rather than replace it. Servers the template names belong to the baseline and refresh from it, which is how you pick up new baseline arguments and environment settings. Servers the template does not name are yours, and those stay byte for byte as they were.
To keep a change of your own, put it under a name the template does not use. Change one of the template's own servers and the next upgrade will overwrite it, because for those names the template wins.
Where the baseline has renamed one of its own servers, that rule has an exception. A name the template has stopped using is normally yours to keep, but a renamed one is dropped and its replacement takes over. src/cli/renames.js holds the record, and it names the old server so nothing else has to. One entry stands there today, mapping the coordination server's former name onto baseline as of 0.26.0. Without it you would carry both names for good, one of them pointing at a directory the overlay no longer ships. A rename applies only once the template carries the replacement, so merging an older template that still ships the old name keeps it.
Top-level keys outside mcpServers behave the same way: the merge adds template keys you are missing and leaves the keys you already have. Where the result would match your file exactly, nothing is written at all and the upgrade reports the file unchanged.
Replacement
Nothing here locks you to a vendor. Article VI.5 requires that a third-party API be checked against current documentation before any code is written against it, and it names that outcome without naming a tool.
Which server does the fetching is named in .claude/docs-provider.json. Replacing it is a config edit, and your governance files stay as they are. gitmcp ships as the default, but a library's own llms.txt will do instead, and so will a pinned local copy of the docs.
If you want a different provider, that is two edits: replace the server entry in .mcp.json, then name the new entry in the pointer. Self-hosting the shipped one takes a single edit, since only the URL changes and the pointer already names it. Should the pointer go missing or stop parsing, the resolver falls back to the shipped default, so a broken pointer never stops a skill from checking an API.
audit-baseline matches these servers by name, and it reads the provider name from the same pointer you edit. Adding a server of your own does not trip it. Swap a server without updating the pointer and the audit will tell you which name it expected to find.