Skip to content

Agents and multimodal systemsGuide

MCP security: where MCP server credentials leak

Every MCP server an agent uses needs a credential, and most setups keep it in a JSON file in your home directory or pass it to a local process that runs with your privileges. Here is where those tokens sit, what the MCP specification forbids, what malicious MCP packages have actually done, and how to shrink the blast radius.

By INFRO Editorial

Published

8 min read

A glowing glass hub on a dark ground with amber lines running out to small glass nodes around it

In short

MCP server credentials usually live as static API keys in plain-text JSON configuration (Claude Code's ~/.claude.json and .mcp.json, Cursor's mcp.json), passed to local servers that run with the user's privileges, or as OAuth tokens held by the client for remote servers. The MCP specification forbids token passthrough and warns about local server compromise; real malicious MCP packages have copied users' emails and harvested environment credentials. Prefer OAuth or narrowly scoped tokens, reference secrets from the environment, pin and review server packages, and put one gateway in front that holds the credentials.

Key takeaways

  • Most MCP credentials are static tokens in plain-text JSON files or environment variables handed to local server processes that run with the user's privileges.
  • The MCP specification says servers MUST NOT accept tokens not explicitly issued for them, and treats local server compromise and over-broad scopes as named attack vectors.
  • Real cases exist: the postmark-mcp npm package copied every email it sent to an attacker in 2025, and the May 2026 Mini Shai-Hulud campaign shipped credential-stealing versions of two MCP server packages.
  • Prefer OAuth or the narrowest token a server accepts, reference secrets from the environment rather than writing them into config, and pin the server packages you run.
  • A gateway that holds server credentials means agents and laptops never see them, and one place records every tool call.

Where do MCP server credentials leak? Mostly from where they are kept. A typical MCP setup stores each server's API key in a plain-text JSON file in the user's home directory or project, or passes it as an environment variable to a local server process that runs with the user's full privileges. Remote servers may use OAuth instead, with tokens held by the client. Credentials leak when those files are committed or copied, when a malicious or compromised server package reads them, and when a server forwards a token it should never have accepted. The fixes are narrow tokens (or OAuth), secrets referenced rather than written, pinned server packages, and one gateway in front that holds the credentials so agents never do.

What is MCP explains the protocol; MCP gateways covers governing tool access in general. This guide is about the credentials.

Where MCP tokens live

SetupWhere the credential sitsWho can read it
Local server (stdio), personal~/.claude.json for Claude Code1, ~/.cursor/mcp.json for Cursor2, as a literal or an environment variableYou, any process running as you, and the server itself
Local server, team-shared.mcp.json (Claude Code) or .cursor/mcp.json (Cursor) in the repository12Everyone with the repository, if a literal key is committed
Remote server, static tokenAn Authorization or API-key header in the same config filesSame as above, plus the server
Remote server, OAuthTokens held by the client; Claude Code says they are "stored securely and refreshed automatically", with a pre-configured client secret in the macOS keychain or a credentials file1The client; the token is issued to that client

Two details raise the stakes. First, these files are plaintext: Claude Code's ~/.claude.json holds app state, OAuth sign-in and personal MCP servers3, and old copies of it are kept in ~/.claude/backups/3. Second, local servers are programs, not configuration: the specification warns that MCP servers run with the same privileges as the client4. A local server you give a GitHub token to can also read your SSH keys.

GitGuardian's 2026 report counts 24,008 unique secrets exposed in MCP configuration files in public GitHub commits5. Those are the files above, committed by mistake.

Reference secrets, do not write them

Both major clients support references instead of literals. Claude Code expands ${VAR} and ${VAR:-default} in .mcp.json so teams can share configuration "while maintaining flexibility for … sensitive values like API keys", and in a remote server's URL and headers it reads some credential variables as empty so a project's file cannot send your credentials to a server it names1. Cursor supports ${env:NAME} interpolation and an envFile for stdio servers, and recommends "restricted API keys with minimal required permissions" and environment variables for secrets2.

.mcp.json with a reference, not a key
{
  "mcpServers": {
    "issues": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "headers": { "Authorization": "Bearer ${ISSUES_MCP_TOKEN}" }
    }
  }
}

A reference keeps the key out of the repository; it does not keep it away from the server process, the agent's shell or anything else running as you. That is what the next sections address.

What the specification says

The MCP specification's Security Best Practices page names several credential attacks. Three matter most for teams running servers.

Token passthrough. An MCP server that accepts a token not issued to it, and forwards it to a downstream API, is an anti-pattern the authorization specification explicitly forbids4. The risks it lists: security controls that depend on the token's audience are bypassed, the server cannot tell clients apart, downstream logs show the wrong identity, and a token accepted by several services lets an attacker who compromises one reach the others4. The rule is short: "MCP servers MUST NOT accept any tokens that were not explicitly issued for the MCP server"4. If you build an MCP server in front of an internal API, give it its own credential for that API, and validate the audience of tokens clients present.

