When no human is present to approve access in a browser, the **OAuth Client Credentials** MCP authorization extension covers machine-to-machine access. The extension text itself defines "OAuth 2.1 Client Credentials flow support for the Model Context Protocol, enabling machine-to-machine authentication without user interaction." It is an **OPTIONAL** extension (Protocol Revision: draft) in the ext-auth repository—not part of the core authorization page. Clients and servers must opt in; extensions are never active by default. The interactive user flow (authorization code + PKCE) stays on the core MCP authorization spec.
Who this is for
You need a CI job, backend worker, or scheduled service to call a remote MCP server, and there is no user available to complete a login redirect.
Extension vs core auth
| Piece | What it is | When it fits |
|---|---|---|
| Core MCP authorization (spec 2026-07-28) | Authorization so clients can call restricted servers on behalf of resource owners, with a browser grant in the happy path | A human should approve access |
| OAuth Client Credentials extension | Machine-to-machine grant with pre-registered credentials; no user interaction | CI, daemons, server-to-server |
| Static `CLIENT_ID` in Cursor `mcp.json` | Fixed client for the user OAuth Connect path when DCR isn't available | Interactive Cursor Connect, not this extension |
The core Authorization introduction says MCP authorization enables clients to make requests "on behalf of resource owners." The client-credentials extension builds on that baseline for cases with no resource owner in the loop. Implementations that adopt the extension "MUST also conform to the baseline authorization requirements," so Protected Resource Metadata discovery and the 401 `WWW-Authenticate` challenge still apply. See Protected Resource Metadata in plain English and the MCP OAuth pillar for Cursor and Claude Connect.
How the machine flow works
Per the extension:
- The client hits the MCP server without a token and gets 401 with `WWW-Authenticate` pointing at resource metadata.
- It discovers the authorization server the same way the core flow does.
- It requests a token with pre-registered credentials—no Dynamic Client Registration in this flow.
- It sends `Authorization: Bearer <access_token>` on MCP HTTP requests.
Client authentication is one of two methods the extension allows: a signed JWT assertion (RFC 7523), which the extension marks RECOMMENDED, or a client secret in the token request body. Prefer JWT when you can avoid shipping a long-lived secret. Store secrets outside the repo; rotate on a schedule you own.
The extension "is specifically designed for HTTP-based transports." For local stdio servers, credentials usually come from the environment instead of this grant.
Cursor static OAuth is not this extension
Cursor's MCP docs let you put an `auth` object with `CLIENT_ID`, optional `CLIENT_SECRET`, and optional `scopes` on a remote server entry. That is static client registration for the interactive Connect path when the provider doesn't support Dynamic Client Registration. Cursor's protocol/extension support table lists Apps among supported extensions; it does not list the client-credentials extension. Do not treat a static `CLIENT_ID` in `mcp.json` as proof that Cursor runs the machine-to-machine grant. For the static-ID pattern itself, see static CLIENT_ID in mcp.json.
Pitfalls
- Calling client credentials "core MCP auth." It is an OPTIONAL authorization extension (draft). Quote the extension or narrow the claim.
- Assuming every MCP client supports it. Extension support varies; check your client and server before designing around it.
- Skipping the 401 + PRM path. Adopters still follow baseline authorization: challenge, metadata, then token.
- Confusing static Connect credentials with client credentials. Same words; different flows.
- Putting secrets in the repo. The marketing extension page warns that leaked client secrets authenticate as your app until rotated.
How to check it
- Confirm your authorization server advertises client-credentials support in its metadata (`token_endpoint_auth_methods_supported` includes at least one of `private_key_jwt` or `client_secret_basic`, per the extension).
- Prove the unauthenticated MCP URL still returns 401 with `resource_metadata` (same failure-card order as WWW-Authenticate stripped).
- Obtain a token with the client-credentials grant against that authorization server, then call the MCP URL with the bearer token.
- Confirm the client you will run in production declares the extension; if it doesn't, this flow will not appear in Connect UI.
Where the kit fits
The MCP Starter Kit ($27) is aimed at shipping remote MCP with OAuth-ready layout for Connect-style clients. Soft path if you're not buying yet: /free. Cheat Sheet for the skim checklist mindset.
Soft next step
Map whether your caller is a human Connect client or a headless service. If it's headless, verify extension support on both sides, then prove 401 → PRM → client-credentials token → bearer MCP call. Soft ladder: /free, then the MCP Starter Kit ($27). Related: MCP OAuth for Cursor and Claude Connect, static CLIENT_ID, PRM plain English, MCP auth checklist.