Skip to content

Pre-approve kcap ledger servers and annotate every MCP tool - #1112

Merged
alexeyzimarev merged 3 commits into
mainfrom
codex-mcp-approval-annotations
Sep 23, 2026
Merged

alexeyzimarev merged 3 commits into
mainfrom
codex-mcp-approval-annotations

Conversation

@alexeyzimarev

@alexeyzimarev alexeyzimarev commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Closes #1111 — AI-3132

What & why

Codex decides whether an MCP call needs approval from the tool's annotations: a tool marked non-destructive and closed-world runs without one, a destructive tool goes to approval, and with approvals_reviewer = "auto_review" that approval is a model that can end the turn. No kcap tool advertised annotations, so every call went to approval and declare_plan_document was refused as an upload with no named destination. Every tool now carries annotations for what its handler does, the plans description names where the content goes, and registration pre-approves kcap-workitems and kcap-plans beside the read-only servers, since even their destructive tools touch only the session's own record. kcap-memory stays on annotations: a save or rescope can widen who sees a memory.

Where to look

McpToolAnnotations fixes six presets; each tool's pick is the claim to check, chosen by what the handler does rather than by the name: the two flow status calls acknowledge the messages they render, so they are not reads, and set_plan_tasks mints ids for entries without one, so it is destructive and not idempotent. A Codex entry kcap wrote is healed to the new shape on the next kcap setup; one Codex has since added per-tool approvals under is left alone.

Verification

Codex 0.155.1 with the auto-reviewer on refused declare_plan_document: "would upload local document contents without explicit destination approval". After the change, --treenode-filter "/*/*/Mcp*/*" on the CLI unit suite: 445 passed, 0 failed; the integration MCP classes: 59 passed; the Core registration and descriptor classes: 132 passed. dotnet publish -c Release: no IL2026/IL3050 warnings. A live Codex run against the healed entry is still owed.

🤖 Generated with Claude Code

Codex reads a missing MCP annotation as destructive and open-world, so an unannotated tool is prompted for on every call, and its automatic reviewer ends the turn on a refusal rather than asking. Pre-approval covers servers whose writes land only in the user's own Capacitor workspace; flows and artefacts keep prompting.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-22T16:43:58.002911Z 264a1bb PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Pre-approve safe ledger MCP servers and annotate all tools

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Pre-approves safe ledger servers while keeping paid launches and visibility changes gated.
• Adds accurate MCP safety annotations to every kcap tool for approval-aware harnesses.
• Clarifies plan content destination and verifies registration and annotation contracts.
Diagram

graph TD
  Setup["Setup Writers"] --> Catalog["Server Catalog"] --> Codex["Codex Config"] --> Approval["Harness Approval"]
  Catalog --> Gemini["Gemini Config"] --> Approval
  Builders["Tool Builders"] --> Presets["Safety Presets"] --> Approval
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Rely only on tool annotations
  • ➕ Avoids blanket server-level approval for future tools.
  • ➕ Keeps approval decisions operation-specific.
  • ➖ Does not help harnesses that rely on per-server trust.
  • ➖ Missing or unsupported annotation handling would restore unnecessary prompts.
2. Generate per-tool approval rules
  • ➕ Provides finer-grained registration policy than server-wide approval.
  • ➕ Could explicitly gate destructive tools inside otherwise trusted servers.
  • ➖ Requires harness-specific configuration and migration logic.
  • ➖ Approval schemas and feature support differ across clients.

Recommendation: Keep the PR's dual-layer approach: server trust supports Codex and Gemini registration behavior, while MCP annotations provide portable, operation-level semantics. Retaining prompts for flows and artefacts appropriately isolates paid, open-world, and audience-widening actions; the cross-server conformance tests reduce annotation drift.

Files changed (26) +272 / -120

Enhancement (2) +36 / -14
KcapMcpServers.csDefine explicit server auto-approval policy +14/-14

Define explicit server auto-approval policy

• Replaces ReadOnly with AutoApprove and enables it for review, sessions, analytics, memory, workitems, and plans. Flows and artefacts remain gated.

src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs

McpToolAnnotations.csIntroduce reusable MCP safety annotation presets +22/-0

Introduce reusable MCP safety annotation presets

