forgejo-mcp: trim tool-schema surface to the ~15 actually-used RPCs #81
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#81
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As the operator, I want the
forgejo-mcpserver registered byagent containers to expose only the ~15 RPCs our skills actually
call, so that the tool-schema bloat in the SDK's system prompt
drops by ~20-25k tokens and agents stop hitting
Prompt is too longon their first turn.
What happened (concrete)
Boss (
claude-opus-4-7, 200k context) died on the first turn oftask
695b934e-6db9-4b35-990c-924b8b39e717on #79 with:Zero events in the task record — the API request never even left
the SDK. The prompt body is tiny (~1.5KB skill template + 5KB issue
body). What's eating the 200k:
forgejo-mcp, serialisedverbatim into the system prompt at startup. Each tool carries
a JSONSchema for its arguments; the aggregate is 25-30k tokens.
(ref anthropics/claude-code#49593).
Container is on 2.1.112, so we inherit that.
Why this matters
The SDK does not lazy-load MCP tool schemas — it ships every
registered tool's full schema on every turn. The
allowedToolsoption only gates invocation, not schema inclusion.
SDK issue #138
documents the same failure mode on first turn; closed as "not planned".
Claude Code #20421
asks for dynamic MCP loading — exists in the CLI, not the SDK.
Translation: we can't trim this from the SDK caller side. We have to
cut the surface in the
forgejo-mcpserver.What our skills actually use
Grepping
skills/,src/webhook-*.ts, and the test suite, the onlymcp__forgejo__*names we invoke are:get_issue_by_index,list_issue_comments,list_repo_issues,list_repo_labels,list_repo_pull_requests,get_pull_request_by_index,list_pull_request_files,list_pull_review_comments,get_pull_review,list_workflow_runs,get_workflow_run,get_file_content.create_issue_comment,update_issue,add_issue_labels,create_pull_request,create_review_requests,submit_pull_review,merge_pull_request.That's ~19 tools, not 65. Everything else (org/team admin, user
management, notifications, repo creation, fork, dispatch_workflow,
interactive review states, file CRUD, etc.) is dead surface.
Acceptance criteria
Server-side tool filtering
forgejo-mcpgains an env-var allowlist — e.g.FORGEJO_MCP_TOOLS="get_issue_by_index,list_issue_comments,..."— and only registers those names at startup.
break unpatched installs.
patches/directory and rebases cleanlyon upstream
v2.17.0(current patched version).Wiring
agent-runner.tsbuildMcpSetupsetsFORGEJO_MCP_TOOLSfrom a single canonical list (probably a
const FORGEJO_TOOLS_ALLOWLISTin the same file).allowedToolsin the SDKquery()call derives from thesame list so the two stay in sync.
Smoke
scripts/smoke-creds.shasserts that an agent'sclaude mcp__forgejo__* list(or equivalent) exposes exactlythe allowlisted count — fails loud if bigger.
(the current failure signature) and runs to completion under
200k context.
Out of scope
Upstream's call; not our codebase.
by #73/#74 adding more. Revisit if this recurs on designers.
References
695b934e-6db9-4b35-990c-924b8b39e717on #79.same first-turn failure mode.
2.1.111 context bloat regression.
dynamic MCP loading not in SDK.
patches/forgejo-mcp/— where the patch goes.Dependencies
[1m]fallback.main./cancelendpoint: accept anagentparam instead of cancelling the first busy worker #87