Skip to content

A public endpoint whose tools change things

Give an agent a key
that only opens one door.

Read-only tools are easy to hand out. The question that decides whether anybody trusts an agent with a write is where the check lives, and a rule written into a prompt is a request: the model can be talked out of it, and a model that has been talked out of it still reports success.

So press the button. It opens a real session against the live server, writes something inside the grant, then tries two things one step outside it and shows you what came back.

This drives the same endpoint your Claude would connect to. Nothing here is a recording.

Or point your own Claude at it

claude mcp add --transport http aoc https://www.ayushopchauhan.com/api/mcp

Ask it to open a session, then ask it to write into a collection that is not yours. Watch it be told which grant it would need. The transport hands the session id back in the Mcp-Session-Id header, so a compliant client starts sending it on its own and the tool list changes without anybody doing anything.

Four things it does that a permission check does not

01

The check runs at the write, not at connect

A session is looked up on every call, so an expired or narrowed grant takes effect on the next request rather than the next reconnect. Everything in lib/mcp/store.ts calls the same decision function before it touches the database, and none of those functions takes an argument that skips it.

02

The tool list is filtered by the grant

A session that was not granted delete is not offered delete_note. Most servers advertise every tool and check permission when it is called, which turns the list into a menu of things to try. Filtering the list means the model never forms the intention, and the call is checked anyway.

03

A refusal names the grant that was missing

Not "forbidden". An agent told only that something failed retries the same call. An agent told it needs the "delete" operation, and that it holds "read" and "write", can either ask for a wider session or stop.

04

Refusals are logged as loudly as successes

Every attempt is written to the audit table with the collection it named, the grant that was missing, and how long it took. A log that only records what worked tells you nothing about what was attempted, which is the half an auditor cares about.

What everyone else has been doing to it

The last 24 calls from every visitor, 0 of them refused. Content is left out; this is who did what, not what they wrote.

16:20:01allowedopen_sessionguest-c9da5ec10428
16:10:00allowedopen_sessionguest-50777ee15063
16:07:01allowedopen_sessionguest-b0058f0f5e5d
16:00:02allowedopen_sessionguest-3bdc3cc18f7b
15:50:01allowedopen_sessionguest-9ff9ddc242d0
15:40:00allowedopen_sessionguest-693c03d02426
15:30:01allowedopen_sessionguest-c6cc1155d5b0
15:20:02allowedopen_sessionguest-4490dd34bf9c
15:10:00allowedopen_sessionguest-d2b40db341ee
15:07:01allowedopen_sessionguest-56491704ef54
15:00:01allowedopen_sessionguest-ae8fe1ab2bbb
14:50:00allowedopen_sessionguest-dddce1754e8a
14:40:01allowedopen_sessionguest-0ea5c14708b0
14:30:02allowedopen_sessionguest-7446488c7d3d
14:20:03allowedopen_sessionguest-1fc10843349a
14:10:02allowedopen_sessionguest-70f3466c612b
14:07:02allowedopen_sessionguest-38f11aa836e8
14:00:04allowedopen_sessionguest-a0099c3a008b
13:50:02allowedopen_sessionguest-0ac90575f590
13:40:01allowedopen_sessionguest-de2394199f2f
13:30:02allowedopen_sessionguest-0a58a3fcecb3
13:20:02allowedopen_sessionguest-5520dbc66e11
13:10:02allowedopen_sessionguest-5669d4f5994c
13:07:01allowedopen_sessionguest-b1fa9e10fd6a

What this is not

There is no login. A session id is the only credential, anyone holding one can use it, and it lasts an hour. That is the right shape for a public demonstration and the wrong shape for real data, where the session would be issued against an identity rather than to whoever asked.

The documents are notes in a table. Pointing the same boundary at something that matters is a change of storage.

53 unit tests cover the decision function and 54 more drive this endpoint over HTTP. Both suites exist because a boundary that is correct and not wired in is the same as no boundary, and only the second kind of test can tell you which one you have.

The same server also carries the read-only tools behind the site console. The address guard is a box you can attack, the eval scores the engine on precision and recall, the token measurement prices the same question four ways, and every defect any of it has had is written down.