Workspace access and revoking it
Per workspace revocation, and what the next call does after it.
An admin can revoke one member's MCP access in one workspace. It stops that member reaching that workspace over MCP and changes nothing else about them.
What revoking does and does not touch
Revocation is keyed on the pair of workspace and user. It is stored as a row scoped to that workspace, under the same row level security every other workspace-scoped table here carries, so a row in one workspace is not readable or writable from another.
Source: services/runtime/src/runtime/auth/mcp_access.py:1-14 and
services/runtime/src/runtime/auth/mcp_access.py:59-64.
That means:
- Their access to your other workspaces is untouched. A revoke here says nothing about anywhere else.
- Their ordinary use of this workspace is untouched. They keep signing in and working normally. Only MCP stops.
Why this lever and not one of the others
Two things already cut off MCP access today, and both are wrong for this job because both take away more than intended.
| Lever | What it also does |
|---|---|
| Suspending the user | Signs them out of the product entirely |
| Removing their membership | Takes away the workspace itself |
If you want to cut off one leaked MCP client, in one workspace, without doing either of those, this is the only lever that does exactly that and no more.
Source: services/runtime/src/runtime/auth/mcp_access.py:34-39.
There is also no session record to revoke. An MCP caller holds a bearer token and nothing else: no cookie, no browser, no session to invalidate. Requiring one would refuse every legitimate MCP caller rather than close anything.
Source: services/runtime/src/runtime/auth/mcp_access.py:24-32.
When the check runs
On every single tool call, at the moment the workspace is resolved and before the tool does anything.
Source: services/runtime/src/runtime/mcp/tools.py:152-157, called from every
handler at services/runtime/src/runtime/mcp/tools.py:249-409.
The check cannot run any earlier. A connection authenticates once and then carries many calls, and no workspace is known at that point. A member of several workspaces may be revoked in only one of them, so a connection-wide check could only answer a question nobody asked.
Source: services/runtime/src/runtime/mcp/verifier.py:38-50.
The consequence is the useful part: there is no cache to expire and no token
lifetime to wait out. The next tool call after a revoke is refused. The caller
gets a 403 saying their MCP access has been revoked in this workspace.
Source: services/runtime/src/runtime/auth/mcp_access.py:85-91.
The two endpoints
Both are admin only.
Revoke
POST /v1/workspace/members/{user_id}/mcp-access/revokeRevoking twice succeeds, and the response carries already: true, so it is safe
to retry. A user who is not a member of this workspace is a 404. The action is
written to the audit log.
Source: services/runtime/src/runtime/api/workspace_admin.py:629-683.
Restore
POST /v1/workspace/members/{user_id}/mcp-access/restoreRestoring someone who was never revoked succeeds, again with already: true. A
user who is not a member is a 404. revoked in the response is the state
afterwards, so a successful restore reports false. This is audit logged too.
Source: services/runtime/src/runtime/api/workspace_admin.py:686-733.
Restoring takes effect on their next call, the same way revoking does.
No Studio screen for this
There is no screen for revoking or restoring MCP access today. An admin does it through the two API calls above. This page does not describe a screen because none exists.