• Defines Read, Upsert, Create, Destructive, and Launch presets covering all four MCP approval hints.

src/Capacitor.Cli/Commands/McpToolAnnotations.cs

Bug fix (11) +96 / -64
McpAnalyticsServer.csAnnotate analytics tools as read-only +2/-2

Annotate analytics tools as read-only

• Marks schema retrieval and governed analytics queries as closed-world reads.

src/Capacitor.Cli/Commands/McpAnalyticsServer.cs

McpArtefactsServer.csClassify artefact tool side effects +6/-6

Classify artefact tool side effects

• Annotates artefact publication, reads, response closure, and visibility replacement according to their actual safety and idempotency semantics.

src/Capacitor.Cli/Commands/McpArtefactsServer.cs

McpFlowResultServer.csAnnotate flow result writes +4/-2

Annotate flow result writes

• Marks result submission and driver messaging as additive record creation operations.

src/Capacitor.Cli/Commands/McpFlowResultServer.cs

McpFlowsServer.csClassify flow launches, reads, and closures +18/-9

Classify flow launches, reads, and closures

• Marks hosted-agent starts and messages as open-world launches, status tools as reads, and closure tools as destructive.

src/Capacitor.Cli/Commands/McpFlowsServer.cs

McpJudgeServer.csExpose and annotate judge tool descriptors +13/-7

Expose and annotate judge tool descriptors

• Makes the tool-list builder test-accessible and marks all judge transcript and session inspection tools as reads.

src/Capacitor.Cli/Commands/McpJudgeServer.cs

McpMemoryServer.csClassify memory operations by side effect +6/-6

Classify memory operations by side effect

• Distinguishes memory reads, creation, idempotent rescoping, and destructive update or archival operations.

src/Capacitor.Cli/Commands/McpMemoryServer.cs

McpPlansServer.csClarify plan destination and annotate plan tools +9/-7

Clarify plan destination and annotate plan tools

• Names the authenticated Capacitor server as the document-content destination. Classifies declaration, task replacement, task updates, and reads for approval decisions.

src/Capacitor.Cli/Commands/McpPlansServer.cs

McpReviewContextServer.csAnnotate review context retrieval +2/-1

Annotate review context retrieval

• Marks the review-context descriptor as a read-only MCP operation.

src/Capacitor.Cli/Commands/McpReviewContextServer.cs

McpReviewServer.csAdd annotations to review tools and wire schema +14/-8

Add annotations to review tools and wire schema

• Extends serialized MCP tool descriptors with annotations, exposes the builder for tests, and marks every review-context operation as read-only.

src/Capacitor.Cli/Commands/McpReviewServer.cs

McpSessionsServer.csAnnotate session discovery tools as reads +12/-6

Annotate session discovery tools as reads

• Marks session searches, summaries, transcripts, turns, and repository listings as closed-world read operations.

src/Capacitor.Cli/Commands/McpSessionsServer.cs

McpWorkItemsServer.csClassify work-item mutations and reads +10/-10

Classify work-item mutations and reads

• Annotates attachments, declarations, topology reads, retractions, merges, and detachment according to side effects and repeatability.

src/Capacitor.Cli/Commands/McpWorkItemsServer.cs

Refactor (1) +3 / -3
McpConfigShape.csAlign trust-shape terminology with AutoApprove +3/-3

Align trust-shape terminology with AutoApprove

• Updates API documentation and comments so harness trust settings reference the explicit AutoApprove policy rather than read-only status.

src/Capacitor.Cli.Core/Mcp/McpConfigShape.cs

Tests (7) +116 / -33
CodexConfigTomlTests.csVerify Codex auto-approval server boundaries +15/-12

Verify Codex auto-approval server boundaries

• Asserts that six safe servers receive approval mode while flows and artefacts remain unapproved.

test/Capacitor.Cli.Core.Tests.Unit/Harness/Codex/CodexConfigTomlTests.cs

JsonMcpConfigWriterTests.csVerify Gemini trust server boundaries +7/-4

Verify Gemini trust server boundaries

• Checks that Gemini trusts read and workspace-only writer servers but not flows or artefacts.

test/Capacitor.Cli.Core.Tests.Unit/Mcp/JsonMcpConfigWriterTests.cs

