One developer’s mcp.json holds a Linear token in plaintext, next to a GitHub
personal access token, next to a Notion integration secret. None of that is
carelessness: every third-party MCP server’s setup guide ends with the same
step, paste your token into the config file.
Three broad-scope credentials in a dotfile that syncs to who knows where. Nobody approved any of it, security has no record it exists, and if that laptop walks there is no clean way to revoke just those grants.
That config is the default, not the exception. Multiply it by every developer and every tool and you have shadow IT for the agent era. Call it shadow MCP.
- Your developers paste GitHub PATs, Slack, Stripe, Linear, or Notion keys into editor config to connect MCP servers
- Security has no inventory of which third-party MCP servers your team has wired into agents
- You cannot revoke one developer's MCP access without rotating a shared credential everyone uses
- You want to allow these tools, not ban them, but you need a record of who reached what
Three problems hiding in one config file
The credential itself. A GitHub PAT or a Stripe key in mcp.json is a
long-lived, broad-scope secret sitting in cleartext on a laptop. Editor configs
sync to dotfile repos, get screen-shared, land in backups, and show up in
support bundles. The credential outlives the task it was pasted in for, because
nobody goes back to delete it.
Visibility. These connections are provisioned one developer at a time, locally, with no central record. Security cannot answer the basic questions: which third-party MCP servers are connected, by whom, holding which scopes. You cannot govern an inventory that lives in a hundred private dotfiles.
Revocation. When someone leaves, or a laptop is lost, or a token leaks, there is no single switch. You either hunt down every config file or rotate the upstream credential and break it for everyone. A shared API key pasted into ten editors is one secret with ten copies and no way to cut off just one.
A pasted token is full account access
This matters more than ordinary shadow IT because of the blast radius. None of these credentials is scoped to the one thing the agent needs. Narrowing scopes is friction, so the developer mints the broad one and the tool works.
| Credential | What a leak reaches |
|---|---|
| GitHub PAT | Every scope minted, usually everything |
| Stripe key | The whole account |
| Slack token | Every channel the user can see |
So a leaked or over-scoped MCP credential is not a contained incident. It is account-level access to a third-party system, granted to an agent acting on instructions you may not have written.
This is the same confused-deputy shape the MCP authorization spec is built to prevent, a trusted intermediary tricked into using its own privileged credentials on someone else’s behalf. It is why the spec is explicit that an MCP server must not forward the token it received: “The MCP server MUST NOT pass through the token it received from the MCP client.”
The token your agent presents and the credential that hits the upstream should be two different things. A PAT in a config file collapses them into one.
Don’t ban shadow MCP, put it behind a gateway

A gateway lets your team keep using Claude Desktop, Cursor, and VS Code while the raw credential never lives in a config file: it stays server-side at the gateway, and the editor only ever holds a short-lived OAuth token.
Banning shadow MCP fails for the same reason banning shadow IT always did. Developers wire these servers in because the agents are genuinely more useful with them. Give them a sanctioned path that is easier than the dotfile, and make that path the one place credentials and access live.
That path is a gateway, stood up once by whoever owns security or platform, not by each developer. Instead of every editor holding its own copy of every secret, each third-party MCP server your team uses sits behind the gateway with its own OAuth-protected URL. The developer points their agent at that URL and authenticates once through your identity provider.
The gateway holds the upstream credential, encrypted at rest, and attaches it
server-side on each call, so the secret never lands in mcp.json. This is the
same boundary
Anthropic argued for when it
described containing agents at a deterministic layer rather than trusting the
model to behave.
The Zuplo MCP Gateway, in public beta, brokers those upstream credentials in three models that ship today. In every one the editor stops being a credential store.
| Credential model | Who holds the grant | Revocation granularity |
|---|---|---|
| Per-user OAuth | Gateway, keyed to each developer’s identity | One developer, at the gateway |
| Gateway-wide OAuth | One grant an administrator connects once | The whole grant |
| Shared API key | Gateway, not the editor | Rotate the key |
Per-user OAuth is the one that fixes revocation: cut off one person at the gateway instead of rotating a shared credential that breaks everyone. And every tool call routes through one place, so you get a per-call audit of who invoked which tool on which server, the inventory shadow MCP never gave you.

Common mistake:
The tempting half-measure is to rotate the shared upstream key on a schedule and call it governance. Rotation limits how long a leaked key lives, but it does nothing for visibility or per-developer revocation, and it breaks every editor at once. Move the secret off the laptops instead.
None of this asks the developer to give up their agent. They still point Cursor or Claude Desktop at an MCP server and call tools. The credential is just no longer theirs to paste, lose, or leak, and you finally have a record of what your agents reach. Put the same rate limits and identity checks on that route you would on any MCP server you ship.
MCP Gateway Quickstart
Put a third-party MCP server behind one OAuth-protected URL, broker the upstream credential, and point an agent at it without pasting a token.
Go look at one developer’s mcp.json this week. Count the long-lived tokens,
then ask who approved them and how you would revoke them. The honest answer is
usually nobody and you can’t. A gateway turns that answer into a query, and the
tokens into something the laptop never holds.
The Zuplo MCP Gateway is in public beta on every plan, the free tier included. Spin up a free Zuplo project and put your team’s shadow MCP behind one front door.