Skip to content

fix(mcp): mark tools that write not read-only and test the schema - #3649

Merged
dan-petty merged 4 commits into
mainfrom
fix/3235-read-only-mcp-tools-have-no-write-option
Nov 5, 2026
Merged

dan-petty merged 4 commits into
mainfrom
fix/3235-read-only-mcp-tools-have-no-write-option

Conversation

@dan-petty

Copy link
Copy Markdown
Owner

A role server and a client choose tools by the read-only flag, so a tool with an option that writes must not be read-only. The change marks pr_check_readiness, roadmap_refine, roadmap_run and ci not read-only. Each command keeps its option. The schemas of scan_injection and tf_plan drop the file options sarif and out, and both tools stay read-only. A new test reads the published schema of every tool. It fails on a read-only tool whose option description holds the verb resolve, write, delete or create. Other tools stay open in #3642 (tools that write local state), #3644 (help text of tf_notify_plan) and #3480 (path decisions).

Closes #3235

Change: openspec/changes/archive/2026-11-05-3235-read-only-mcp-tools-have-no-write-option/
Elapsed: 3.61s

The exposure table marked pr check-readiness, roadmap refine and tf plan as read-only. Each has an option that writes to GitHub or to a file. Mark the three tools not read-only. Drop the sarif option from the scan injection tool, which stays read-only. A new test fails on a read-only tool with an option whose description holds resolve, write, delete or create.

Refs #3235
The review of #3235 found two more tools that write: roadmap run with --confirm and ci with --fix. The tf plan tool published --out, a path that the command writes and nothing confines. Its schema now leaves out that option and the tool stays read-only. The change folder names the follow-up issues.
@dan-petty dan-petty added type/bug Defect, regression, or incorrect runtime behavior scope/mcp Model Context Protocol tools, system resources, and prompts labels Nov 5, 2026
@dan-petty

Copy link
Copy Markdown
Owner Author

Test results

Fail-to-pass run (uv run devops ci fail-to-pass --base origin/main): 7 tests fail on the base and 7 pass. The new test file tests/ai/mcp/test_mcp_read_only_write_options.py holds all 14.

The 7 tests that fail on the base:

  • test_no_read_only_tool_publishes_a_write_option
  • test_a_tool_that_keeps_a_writing_option_is_not_read_only for pr_check_readiness, roadmap_refine, roadmap_run and ci
  • test_a_read_only_tool_leaves_out_an_option_that_writes_a_file for scan_injection (sarif) and tf_plan (out)

Full gate (uv run devops ci, on the final code): 18,802 tests pass and 4 fail with 1 error. All other checks pass: lint, format, typecheck, security, docs, openspec, build, deps and the rest.

The 4 failures and the 1 error read the state of the host. They fail the same way on a clean main checkout at 66a8a63, with none of these changes:

  • tests/crypto/test_ssh.py::test_get_ssh_key_prefix_resolution
  • tests/telemetry/test_config_env_overrides.py::test_find_project_config_path_skips_directory (a stray /tmp/config.yaml on the host)
  • tests/commands/test_devcontainer_install_tools_dry_run.py::test_mark_only_commands_under_global_dry_run (the host has the devcontainer tool)
  • tests/ai/test_tool_executor_contract.py::test_the_direct_executor_refuses_a_network_profile_before_it_starts_the_tool[direct] (the host has Popeye), with its teardown error

Open issues already own them (#3585, #3590, #3593, #3594, #3597 and #3025). This change touches none of them.

Review findings

A review of the first version gave five findings. I checked each one.

  1. Criterion 1 not met for other tools. Partly right.
    • roadmap_run.confirm and ci.fix are true writes. Both tools are now not read-only, and the new test covers them.
    • tf_notify_plan.pr_number is a wrong finding. devops tf notify-plan sends no request. It prints the comment and puts the PR number in its payload. The tool is read-only. Its help says that it posts, and issue fix(tf): tf notify-plan says it posts a comment and posts nothing #3644 owns that text.
    • ai_gateway_failover.reset and review_export_feedback.output are true. So are ai_quiesce, ai_resume and ai_failover, which the review did not list. Each command writes local state or a file, and each has the class no-external-request. The requirement mcp-read-only-hint-agrees-with-no-external-request and its ratchet test force readOnlyHint true. Dropping one option would leave the whole command as a write. Issue fix(mcp): tools that write local state are flagged read-only #3642 decides what the class means for the flag. The proposal and the tasks.md follow-up list say that criterion 1 is met for the tools that the rule and the review found.
  2. tf_plan.out is an unconfined write path. Right. The tool now leaves out out and stays read-only, like scan_injection.sarif. The spec, the test, the design and docs/MCP_TOOLS.md follow. scan_injection.suppress and review_export_feedback.output stay as before. Issue fix(mcp): the path audit finds path options by type and by name #3480 owns both.
  3. No follow-up bullet. Right. tasks.md names fix(mcp): tools that write local state are flagged read-only #3642, fix(tf): tf notify-plan says it posts a comment and posts nothing #3644 and fix(mcp): the path audit finds path options by type and by name #3480 under ## Workflow follow-up.
  4. "Four flags change" was wrong. Right. With the new rows, four flags change against main: pr_check_readiness, roadmap_refine, roadmap_run and ci. The text is correct now.
  5. Long sentences. Right. I split the long sentences in the proposal, the design, the tasks, the spec and the test docstring.

@dan-petty
dan-petty marked this pull request as ready for review November 5, 2026 16:25
@dan-petty
dan-petty merged commit 6d9dded into main Nov 5, 2026
23 checks passed
@dan-petty
dan-petty deleted the fix/3235-read-only-mcp-tools-have-no-write-option branch November 5, 2026 16:26
dan-petty pushed a commit that referenced this pull request Nov 5, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.62.6](v0.62.5...v0.62.6)
(2026-11-05)


### Bug Fixes

* **mcp:** mark tools that write not read-only and test the schema
([#3649](#3649))
([6d9dded](6d9dded))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: dan-petty-release[bot] <346998822+dan-petty-release[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope/mcp Model Context Protocol tools, system resources, and prompts type/bug Defect, regression, or incorrect runtime behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(mcp): pr_check_readiness is read-only in the exposure table but can resolve threads

1 participant