Local server compromise. The specification describes three attacks on local servers: a malicious startup command in a client configuration, a malicious payload inside the server, and an insecure server left listening on localhost reached through DNS rebinding4. Its example of a malicious startup command installs a package and posts ~/.ssh/id_rsa to a remote host4. Clients that offer one-click local server setup must show the exact command and require explicit approval, and should run servers sandboxed with minimal default privileges4. Claude Code, for example, asks for approval before using project-scoped servers from .mcp.json in interactive sessions1.

Scope minimization. An access token carrying broad scopes such as files:* or admin:*, stolen from a log or memory, "enables lateral data access, privilege chaining, and difficult revocation"4. The specification recommends a minimal initial scope set with incremental elevation when a privileged operation is first attempted, and lists wildcard scopes and bundled privileges as common mistakes4.

What malicious MCP packages have done

Two reported cases show both ways a server package can turn on its user.

postmark-mcp (2025): a server that abused the access it was given. Koi Security found that the npm package postmark-mcp, impersonating Postmark's MCP server, which Postmark publishes on GitHub rather than npm, added a backdoor in version 1.0.16 after 15 clean versions; it silently copied outgoing emails to an attacker-controlled address, as reported by The Register6. The package had about 1,500 downloads in a week before removal; Postmark said it "had absolutely nothing to do with this package", and the advice was to remove it, review email logs and rotate credentials sent by email6.

Mini Shai-Hulud (May 2026): a server package that stole the environment. The OSV advisory MAL-2026-4068 records malicious versions 0.2.8 and 0.3.8 of @antv/mcp-server-antv as part of a campaign in which a compromised npm maintainer account published 631 malicious versions across 314 packages in a 22-minute burst7. Each added a preinstall hook running an obfuscated script that, per the advisory, took AWS keys, GCP service accounts, Azure credentials, GitHub and npm tokens, Kubernetes tokens, SSH keys and database connection strings, and persisted through CI workflow injection and AI agent session hooks7. Nobody had to call a tool: installing the package was enough.

The first case is a reason to scope the token you give a server. The second is a reason to keep every other credential away from the machine that installs it. AI supply chain attacks in 2026 puts both in context.

Reducing the blast radius

  • Prefer OAuth where the server offers it. A token issued to one client, with narrow scopes and an expiry, revocable per client, beats a long-lived personal access token pasted into JSON. It does not make a stolen token harmless; it makes it smaller and shorter-lived.
  • Use the narrowest token the server accepts. Read-only tokens or read-only server modes when the agent does not need to write; one token per server; never an organization-admin token.
  • One token per person and per server. Shared tokens make revocation break everyone and make audit trails useless.
  • Pin and verify server packages. Install servers from the vendor's own publication, pin exact versions, read changelogs before upgrading, and treat a server like any other dependency in your supply chain review.
  • Review startup commands. npx some-package@latest in a config file runs whatever was published last.
  • Run local servers with less. Containers or the client's sandbox, without access to ~/.ssh, cloud credential files or unrelated environment variables. Coding agents and secrets has the Claude Code sandbox settings.
  • Keep secrets out of config files with references, and scan for them before push.
  • Rehearse revocation. For each server, know where its token is issued and how fast you can revoke it.

Put one gateway in front

The structural fix is to stop distributing server credentials to every laptop and agent. A gateway registers each MCP server once, with its credential, and agents reach the server through the gateway with their own identity. The credential lives in one sealed place; revoking an agent's access does not require rotating the server's token; and one log records which agent called which tool.

A gateway does not remove the risks inside the tool call. A server you trust can return content that steers the model, and a granted tool can still be misused by an agent following injected instructions. Least-privilege grants, read-only credentials and human review of writes remain necessary.

How INFRO's MCP gateway handles server credentials

INFRO's MCP gateway, on the Business plan, puts INFRO between your agents and the MCP servers they use. As documented in its security model:

  • Server credentials are sealed. An owner or admin registers a server with up to eight header values, such as a bearer token; they are encrypted at rest with AES-256-GCM, bound to the organization and the server, and never returned by any API, console screen, log, error or trace. Only header names are shown.
  • The agent never holds the server credential, and the server never sees the INFRO key. Agents call with their INFRO gateway key; INFRO adds the server's headers to each call, and strips the agent's Authorization and X-INFRO-* headers — no passthrough in either direction.
  • Access is denied by default. A gateway key with no grant sees no tools; a grant gives one key one server in a chosen mode, and only tools an admin approved are served. A tool whose definition changed on the server since approval is refused.
  • Guardrails apply to tool calls. A secret rule with block on the input stage refuses tool calls whose arguments contain a credential, a common sign of an agent being steered into sending one out.
  • Every call is recorded with metadata (server, tool, outcome, sizes, key, project, environment) on the same trace as the agent's model calls; contents only if you opt in.

Two limits, stated plainly. Servers that only accept OAuth sign-in, such as Notion, Vercel and Asana, cannot be registered yet; INFRO's gateway takes servers with no authentication or a static header credential. And INFRO governs calls that go through it: a server token that also sits on a laptop, or is stolen from anywhere, can be used directly against the server. Register with a dedicated, narrowly scoped token, keep it nowhere else, and keep revocation at the issuing service as the backstop.

