Plan mode: admit an MCP tool that declares readOnlyHint and is allow-listed
Problem
In plan mode, an MCP tool that is explicitly allow-listed still prompts on every call if plan mode's classifier considers it write-capable.
Concrete symptom, MariaDB MCP server started in read-only mode (MCP_READ_ONLY=true):
mcp__mariadb-production-readonly__list_tables— passes silently in plan modemcp__mariadb-production-readonly__get_table_schema— passes silentlymcp__mariadb-production-readonly__execute_sql— prompts on every call, althoughmcp__mariadb-production-readonly__execute_sqlis inpermissions.allowin our organisation's managed settings
The server physically cannot write: with MCP_READ_ONLY=true it enforces a statement allowlist and rejects anything that is not a read. Answering a schema question while planning therefore costs one permission prompt per query, for a tool that is both incapable of writing and pre-approved by the user.
There is no workaround. Plan mode's write-capability gate is a classifier check, not a permission rule, so neither an allow entry nor a PreToolUse hook returning {"permissionDecision": "allow"} suppresses it.
Proposal
In plan mode, admit an MCP tool without a prompt when both hold:
- the tool declares
readOnlyHint: truein its MCPToolAnnotations, and - a
permissions.allowentry matches it.
Both signals already exist. readOnlyHint has been part of the MCP spec since revision 2025-03-26 (ToolAnnotations), and permissions.allow is today's config surface. No new rule kind, no planModeAllow, no new configuration to document.
The two-signal requirement is what makes this safe. ToolAnnotations carries the spec warning that clients "should never make tool use decisions based on ToolAnnotations received from untrusted servers" — the spec deliberately leaves trust establishment to the client. The user's allow entry is that trust establishment. A rogue server cannot self-grant plan-mode access by asserting readOnlyHint: true, because it still needs the user to have allow-listed the tool. Conversely, an allow entry alone stays insufficient for a tool that does not declare itself read-only, so today's behaviour is unchanged for everything else.
That is the difference from #79484, which asks for an exemption for write-capable tools and needs a new opt-in surface. This asks only that an existing declaration be consulted.
Relation to prior issues
- https://github.com/anthropics/claude-code/issues/12368 asked essentially this question. It was auto-closed
NOT_PLANNEDby the stale bot after 60 days and then locked — closed by inactivity, not declined on the merits. - https://github.com/anthropics/claude-code/issues/79484 is open but asks for the write-capable case, which is easy to decline and does not help the read-only case.
Supply side
The annotation has to come from somewhere, so we are upstreaming it: a PR to https://github.com/MariaDB/mcp adds readOnlyHint to every tool, with readOnlyHint=self.is_read_only on execute_sql — the same flag that enforces the read-only statement allowlist. The annotation reports enforced behaviour rather than promising good behaviour.
Servers can add the annotation today. Nothing improves for any user until Claude Code consults it.