MCP OAuth: Secure Your MCP Endpoint with OAuth 2.1 and API Keys
MCP OAuth is how an AI client proves who is calling before it can use your tools. GetMCP gives every MCP server an endpoint you can lock down with OAuth 2.1 and PKCE, with API keys, or with passthrough credentials your own API checks. Claude, Cursor and VS Code discover the OAuth setup on their own, register themselves and open a browser sign-in, so there is nothing for your users to copy.
This guide covers the inbound side: what an MCP client must present to reach your server. It is for anyone putting a GetMCP server on the public internet, from a solo developer to a SaaS team giving customers access. The credential GetMCP then sends to your API is covered in MCP server authentication.
What is inbound security for an MCP endpoint?
Each GetMCP server answers at its own URL, /mcp/{slug} on your site. Anyone who knows that URL can try to call it. Inbound security is the rule GetMCP applies to every request before any tool runs.
You set it under Client Authentication on the server’s Authentication tab. There are five choices:
| Authentication Type | What the client must send | Who validates it |
|---|---|---|
| None | Nothing. The endpoint is public. | No one |
| OAuth 2.0 | An access token from GetMCP’s OAuth flow | GetMCP |
| API Key | A key in the header or query parameter you name | GetMCP, once you issue keys; otherwise your API |
| Bearer Token | Authorization: Bearer … | Your API (passthrough) |
| Basic Auth | Authorization: Basic … | Your API (passthrough) |
Only OAuth and issued API keys are checked by GetMCP itself. For Bearer, Basic and API Key without issued keys, GetMCP checks that a credential is present and forwards it; the upstream API is the real gate. The admin screen says this in an amber notice so nobody mistakes passthrough for validation.
How MCP OAuth works in GetMCP
When a server is set to OAuth 2.0, GetMCP acts as the authorization server for that endpoint. It follows the MCP authorization spec, so standard clients need nothing but the URL.
- Challenge. A request without a valid token gets HTTP 401 with
WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource". - Discovery. The client reads the protected-resource document, then the authorization server metadata. Both are served under the server’s own path, in the appended form and the RFC 8414 path-inserted form.
- Registration. The client registers itself at
/oauth/register(RFC 7591 dynamic client registration) and receives a public client ID with no secret. Clients that identify themselves with a Client ID Metadata Document URL can skip this step. - Sign-in. The client opens
/oauth/authorizewith a PKCE challenge. OnlyS256is accepted, and the redirect URI must exactly match one the client registered. - Token. The client exchanges the code at
/oauth/tokenand receives an access token valid for one hour and a refresh token valid for 30 days.
Every token is bound to the server it was issued for (RFC 8707 resource binding). A token minted for one server is refused by every other server on the same install. GetMCP stores only hashes of the tokens it issues.

