Zuplo
Model Context Protocol

Your Team Already Installed Shadow MCP

Nate TottenNate Totten
June 11, 2026
5 min read

Developers paste GitHub, Slack, and Stripe keys into editor configs to wire up MCP servers nobody approved. Govern this shadow MCP with an MCP gateway, don't ban it.

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.

Use this approach if you're:
  • 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.

CredentialWhat a leak reaches
GitHub PATEvery scope minted, usually everything
Stripe keyThe whole account
Slack tokenEvery 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

Before: each editor holds its own static tokens and connects directly to GitHub, Stripe, and Notion. After: the editors authenticate to one Zuplo MCP Gateway over OAuth, and the gateway brokers the credential to each upstream, so the secret never lives on the laptop.

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 modelWho holds the grantRevocation granularity
Per-user OAuthGateway, keyed to each developer’s identityOne developer, at the gateway
Gateway-wide OAuthOne grant an administrator connects onceThe whole grant
Shared API keyGateway, not the editorRotate 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.

Zuplo MCP Gateway analytics for a clickhouse-mcp-server virtual server, showing each tool called (run_select_query, get_services_list, run_postgres_select_query, get_organizations) with call counts, error rates, and p95 latency, plus the consumers who invoked them broken down by email and event volume.

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.