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

Securing MCP Servers: How to Stop Your AI Agent From Leaking API Keys

Cover image for Securing MCP Servers: How to Stop Your AI Agent From Leaking API Keys
AI Security • MCP • API Key Management

TL;DR

MCP servers give AI agents access to your tools, databases, and cloud services. Every one of those connections requires API keys. The OWASP MCP Top 10 ranks token mismanagement as the #1 security risk. This post covers how to manage those keys securely: scoped access, runtime injection, and keeping credentials out of config files and context windows.

MCP Is Everywhere — And So Are the Keys

The Model Context Protocol (MCP) has become the standard way to connect AI agents to external tools. Claude, ChatGPT, Cursor, VS Code Copilot, and dozens of other tools now support it. The protocol has over 97 million monthly SDK downloads and 10,000+ active servers.

The architecture is simple: MCP servers expose tools (functions the AI can call), resources (data the AI can read), and prompts. Your AI agent connects to one or more MCP servers, and suddenly it can query databases, deploy code, send emails, manage cloud infrastructure, and more.

Every one of those capabilities requires credentials. A GitHub MCP server needs a personal access token. A database MCP server needs connection strings. A Vercel MCP server needs an API key. An AWS MCP server needs access keys.

The question is: where do those credentials live?

The #1 MCP Security Risk: Token Mismanagement

In early 2026, OWASP published the MCP Top 10 — a ranked list of the most critical security risks in MCP deployments. The number one entry is MCP01: Token Mismanagement & Secret Exposure.

The pattern they describe is familiar:

  • API keys hard-coded in MCP server configuration files
  • Long-lived tokens with no expiration or rotation
  • Secrets stored in model memory or protocol logs
  • Credentials shared across MCP servers with no access scoping

If you’ve seen the research on OpenClaw skills leaking credentials, this is the same problem in a different context. The AI agent ecosystem keeps finding new ways to put secrets in places they don’t belong.

Real Incidents, Real Consequences

This isn’t theoretical. Here’s what has already happened with MCP server security:

Anthropic’s own Git MCP server had three CVEs (CVE-2025-68145, CVE-2025-68143, CVE-2025-68144) that enabled arbitrary file read, file deletion, and remote code execution through prompt injection.

GitHub’s MCP server was exploited via a malicious public GitHub issue that hijacked an AI assistant, causing it to exfiltrate private repository contents, internal project details, and personal salary information.

A WhatsApp MCP server was compromised through tool poisoning, allowing silent exfiltration of an entire chat history.

Microsoft’s MarkItDown MCP server had an SSRF vulnerability. Researchers estimated that roughly 37% of all MCP servers may have similar exposure.

Hundreds of MCP servers were found binding to 0.0.0.0, making them accessible to anyone on the network — along with whatever API keys they held.

In every case, the blast radius was determined by what credentials the compromised MCP server had access to. A server with a scoped, read-only token for one repository is a very different risk than a server holding your AWS root keys.

The Problem: How MCP Servers Typically Handle Keys

Most MCP server documentation tells you to do something like this:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_xxxxxxxxxxxxxxxxxxxx"
      }
    }
  }
}

That’s a plaintext API key in a JSON config file on your filesystem. It’s the MCP equivalent of putting your password in a .env file and calling it a day.

The problems compound:

  1. No access scoping — the MCP server gets whatever permissions the token has. If your GitHub PAT has full repo access, so does the AI agent.
  2. No rotation — the key sits in the config file until someone manually changes it.
  3. No audit trail — there’s no record of which agent used which key or when.
  4. Blast radius — if the MCP server is compromised (through prompt injection, tool poisoning, or a vulnerability in the server itself), the attacker gets the full token.
  5. Config file sprawl — every developer on the team has their own copy of the config with their own keys hard-coded in it.

The Fix: Runtime Key Injection for MCP Servers

The principle is the same one we apply to OpenClaw and any other AI agent: credentials should be injected at runtime, not stored in configuration files.

Here’s how to set this up with the API Stronghold CLI:

Step 1: Store Your MCP Keys in the Vault

Instead of pasting keys into MCP config files, store them in API Stronghold:

api-stronghold-cli key create GITHUB_PAT ghp_xxxxxxxxxxxx
api-stronghold-cli key create OPENAI_API_KEY sk-xxxxxxxxxxxx
api-stronghold-cli key create VERCEL_TOKEN vrc_xxxxxxxxxxxx

Step 2: Create a Scoped Deployment Profile

In the API Stronghold dashboard, create a deployment profile specifically for your MCP environment. Map only the keys your MCP servers actually need — your GitHub MCP server doesn’t need your Stripe key, and your database MCP server doesn’t need your OpenAI key.

You can also create a user group and assign the deployment profile to it, so only authorized team members can pull these keys.

