Problem
The Coding Agent runtime's MCP permission gate auto-approves tool calls only when the underlying tool is annotated with ReadOnlyHint: true. Anything else (including undefined / missing annotation, or ReadOnlyHint: false) prompts the user.
In production we're seeing read-intent github-mcp-server tools prompting users — for example, callers using the legacy alias get_review (now consolidated into pull_request_read).
Source flow on the runtime side:
runtime/src/mcp-client/known-mcp-servers.ts:585-596 — extractMCPToolAnnotations requires readOnlyHint to be a strict boolean; missing/non-boolean → undefined.
runtime/src/tools/mcp-transport.ts:509 — readOnly: toolConfig.readOnly ? true : false collapses undefined → false → user prompted.
runtime/src/apps/permission-gate.ts — auto-approves only when request.readOnly === true.
Per agreement with the runtime team, defaulting undefined to "read-only" is not the right fix (would over-grant). Instead, ensure the github-mcp-server side is the source of truth.
What's needed
- Audit every tool currently registered by github-mcp-server for missing or incorrect
Annotations.ReadOnlyHint. Most existing read-only tools already have this set (verified pull_request_read, issue_triage_context, semantic_issues_search, package_search, dependabot, find_closing_pull_requests, summarize_actions). Find the gaps.
- Deprecated tool aliases: when
DeprecatedToolAliases (pkg/github/deprecated_tool_aliases.go) routes a call from an old name (get_review, list_issues, etc.) to a new canonical tool (pull_request_read, issue_read, etc.), make sure the alias's tool descriptor inherits the canonical tool's annotations. Today the aliased tool may be exposed without annotations, defeating the runtime's auto-approve path.
- Consider adding a CI check that fails if any tool registered via
mcp.NewTool lacks an explicit ReadOnlyHint (true or false). Forcing the choice at registration time prevents future regressions.
How to verify
Quick way to spot missing annotations in this repo:
grep -rln 'mcp.NewTool\|toolset.NewTool' --include='*.go' | grep -v _test | xargs -L1 -I{} sh -c 'grep -L ReadOnlyHint "{}"'
Repeat for the deprecated-alias dispatch path.
Related
- Coding Agent runtime:
runtime/src/mcp-client/{known-mcp-servers.ts,out-of-proc-mcp-host.ts,mcp-registry.ts} — current consumer of these annotations.
- Coding Agent permission gate behavior: github/sweagentd
runtime/src/apps/permission-gate.ts.
cc @ritchxu
Problem
The Coding Agent runtime's MCP permission gate auto-approves tool calls only when the underlying tool is annotated with
ReadOnlyHint: true. Anything else (includingundefined/ missing annotation, orReadOnlyHint: false) prompts the user.In production we're seeing read-intent github-mcp-server tools prompting users — for example, callers using the legacy alias
get_review(now consolidated intopull_request_read).Source flow on the runtime side:
runtime/src/mcp-client/known-mcp-servers.ts:585-596—extractMCPToolAnnotationsrequiresreadOnlyHintto be a strictboolean; missing/non-boolean →undefined.runtime/src/tools/mcp-transport.ts:509—readOnly: toolConfig.readOnly ? true : falsecollapsesundefined→false→ user prompted.runtime/src/apps/permission-gate.ts— auto-approves only whenrequest.readOnly === true.Per agreement with the runtime team, defaulting
undefinedto "read-only" is not the right fix (would over-grant). Instead, ensure the github-mcp-server side is the source of truth.What's needed
Annotations.ReadOnlyHint. Most existing read-only tools already have this set (verifiedpull_request_read,issue_triage_context,semantic_issues_search,package_search,dependabot,find_closing_pull_requests,summarize_actions). Find the gaps.DeprecatedToolAliases(pkg/github/deprecated_tool_aliases.go) routes a call from an old name (get_review,list_issues, etc.) to a new canonical tool (pull_request_read,issue_read, etc.), make sure the alias's tool descriptor inherits the canonical tool's annotations. Today the aliased tool may be exposed without annotations, defeating the runtime's auto-approve path.mcp.NewToollacks an explicitReadOnlyHint(true or false). Forcing the choice at registration time prevents future regressions.How to verify
Quick way to spot missing annotations in this repo:
Repeat for the deprecated-alias dispatch path.
Related
runtime/src/mcp-client/{known-mcp-servers.ts,out-of-proc-mcp-host.ts,mcp-registry.ts}— current consumer of these annotations.runtime/src/apps/permission-gate.ts.cc @ritchxu