cd /news/developer-tools/your-mcp-json-probably-has-a-live-ap… · home topics developer-tools article
[ARTICLE · art-114218] src=dev.to ↗ pub= topic=developer-tools verified=true sentiment=· neutral

Your .mcp.json probably has a live API key in it

A developer has released mcp-secrets-runner, an open-source tool that prevents live API keys from being committed in MCP configuration files. The tool authenticates with machine credentials from secret managers like Infisical, 1Password, and Vault, fetching short-lived tokens to run MCP servers securely. It includes a diagnostic doctor command and fails closed on authentication errors.

read3 min views1 publishedAug 28, 2026

Nearly every guide to setting up an MCP server tells you to do this:

{
  "mcpServers": {
    "stripe": {
      "command": "npx",
      "args": ["-y", "@stripe/mcp@latest"],
      "env": { "STRIPE_SECRET_KEY": "sk_live_51J..." }
    }
  }
}

That is a live production key sitting in a file that gets committed to repositories, synced between machines, screenshotted for tutorials and pasted into bug reports. I have seen sk_live_

keys in all four.

It is also, in my experience, the single biggest reason MCP stalls at a company's security review. Not the protocol. Not the tooling. The config file.

So you wrap the server in your secret manager's CLI instead:

"args": ["run", "--env=prod", "--", "npx", "-y", "@stripe/mcp@latest"]

Better. The key is gone from the file. But those CLIs authenticate with a developer session stored in your OS keyring, and that session expires.

When it does, every MCP server wrapped this way stops starting at the same moment. And the error surfaces in your MCP client, which knows nothing about secret managers or expired logins. You get a generic startup failure on ten servers at once and go looking in entirely the wrong place.

I lost an afternoon to this before the pattern clicked.

Every serious secret manager has a concept for unattended access: a credential meant for machines rather than humans, with no TTL of its own. Infisical calls it a machine identity, 1Password calls it a service account, Vault calls it AppRole.

The credential is long-lived; what it produces is short-lived. You exchange it for a token at process start, use the token, and never think about it again.

That is the whole idea behind mcp-secrets-runner

. It sits between the MCP client and the server, authenticates with a machine credential, fetches the secrets and execs the real server:

{
  "mcpServers": {
    "stripe": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "mcp-secrets-runner", "--env=prod", "--path=/mcp",
               "--", "npx", "-y", "@stripe/mcp@latest"]
    }
  }
}

No secret values in the file. No session to renew. The same config works on every machine that has the machine credentials in its environment, which is what makes it safe to commit.

The interesting part of building this was that the three supported backends work nothing alike:

op run

, which authenticates itself.A provider only has to answer one question: which child process do I start, and what environment does it get. That the three answers look so different is the best evidence I have that the interface is not overfitted to the first one I wrote.

"My MCP server won't start" is almost always one of four things, and an MCP client reports all four identically. So there is a doctor

:

$ mcp-secrets-runner doctor --provider=vault

mcp-secrets-runner doctor (provider: vault)

  [ok  ] Node 22.14.0
  [ok  ] instance
         http://127.0.0.1:8200
  [ok  ] AppRole credentials present
  [ok  ] cached token available
  [ok  ] authentication succeeded
         token valid for 20 min

All checks passed.

Missing CLI, missing credentials, wrong instance URL, unreadable secret path. One line each, instead of one opaque failure.

All diagnostics go to stderr. stdout belongs to the MCP protocol. One stray byte there corrupts the JSON-RPC stream and the client reports a parse error pointing nowhere useful.

It fails closed. If credentials are set but authentication fails, the runner exits. The alternative is worse than it sounds: a credential-less CLI invocation opens an interactive browser login, which hangs the MCP server on stdin forever while the client waits.

MIT, zero dependencies, Node 18+.

── more in #developer-tools 4 stories · sorted by recency
── more on @mcp-secrets-runner 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-mcp-json-probab…] indexed:0 read:3min 2026-08-28 ·