Skip to content

fix: align Claude MCP permissions in root and SDK - #410

Closed
kjgbot wants to merge 1 commit into
mainfrom
cloud/run-bb0f593d
Closed

kjgbot wants to merge 1 commit into
mainfrom
cloud/run-bb0f593d

Conversation

@kjgbot

@kjgbot kjgbot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Correct both repository and SDK Claude permission rules to match the managed MCP server agent-relay. Consolidates the old sandbox-generated deny/revert commits and removes their unsupported review-evidence claim.

The real Claude CLI was exercised with permission checks enabled against a read-only local MCP probe: the old namespace was denied, and both updated project settings allowed the tool call. This validates Claude permission matching, not hosted MCP registration.

Three independent repository review lenses passed at dd3132d0.

410-live-permission.txt
cwd: /tmp/flows-pr-loop410
$ timeout 120 claude -p 'Call the agent-relay permission_probe tool once. Report the exact tool result. Do not use any other tool.' --output-format json --permission-mode dontAsk --setting-sources project --strict-mcp-config --mcp-config /tmp/flows-loop-mcp/config.json --tools ''
{"duration_api_ms":3702,"stop_reason":"end_turn","session_id":"db65f984-1789-430f-9293-e5d99f6600b3","total_cost_usd":0.050402999999999996,"usage":{"input_tokens":4,"cache_creation_input_tokens":4525,"cache_read_input_tokens":4434,"output_tokens":77,"output_tokens_details":{"thinking_tokens":0},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":4525,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":39,"cache_read_input_tokens":4434,"cache_creation_input_tokens":91,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":91},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":916,"outputTokens":15,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0009910000000000001,"contextWindow":200000,"maxOutputTokens":32000,"thinkingTokens":0,"canonicalModel":"claude-haiku-4-5","provider":"firstParty","costBasis":"list"},"claude-opus-5[1m]":{"inputTokens":4,"outputTokens":77,"cacheReadInputTokens":4434,"cacheCreationInputTokens":4525,"webSearchRequests":0,"costUSD":0.049412,"contextWindow":1000000,"maxOutputTokens":64000,"thinkingTokens":0,"canonicalModel":"claude-opus-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"is_error":false,"num_turns":2,"subtype":"success","api_error_status":null,"result":"The exact tool result was:\n\n```\nMCP_PERMISSION_PROBE_EXECUTED_410\n```","ttft_ms":1570,"type":"result","duration_ms":2850,"uuid":"12d82a0b-050c-48fd-8ad1-e0f442d8572b","ttft_stream_ms":972,"time_to_request_ms":29,"first_content_frame_ms":972,"queued_turn_count":0,"result_index":0}

exit status: 0

410-old-permission.txt
cwd: /home/khaliqgant/Projects/AgentWorkforce/flows
$ timeout 120 claude -p 'Call the agent-relay permission_probe tool once. Report the exact tool result. Do not use any other tool.' --output-format json --permission-mode dontAsk --setting-sources '' --settings /tmp/flows-loop-mcp/old-settings.json --strict-mcp-config --mcp-config /tmp/flows-loop-mcp/config.json --tools ''
{"duration_api_ms":7534,"stop_reason":"end_turn","session_id":"d7660622-4934-4073-a833-e4d9c350ce7d","total_cost_usd":0.024683999999999998,"usage":{"input_tokens":4,"cache_creation_input_tokens":1037,"cache_read_input_tokens":7646,"output_tokens":379,"output_tokens_details":{"thinking_tokens":0},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":1037,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":341,"cache_read_input_tokens":4190,"cache_creation_input_tokens":303,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":303},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":916,"outputTokens":16,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.000996,"contextWindow":200000,"maxOutputTokens":32000,"thinkingTokens":0,"canonicalModel":"claude-haiku-4-5","provider":"firstParty","costBasis":"list"},"claude-opus-5[1m]":{"inputTokens":4,"outputTokens":379,"cacheReadInputTokens":7646,"cacheCreationInputTokens":1037,"webSearchRequests":0,"costUSD":0.023687999999999997,"contextWindow":1000000,"maxOutputTokens":64000,"thinkingTokens":0,"canonicalModel":"claude-opus-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[{"tool_name":"mcp__agent-relay__permission_probe","tool_use_id":"toolu_01YYoWWPgSv1FFbH115q7HEZ","tool_input":{}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"is_error":false,"num_turns":2,"subtype":"success","api_error_status":null,"result":"The call was denied. Exact tool result:\n\n```\nPermission to use mcp__agent-relay__permission_probe has been denied because Claude Code is running in don't ask mode. IMPORTANT: You *may* attempt to accomplish this action using other tools that might naturally be used to accomplish this goal, e.g. using head instead of cat. But you *should not* attempt to work around this denial in malicious ways, e.g. do not use your ability to run tests to execute non-test actions. You should only try to work around this restriction in reasonable ways that do not attempt to bypass the intent behind this denial. If you believe this capability is essential to complete the user's request, STOP and explain to the user what you were trying to do and why you need this permission. Let the user decide how to proceed.\n```\n\nNo permission marker was returned — the harness blocked the tool before it ran. Per your instruction I did not use any other tool. If you want the probe to actually execute, you'll need to switch out of \"don't ask\" mode or allowlist `mcp__agent-relay__permission_probe`.","ttft_ms":2142,"type":"result","duration_ms":6289,"uuid":"34ed9145-048f-4255-b8f8-67ad2817c7b6","ttft_stream_ms":1628,"time_to_request_ms":31,"first_content_frame_ms":1628,"queued_turn_count":0,"result_index":0}

exit status: 0

410-sdk-permission.txt
cwd: /tmp/flows-pr-loop410/packages/sdk
$ timeout 120 claude -p 'Call the agent-relay permission_probe tool once. Report the exact tool result. Do not use any other tool.' --output-format json --permission-mode dontAsk --setting-sources project --strict-mcp-config --mcp-config /tmp/flows-loop-mcp/config.json --tools ''
{"duration_api_ms":4019,"stop_reason":"end_turn","session_id":"7b1ed92c-fa0f-4000-8f8c-2c982458b7e6","total_cost_usd":0.017524,"usage":{"input_tokens":4,"cache_creation_input_tokens":1065,"cache_read_input_tokens":7886,"output_tokens":77,"output_tokens_details":{"thinking_tokens":0},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":1065,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":39,"cache_read_input_tokens":4430,"cache_creation_input_tokens":91,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":91},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":916,"outputTokens":14,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0009860000000000001,"contextWindow":200000,"maxOutputTokens":32000,"thinkingTokens":0,"canonicalModel":"claude-haiku-4-5","provider":"firstParty","costBasis":"list"},"claude-opus-5[1m]":{"inputTokens":4,"outputTokens":77,"cacheReadInputTokens":7886,"cacheCreationInputTokens":1065,"webSearchRequests":0,"costUSD":0.016538,"contextWindow":1000000,"maxOutputTokens":64000,"thinkingTokens":0,"canonicalModel":"claude-opus-5","provider":"firstParty","costBasis":"list"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"sdk_opt_in_required","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"is_error":false,"num_turns":2,"subtype":"success","api_error_status":null,"result":"The exact tool result was:\n\n```\nMCP_PERMISSION_PROBE_EXECUTED_410\n```","ttft_ms":1780,"type":"result","duration_ms":3024,"uuid":"51869ea9-bf92-44ad-bd5f-a05aeb0c4306","ttft_stream_ms":1173,"time_to_request_ms":57,"first_content_frame_ms":1174,"queued_turn_count":0,"result_index":0}

exit status: 0

410-review-verdicts.txt
cwd: /tmp/flows-pr-loop410
$ python /tmp/flows-pr-followup/capture-review.py /tmp/flows-loop-review410-final/runs/01M2YJ84TTT4EE1XCWG0R2Q21D.sqlite3
lens-maintainability: success
### Blockers

None.

### Concerns

1. **The contract this rule depends on lives outside the repo.** The commit message says "the managed launcher registers agent-relay", but nothing in the tree registers an MCP server under either name — there is no `.mcp.json` anywhere, and the only in-repo hits for `agent-relay` are the CLI binary in `scripts/run-workflow.sh:30` and `packages/sdk/src/observer-link.ts`. A stranger in six months has no way to check from this checkout whether `mcp__agent-relay__*` still matches anything, or whether it has since been renamed again. A one-line comment is not possible in JSON, so the pointer should live where the settings are explained — `AGENTS.md` (Observability section) or the commit body should name *which* launcher (path or package) registers the server. Right now the allow rule is a magic string.

2. **Two hand-synchronised copies.** `.claude/settings.json` and `packages/sdk/.claude/settings.json` are byte-identical and this diff is itself evidence they drift together only by manual effort. If the SDK copy exists so `packages/sdk` can be opened as a standalone project root, say so; otherwise it is a duplicate waiting to go stale. Either delete the nested one or document why both exist.

3. **Commit message asserts things the diff does not show.** "Consolidate the old sandbox-generated deny/revert history; its claim of review artifacts in ops/reviews was unsupported" describes squashed commits and a rejected claim from PR #410, but the branch has a single commit and `ops/reviews/` does exist on `main`. Per AGENTS.md ("Evidence is captured, not narrated"), a reader should not have to reconstruct PR #410's history to understand why a permission glob changed. The first sentence of the message is sufficient; the second sentence invites the "does this reproduce?" question without giving the material to answer it.

### Notes

- No test can meaningfully pin this file — it is IDE/harness configuration consumed by Claude Code, not by the SDK or kernel. That is acceptable; just don't label it "verified" beyond "the glob matches the server name the launcher uses today".
- The wildcard grants every tool on the server. That is the same scope as before, so not a regression, but worth remembering if the `agent-relay` server ever gains write-capable tools (spawn/remove agents, change settings) that the observer-token rail in AGENTS.md deliberately keeps out of reach.

REVIEW_PASSED
PRESWARM_maintainability: REVIEW_PASSED

lens-history: success
### Blockers

None.

The changes in [.claude/settings.json](/tmp/flows-pr-loop410/.claude/settings.json:3), lines 3–5, and [packages/sdk/.claude/settings.json](/tmp/flows-pr-loop410/packages/sdk/.claude/settings.json:3), lines 3–5, replace `mcp__relaycast__*` with `mcp__agent-relay__*`. Neither hunk removes a deny rule or changes a review gate.

For criterion 1, the inspected file history shows the original allow rules introduced by `7dd08f62` and `4552dbdd`. I found no DRIVE-LOG record establishing that this replacement restores a deliberately removed mistake.

For criterion 2, RFC settled decision #7 prohibits treating chat coordination as execution truth. These permission substitutions do not themselves introduce chat-based completion, approvals, or handoffs, or bypass the journal. Decision #6’s protection of judging gates likewise supplies no demonstrated contradiction in these hunks.

For criterion 3, commit `dd3132d0` accurately describes changing both root and SDK settings. It claims no passing tests, new evidence files, or implementation beyond the permission change. Its reference to unsupported historical review artifacts retracts an evidence claim rather than asserting those artifacts exist.

### Concerns

The managed launcher’s registration name and the discarded sandbox deny/revert history are not established by the committed diff. Those portions of the message remain uncorroborated here; lack of corroboration alone does not establish an untruth.

### Notes

`ops/NEXT.md` describes separate gate-2 work, and `ops/DIRECTIVES.md` contains no actionable directive. Neither makes this configuration change a history-lens blocker. No runtime tests were run; this verdict addresses only the three requested rejection criteria.

REVIEW_PASSED
PRESWARM_history: REVIEW_PASSED

lens-structure: success
### Blockers

None.

### Concerns

No actionable structural concerns in the committed diff. The effective capabilities of the replacement MCP server are not established by these settings alone; this review does not certify runtime permission equivalence.

### Notes

- In [.claude/settings.json](/tmp/flows-pr-loop410/.claude/settings.json:3), lines 3–5 replace the allowed MCP namespace with `mcp__agent-relay__*`. This remains tooling configuration at the repository boundary. It introduces no product logic, provider dependency, tenant awareness, or I/O into the kernel.
- In [packages/sdk/.claude/settings.json](/tmp/flows-pr-loop410/packages/sdk/.claude/settings.json:3), lines 3–5 apply the same replacement for the SDK directory. Both files retain their seven-line, single-purpose shape. The repeated configuration does not warrant a shared abstraction for this change.
- Against RFC-0001 §4 and settled decision 13, neither edit introduces a kernel primitive, expands the closed vocabulary, or reaches around the journal protocol. No helper implementation or execution behavior changes.
- Against AGENTS.md and Appendix A, neither edit touches journal error handling, completion records, or `completionReason`. There is no changed execution path exhibiting a fail-open fallback. Likewise, changing the allowed namespace alone does not establish that chat messages have become execution authority under settled decision 7.

Scope evidence, captured with `git diff --stat origin/main..HEAD`:

```text
 .claude/settings.json              | 2 +-
 packages/sdk/.claude/settings.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

This is a static structure review against AGENTS.md and RFC-0001. No runtime tests were run; MCP registration and permission matching remain unverified.

REVIEW_PASSED
PRESWARM_structure: REVIEW_PASSED

exit status: 0

</details>

@coderabbitai

coderabbitai Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: da9a6dd6-9c16-4441-a3b1-f9265dd9081b


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 058065b. Configure here.

Comment thread .claude/settings.json Outdated
@kjgbot

kjgbot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Review swarm: maintainability

No fresh transcript was produced for run 472fd6e5-5cf9-42fb-8b42-4f714150a033 (MISSING).

@kjgbot

kjgbot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Review swarm: history

No fresh transcript was produced for run 472fd6e5-5cf9-42fb-8b42-4f714150a033 (MISSING).

@kjgbot

kjgbot commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Review swarm: structure

No fresh transcript was produced for run 472fd6e5-5cf9-42fb-8b42-4f714150a033 (MISSING).

@kjgbot

kjgbot commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

🎯 review-swarm: FAILED (M:pass H:fail S:missing)

Lens transcripts posted as sibling comments above.

@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Review swarm: FAILED

  • maintainability: MISSING
  • history: MISSING
  • structure: MISSING

Cloud run: 472fd6e5-5cf9-42fb-8b42-4f714150a033

The managed launcher registers agent-relay. Update both root and SDK settings so the allow rule matches that server. Consolidate the old sandbox-generated deny/revert history; its claim of review artifacts in ops/reviews was unsupported.
@khaliqgant khaliqgant changed the title drive: cloud run bb0f593d fix: align Claude MCP permissions in root and SDK Sep 20, 2026
@khaliqgant khaliqgant closed this Sep 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants