Repository navigation
Conversation
…works An agent reads a denial and relays it to the person it acts for. The denials were held only to "state what the method does", and an audit of every MCP-facing message found 36 that misled or confused. ApproveIssue on an issue someone else created was refused with "an agent does not move its own change through that gate", which tells the reader that approving another person's change is fine. Each reason now states what the method can do at the gate's grain and carries its own next step, overridden per method where the step would misdirect. The templates say whether any MCP access policy could help, in the Access policy page's words, and every gate refusal keeps "not available to MCP sessions". The ceiling verdicts are complete ASCII sentences, since an OAuth error_description carries them. The same scope fix reaches the proto comments, the ladder and consent copy in every locale, and the design doc (D13). The MCP tools stop reporting a timeout as a network error, point a not-found database at ListDatabases, and say what a database pick is for before a change. TestMCPDenialWording renders every refusal path and checks the rules, the classification inventory prints each reason's denial beside its methods, and the policy-refusal contract covers every producer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest Buf updates on your PR. Results from workflow CI / lint-protos (pull_request).
|
The timeout advice told the agent to narrow the load "with the filter argument", but get_schema takes schema and table and builds the internal filter from them, so the advice could not be followed. Name the two arguments it does take, and pin that the advice names only arguments SchemaInput accepts. Found by Codex review. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cbee694222
ℹ️ About Codex in GitHub
Codex has been enabled to automatically 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 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
|
|
||
| // listDatabasesHint is where a not-found answer sends the agent. search_api | ||
| // lists API operations, not databases. | ||
| const listDatabasesHint = `call call_api with operationId "DatabaseService/ListDatabases" to list the databases you can access; ones you cannot access are not listed` |
There was a problem hiding this comment.
Include the required parent in database-list guidance
When a database lookup returns DATABASE_NOT_FOUND, this hint directs the agent to invoke call_api with only an operation ID. call_api forwards an empty body, but DatabaseService/ListDatabases requires parent and rejects an empty value as invalid parent "" (backend/api/v1/database_service.go:346-347), so the prescribed next step cannot list anything. Include a usable parent or direct the agent through a tool that derives the current workspace parent.
Useful? React with 👍 / 👎.
Rewords the refusals an MCP agent, and the person it acts for, can receive. The trigger: ApproveIssue on an issue someone else created was refused with "an agent does not move its own change through that gate". That sentence tells the reader that approving someone else's change is fine, when the gate refuses approval decisions on every issue. An audit of every MCP-facing message found 36 with problems; this PR fixes the wording defects and the design gap behind them.
What a reader sees
Also:
DatabaseService/ListDatabasesrather thansearch_api, which lists API operations.Why they were wrong
The denials followed one rule, "state what the method does", and nothing more:
reauthorize), and for approvals, which only an approver can make.READ_ONLY,ROLE_GRANTand "principal" appeared where the UI says "MCP access policy: Read-only / Read-write".How it is kept true
mcp_gate.go.docs/design/mcp-capability-ladder.mdD13 records the decision. The doc's own "never approves its own change" is corrected, along with its approval sentence: whether a human must approve depends on the workspace's approval rules and the project's settings.TestMCPDenialWordingrenders every reason and refusal path and checks what a check can. A reason must continue "because", a next step must be its own sentence, a rendered denial must be complete sentences, and banned words such as "ceiling", enum names and "own change" must not appear. Put the old ApproveIssue sentence back and the test fails.TestMCPRefusalsNameThemselvesToTheQueryToolnow also covers the permanently-refused and no-policy templates, an unsupported policy value, and Disabled.IsPolicyRefusalkeys on "MCP session" or "MCP access policy".error_description.Verification
go testpasses forbackend/api/v1,backend/api/auth,backend/api/oauth2,backend/api/mcpandbackend/utils.backend/teststhat pin or exercise MCP refusal wording pass. They span the gate, the credential and workspace-escape guards, the SQL clamp, the capability setting, OAuth2 grants, migration, denial audit and read-path redaction.golangci-lintv2.13.2 (the CI version) is clean,gofmtis applied, and the server builds.buf format,buf lintandbuf generateran for the enum comments.tsc, the release bundle, and 531 files / 5790 tests.Not included
These findings need logic changes rather than wording, so they're left for follow-ups:
query_databasereads only the first result, so an error in a later statement is dropped.PermissionDeniedDetailrather than on missing wording, which would let the tools stop matching text.SQLService/AdminExecuteanswers "unknown operation" because it's never indexed.search_apistill describes a refused operation as if it were callable.CreateAccessGrantis classed as workspace administration, but its real risk is an auto-approved grant.Audit-log rows record the refusal text, so rows written after this change carry the new wording. Searching the audit log for the old phrases won't find them.
🤖 Generated with Claude Code