KcapMcpServersTests.csContract-test the canonical AutoApprove set +7/-12

Contract-test the canonical AutoApprove set

• Replaces read-only assertions with a single exact-set assertion for all auto-approved server descriptors.

test/Capacitor.Cli.Core.Tests.Unit/Mcp/KcapMcpServersTests.cs

FlowsDriverSchemaConformanceTests.csKeep flows excluded from automatic approval +1/-1

Keep flows excluded from automatic approval

• Updates the flow registration contract to assert the new AutoApprove property remains false.

test/Capacitor.Cli.Tests.Unit/Commands/FlowsDriverSchemaConformanceTests.cs

McpPlansServerTests.csVerify plan upload destination disclosure +9/-0

Verify plan upload destination disclosure

• Ensures the declaration tool description identifies the Capacitor server and authenticated login destination.

test/Capacitor.Cli.Tests.Unit/Commands/McpPlansServerTests.cs

McpToolAnnotationsTests.csAdd cross-server annotation conformance tests +72/-0

Add cross-server annotation conformance tests

• Ensures every tool declares read/write semantics, validates representative classifications, and checks wire serialization naming and omission behavior.

test/Capacitor.Cli.Tests.Unit/Commands/McpToolAnnotationsTests.cs

PluginCommandGeminiTests.csVerify Gemini installation trust policy +5/-4

Verify Gemini installation trust policy

• Expands plugin installation assertions for all six trusted servers and confirms flows and artefacts remain gated.

test/Capacitor.Cli.Tests.Unit/Commands/PluginCommandGeminiTests.cs

Documentation (3) +18 / -2
README.mdDocument expanded MCP auto-approval behavior +1/-1

Document expanded MCP auto-approval behavior

• Explains which kcap servers Codex and Gemini pre-approve, which remain gated, and how tool annotations affect approval-aware harnesses.

README.md

CHANGES.mdRecord the MCP approval and annotation policy +16/-0

Record the MCP approval and annotation policy

• Documents why missing annotations triggered Codex approval failures and why ledger-only writers are now pre-approved.

docs/CHANGES.md

help-mcp.txtClarify flows registration approval policy +1/-1

Clarify flows registration approval policy

• States that the flow-launching server is never auto-approved during registration without conflating that policy with tool annotations.

src/Capacitor.Cli.Core/Resources/help-mcp.txt

Other (2) +3 / -4
CodexConfigToml.csDrive Codex approval from AutoApprove policy +1/-1

Drive Codex approval from AutoApprove policy

• Uses the server descriptor's AutoApprove flag instead of its former ReadOnly classification when writing Codex approval mode.

src/Capacitor.Cli.Core/Harness/Codex/CodexConfigToml.cs

JsonMcpConfigWriter.csTrust AutoApprove servers in supported JSON configs +2/-3

Trust AutoApprove servers in supported JSON configs

• Writes Gemini's trust flag for servers explicitly marked safe for automatic approval, including workspace-only writers.

src/Capacitor.Cli.Core/Mcp/JsonMcpConfigWriter.cs

@qodo-code-review

qodo-code-review Bot commented Sep 22, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 🔗 Cross-repo conflicts (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Destructive updates appear additive 🐞 Bug ⛨ Security
Description
rescope_memory, close_artefact_responses, and update_plan_task use the Upsert preset, which
advertises DestructiveHint: false, even though they replace existing audience, closure, or task
state and rescope_memory can widen access to team, organization, or project members. When a
harness or approval client relies on MCP annotations rather than a server-trust setting, it can
classify audience changes, response closure, and status or notes overwrites as additive writes and
omit the intended sensitive-state review.
Code

src/Capacitor.Cli/Commands/McpMemoryServer.cs[413]

+            }, ["id"]), McpToolAnnotations.Upsert),
Relevance

●●● Strong

Annotation mismatches affecting replacement, access, or overwrite semantics are concrete security
classification bugs.

PR-#619

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The Upsert preset explicitly marks operations as non-destructive and is emitted to clients as MCP
tool metadata, while the tool descriptions and request builders show that these operations replace
an existing memory's audience, team, project, or home scope, change response-acceptance state, and
overwrite task status or notes. The annotation preset definitions themselves classify replacements
and overwrites as destructive, demonstrating that the selected preset does not match these tools'
behavior.

src/Capacitor.Cli/Commands/McpToolAnnotations.cs[11-18]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[292-319]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[405-413]
src/Capacitor.Cli/Commands/McpArtefactsServer.cs[553-561]
src/Capacitor.Cli/Commands/McpPlansServer.cs[254-266]
src/Capacitor.Cli/Commands/McpPlansServer.cs[577-588]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[347-363]
src/Capacitor.Cli/Commands/McpReviewServer.cs[427-467]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Three tools that overwrite existing state use the non-destructive `Upsert` annotation. `rescope_memory` can also widen who can see and edit an existing memory by promoting it to team, organization, or project audiences, so clients deriving approval decisions from MCP annotations cannot distinguish these operations from harmless additive updates.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/McpMemoryServer.cs[405-413]
- src/Capacitor.Cli/Commands/McpArtefactsServer.cs[553-561]
- src/Capacitor.Cli/Commands/McpPlansServer.cs[577-588]
- src/Capacitor.Cli/Commands/McpToolAnnotations.cs[11-18]

## Recommended Fix
Assign `McpToolAnnotations.Destructive` to `rescope_memory`, `close_artefact_responses`, and `update_plan_task`. Retain their existing idempotent and closed-world behavior while advertising that they replace sensitive existing state, then extend annotation tests to assert that `destructiveHint` is `true` for each operation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Shared memories bypass approval 🔗 Cross-repo conflict ⛨ Security
Description
KcapMcpServers marks the mixed-capability kcap-memory, kcap-workitems, and plans servers as
AutoApprove even though they expose shared-scope and destructive writes rather than only private
or read-only operations. When Codex or Gemini consumes the generated server-level trust settings,
calls can create, rescope, archive, or expose memories; merge work items, detach sessions, and alter
cross-repository breakdowns or relations; replace task lists; and upload project-file contents
without applying the individual tools’ approval annotations.
Code

src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[R29-30]

        new("kcap-memory",   ["mcp", "memory"],   NeedsProjectCwd: true,
-            "Team memory — search, read, and save durable learnings."),
+            "Team memory — search, read, and save durable learnings.", AutoApprove: true),
Relevance

●●● Strong

Recent security precedents accept fixes preventing shared-scope data exposure and unsafe MCP
behavior.

PR-#619
PR-#643

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The changed KcapMcpServers descriptors enable approval for every tool on each server, and the
Codex and JSON/Gemini configuration writers apply that setting at the server entry rather than per
tool. The memory tool schema accepts audience and target values that kcap-server resolves to team,
organization, project, or cross-repository scopes, while the work-items server dispatches
authenticated merge, detach, breakdown, and relation mutations that alter visible graph state and
durable associations without restricting them to the current repository; the implementations also
include archival or deletion, destructive task replacement, and transmission of project-file
content.

src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[29-30]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[383-416]
src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[29-34]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[176-180]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[237-273]
src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[191-211]
src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[458-477]
src/Capacitor.Cli/Commands/McpPlansServer.cs[183-220]
src/Capacitor.Cli/Commands/McpPlansServer.cs[308-342]
src/Capacitor.Cli.Core/Harness/Codex/CodexConfigToml.cs[224-230]
src/Capacitor.Cli.Core/Mcp/JsonMcpConfigWriter.cs[117-122]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[154-180]
src/Capacitor.Cli/Commands/McpMemoryServer.cs[347-363]
src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[31-32]
src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[410-477]
src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[31-34]
src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[172-207]
src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[419-477]
External repo: kurrent-io/kcap-server, src/Capacitor.Server.Services/Memories/MemoryService.cs [175-201]
External repo: kurrent-io/kcap-server, src/Capacitor.Server/WorkItems/WorkItemBreakdownEndpointHandlers.cs [10-36]
External repo: kurrent-io/kcap-server, src/Capacitor.Server/WorkItems/WorkItemCorrectionEndpointHandlers.cs [10-35]
External repo: kurrent-io/kcap-server, src/Capacitor.Api.Public/WorkItems/WorkItemEndpoints.cs [135-176]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The generated Codex and Gemini configurations grant server-wide approval to the mixed-capability memory, work-items, and plans servers. Those servers expose shared-scope and destructive operations—including visibility changes, archival, cross-repository work-item mutations, task replacement, and project-file uploads—so server-level trust bypasses the per-tool safety annotations intended to distinguish reads from sensitive writes.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[29-34]
- src/Capacitor.Cli.Core/Harness/Codex/CodexConfigToml.cs[224-230]
- src/Capacitor.Cli.Core/Mcp/JsonMcpConfigWriter.cs[117-123]
- src/Capacitor.Cli/Commands/McpMemoryServer.cs[383-416]
- src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[172-207]
- src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[410-477]

## Recommended Fix
Remove server-level `AutoApprove: true` from `kcap-memory`, `kcap-workitems`, and other servers containing writable tools, including plans. Preserve the per-tool MCP annotations so annotation-aware clients can approve read-only tools individually and distinguish write types, while clients that support only server-wide trust continue prompting before shared-scope or destructive mutations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Safe work-item retries are disabled ✓ Resolved 🔗 Cross-repo conflict ≡ Correctness
Description
declare_work_item and declare_loose_end use the non-idempotent Create preset even though
kcap-server resolves existing work-item identities and deterministically deduplicates repeated
loose-end declarations. Annotation-aware clients consequently cannot rely on the server’s
established safe-retry contract for either operation.
Code

src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[395]

+            }, []), McpToolAnnotations.Create),
Relevance

●●● Strong

The repository accepts corrections that expose deterministic server deduplication and safe retry
behavior.

PR-#262

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The PR declares both operations non-idempotent, but kcap-server resolves or reuses existing work
items and derives a stable loose-end declaration identity whose repeated command reports no new
creation.

src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[387-409]
src/Capacitor.Cli/Commands/McpToolAnnotations.cs[11-15]
External repo: kurrent-io/kcap-server, src/Capacitor.Server/WorkItems/WorkItemEndpointHandlers.cs [150-207]
External repo: kurrent-io/kcap-server, src/Capacitor.Server/WorkItems/WorkItemEndpointHandlers.cs [218-233]
External repo: kurrent-io/kcap-server, src/Capacitor.Api.Public/LooseEnds/LooseEndEndpointHandlers.cs [68-91]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Two work-item declarations advertise non-idempotent creation despite kcap-server deliberately returning existing identities or no-op outcomes for repeated calls.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[387-409]

## Recommended Fix
Change both `declare_work_item` and `declare_loose_end` from `McpToolAnnotations.Create` to `McpToolAnnotations.Upsert`, and extend the annotation tests to assert their idempotent hints.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

4. Two shared models lack matching files 📘 Rule violation ⚙ Maintainability
Description
The modified KcapMcpServer and McpTool records remain top-level types in files named for
different primary types, despite being consumed outside those files. Future changes to either shared
model must be located through unrelated registry or review-server implementations, and additional
protocol records remain grouped beside McpTool.
Code

src/Capacitor.Cli/Commands/McpReviewServer.cs[435]

+record McpTool(string Name, string Description, McpInputSchema InputSchema, McpToolAnnotations Annotations);
Relevance

● Weak

Recent precedent rejects splitting grouped protocol records solely to satisfy
one-primary-type-per-file rules.

PR-#817

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
Rule 3162234 requires each primary top-level type to have a matching file, except for narrow
groupings that are not shared externally. The cited regions show KcapMcpServer beside
KcapMcpServers and McpTool among numerous protocol records in McpReviewServer.cs; both records
are modified by this PR and serve code outside their containing types.

Rule 3162234: One primary type per file, with only narrow documented exceptions
src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[9-13]
src/Capacitor.Cli/Commands/McpReviewServer.cs[429-438]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The modified shared `KcapMcpServer` and `McpTool` records are top-level types in files whose names correspond to other primary types, violating the one-primary-type-per-file convention.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[9-13]
- src/Capacitor.Cli/Commands/McpReviewServer.cs[429-438]

## Recommended Fix
Move `KcapMcpServer` into `KcapMcpServer.cs` and `McpTool` into `McpTool.cs`, preserving their existing namespaces and accessibility. Leave each registry or server implementation in its correspondingly named file and update project references if required.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Compliance rules (platform): 64 rules
✅ Cross-repo context — repo relationships
  Explored: repo: kurrent-io/kcap-server (sha: c2e0984f)
