Setting it up
One file of plain Node, zero dependencies, speaking stdio JSON-RPC. It gives a coding agent a project’s roadmap, its issues, its changelog and — inside a run started from the console — the tools that let it report, ask, and read its own task. The API was built to mirror these tools one for one, so an agent gets the same verbs a person gets in the console.
Mint a token
Section titled “Mint a token”In the console, under Agent tokens, mint one and grant it scopes on the project:
| Scope | Lets the token |
|---|---|
roadmap:read / roadmap:write |
Read, or read and write, the roadmap and issues |
changelog:read / changelog:write |
Read, or read and write, the changelog |
backlog:write |
File feedback only — not read the roadmap, not accept its own filing |
You can only grant what you hold. A READER on the project can mint read
scopes and backlog:write; only a WRITER can mint roadmap:write or
changelog:write. A token meant only to file feedback — a tool built beside
cawdev, say, or an agent you don’t fully trust — should get backlog:write
alone: it can propose, but deciding what the feedback becomes is a signed-in
person’s act, refused to every token.
Wire it into a repository
Section titled “Wire it into a repository”Add .mcp.json in the repository the agent works in:
{ "mcpServers": { "cawdev": { "command": "node", "args": ["/path/to/cawdev/tools/mcp/server.mjs"], "env": { "CAWDEV_URL": "https://app.cawdev.com", "CAWDEV_TOKEN": "cawd_…" } } }}Or leave env out and put CAWDEV_URL / CAWDEV_TOKEN / CAWDEV_PROJECT in a
gitignored .env at the repository root. The server searches upward from
its working directory for one, so it works from a subdirectory too.
Which project
Section titled “Which project”A token can be scoped to one project or several. The MCP tools that touch a
project all take an optional project argument:
| Your token grants | What the agent must do |
|---|---|
| exactly one project | nothing — it’s unambiguous |
| several projects | pass project per call, or set CAWDEV_PROJECT |
Get it wrong and the error lists exactly what the token can actually see, rather than a bare “not found”.
When something is confusing
Section titled “When something is confusing”Call roadmap_where. It answers four questions at once — which platform
this is talking to, which token it’s using, where each of those values was
read from (environment, .env, or a default), and who the platform thinks
you are, including every project you can reach and the scopes you hold on
each. Most confusion an agent runs into is one of those four being different
from what somebody assumed.
Checking it works
Section titled “Checking it works”Two smoke tests drive the server the way a real client would — spawned, written to over stdin, read from stdout — rather than importing its functions, because the transport and framing are the part most likely to break:
CAWDEV_URL=https://app.cawdev.com CAWDEV_TOKEN=cawd_… \ node tools/mcp/smoke.mjs scratch-projectName a scratch project. This test creates a roadmap entry and declines it, and entries cannot be deleted — so it refuses to guess which project you meant.
node tools/mcp/orchestration-smoke.mjs scratch-projectThis one starts a real run, drives it through a runner, and exercises the
ask_user → someone answers → the call returns path.
Or drive it by hand, one call at a time:
printf '%s\n' \ '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}}}' \ '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"roadmap_where","arguments":{}}}' \ | CAWDEV_TOKEN=cawd_… node tools/mcp/server.mjs