Many MCP servers still accept a single static API key from every client, even though the MCP specification defines OAuth for remote servers and forbids the shortcuts that shared keys tend to invite. The choice is not purely academic: the key decides whether a tool call can be traced to a person, how far a leaked credential reaches and whether an agent can be cut off without breaking everyone else. This guide is the MCP-specific decision: what the specification requires by transport, where a static key is still a reasonable answer (local stdio servers, tightly bounded internal cases), where OAuth is the only defensible choice, and how to migrate a live server without an outage. It is for MCP server builders, platform teams hosting MCP for staff, and identity architects approving agent tool access. The general credential comparison is in the API Keys vs OAuth Tokens Guide, and the OAuth flow itself in the MCP Authorisation Specification Guide.
Key takeaways
- The transport sets the default. MCP authorisation is optional, but HTTP-based servers should follow the OAuth-based specification, while stdio servers should not and should take credentials from the environment instead.
- A shared key erases the user. One key used by every client means every tool call looks the same in logs, revocation is all or nothing, and the key's permission becomes everyone's permission.
- OAuth done wrong is not better. Token passthrough, missing audience checks and omnibus scopes recreate the shared-key problem with extra moving parts. The specification forbids passthrough outright.
- There is an OAuth answer for machines too. The MCP client credentials extension covers agents with no user present, and enterprise-managed authorisation covers single sign-on fleets, so "no user to log in" no longer justifies a static key.
- Migrate by running both, then removing one. Add OAuth alongside the key, move clients by ring, measure remaining key use from server logs, and only then revoke.
Short answer
Use OAuth for any MCP server reached over the network by more than one person or agent, and for any server whose tools touch data that belongs to individual users. Accept a static credential only where the server runs locally over stdio and takes its downstream credentials from its environment, or where a single, named machine client calls an internal server across a private path and the key is stored in a secrets manager, rotated and scoped. Even then, plan the move to OAuth client credentials. If you are unsure whether a server is "internal enough" for a key, it is not.
What the specification requires, by transport
The MCP authorisation text (revision 2026-07-28, checked 13 November 2026) states that authorisation is optional for MCP implementations, and then sets expectations per transport.
| Transport or deployment | What the specification says | Practical meaning for keys vs OAuth |
|---|---|---|
| stdio (local subprocess) | Implementations SHOULD NOT follow the authorisation specification and should instead retrieve credentials from the environment | No inbound authentication: the client launches the process. Downstream keys come from environment variables or a local secret store |
| HTTP-based (Streamable HTTP, remote) | Implementations SHOULD conform to the authorisation specification: the server is an OAuth 2.1 resource server, publishes Protected Resource Metadata (RFC 9728) and validates audience (RFC 8707) | OAuth is the expected model. A bespoke API key header is outside the specification and outside what standard clients can discover |
| HTTP on localhost, intended for local use | The security best practices say local servers SHOULD use stdio, or if they use HTTP, restrict access, for example by requiring an authorisation token or using unix domain sockets or other restricted IPC | A locally generated token is acceptable here; an open localhost port is not, because any local process or a DNS rebinding page can reach it |
| Alternative transports | Implementations MUST follow established security best practices for their protocol | Use the transport's own strong authentication; do not invent a key scheme |
When OAuth is used, several rules apply on every request: the client sends Authorization: Bearer on every HTTP request, never puts the token in the query string, and MCP servers "MUST NOT accept or transit any other tokens". See the Local MCP Server Security Guide for the stdio side and the Remote MCP Server Hardening Guide for the network side.
Side-by-side comparison for MCP
| Property | Static API key | OAuth access token (per the MCP profile) |
|---|---|---|
| Who it identifies | Whoever holds the key; usually a project or team, not a person or agent | A client and, for user flows, a resource owner; claims carry subject and scopes |
| Lifetime | Until revoked or rotated | Short-lived access token; refresh at the authorisation server's discretion |
| Audience binding | None: works anywhere the key is accepted | Bound to the MCP server's canonical URI through the resource parameter and validated by the server |
| Scope granularity | Whatever the server builds per key, often all or nothing | Scopes advertised in metadata and challenged per operation with 403 insufficient_scope |
| Discovery by standard clients | Manual configuration in each client | 401 with resource_metadata, then authorisation server discovery |
| Revocation impact | Revoking a shared key breaks every client using it | Revoke one user's grant or one client without touching others |
| Audit trail | All calls look identical | Per user and per client, if the server logs token claims |
| Where it is stored on clients | Plain text in a client config file or environment variable, in many deployments | Client-managed token cache; refresh tokens must be kept confidential |
| Build effort | Low | Higher: authorisation server, metadata, token validation, consent |
Static API keys in depth
Threat model
The attacker's goal is the key. It leaks from client configuration files, shell history, a repository, a screenshot or a log, and then works from anywhere until someone notices. Because one key is shared, the attacker inherits the union of every client's access and is indistinguishable from legitimate agents. If the server also uses that key to decide what tools are allowed, there is no way to give a read-only agent less than a write-capable one. OWASP API2:2023 Broken Authentication covers the API side of this weakness.
Architecture in words
The MCP client stores the key in its server configuration and sends it in a header on every request. The server compares it with a stored value (ideally a hash), maps it to a permission set, and runs the tool. Often the server then calls its downstream API with a second static key from its environment, which is the problem covered by the MCP Static Token Audit.
Where keys remain acceptable
- stdio servers: no inbound key exists; the server reads downstream credentials from its environment as the specification expects. Prefer a secret store or short-lived credential over a long-lived key in the environment.
- Localhost HTTP for a single user: a random token generated at install, stored in the operating system's credential store and checked on every request, combined with binding to loopback or a unix socket.
- One named machine client on a private path: for example a scheduled job calling an internal MCP server through a gateway, with one key per client, stored in a secrets manager, scoped to read-only tools and rotated on a schedule. Treat this as transitional.
Controls if you keep a key
One key per client, never shared; hashed at rest on the server; scoped to a tool allowlist; rotated with overlap; never in query strings or logs; and fail closed when validation fails. See the API Key Management Guide.
OAuth in depth
Threat model
OAuth moves the target from a static secret to tokens and to the flow that issues them. The specific MCP threats are token passthrough (a server accepting a token not issued for it and forwarding it downstream), the confused deputy in MCP proxy servers (a static upstream client ID, dynamic registration and a consent cookie letting an attacker obtain codes without consent), mix-up between authorisation servers, theft of broad tokens, and SSRF during discovery. The Confused Deputy in AI Agents Guide covers the wider agent version of the problem.
Architecture in words: three patterns
| Pattern | Use when | How it works | Status when checked |
|---|---|---|---|
| User-delegated authorisation code with PKCE | A person uses an MCP client and tools act on their data | Discovery from a 401, client registration, browser consent, token bound to the server's URI | Core specification |
| Client credentials | An agent or service with no user present | Pre-registered client authenticates to the token endpoint, with JWT authentication (RFC 7523) recommended over a client secret; dynamic registration is not used | Extension, listed as stable in the MCP ext-auth repository |
| Enterprise-managed authorisation | Staff use MCP clients and servers that share an enterprise identity provider | The client exchanges the user's single sign-on assertion at the identity provider for an Identity Assertion JWT Authorization Grant (ID-JAG), then presents it to the MCP server's authorisation server; the access token must be audience-restricted to the MCP server | Extension, listed as stable in the MCP ext-auth repository |
Client credentials still involves a client secret or private key, but it is presented only to the authorisation server and exchanged for a short-lived, audience-bound token; the MCP server never sees it. For the enterprise pattern, see Enterprise-Managed Authorisation for AI Agents (ID-JAG and Cross App Access). For machine flows generally, see the Machine-to-Machine OAuth (Client Credentials) Guide.
Where OAuth fails
- Passthrough: the server forwards the client's token to an upstream API. The security best practices list the risks: downstream controls bypassed, clients indistinguishable in logs, and a stolen token usable through the server for exfiltration.
- No audience check: the server accepts any token its identity provider signed, so a token for another application works here.
- Omnibus scopes: every scope published in
scopes_supportedand requested up front, which gives a stolen token the reach of a shared key. - Proxy without per-client consent: the confused deputy conditions above. MCP proxy servers must keep a registry of approved client IDs per user and check it before forwarding to the third-party authorisation server.
- Trusting state handles: a workflow or cart ID treated as proof of identity. The best practices say servers must not treat possession of a state handle as authentication.
Controls
Validate signature, issuer, audience, expiry and scope on every call; obtain a separate token for each downstream API (see the OAuth Token Exchange and Delegation Guide); implement per-client consent in proxies; and apply RFC 9700, which says access token privileges should be restricted to the minimum required and tokens should be audience-restricted.
Per-user vs shared credentials
| Model | Accountability | Blast radius of one leak | Fits |
|---|---|---|---|
| One shared key for all clients | None per user or agent | Everything the key allows, for everyone | Nowhere in production |
| One key per client or agent | Per client, not per person | That client's permissions | Transitional machine-to-machine cases |
| Client credentials token per agent | Per agent identity | That agent's scopes, until the token expires | Autonomous agents and services |
| User-delegated token per user and client | Per person and per client | That user's granted scopes on that server | Interactive assistants and IDE clients |
For multi-tenant servers, the tenant and user must come from the verified token, never from tool arguments. See Multi-Tenant Remote MCP Server Design.
Scope design for MCP tools
- Start small: the security best practices suggest a minimal initial scope set containing only low-risk discovery and read operations (their example is
mcp:tools-basic), with elevation through targetedWWW-Authenticatescope challenges. - Group tools by risk, not by name: read, write, delete and external send are different scopes even when one tool does several.
- Challenge once, completely: servers should include all scopes required for the current operation in a single challenge; clients compute the union with scopes already held.
- Avoid the listed mistakes: wildcard or omnibus scopes such as
*orfull-access, publishing every scope in metadata, and treating a scope claim as sufficient without server-side authorisation logic. - Keep offline_access out of challenges: the specification says servers should not list it in challenges or
scopes_supported, because refresh tokens are not a resource requirement.
Key and token storage on clients
Static keys for MCP servers commonly sit in plain-text client configuration files and environment variables, readable by any process the user runs, including other MCP servers the client launches. Prefer the operating system credential store (macOS Keychain, Windows Credential Manager, a Secret Service implementation on Linux) or a secrets manager reference over a literal value. OAuth clients must keep refresh tokens confidential, and RFC 9700 requires refresh tokens for public clients to be sender-constrained or rotated. Launch local servers with a minimal environment so they inherit only what they need. See How to audit MCP servers on developer laptops.
Choosing: decision criteria
| Situation | Choose | Reason |
|---|---|---|
| Local server launched by the client | stdio, credentials from the environment or a secret store | Specification default; no network listener to protect |
| Local server that must use HTTP | Generated per-install token, loopback or unix socket | Blocks other local processes and browser-based access |
| Remote server used by staff through standard clients | OAuth authorisation code, or enterprise-managed authorisation where the identity provider supports it | Per-user audit and revocation; standard client discovery |
| Remote server called by an autonomous agent | OAuth client credentials with JWT client authentication | Short-lived audience-bound tokens with no user prompt |
| Public or multi-tenant MCP server | OAuth with Client ID Metadata Documents and a domain trust policy | Unknown clients; dynamic registration is deprecated |
| Internal server, one batch job, private network | Per-client key in a secrets manager, as a stepping stone | Acceptable short term; migrate to client credentials |
Small teams can often use the hosted identity provider they already have as the authorisation server and pre-register their few clients. Large organisations should standardise on one authorisation server for MCP, put remote servers behind an MCP gateway, and use enterprise-managed authorisation so administrators control which servers each client may reach. See the MCP Gateway and MCP Server Governance Guide.
Worked scenario: a shared ticketing MCP server
A platform team runs a remote MCP server exposing ticket search, ticket update and ticket delete tools. Forty developers and two scheduled agents use it with one shared key copied into each client's configuration.
- Assess: the key allows all three tools; logs show one identity; revoking it would stop every user and both agents at once.
- Design scopes:
tickets:read,tickets:writeandtickets:delete, with read as the minimal set in Protected Resource Metadata. - Add OAuth alongside the key: the server publishes metadata, returns 401 with
resource_metadatato requests without a valid token, and keeps accepting the old key only on a separate, monitored code path. - Move people: developers reconnect through the company identity provider; each tool call now logs the user and client.
- Move agents: the two agents are pre-registered as client credentials clients with private key JWT authentication and read and write scopes only; delete stays a human operation.
- Retire the key: after two weeks with no key traffic in server logs, disable it, then delete it a week later.
Result: a leaked agent token now reaches read and write for one hour, not delete for everyone indefinitely.
Migration path
- Inventory: list every MCP server, its transport, the inbound credential type and every client holding a key. Use the MCP Server Inventory Template.
- Classify: stdio and local servers stay on environment credentials; remote servers move to OAuth; note which have user-owned data.
- Stand up the authorisation side: pick the authorisation server, define scopes, publish Protected Resource Metadata, and implement audience and scope validation with fail-closed behaviour.
- Dual-run: accept OAuth and the legacy key together, log which path each request used, and alert on new key enrolments.
- Move clients in rings: pilot users first, then the wider population, then machine clients onto client credentials. Watch 401 and 403 rates per ring.
- Remove passthrough: if the server forwarded client tokens downstream, replace that with its own downstream token per API.
- Retire keys: disable, observe, then delete. Rollback is re-enabling the disabled key for a named client while the cause is fixed, never issuing a new shared key.
When troubleshooting the cut-over, see the MCP Authorisation Errors Troubleshooting Guide.
Detection and measurement
- OAuth coverage: share of remote MCP servers that publish Protected Resource Metadata and reject requests without a valid audience-bound token.
- Residual key traffic: share of requests per server still authenticated by a static key, trending to zero.
- Shared credentials: count of keys or client IDs used from more than one host or by more than one person.
- Scope breadth: share of issued tokens carrying write or delete scopes, and step-up events per week.
- Passthrough findings: number of servers that forward inbound tokens downstream, target zero.
- Logged events to watch: tokens with the wrong audience, repeated insufficient_scope loops, authentication fallbacks and keys presented from new networks.
Common failure patterns
- Fail-open validation: the LiteLLM MCP Auth Bypass 2026 showed a gateway that fell back to an unrestricted identity when key validation failed, and many exposed instances still accepted a documented example master key. Validation must reject, and example keys must never reach production.
- Ambient client credentials: in the Amazon Q MCP Config Vulnerability 2026, MCP server processes defined in a repository's configuration inherited the developer's environment, including cloud keys and tokens. Keys kept in environment variables are available to every server a client launches.
- "OAuth" that is really passthrough: a server labelled as OAuth-protected that forwards the user's identity provider token to downstream APIs.
- Local HTTP with no token: a developer tool listening on a localhost port without authentication, reachable by other processes or a rebinding web page.
- One client ID for all agents: client credentials adopted, but every agent shares the same client, recreating the shared-key audit gap.
- Keys rotated by replacement only: no overlap window, so rotation causes outages and teams stop rotating.
Framework mapping
| Framework | Reference | How it applies |
|---|---|---|
| NIST SP 800-53 Rev. 5 | IA-9 Service Identification and Authentication; IA-5 Authenticator Management | Authenticate MCP clients and agents as services; manage key and secret lifecycle |
| NIST SP 800-53 Rev. 5 | AC-6 Least Privilege; AU-2 Event Logging | Per-tool scopes; log user, client and scope per call |
| NIST CSF 2.0 | PR.AA-05 access permissions defined, managed, enforced and reviewed | Scope design and per-client grants |
| OWASP API Security Top 10 2023 | API2:2023 Broken Authentication | Shared static keys and fail-open validation |
| MCP security best practices | Token Passthrough; Confused Deputy Problem; Scope Minimization; Local MCP Server Compromise | MCP-specific requirements for servers and proxies |
| IETF | RFC 9700 Best Current Practice for OAuth 2.0 Security | Audience restriction, minimum privilege, refresh token protection |
Practitioner checklist
- Every MCP server is recorded with its transport and inbound credential type.
- Local servers use stdio, or HTTP restricted by a per-install token on loopback or a unix socket.
- Remote servers publish Protected Resource Metadata and validate signature, issuer, audience, expiry and scope on every request.
- No server forwards inbound tokens to downstream APIs; each downstream call uses the server's own token.
- Autonomous agents use client credentials with one client per agent and JWT client authentication.
- Scopes separate read, write, delete and external send, with a minimal default set.
- Any remaining static key is per client, stored in a secrets manager or credential store, hashed on the server and on a dated retirement plan.
- MCP proxy servers implement per-client consent and exact redirect URI matching.
- Logs record user, client, scope and authentication path for every tool call.
Standards and references
- Model Context Protocol: Authorization (revision 2026-07-28)
- Model Context Protocol: Security Best Practices
- Model Context Protocol: Authorization Extensions (ext-auth)
- IETF: RFC 9700 Best Current Practice for OAuth 2.0 Security
- IETF: RFC 9728 OAuth 2.0 Protected Resource Metadata
- IETF: RFC 8707 Resource Indicators for OAuth 2.0
- OWASP: API Security Top 10 2023
Related NHI Mgmt Group resources: MCP Authorisation Specification Guide, MCP Static Token Audit, API Keys vs OAuth Tokens Guide, MCP Security Guide, MCP Server Security Checklist.