Skip to content

Audit and fix missing ReadOnlyHint annotations on read-intent tools #2483

@ritchxu

Description

@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 (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-596extractMCPToolAnnotations requires readOnlyHint to be a strict boolean; missing/non-boolean → undefined.
  • runtime/src/tools/mcp-transport.ts:509readOnly: toolConfig.readOnly ? true : false collapses undefinedfalse → 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

  1. 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.
  2. 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.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions