Part of #334 (3): "the MCP as the roadmapping door". The forge already has the map (GET /api/v1/map) and dependency actions (src/actions/dependencies.tslinkIssue/unlinkIssue); the MCP (src/http/mcp.ts) has none of them.
Done when
[ ] map (read): an app's open issues as ready / waiting / blocked, with what each waits for — the same data as /api/v1/map, from the same function, not a second query
[ ] link and unlink (write, rw token): { app, issue, blockedBy }, calling the same actions the API calls, with the same refusals (cycles, cross-repository, unknown issues)
[ ] tools carry readOnlyHint correctly and appear in tools/list; docs/MCP.md's table lists them
[ ] a private app is "no such app" to a token that cannot read it
[ ] tests through POST /mcp: map answers; link then unlink round-trips; an ro token is refused on link; a cycle is refused with the API's words
Files: src/http/mcp.ts, docs/MCP.md, tests.
Risks: conflicts with #333 (same file and doc) — land after it.
Brief: the builder who did #333.
Part of #334 (3): "the MCP as the roadmapping door". The forge already has the map (
GET /api/v1/map) and dependency actions (src/actions/dependencies.tslinkIssue/unlinkIssue); the MCP (src/http/mcp.ts) has none of them.Done when
map(read): an app's open issues as ready / waiting / blocked, with what each waits for — the same data as/api/v1/map, from the same function, not a second querylinkandunlink(write,rwtoken):{ app, issue, blockedBy }, calling the same actions the API calls, with the same refusals (cycles, cross-repository, unknown issues)readOnlyHintcorrectly and appear intools/list;docs/MCP.md's table lists themPOST /mcp: map answers; link then unlink round-trips; anrotoken is refused on link; a cycle is refused with the API's wordsFiles:
src/http/mcp.ts,docs/MCP.md, tests. Risks: conflicts with #333 (same file and doc) — land after it. Brief: the builder who did #333.