DEV Community

Discussion on: Enforcing MCP Permissions Before a Tool Handler Runs

Collapse
 
mickyarun profile image
arun rajkumar •

The line that does the work is that the decision never reads readOnlyHint. The sharper version: an annotation is a claim the server makes about itself, which is the same class of evidence as an audit log written by the system being audited. It can tell a client how to render a button. It can't be an authorization input.

One gap in the sketch when you take it out of memory. The ownership check reads the record, and then tool.run mutates it. In-memory those are one step. Against a real database they're two round trips, so a record whose workspace changes in between passes a check that no longer holds when the write lands. The fix is the same shape as the rest of your argument: workspaceId goes in the WHERE clause of the write, not only in an earlier if. Enforcement at the service is necessary. Enforcement in the same statement as the mutation is what actually holds.

The row people skip is tool.validate. Scope plus tool name is checkable from a token. set_interval to one second with a valid automation:write scope is fully authorized and still an incident, and nothing but domain knowledge catches it.

@autenai — for computer use there's no credential to narrow, but there's still a boundary: the OS session the clicks land in. Scope the session rather than the tool. A separate user account with its own filesystem and keychain access makes the enforcement the OS's permission model. A policy layer that tells the agent to ask is a hint, in exactly the sense this post is arguing against.

Collapse
 
smtasker profile image
SMTasker Team SMTasker •

Good catch on the database boundary. The demo's in-memory ownership check shouldn't be copied unchanged into a database-backed handler. The write needs both the record ID and workspace ID in its predicate, with a non-matching write treated as a refusal rather than success. A regression test that changes ownership between the initial read and the mutation would make that boundary explicit. The interval bounds remain a separate domain-validation check, even when the caller has the right scope.