[FEATURE] Permission engine should process MCP ToolAnnotations hints (readOnlyHint, destructiveHint, etc.)

Status Open
Maintainer reply None cached
Activity 1 comment · opened Aug 17, 2026

Preflight Checklist

  • [x] I have searched existing requests and this feature hasn't been requested yet
  • [x] This is a single feature request (not multiple features)

Problem Statement

Claude Code's permission engine treats all MCP tool calls uniformly for approval purposes, regardless of the tool's actual risk. The MCP spec defines standard ToolAnnotationsreadOnlyHint, destructiveHint, idempotentHint, openWorldHint — which many MCP servers already declare in their tools/list response.

Ref: https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations

interface ToolAnnotations {
  [title](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-title)?: string;
  [readOnlyHint](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-readonlyhint)?: boolean;
  [destructiveHint](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-destructivehint)?: boolean;
  [idempotentHint](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-idempotenthint)?: boolean;
  [openWorldHint](https://modelcontextprotocol.io/specification/2025-06-18/schema#toolannotations-openworldhint)?: boolean;
}

This has been in the MCP spec since Q2 2025, yet Claude Code doesn't read or act on any of these; it only recognizes its own Anthropic-specific _meta fields (anthropic/requiresUserInteraction, anthropic/maxResultSizeChars, anthropic/alwaysLoad), none of which express read/write risk.

In practice this means a read-only lookup (e.g. getJiraIssue) and a destructive write (e.g. deleteJiraIssue) get identical prompting behavior. This pushes users toward either approving every MCP call individually — disruptive during multi-step agentic work — or switching to bypassPermissions entirely just to get unblocked, which removes protection for genuinely risky actions too.

Proposed Solution

Have the permission engine consult standard MCP ToolAnnotations when a server declares them:

  • Auto-allow (or apply lighter-weight prompting) for tools with readOnlyHint: true.
  • Continue prompting for destructiveHint: true (or tools with no declared hints at all, preserving today's conservative default).
  • Surface which annotation drove the decision in /permissions / tool-call UI, so behavior is legible rather than a black box.

This scales trust to actual declared risk instead of one-size-fits-all prompting, without requiring users to hand-maintain global allowlists for every read-only tool.

Alternative Solutions

  1. Manually allowlisting individual MCP tools in permissions.allow in settings.json (works, but doesn't scale — every new read-only tool needs a manual entry).
  1. Switching to bypassPermissions mode to stop the prompting — works but removes protection for destructive actions too.

Priority

High - Significant impact on productivity

Feature Category

MCP server integration

Use Case Example

Using the Atlassian MCP server in an agentic session: asking Claude to create a Jira issue triggers a permission prompt indistinguishable from one that would fire for a destructive Jira operation, even though the server declares readOnlyHint/destructiveHint annotations that could differentiate the two. Had to interrupt my code flow to approve, or pre-populate a global allowlist entry, or bypass permissions entirely.

Additional Context

_No response_

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