← Back to Blog
· 6 min read · API Stronghold Team

Your MCP Server Doesn't Need Long-Lived API Keys

Cover image for Your MCP Server Doesn't Need Long-Lived API Keys

In our last post, we walked through the authentication gap that most MCP deployments ignore: the protocol tells you to authenticate the client, but says almost nothing about how the server should handle the credentials it accumulates. Spec discussions are still ongoing. In the meantime, people are shipping MCP servers loaded with API keys.

This post is about what happens when those servers get compromised, and what you can do about it today.

The .env file problem, one layer up

There’s a well-worn failure mode in web development. A developer hardcodes a secret into .env, commits it, and then either the repo leaks or the key quietly outlives the project it was meant for. The key is valid, full-access, and sitting there waiting.

MCP servers have the same problem, just one abstraction higher.

The server needs credentials to call external APIs on behalf of the agent. So you give it an API key. That key is usually long-lived (months to years), often has broad permissions, and the server process holds it in memory for as long as it’s running. If the server is compromised, the attacker gets the key. If the key is for Stripe or GitHub or your internal platform, you have a real problem.

The attack vector I keep coming back to is prompt injection. An LLM powering an MCP server can be told, mid-session, to do things the developer never intended. The model gets a crafted input that redirects its behavior. The model complies, because it’s a language model and that’s what they do. And now your MCP server is executing attacker-controlled actions with your production API key.

The key is the blast radius. Shrink the key, shrink the damage.

The proxy routing pattern described here is built into API Stronghold. Your MCP server routes through AS, the agent gets a session token, never the real key. Try the proxy routing →

The credential broker pattern

The fix is not a new MCP spec or a different prompt. It’s a pattern that web backends have used for years: the untrusted component (the frontend, in that world; the MCP server or LLM agent, in this one) never holds the real credential. Instead, it gets a short-lived, scoped token from a broker that holds the actual keys.

Here’s how API Stronghold implements this:

Register: You register your real API key with API Stronghold once. It never leaves the gateway. Your MCP server config, your agent runtime, your LLM prompt, none of them see it.

Scope: When issuing a token, you define exactly what it can do. This is not “read access vs. write access” in the abstract. It’s specific: which key IDs, which providers, which HTTP methods, which domains, and a rate limit per minute.

Issue: The gateway issues a session token. That token is what your MCP server gets. It’s time-limited, typically hours.

Validate: Every request your MCP server makes goes through the gateway. The gateway checks the token, verifies the request is within its declared scope, and proxies it if everything checks out.

Expire: When the token expires, it’s done. The real key is untouched.

This is the same architecture as OAuth 2.0 bearer tokens or AWS STS temporary credentials. Nothing novel. The difference is that it’s applied at the MCP credential layer, not the protocol layer.

What scoping actually looks like

When you issue a token through API Stronghold, you set fields like these:

{
  "allowedKeyIds": ["stripe-prod-001"],
  "allowedProviders": ["stripe"],
  "allowedMethods": ["GET", "POST"],
  "allowedDomains": ["api.stripe.com"],
  "rateLimitPerMinute": 30,
  "expiresIn": "4h"
}

An MCP server holding this token can call Stripe’s API at a rate of 30 requests per minute. It cannot call any other provider. It cannot use any other key. It cannot PUT or DELETE.

If prompt injection redirects the agent to exfiltrate data from a different service, the gateway rejects the request outright. The attacker’s injected instruction runs into a wall at the credential layer, not at the application layer.

Scope freezing

One thing we were deliberate about: token scopes are immutable after issuance. You cannot expand a token’s permissions after the fact.

This matters because the obvious attack against a broker pattern is to convince the broker to widen the scope mid-session. If the LLM can call the broker API, and the broker API accepts scope upgrades, prompt injection just gets redirected one step up.

API Stronghold does not accept scope expansion requests after issuance. The only way to get a broader token is to issue a new one, which requires authenticating as a principal who has permission to do so, separate from the token itself. The LLM cannot initiate that flow from inside a session.

Blast radius: a concrete comparison

Consider an MCP server for a customer support agent. It needs to look up orders, issue refunds up to $50, and check inventory.

With a long-lived key:

The server holds a Stripe API key with full account access. A successful prompt injection attack can list all customers, export transaction history, issue unlimited refunds, or cancel subscriptions. Detection might happen hours or days later. Rotating the key requires updating every system that uses it.

With a session-scoped token:

The server holds a 4-hour token scoped to GET /v1/charges/*, POST /v1/refunds with a maximum refund check downstream, and GET /v1/products/*. A successful prompt injection can try to do what the token allows. Nothing more. The token expires in 4 hours regardless. The real Stripe key is never touched.

The total available damage is the token scope. That’s a meaningful reduction.

What this isn’t

This does not eliminate prompt injection. A compromised agent can still do bad things within its allowed scope. Scope design matters, and the principle of least privilege applies here the same way it does everywhere else.

This also does not replace MCP authentication at the transport or protocol level. You still want to authenticate which clients can connect to your MCP server. The credential broker operates at a different layer.

What it does is contain the consequences. The conversation about MCP auth specs is real and worth having, but it’s a conversation that will take months to resolve. Credential-layer enforcement is something you can ship today, regardless of what the spec settles on.

Getting started

If you want to try this with your existing MCP server, the setup is:

  1. Register your API keys with API Stronghold
  2. Issue a session token with the scope your server actually needs
  3. Point your MCP server’s API calls through the API Stronghold gateway
  4. Set token TTL to match your session length

The gateway is a drop-in proxy. You don’t need to rewrite your MCP server logic.

The proxy routing pattern described here is built into API Stronghold. Your MCP server routes through AS, the agent gets a session token, never the real key. Try the proxy routing →

Secure your API keys today

Stop storing credentials in Slack and .env files. API Stronghold provides enterprise-grade security with zero-knowledge encryption.

View Pricing →