Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

README.md

Authenticated MCP Server

An MCP server protected by OAuth 2.1, using @cloudflare/workers-oauth-provider. Clients must complete the OAuth flow before calling tools — the auth context is then available inside tool handlers.

What it demonstrates

  • OAuth 2.1 with MCP — dynamic client registration, authorization code flow, and token exchange
  • OAuthProvider — wrapping createMcpHandler with @cloudflare/workers-oauth-provider
  • getMcpAuthContext() — accessing the authenticated user's identity inside tool handlers
  • Custom authorization UI — a Hono-based approval page for the OAuth flow

Running

First, create a KV namespace for OAuth state:

npx wrangler kv namespace create OAUTH_KV

Update the kv_namespaces binding in wrangler.jsonc with the returned ID, then:

npm install
npm run dev

Open the browser to see the server info page. To test the tools, use the MCP Inspector — it will handle the OAuth flow automatically.

How it works

The OAuthProvider wraps the entire Worker. It intercepts OAuth endpoints (/authorize, /oauth/token, /oauth/register) and validates Bearer tokens on the API route (/mcp).

import { OAuthProvider } from "@cloudflare/workers-oauth-provider";
import { createMcpHandler, getMcpAuthContext } from "agents/mcp";

const apiHandler = {
  async fetch(request, env, ctx) {
    const server = createServer();
    return createMcpHandler(server)(request, env, ctx);
  }
};

export default new OAuthProvider({
  authorizeEndpoint: "/authorize",
  tokenEndpoint: "/oauth/token",
  clientRegistrationEndpoint: "/oauth/register",
  apiRoute: "/mcp",
  apiHandler,
  defaultHandler: { fetch: (req, env, ctx) => AuthHandler.fetch(req, env, ctx) }
});

Inside tool handlers, access the authenticated user:

server.registerTool("whoami", { description: "Who am I?" }, async () => {
  const auth = getMcpAuthContext();
  return {
    content: [{ type: "text", text: JSON.stringify(auth?.props) }]
  };
});

Related examples

  • mcp-worker — same stateless pattern without authentication
  • mcp-client — connecting to authenticated MCP servers as a client (handles OAuth automatically)