Inline Sign in

← ARTICLES RESEARCH 5 min read

Workspace MCP binds identity to the connection, not to the agent

An audit of Google's five Workspace MCP servers against the five REST APIs underneath them. Both wrappers reach the same endpoints with the same OAuth scopes; only one of them lets a manager agent hand a sub-agent less access than it holds itself.

The finding

Google’s Workspace MCP servers and a hand-built binary calling the Workspace REST APIs directly are, at the level of the wire, the same thing. Same base URLs, same resource collections, same OAuth scope strings, same response shapes. Where they diverge is in a property that none of the reference documentation names: at what level the caller’s identity is bound.

For the MCP servers, it is bound once, at connection setup, for the whole host session. Every agent that can reach the connection — a manager, a sub-agent it spawned five minutes ago, a sub-agent spawned by that one — operates under that single OAuth consent. There is no mechanism in the protocol for a manager to hand a sub-agent a narrowed view of a connection the manager itself uses.

That is not a bug. It is a consequence of where the consent lives. But it is the whole question if you are building anything where one agent delegates to another, and it is not something the launch material tells you.

The substrate both wrappers sit on

We inventoried the five Workspace REST APIs and the five MCP servers that front them, one server per API, all launched on the same day in May 2026. Neither list is surprising on its own; putting them side by side is the point.

APIBase URLKey resources
Gmail v1https://gmail.googleapis.com/gmail/v1/users.messages, users.threads, users.labels, users.drafts
Drive v3https://www.googleapis.com/drive/v3/files, permissions, revisions, drives
Calendar v3https://www.googleapis.com/calendar/v3/events, calendars, calendarList, acl
Chat v1https://chat.googleapis.com/v1/spaces, messages, members, reactions
People v1https://people.googleapis.com/v1/people, contactGroups, otherContacts

Each MCP server is a remote HTTP server hosted by Google, exposing tools named after the operations underneath: gmail_list_messages, gmail_send_message, drive_list_files, calendar_list_events, and so on.

We then coded four common operations twice — once as an MCP tool call, once as an invocation of a role-scoped binary — and checked where each landed.

OperationMCP toolUnderlying REST endpoint
List messagesgmail_list_messagesGET /gmail/v1/users/me/messages
Send a messagegmail_send_messagePOST /gmail/v1/users/me/messages/send
List filesdrive_list_filesGET /drive/v3/files
List eventscalendar_list_eventsGET /calendar/v3/calendars/primary/events

The binary form of the same four calls resolves to the identical endpoints with the identical query parameters. Listing Gmail messages through the MCP server sends maxResults and q; so does the binary. Listing Drive files requests the same files(id,name,mimeType,modifiedTime) field mask either way.

This matters because it removes an argument. Choosing between the two wrappers is not a capability trade-off. You do not lose an endpoint, a parameter or a response field by going one way rather than the other. Whatever you decide, you decide on other grounds.

Where the two patterns stop being the same

The Gmail scope catalogue makes the divergence concrete. Take three roles you would plausibly want in a system where agents delegate to each other, and ask how each wrapper expresses them.

RoleOAuth scopePermittedMCPScoped binary
Adminhttps://mail.google.com/list, read, send, modify, deleteGrant the scope at connection setup; every tool is then available to everyone on the connectionOne binary holding that credential
Read-only.../auth/gmail.readonlylist, readRequires a separate, narrower OAuth consent — you cannot narrow an existing connection per agentA different binary holding the read-only credential
Modify, no delete.../auth/gmail.modifylist, read, send, modifySame: a separate consent, not a narrowingA third binary; delete is refused

The read-only and modify rows are the interesting ones. In the MCP pattern you can have a read-only Gmail connection — you set one up with a read-only consent. What you cannot do is hold a full-access connection as a manager and hand a sub-agent a read-only slice of it. The narrowing has to exist before the connection does, as a separate consent, negotiated with the user, at the host level. A manager agent, at runtime, deciding that this particular sub-agent should not be able to send mail, has only one instrument available: telling it not to.

In the binary pattern the narrowing is a different file. gmail_readonly.py carries a credential issued for gmail.readonly. It cannot send mail, and the reason is not that it was asked nicely. A sub-agent handed only that binary never has the admin credential in its process. Handing over a different binary is exactly equivalent to handing over different credentials, because that is literally what it is.

What the documentation left unclear

Three things we had to establish by inspection rather than by reading.

Agent isolation is not a documented field. Every one of the five servers behaves the same way here, and none of the launch material frames it as a property at all. We ended up recording it explicitly for each server — agent_isolation: none — because there was no published statement to cite either way. If you are evaluating these servers for a multi-agent system, this is the first thing you need and the last thing you will find written down.

“Scope” is used for two different things. In the REST documentation a scope is a property of a token. In MCP discussions it tends to mean the set of tools a server exposes. These coincide only when the connection was consented at exactly the granularity you want. Once a manager holds a broader consent than a sub-agent should have, the two senses come apart, and the tool-level sense is the one that is not enforced anywhere.

gmail.modify excludes permanent deletion. This is stated in the scope reference but is easy to read past, and it is the most useful scope boundary in the catalogue: an agent that can triage, label, archive and reply, but cannot permanently destroy anything, is a very common thing to want. It is worth knowing that the API gives it to you without any work on your part.

What follows from it

The useful conclusion is narrow. MCP is not weaker than a direct API client at reaching data; it reaches the same data. It is weaker at one specific thing: expressing that agent A may do less than agent B when both are working from one user’s consent. If your system has exactly one agent, this costs you nothing. If your system has a manager and sub-agents, it means the only boundary you have between them is instruction text — and instruction text can be ignored, overridden by an injected instruction in some document the agent reads, or lost in a long context.

Moving the boundary from the instruction layer to the credential layer changes what kind of thing it is. An instruction is a request. A credential that was issued for gmail.readonly is a fact about what the API server will accept. The rest of this series takes that claim and tries to break it.