MCP OAuth: Secure Your MCP Endpoint with OAuth 2.1 and API Keys

GetMCP MCP OAuth: an AI client receives a 401 challenge, discovers the OAuth metadata, signs in through the browser and uses the issued token to call tools.

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 TypeWhat the client must sendWho validates it
NoneNothing. The endpoint is public.No one
OAuth 2.0An access token from GetMCP’s OAuth flowGetMCP
API KeyA key in the header or query parameter you nameGetMCP, once you issue keys; otherwise your API
Bearer TokenAuthorization: Bearer …Your API (passthrough)
Basic AuthAuthorization: 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.

  1. Challenge. A request without a valid token gets HTTP 401 with WWW-Authenticate: Bearer resource_metadata="…/.well-known/oauth-protected-resource".
  2. 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.
  3. 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.
  4. Sign-in. The client opens /oauth/authorize with a PKCE challenge. Only S256 is accepted, and the redirect URI must exactly match one the client registered.
  5. Token. The client exchanges the code at /oauth/token and 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.

GetMCP server Authentication tab with Client Authentication set to OAuth 2.0, showing the Authorized Redirect URI ending in /oauth/callback and the Authorize URL, Token URL, Client ID, Client Secret and Default Scopes fields.
Client Authentication set to OAuth 2.0, with the redirect URI to register and the identity provider fields.

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.
  • --scopes limits a key to tools, resources or prompts. A key without the prompts scope gets a 403 on prompts/get. Leave it out for an unrestricted key.
  • --expires_in_days sets 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; --hard deletes 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, .test or localhost can’t be reached by providers or cloud clients. Behind a tunnel or reverse proxy, set the GETMCP_PUBLIC_URL constant in wp-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

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.

InfiWebs
All posts

Leave a reply

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.