Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.mcp-use.com/llms.txt

Use this file to discover all available pages before exploring further.

Use oauthCustomProvider when your identity provider supports Dynamic Client Registration (DCR) and advertises a registration_endpoint in its OAuth metadata. Clients will discover the endpoints and register themselves directly with the upstream — your server only verifies the resulting tokens.
If your provider doesn’t support DCR — Google, GitHub, Okta, Azure AD, or any provider where you register an app in a dashboard and receive a fixed clientId/clientSecret — use oauthProxy instead.

Quick start

import { MCPServer, oauthCustomProvider } from "mcp-use/server";
import { jwtVerify, createRemoteJWKSet } from "jose";

const JWKS = createRemoteJWKSet(
  new URL("https://auth.example.com/.well-known/jwks.json"),
);

const server = new MCPServer({
  name: "my-server",
  version: "1.0.0",
  oauth: oauthCustomProvider({
    issuer: "https://auth.example.com",
    authEndpoint: "https://auth.example.com/oauth/authorize",
    tokenEndpoint: "https://auth.example.com/oauth/token",

    async verifyToken(token: string) {
      const result = await jwtVerify(token, JWKS, {
        issuer: "https://auth.example.com",
        audience: "your-audience",
      });
      return { payload: result.payload as Record<string, unknown> };
    },

    getUserInfo(payload) {
      return {
        userId: payload.sub as string,
        email: payload.email as string | undefined,
        name: payload.name as string | undefined,
        roles: (payload.roles as string[]) || [],
      };
    },
  }),
});

await server.listen(3000);

All configuration options

oauthCustomProvider({
  // Required: OAuth endpoints
  issuer: "https://auth.example.com",
  authEndpoint: "https://auth.example.com/oauth/authorize",
  tokenEndpoint: "https://auth.example.com/oauth/token",

  // Required: Token verification — must return { payload: Record<string, unknown> }
  async verifyToken(token: string) {
    const { payload } = await jwtVerify(token, JWKS, { issuer: "..." });
    return { payload: payload as Record<string, unknown> };
  },

  // Optional: JWKS endpoint advertised in discovery metadata
  jwksUrl: "https://auth.example.com/.well-known/jwks.json",

  // Optional: User info endpoint URL
  userInfoEndpoint: "https://auth.example.com/userinfo",

  // Optional: Override advertised scopes
  scopesSupported: ["openid", "profile", "email"],

  // Optional: Override advertised grant types
  // Default: ['authorization_code', 'refresh_token']
  grantTypesSupported: ["authorization_code", "refresh_token"],

  // Optional: Audience for JWT verification
  audience: "your-api-identifier",

  // Optional: Custom user info extraction
  getUserInfo(payload) {
    return {
      userId: payload.sub as string,
      email: payload.email as string | undefined,
      name: payload.name as string | undefined,
    };
  },
});

Accessing user info in tools

server.tool(
  {
    name: "get-user-info",
    description: "Get authenticated user info",
  },
  async (_args, ctx) => ({
    userId: ctx.auth.user.userId,
    email: ctx.auth.user.email,
    name: ctx.auth.user.name,
    scopes: ctx.auth.scopes,
  }),
);

Resources

Next Steps