Review mode: 🧠 Deep: This is a broad, behavior-changing MCP security/approval change spanning many independent tool classifications, server registrations, configuration writers, serialization paths, and harness integrations, creating substantial opportunity for subtle defects.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

["audience_project"] = new("string", "Target project slug when audience is 'project' — the PEOPLE axis (its members become editors; you must be a member). Distinct from 'project' below"),
["project"] = new("string", "Target project slug — the PLACE axis: moves the memory's home context to that project (takes precedence over audience)")
}, ["id"])),
}, ["id"]), McpToolAnnotations.Upsert),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Destructive updates appear additive 🐞 Bug ⛨ Security

rescope_memory, close_artefact_responses, and update_plan_task use the Upsert preset, which
advertises DestructiveHint: false, even though they replace existing audience, closure, or task
state and rescope_memory can widen access to team, organization, or project members. When a
harness or approval client relies on MCP annotations rather than a server-trust setting, it can
classify audience changes, response closure, and status or notes overwrites as additive writes and
omit the intended sensitive-state review.
Agent Prompt
## Issue description
Three tools that overwrite existing state use the non-destructive `Upsert` annotation. `rescope_memory` can also widen who can see and edit an existing memory by promoting it to team, organization, or project audiences, so clients deriving approval decisions from MCP annotations cannot distinguish these operations from harmless additive updates.

## Fix Focus Areas
- src/Capacitor.Cli/Commands/McpMemoryServer.cs[405-413]
- src/Capacitor.Cli/Commands/McpArtefactsServer.cs[553-561]
- src/Capacitor.Cli/Commands/McpPlansServer.cs[577-588]
- src/Capacitor.Cli/Commands/McpToolAnnotations.cs[11-18]

## Recommended Fix
Assign `McpToolAnnotations.Destructive` to `rescope_memory`, `close_artefact_responses`, and `update_plan_task`. Retain their existing idempotent and closed-world behavior while advertising that they replace sensitive existing state, then extend annotation tests to assert that `destructiveHint` is `true` for each operation.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

rescope_memory now advertises destructiveHint: true. close_artefact_responses and update_plan_task stay non-destructive: a reversible flag and a status transition are the operation itself, not an overwrite of data, and marking every state change destructive would leave the hint saying nothing.

Comment on lines +29 to +30
new("kcap-memory", ["mcp", "memory"], NeedsProjectCwd: true,
"Team memory — search, read, and save durable learnings."),
"Team memory — search, read, and save durable learnings.", AutoApprove: true),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

2. Shared memories bypass approval 🔗 Cross-repo conflict ⛨ Security

KcapMcpServers marks the mixed-capability kcap-memory, kcap-workitems, and plans servers as
AutoApprove even though they expose shared-scope and destructive writes rather than only private
or read-only operations. When Codex or Gemini consumes the generated server-level trust settings,
calls can create, rescope, archive, or expose memories; merge work items, detach sessions, and alter
cross-repository breakdowns or relations; replace task lists; and upload project-file contents
without applying the individual tools’ approval annotations.
Agent Prompt
## Issue description
The generated Codex and Gemini configurations grant server-wide approval to the mixed-capability memory, work-items, and plans servers. Those servers expose shared-scope and destructive operations—including visibility changes, archival, cross-repository work-item mutations, task replacement, and project-file uploads—so server-level trust bypasses the per-tool safety annotations intended to distinguish reads from sensitive writes.

## Fix Focus Areas
- src/Capacitor.Cli.Core/Mcp/KcapMcpServers.cs[29-34]
- src/Capacitor.Cli.Core/Harness/Codex/CodexConfigToml.cs[224-230]
- src/Capacitor.Cli.Core/Mcp/JsonMcpConfigWriter.cs[117-123]
- src/Capacitor.Cli/Commands/McpMemoryServer.cs[383-416]
- src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[172-207]
- src/Capacitor.Cli/Commands/McpWorkItemsServer.cs[410-477]