Who signs in: the identity provider
On a server you build, OAuth 2.0 is a broker. Users sign in at an identity provider you choose, such as Google or GitHub, and GetMCP issues its own token after they approve. You fill in the provider’s Authorize URL, Token URL, Client ID, Client Secret and optional Default Scopes, and register the Authorized Redirect URI the tab shows, which ends in /oauth/callback.
All four of the URL and client fields are required. Without them the tab shows “No identity provider configured” and clients cannot authorize.
If you want people to sign in with their accounts on your own site instead, use the MCP Gateway. Its OAuth is built in: the person approves a consent screen while signed in to your dashboard, and their account must be allowed to manage GetMCP servers. GetMCP re-checks that permission on every call, so removing it cuts off access on the next request.
API keys for scripts and agents
OAuth needs a browser. For a cron job, a CI pipeline or a server-side agent, use API Key mode with keys GetMCP issues. On WordPress you create them with WP-CLI:
wp getmcp keys create --name="Nightly report" --server=acme-crm --scopes=tools --expires_in_days=90
- The key starts with
getmcp_and is printed once. GetMCP keeps only a SHA-256 hash, so a lost key is replaced, not recovered. --scopeslimits a key totools,resourcesorprompts. A key without thepromptsscope gets a 403 onprompts/get. Leave it out for an unrestricted key.--expires_in_dayssets an expiry. Expired keys are refused with “API key has expired.”wp getmcp keys revoke <id>switches a key off and keeps the row for auditing;--harddeletes it.
The client sends the key in the header or query parameter set under Header / Param Name and Location; the default is X-API-Key in a header. Once a server has had a key issued, only issued keys are accepted, even after you revoke them all. Only hard-deleting every key returns the server to passthrough.
Use cases
Give a sales team Claude access with their Google accounts
Acme sets its CRM server to OAuth 2.0 with Google as the provider, and its Google consent screen limits who can sign in. Priya Sharma adds the server URL to Claude, approves the sign-in once and starts asking about deals.
Claude → 401 + discovery → Google sign-in → GetMCP token → CRM tools
Let a nightly job call MCP tools without a browser
A reporting script needs tools/call and nothing else. Issue it a key scoped to tools with a 90-day expiry, and rotate it on schedule.
Cron → X-API-Key → GetMCP (hash match, scope check) → tools
Publish a server for SaaS customers who already have tokens
Northwind’s customers each hold a personal API token. Setting Client Authentication to Bearer passes each token through, so the Northwind API applies that customer’s own permissions.
Customer's Cursor (Bearer) → GetMCP (passthrough) → Northwind API
Let internal staff sign in with their site accounts
An operations team wants every internal server behind one sign-in. They switch on the Gateway with OAuth, so staff approve access with the dashboard accounts they already have.
VS Code → Gateway OAuth (site account) → every published server
Keep a demo server open, but only to read
A marketing team wants prospects to try a public product-catalogue server without signing up. Client Authentication stays on None, and the server only has lookup tools.
Any client → GetMCP (no auth) → read-only tools
Separate read and write access by server
Support agents should look up orders; only team leads may refund them. Build two servers, one with lookup tools and one with write tools, and give each its own authentication.
Agents → read server · Leads → write server (OAuth)
Tips and gotchas
- OAuth needs a public address. An authorization server on
.local,.testorlocalhostcan’t be reached by providers or cloud clients. Behind a tunnel or reverse proxy, set theGETMCP_PUBLIC_URLconstant inwp-config.php; there is deliberately no admin field for it. - Pretty permalinks are required. MCP and OAuth endpoints are rewrite rules.
- A stored server credential closes passthrough. If the server has a server-stored API credential, Bearer and Basic clients are refused, because their credential would no longer be what reaches your API.
- Registration is rate-limited. Open registration accepts five registrations per minute per IP for each server by default.
- Cross-origin browser calls are refused by default. With CORS Origins empty, only your site’s own origin is allowed. List exact origins in Settings, or enter
*for local testing only. - Claude’s Connector only does OAuth or no auth. Header-based modes use the config-file method instead.
Related features
- MCP server authentication: the credential GetMCP sends to your API.
- MCP Gateway: one endpoint for every server, with built-in sign-in.
- Connecting clients: what each client needs for each mode.
- MCP authentication explained: a plain-language primer on keys, tokens and OAuth 2.1.
FAQ
Does GetMCP support OAuth 2.1 for MCP servers?
Yes. A server set to OAuth 2.0 runs the authorization-code flow with PKCE (S256 only), exact redirect-URI matching, resource binding, dynamic client registration and authorization server metadata, as the MCP authorization spec describes. OAuth availability depends on your plan; see pricing.
Do my users need to copy a client ID or secret?
No. Clients that follow the MCP spec register themselves and receive a public client ID. Your users paste the server URL and approve a sign-in in their browser.
How long do MCP OAuth tokens last?
Access tokens GetMCP issues last one hour and refresh tokens 30 days. Each token works only on the server it was issued for. A refresh token cannot be moved to a different server.
Can people sign in with their WordPress accounts?
Yes, through the MCP Gateway, whose OAuth uses your site’s own accounts. A server you build uses OAuth with an external identity provider instead. For site-account sign-in, set that server to API Key or None and publish it through the Gateway.
Pick the mode that matches who your callers are, and GetMCP enforces it before any tool runs. Read more about how GetMCP protects your endpoints on the security page.
Ship an MCP server for your product this week.
Install GetMCP on any PHP host, import your API and share one URL. Your users can call your tools from Claude tonight.