Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Comprehensive guide for building production-ready MCP servers with tools, resources, prompts, and React widgets using mcp-use.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/authentication/workos.md
1# WorkOS Authentication23Setting up OAuth with WorkOS AuthKit. DCR mode only — MCP clients register themselves directly with WorkOS; the MCP server just verifies the resulting tokens.45**Learn more:** [WorkOS AuthKit MCP docs](https://workos.com/docs/authkit/mcp) · [Standalone starter template](https://github.com/mcp-use/mcp-oauth-workos-template) · [Runnable example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/mcp-use/examples/server/oauth/workos)67---89## Quick Start1011```typescript12import { MCPServer, oauthWorkOSProvider, object } from "mcp-use/server";1314const server = new MCPServer({15name: "my-server",16version: "1.0.0",17oauth: oauthWorkOSProvider(),18});1920server.tool(21{ name: "whoami", description: "Get authenticated user info" },22async (_args, ctx) =>23object({24userId: ctx.auth.user.userId,25email: ctx.auth.user.email,26name: ctx.auth.user.name,27})28);2930server.listen();31```3233With a `.env` file:3435```bash36MCP_USE_OAUTH_WORKOS_SUBDOMAIN=your-company.authkit.app37```3839That's it. JWT verification, OAuth discovery, and `.well-known` passthrough are handled automatically.4041---4243## Setup44451. Sign up at the [WorkOS Dashboard](https://dashboard.workos.com/) and create a project.462. **Connect → Configuration** — enable **Dynamic Client Registration**.473. **Configuration → Redirects** — add your MCP client redirect URI (e.g. `http://localhost:3000/callback`).484. Copy the full AuthKit domain from **Domains → AuthKit Domain** (e.g. `your-company.authkit.app` — including `.authkit.app`, not just `your-company`).4950---5152## Environment Variables5354| Variable | Required | Description |55|----------|----------|-------------|56| `MCP_USE_OAUTH_WORKOS_SUBDOMAIN` | Yes | Full AuthKit domain (e.g. `my-company.authkit.app`) |5758> If you also need to call the WorkOS Management API from a tool handler, store the API key in any env var you like (e.g. `WORKOS_API_KEY`) and read it inside the tool. It's **not** part of the OAuth provider config anymore.5960---6162## Configuration Options6364Zero-config (reads from env vars):6566```typescript67oauth: oauthWorkOSProvider()68```6970Explicit config (overrides env vars):7172```typescript73oauth: oauthWorkOSProvider({74subdomain: "my-company.authkit.app",75verifyJwt: process.env.NODE_ENV === "production", // default: true76scopesSupported: ["email", "offline_access", "openid", "profile"], // override advertised scopes77})78```7980| Option | Type | Default | Description |81|--------|------|---------|-------------|82| `subdomain` | `string` | env var | Full AuthKit domain (e.g., `my-company.authkit.app`) |83| `verifyJwt` | `boolean?` | `true` | Set `false` to skip JWT verification (**development only**) |84| `scopesSupported` | `string[]?` | `["email", "offline_access", "openid", "profile"]` | Override advertised scopes |8586---8788## User Context8990WorkOS populates these fields on `ctx.auth.user`:9192| Field | Type | Source |93|-------|------|--------|94| `userId` | `string` | `sub` claim |95| `email` | `string?` | `email` claim |96| `name` | `string?` | `name` claim |97| `username` | `string?` | `preferred_username` claim |98| `picture` | `string?` | `picture` claim |99| `roles` | `string[]?` | `roles` claim |100| `permissions` | `string[]?` | `permissions` claim |101| `email_verified` | `boolean?` | `email_verified` claim |102| `organization_id` | `string?` | `org_id` claim — multi-tenant org ID |103| `sid` | `string?` | Session ID |104105### Role-Based Access106107```typescript108server.tool(109{ name: "admin-action", description: "Admin-only operation" },110async (_args, ctx) => {111if (!ctx.auth.user.roles?.includes("admin")) {112return error("Forbidden: admin role required");113}114115// ... admin logic116return text("Done");117}118);119```120121### Multi-Tenant Filtering122123Scope queries to the authenticated user's organization:124125```typescript126server.tool(127{ name: "get-documents", description: "Get documents for the authenticated org" },128async (_args, ctx) => {129// Custom claims come back as `unknown` — narrow before use130const orgId = ctx.auth.user.organization_id as string | undefined;131if (!orgId) return error("Organization context required");132133const documents = await db.documents.findMany({134where: { organizationId: orgId },135});136137return object(documents);138}139);140```141142---143144## Making WorkOS API Calls145146Use a WorkOS API key (not the user's access token) for management API calls:147148```typescript149const WORKOS_API_KEY = process.env.WORKOS_API_KEY;150151server.tool(152{ name: "get-workos-user", description: "Fetch user profile from WorkOS" },153async (_args, ctx) => {154if (!WORKOS_API_KEY) return error("WorkOS API key not configured");155156const res = await fetch(157`https://api.workos.com/user_management/users/${ctx.auth.user.userId}`,158{159headers: {160Authorization: `Bearer ${WORKOS_API_KEY}`,161"Content-Type": "application/json",162},163}164);165166if (!res.ok) return error(`WorkOS API failed: ${res.status}`);167return object(await res.json());168}169);170```171172---173174## Example `.env`175176```bash177# Required: Full AuthKit domain (WorkOS Dashboard → Domains → AuthKit Domain)178MCP_USE_OAUTH_WORKOS_SUBDOMAIN=my-company.authkit.app179180# Optional: WorkOS API key if you call the Management API from tools181WORKOS_API_KEY=sk_test_...182```183184---185186## Troubleshooting187188### Redirect URI Mismatch189190If you get a redirect URI error during OAuth, add your client's callback URL to WorkOS:1911921. WorkOS Dashboard → **Developer** → **Redirects**1932. Click **Edit redirect URIs** and add the one the client expects (e.g. `http://localhost:3000/oauth/callback`).194195Changes may take a few minutes to propagate.196197### DCR Not Registering198199If the MCP Inspector stalls at the registration step, double-check that **Dynamic Client Registration** is enabled in WorkOS Dashboard → **Connect → Configuration**. Without DCR enabled, there's no pre-configured `client_id` for the Inspector to use.200201---202203## Next Steps204205- **Auth overview** → [overview.md](overview.md)206- **Supabase setup** → [supabase.md](supabase.md)207- **Auth0 setup** → [auth0.md](auth0.md)208- **Build tools** → [../server/tools.md](../server/tools.md)209