Currently Available: Need a skilled Software Developer for your next project?
Categories
Coding Agents

How to Add OAuth Authorization to a Remote MCP Server

A remote Model Context Protocol (MCP) server receives network requests from MCP clients and provides tools or other data. OAuth lets an authorization server, such as an identity provider, issue access tokens after authenticating a user or client. An access token is a credential the MCP server checks before handling a request. The server then decides whether the token grants access.

To set this up, give the MCP resource a stable HTTPS address and publish metadata that tells clients where to get authorization. Check each token before the request reaches an MCP handler, then enforce permissions for protected operations. The MCP server protects access to the resource; it does not need to handle user login or issue tokens. The current MCP authorization specification describes this approach.

Choose a stable resource address

Choose a fixed resource URI, the address clients use to identify the MCP server they are contacting. For example, a server might use https://api.example.com/mcp. Configure this value directly rather than deriving it from the incoming request’s Host header. Request-controlled host data could cause the server to validate a token against an unintended resource address.

The authorization server must issue tokens intended for that URI. This intended recipient is called the token’s audience. A token can be valid and still be wrong for the MCP server if it was issued for another API. If one host serves multiple MCP resources, choose an address that distinguishes each resource.

Configure the authorization server

Use an existing identity provider or authorization server to authenticate users or clients and issue access tokens. Configure it with the MCP resource’s audience and the permissions the server will enforce. A scope is a named permission, such as read or write access.

The MCP server also needs a way to verify tokens. Some authorization servers issue signed JSON Web Tokens (JWTs), which the server can check using trusted signing keys. Others issue opaque tokens, which the server must check by asking the provider’s token-introspection service whether they are valid. The MCP TypeScript SDK authorization guide describes both local verification and introspection patterns. Use the approach supported by your provider and SDK version.

Publish metadata for client discovery

Publish a Protected Resource Metadata (PRM) document. This small document identifies the protected resource and names at least one authorization server that protects it. Clients use the document to find where to start OAuth authorization.

For a resource at https://api.example.com/mcp, a path-aware metadata address could be:

https://api.example.com/.well-known/oauth-protected-resource/mcp

An example document is:

{
  "resource": "https://api.example.com/mcp",
  "authorization_servers": ["https://auth.example.com"],
  "scopes_supported": ["mcp:read", "mcp:write"]
}

The resource URI, authorization server issuer, token audience, and verifier settings must agree. Confirm the metadata route your server actually publishes; SDKs and web frameworks do not necessarily mount it in the same place.

Challenge requests and verify tokens before handling them

Place token verification in middleware or an equivalent request gate before the MCP handler. When a client sends a request without a token, or sends an invalid or expired token, return 401 Unauthorized with a bearer challenge that points to the PRM document:

WWW-Authenticate: Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource/mcp"

The client can use that address to discover the authorization server, obtain a token, and retry the request with the token in an HTTP Authorization: Bearer header. The MCP authorization specification defines this discovery flow.

For each token, check that it comes from a trusted issuer, remains valid, and targets the MCP resource. Then check whether it grants the required permission. A valid token without the scope needed for a request should receive 403 Forbidden with an insufficient_scope challenge. A broad baseline scope can protect every MCP request, while a server can require additional scopes for sensitive tools or operations.

Keep credentials within their intended boundary

Require clients to send bearer tokens in the Authorization header. Do not put tokens in URL query strings, where URLs can be copied or recorded. Avoid logging tokens, and do not forward an MCP access token to a separate downstream API unless that API explicitly accepts it. The audience check exists to keep a token limited to its intended resource; downstream access needs credentials accepted by that service.

When choosing client registration behavior, follow the current MCP specification and the client and authorization-server capabilities. The specification prefers Client ID Metadata Documents (CIMD), in which a client identifies itself through a metadata document. Dynamic Client Registration (DCR), which lets a client register with an authorization server at runtime, remains for compatibility but is deprecated. Older examples may describe DCR as the default, so check that an example matches the specification and SDK version you deploy. The 2026-07-28 release notes describe this change.

Test both access and rejection

Test the full request path, including the response headers and whether requests reach the MCP handler. Confirm that an unauthenticated request receives 401 and a discoverable challenge, and that a valid token for the configured resource reaches the handler. Then test a token issued for a different resource and a token that lacks a required scope. The first must fail resource validation; the second must receive 403 insufficient_scope.

Use the authorization helper and middleware documented for your installed SDK version. SDK examples show an implementation pattern, but the exact routes and configuration depend on that version and your hosting setup.

What I'm building

Delegate tasks. Get software.

Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.

Take a look at vroni.com

Email updates

Usually a new article and a few links I found interesting.

No spam. Unsubscribe with one click.

Leave a Reply

Your email address will not be published. Required fields are marked *