Implements the final two slices of the OpenSpec change
mcp-resource-templates. The change now ships all 7 entity
resources (owner, repo, commit, status, issue, comment, pr) on
the forgejo:// URI scheme.
Slice 6 — mcp-resource-pr
- operation/pull/resources.go registers
forgejo://repo/{owner}/{repo}/pr/{index}
- Handler returns JSON metadata (head/base refs, mergeability,
state) + text/markdown sidecar + bounded recent_comments and
recent_reviews (cap 30, sentinels name list_issue_comments
and list_pull_reviews respectively)
- Non-numeric index → -32602; missing PR → -32003
- 6 test cases: open/merged PR, > cap comments, > cap reviews,
non-numeric index, 404
- Wired from RegisterCoreResources
Slice 7 — docs/wrap
- README "Resources" section enriched with URI scheme rationale,
the coexist-with-tools rule, and the embedded-list bounding
policy
- AGENTS.md "## Resources" subsection added for future AI
assistants modifying the resource surface
- CHANGELOG.md unreleased section: additive resource surface
- Follow-up beads filed:
- forgejo-mcp-7ra: revisit subscribe=true once a real
subscription use case appears
- forgejo-mcp-7de: revisit EmbeddedListCap=30 once telemetry
available
Tasks 6.1-6.5, 7.1-7.6 ticked. Final tick count: 46/47.
Only 1.11 (manual client verification across Claude
Code/Desktop/Codex/Cursor) remains, out of scope for this team.
Driven by team:dev-loop (impl, runner; impl replaced by impl2
mid-slice-6 after the original impl ignored two checkpoint
probes). Closes the implementation portion of forgejo-mcp-13x.
5.7 KiB
5.7 KiB
1. Resource Framework (slice 1 — mcp-resources-core)
- 1.1 Add
server.WithResourceCapabilities(false, false)tonewMCPServerinoperation/operation.go - 1.2 Create
operation/resource/package skeleton withdoc.go - 1.3 Implement URI parser helpers in
operation/resource/parse.go: one typed-struct parser per entity (ParseOwner,ParseRepo,ParseCommit,ParseIssue,ParsePR,ParseComment,ParseStatus) - 1.4 Implement template-registration helpers in
operation/resource/register.go(thin wrapper aroundmcp.NewResourceTemplate+s.AddResourceTemplate) - 1.5 Implement embedded-list bounding helper in
operation/resource/bound.go: produces sentinel block referencing a named list tool, default cap = 30 exposed asconst EmbeddedListCap = 30 - 1.6 Implement error-mapping helper in
operation/resource/errors.go:MapForgejoError(uri, err) *mcp.JSONRPCErrormapping HTTP403→-32002,404→-32003 - 1.7 Add unit tests for
operation/resource/parse.gocovering: happy path each entity, short sha, non-numeric index, unknown kind - 1.8 Add unit tests for
operation/resource/bound.gocovering: under-cap, at-cap, over-cap with sentinel contents - 1.9 Add unit tests for
operation/resource/errors.gocovering both code paths - 1.10 Add
RegisterCoreResources(s *server.MCPServer)stub function inoperation/operation.go(no-op for slice 1, gives stable wiring point) - 1.11 Manual verification against Claude Code, Claude Desktop, Codex, Cursor: confirm each sends
resources/templates/listandresources/read; record results in design.md "Open Questions" answer
2. Commit Resource (slice 2 — mcp-resource-commit)
- 2.1 Create
operation/repository/resources_commit.go(commit lives under repository domain) withRegisterCommitResource(s *server.MCPServer) - 2.2 Register template
forgejo://repo/{owner}/{repo}/commit/{sha}with description marking immutability - 2.3 Implement handler returning JSON metadata block plus
text/markdownbody sidecar - 2.4 Reject shas not exactly 40 hex chars via
operation/resource.ParseCommit - 2.5 Unit tests: existing sha (mock client), short sha, missing sha, sidecar present
- 2.6 Wire
RegisterCommitResourcefromoperation/operation.go - 2.7 README: append commit row to a new "Resources" table
3. Commit Status Resource (slice 3 — mcp-resource-status)
- 3.1 Create
operation/repository/resources_status.gowithRegisterStatusResource(s *server.MCPServer) - 3.2 Register template
forgejo://repo/{owner}/{repo}/commit/{sha}/statuswith cacheability note in description - 3.3 Implement handler returning aggregate state + bounded
statusesarray viaoperation/resource.Bounded(..., "get_commit_statuses") - 3.4 Map empty-statuses case to aggregate
state="unknown" - 3.5 Unit tests: < cap, > cap with sentinel naming
get_commit_statuses, empty case, short sha, missing sha - 3.6 Wire from
operation/operation.go - 3.7 README: append status row to Resources table
4. Repo + Owner Resources (slice 4)
- 4.1 Create
operation/repository/resources_repo.gowithRegisterRepoResource(s *server.MCPServer); templateforgejo://repo/{owner}/{repo}; return counts only, no embedded lists - 4.2 Create
operation/user/resources_owner.gowithRegisterOwnerResource(s *server.MCPServer); templateforgejo://owner/{owner}; resolve user or org - 4.3 Unit tests for each: happy path, 403, 404
- 4.4 Wire both from
operation/operation.go - 4.5 README: append rows for
repoandownerto Resources table
5. Issue + Comment Resources (slice 5)
- 5.1 Create
operation/issue/resources.gowithRegisterIssueResources(s *server.MCPServer) - 5.2 Register issue template
forgejo://repo/{owner}/{repo}/issue/{index}with handler returning metadata + markdown sidecar + boundedrecent_comments(sentinel nameslist_issue_comments) - 5.3 Register comment template
forgejo://repo/{owner}/{repo}/{kind}/{index}/comment/{id}constrainingkind ∈ {issue, pr}in parser (rejectwikietc. with-32602) - 5.4 Unit tests: issue happy path, issue with > cap comments, non-numeric index, unknown kind for comment, missing comment
- 5.5 Wire from
operation/operation.go - 5.6 README: append rows for
issueandcommentto Resources table
6. PR Resource (slice 6 — mcp-resource-pr)
- 6.1 Create
operation/pull/resources.gowithRegisterPullResources(s *server.MCPServer) - 6.2 Register template
forgejo://repo/{owner}/{repo}/pr/{index}with handler returning metadata + head/base refs + mergeability + markdown sidecar + boundedrecent_comments(sentinel nameslist_issue_comments) + boundedrecent_reviews(sentinel nameslist_pull_reviews) - 6.3 Unit tests: open PR, merged PR, PR with > cap comments, PR with > cap reviews, non-numeric index, missing PR
- 6.4 Wire from
operation/operation.go - 6.5 README: append row for
prto Resources table
7. Documentation & Wrap-up
- 7.1 Add "Resources" section to README explaining the URI scheme, listing all templates in one table, and stating the coexist-with-tools rule
- 7.2 Add "Resources" subsection to AGENTS.md mirroring the README rule for AI assistants modifying the codebase
- 7.3 Update CHANGELOG (or release notes file) noting the additive surface
- 7.4 Verify
make buildand full test suite pass with all sevenRegisterXResourcescalls wired - 7.5 File a follow-up bead to revisit
WithResourceCapabilities(subscribe=true, …)once a real subscription use case appears (forgejo-mcp-7ra) - 7.6 File a follow-up bead to revisit the default embedded-list cap (currently
30) once usage telemetry is available (forgejo-mcp-7de)