Step 3: Inject Keys at Agent Startup

Before launching your AI agent (Claude Desktop, Cursor, etc.), load the scoped keys into your environment:

eval $(api-stronghold-cli deployment env-file mcp-dev --stdout)

Your MCP servers then read credentials from environment variables instead of hard-coded config values. For example, the GitHub MCP server reads GITHUB_PERSONAL_ACCESS_TOKEN from the environment automatically.

The keys exist in process memory for the duration of the session. They’re not in a config file, not in the context window, and not accessible to a compromised MCP server that tries to read the filesystem.

Wrapper Script Approach

Most MCP clients don’t resolve environment variables inside JSON config files. The recommended approach is to use a wrapper script that loads secrets and then launches the client:

#!/bin/bash
eval $(api-stronghold-cli deployment env-file mcp-dev --stdout)
exec cursor  # or claude, code, etc.

This ensures all MCP servers in the session have access to the scoped keys via environment variables. See the CLI docs for more examples.

Scoping Keys Per MCP Server

The OWASP MCP Top 10’s second entry is MCP02: Privilege Escalation via Scope Creep — MCP servers accumulating more permissions than they need over time.

With API Stronghold’s user groups and deployment profiles, you can create separate scopes for each MCP server:

  • GitHub MCP → deployment profile with only GITHUB_PAT (and use a fine-grained PAT scoped to specific repos)
  • Database MCP → deployment profile with only DATABASE_URL (and use a read-only connection string)
  • Vercel MCP → deployment profile with only VERCEL_TOKEN

If one MCP server is compromised through tool poisoning or prompt injection, the attacker only gets the keys scoped to that server. Your AWS credentials, Stripe keys, and database admin passwords are in separate profiles that the compromised server never had access to.

Defending Against Tool Poisoning and Prompt Injection

Two of the most dangerous MCP attack vectors — tool poisoning (MCP03) and prompt injection (MCP06) — both target credentials:

Tool poisoning: A malicious MCP server embeds hidden instructions in tool descriptions that manipulate the AI agent into revealing secrets or calling tools in unintended ways.

Prompt injection: Malicious content in data the agent processes (a GitHub issue, a document, an email) instructs the agent to exfiltrate credentials through an MCP tool.

Both attacks depend on the same thing: the credentials being accessible to the agent. If an attacker tricks the agent into running echo $STRIPE_SECRET_KEY, it only works if that key is in the agent’s environment.

This is why scoping matters. An MCP server that only has access to a read-only GitHub token can’t leak your payment processing keys, no matter how sophisticated the prompt injection.

Team Workflows: Stop Sharing MCP Configs

MCP config files with embedded keys create a secondary problem: every developer on the team needs their own copy, and they share keys over Slack, email, or spreadsheets.

With centralized secrets management:

  1. Store all MCP-related keys in API Stronghold
  2. Create a user group (e.g., frontend-team) and assign the relevant deployment profiles
  3. Each developer pulls their own scoped keys via the CLI:
api-stronghold-cli deployment env-file mcp-dev .env

New team members get access to the right keys through group membership. When someone leaves the team, remove them from the group. When a key needs to be rotated, update it once in the vault and every developer gets the new value on their next pull.

No more copying config files around. No more stale keys on ex-employees’ laptops.

Zero-Knowledge Encryption: Defense in Depth

All of this is backed by zero-knowledge encryption. Your API keys are encrypted client-side with AES-256-GCM before they leave your machine. API Stronghold never sees your plaintext keys.

This matters because MCP security is defense in depth. Even if an attacker compromises an MCP server, the vault itself can’t leak your keys — because we don’t have them.

Quick Reference: MCP Security Checklist

Here’s a practical checklist for securing your MCP deployment:

  • Never hard-code API keys in MCP config files — use environment variables injected at runtime
  • Scope each MCP server’s access — create separate deployment profiles with only the keys each server needs
  • Use fine-grained tokens — a GitHub PAT should be scoped to specific repos, not your entire account
  • Rotate keys regularly — update keys in the vault, pull fresh values via the CLI
  • Audit MCP server sources — only install MCP servers from trusted sources, check for known vulnerabilities
  • Don’t bind to 0.0.0.0 — MCP servers should only listen on localhost unless explicitly needed
  • Require human confirmation — enable approval prompts for sensitive or irreversible MCP tool calls
  • Monitor tool descriptions — watch for changes that could indicate tool poisoning or rug-pull attacks
  • Separate MCP keys from production keys — your AI agent’s development environment shouldn’t share keys with production

Getting Started

Install the CLI and start managing your MCP server keys in minutes:

curl -fsSL https://www.apistronghold.com/cli/install.sh | sh
api-stronghold-cli login
api-stronghold-cli key list

For the full command reference, see the CLI docs. For pricing, see plans.


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 →