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.

WorkOS uses Dynamic Client Registration (DCR). MCP clients discover WorkOS’s OAuth endpoints via .well-known passthrough and register themselves directly with WorkOS. Your server only verifies the resulting tokens.

Setup

1. Create a WorkOS account

Sign up at the WorkOS Dashboard and create a project.

2. Enable Dynamic Client Registration

In the WorkOS Dashboard, go to Connect → Configuration and enable Dynamic Client Registration.

3. Configure redirect URIs

Go to Configuration → Redirects and add your redirect URI:
http://localhost:3000/callback

4. Environment variables

MCP_USE_OAUTH_WORKOS_SUBDOMAIN=your-company.authkit.app  # Full AuthKit domain

Configuration

import { MCPServer, oauthWorkOSProvider } from 'mcp-use/server'

// Zero-config: reads MCP_USE_OAUTH_WORKOS_SUBDOMAIN
const server = new MCPServer({
  name: 'my-server',
  version: '1.0.0',
  oauth: oauthWorkOSProvider()
})

await server.listen(3000)
Or pass config explicitly:
oauth: oauthWorkOSProvider({
  subdomain: 'your-company.authkit.app',

  // Disable JWT verification during development only
  verifyJwt: process.env.NODE_ENV === 'production',

  // Override advertised scopes
  // Default: ['email', 'offline_access', 'openid', 'profile']
  scopesSupported: ['email', 'offline_access', 'openid', 'profile'],
})
If you need to call the WorkOS Management API from your tool handlers, store your API key in any env var you like (e.g. WORKOS_API_KEY) and read it inside the tool — it isn’t part of the OAuth provider config.

Accessing user info in tools

WorkOS provides standard OIDC claims plus organization context:
server.tool(
  {
    name: 'get-profile',
    description: 'Get authenticated user profile',
  },
  async (_args, ctx) => ({
    userId: ctx.auth.user.userId,
    email: ctx.auth.user.email,
    name: ctx.auth.user.name,
    organizationId: ctx.auth.user.organization_id,
    roles: ctx.auth.user.roles,
    scopes: ctx.auth.scopes,
  })
)

Multi-tenant filtering

Use ctx.auth.user.organization_id to scope data to the authenticated user’s organization:
server.tool(
  {
    name: 'get-documents',
    description: 'Get documents for the authenticated organization',
  },
  async (_args, ctx) => {
    // Custom claims come back as `unknown` — narrow before use
    const orgId = ctx.auth.user.organization_id as string | undefined

    if (!orgId) {
      return { content: [{ type: 'text', text: 'Organization context required' }], isError: true }
    }

    const documents = await db.documents.findMany({
      where: { organizationId: orgId }
    })

    return { content: [{ type: 'text', text: JSON.stringify(documents) }] }
  }
)

Resources

Next Steps