Summary

MCP credentials leak from where they are kept: plaintext JSON, inherited environments and local server processes with full user privileges. Follow the specification — no token passthrough, consent before running local servers, minimal scopes — and learn from the real cases: a server package can abuse the access you give it, or steal everything else on the machine. Use OAuth or the narrowest token, reference secrets instead of writing them, pin server packages, and centralize credentials in one gateway so agents never hold them.

Questions readers ask

Where are MCP server API keys stored?
Usually in plain-text JSON. Claude Code keeps personal MCP servers in ~/.claude.json and team servers in a project's .mcp.json; Cursor uses ~/.cursor/mcp.json and .cursor/mcp.json. Keys either sit in those files or in environment variables passed to the server process. Remote servers that use OAuth keep tokens with the client instead.
What is token passthrough in MCP?
An anti-pattern where an MCP server accepts a token that was not issued for it and forwards it to a downstream API. The MCP specification forbids it: servers must not accept any tokens that were not explicitly issued for the MCP server, because passthrough bypasses controls, breaks audit trails and lets one stolen token reach several services.
Is OAuth safer than an API key for MCP servers?
Usually. An OAuth token is issued to one client, can carry narrow scopes, expires and can be revoked per client, and it is not written into a config file by hand. It is not a cure: a stolen access token still works until it expires, and broad scopes widen the damage, which is why the specification recommends minimal initial scopes.
Have malicious MCP servers actually been found?
Yes. Koi Security found that version 1.0.16 of the npm package postmark-mcp, which impersonated Postmark's server, copied every outgoing email to an attacker, as The Register reported in 2025. In May 2026 the OSV database recorded malicious versions of two @antv MCP server packages that harvested cloud keys, tokens and SSH keys during install.

From the team that builds it

Where this shows up in INFRO

INFRO is a control plane in front of the provider accounts you already hold. The capabilities below are the parts of it this article touches, each with the documentation that defines its behaviour.

  • MCP gateway for your agents' tools

    Available with a plan

    Register your own MCP servers once with their credentials, approve and pin each tool's definition, grant gateway keys access, and let agents call those tools through INFRO with guardrails, a call log on the same trace as their model calls, and kill switches checked on every call. INFRO executes no tool.

    Read the documentation for MCP gateway for your agents' tools
  • Guardrails

    Available with a plan

    Pattern-based checks on chat completion prompts and responses: block, redact or flag email addresses, phone numbers, card numbers, IBANs, US Social Security numbers, IP addresses, API keys and your own terms, plus optional classifier checks on your own connection to a decision model's provider. Detection can miss things. Included from the Business plan.

    Read the documentation for Guardrails
  • Key limits and rotation

    Available with a plan

    Limit a gateway key to chosen providers or IP ranges, and rotate it with an overlap window so the old key keeps working while you deploy the new one.

    Read the documentation for Key limits and rotation
  • Audit log

    Available with a plan

    Member, key, and policy changes recorded with actor and timestamp, viewable in the console.

    Read the documentation for Audit log
  • Request traces and payload logs

    Available with a plan

    Per-request timing detail, with prompt and completion logging off by default and a retention window you choose.

    Read the documentation for Request traces and payload logs
  • Environments

    Available with a plan

    Production, staging and development to start, and your own beside them. A connection or route serves one, several or every environment; each gateway key belongs to exactly one, and never reaches a connection outside it.

    Read the documentation for Environments

INFRO accounts are self-serve. Provider usage is billed to you by your providers; INFRO charges a software subscription and takes 0% of model spend. See plans.

Sources

Numbered in order of first citation. Each was opened and checked against the claim on the date shown.

  1. 1.Connect Claude Code to tools via MCP (opens in a new tab) — Claude Code Docs. Accessed Oct 21, 2026.
  2. 2.Model Context Protocol (MCP) (opens in a new tab) — Cursor Docs. Accessed Oct 21, 2026.
  3. 3.Explore the .claude directory (opens in a new tab) — Claude Code Docs. Accessed Oct 21, 2026.
  4. 4.Security Best Practices (opens in a new tab) — Model Context Protocol. Accessed Oct 21, 2026.
  5. 5.The State of Secrets Sprawl 2026 (opens in a new tab) — GitGuardian. Accessed Oct 21, 2026.
  6. 6.Postmark MCP server code hijacked (opens in a new tab) — The Register. Accessed Oct 21, 2026.
  7. 7.MAL-2026-4068: Malicious code in @antv/mcp-server-antv (npm) (opens in a new tab) — OSV. Accessed Oct 21, 2026.

About this article

On 2026-10-21 we opened the MCP specification's Security Best Practices page, Claude Code's MCP and .claude directory documentation, Cursor's MCP documentation, GitGuardian's State of Secrets Sprawl 2026 page, The Register's report on postmark-mcp and the OSV advisory MAL-2026-4068. INFRO's MCP gateway is described from its public documentation. Written by the team that builds INFRO.

Last checked against its sources on . The next review is due by . No separate named reviewer is recorded for this article.

How articles are written, sourced and corrected is set out in the editorial standards.