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.
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.
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