## Recommended Fix
Remove server-level `AutoApprove: true` from `kcap-memory`, `kcap-workitems`, and other servers containing writable tools, including plans. Preserve the per-tool MCP annotations so annotation-aware clients can approve read-only tools individually and distinguish write types, while clients that support only server-wide trust continue prompting before shared-scope or destructive mutations.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

kcap-memory no longer carries server-level auto-approve and relies on its annotations. kcap-workitems and kcap-plans keep it: their destructive tools touch only the record of the session that calls them, the destination the hooks already post to without a prompt. Codex runs a non-destructive, closed-world tool without approval and sends a destructive one to approval, so on Codex the split follows the annotations either way.

Comment thread src/Capacitor.Cli/Commands/McpWorkItemsServer.cs Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 264a1bba47

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +29 to +30
new("kcap-memory", ["mcp", "memory"], NeedsProjectCwd: true,
"Team memory — search, read, and save durable learnings."),
"Team memory — search, read, and save durable learnings.", AutoApprove: true),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep audience-changing memory tools behind approval

When save_memory is called with audience: "org" or rescope_memory promotes an existing private memory, this flag renders trust: true for Gemini and default_tools_approval_mode = "approve" for Codex, so the disclosure runs without user confirmation. McpMemoryServer.BuildToolsList explicitly permits team, project, and organization-wide audiences, making this unlike a purely private ledger write and creating the same audience-widening risk for which this change leaves kcap-artefacts unapproved.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

kcap-memory is no longer pre-approved at registration and relies on its annotations, which mark rescope_memory destructive; save_memory stays additive.

["flow_run_id"]
)
),
McpToolAnnotations.Read

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark status tools as mutating when they acknowledge messages

On a successful get_review_flow_status call, HandleToolCallAsync formats pending messages and then calls AckRenderedMessagesAsync, so the call modifies server state and those messages normally cannot be retrieved again; the same applies to get_flow_status. Advertising readOnlyHint: true lets clients treat this as a harmless read, which is especially problematic if the MCP response is lost after the acknowledgement and the client retries expecting the messages to remain available.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Both status tools now advertise readOnlyHint: false, destructiveHint: false, idempotentHint: false.

["plan_id"] = new("string", "Plan to write to. Defaults to the session's current plan."),
["session_id"] = new("string", "Session making the declaration. Defaults to the session this server runs in when omitted.")
}, ["tasks"])),
}, ["tasks"]), McpToolAnnotations.Destructive),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid claiming task replacement is idempotent

When task objects omit task_id, as the advertised schema permits, the description says IDs are minted for them; repeating the same full-snapshot call therefore replaces the list with newly identified tasks rather than having no additional effect. McpToolAnnotations.Destructive sets idempotentHint: true, so clients may incorrectly consider this call safe to retry and silently churn task identities; this tool needs a destructive, non-idempotent annotation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

set_plan_tasks now advertises destructiveHint: true and idempotentHint: false.

["audience_project"] = new("string", "Target project slug when audience is 'project' — the PEOPLE axis (its members become editors; you must be a member). Distinct from 'project' below"),
["project"] = new("string", "Target project slug — the PLACE axis: moves the memory's home context to that project (takes precedence over audience)")
}, ["id"])),
}, ["id"]), McpToolAnnotations.Upsert),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Mark memory audience rescoping as destructive

When an existing memory is moved from an organization or team audience to a private or different audience, this operation revokes existing viewers and overwrites the access scope. The Upsert preset advertises destructiveHint: false, which describes the operation as additive and can cause annotation-driven approval clients to under-classify a consequential access-control change; use a destructive annotation for rescope_memory.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

rescope_memory now advertises destructiveHint: true.

alexeyzimarev and others added 2 commits September 23, 2026 13:06
A flow status call acknowledges the messages it renders, so it is not a read; replacing the task list mints ids for entries without one, so a repeat is not a no-op; rescoping a memory overwrites its access scope; a loose end re-declared lands on the same server stream.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A save or rescope can widen who sees a memory, the same reason artefacts are not pre-approved. Codex's default mode already runs the non-destructive memory tools without a prompt from the annotations, so only archive, update and rescope reach its reviewer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
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.

Codex auto-reviewer rejects kcap-plans, work-items and memory tool calls

1 participant