Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ server.tool("userData", {}, async (args, extra) => {

### How It Works

1. **Wrap your handler** with `experimental_withMcpAuth`:
1. **Wrap your handler** with `withMcpAuth`:
```typescript
const authHandler = experimental_withMcpAuth(handler, verifyToken, {
const authHandler = withMcpAuth(handler, verifyToken, {
required: false // ← Tools decide individually
});
```

2. **Verify tokens** with direct WorkOS calls:
1. **Verify tokens** with direct WorkOS calls:
```typescript
const verifyToken = async (req: Request, bearerToken?: string) => {
if (!bearerToken) return undefined; // Allow unauthenticated requests
Expand Down Expand Up @@ -60,7 +60,7 @@ That's it! Your MCP server now has enterprise authentication with zero global au

```typescript
// app/mcp/route.ts - Complete authenticated MCP server
import { createMcpHandler, experimental_withMcpAuth } from "@vercel/mcp-adapter";
import { createMcpHandler, withMcpAuth } from "@vercel/mcp-adapter";
import { jwtVerify } from "jose";
import { ensureUserAuthenticated, isAuthenticated } from "../../lib/auth/helpers";

Expand Down Expand Up @@ -103,7 +103,7 @@ const verifyToken = async (req: Request, bearerToken?: string) => {
};

// Authenticated handler
const authHandler = experimental_withMcpAuth(handler, verifyToken, { required: false });
const authHandler = withMcpAuth(handler, verifyToken, { required: false });

export { authHandler as GET, authHandler as POST };
```
Expand Down
4 changes: 2 additions & 2 deletions app/getting-started/steps/[step]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ WORKOS_REDIRECT_URI=http://localhost:3000/callback`,
E -->|No| F["✅ Execute Tool (ping)"]
E -->|Yes| G["❌ Throw Auth Error"]

B -->|Yes| H["🔐 experimental_withMcpAuth"]
B -->|Yes| H["🔐 withMcpAuth"]
H --> I["📋 Extract Bearer Token"]
I --> J["🔍 Verify JWT with WorkOS JWKS"]
J --> K{Valid JWT?}
Expand Down Expand Up @@ -220,7 +220,7 @@ const handler = createMcpHandler((server) => {
});

// 2. Add authentication wrapper (line ~37-80 in app/mcp/route.ts)
const authHandler = experimental_withMcpAuth(
const authHandler = withMcpAuth(
handler,
async (request, token) => {
// Verify JWT and get user from WorkOS
Expand Down
8 changes: 4 additions & 4 deletions app/mcp/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
*
* Key components:
* 1. createMcpHandler() - builds the MCP server with type-safe tools
* 2. experimental_withMcpAuth() - wraps with WorkOS authentication
* 2. withMcpAuth() - wraps with WorkOS authentication
* 3. Zero-config deployment to Vercel Edge
*/

import {
createMcpHandler,
experimental_withMcpAuth,
withMcpAuth,
} from '@vercel/mcp-adapter';
import { getWorkOS } from '@workos-inc/authkit-nextjs';
import { jwtVerify, createRemoteJWKSet } from 'jose';
Expand All @@ -40,8 +40,8 @@ const handler = createMcpHandler((server) => {

// 🔐 THE AUTHHANDLER PATTERN 🔐
// This is the magic: wrap any MCP server with enterprise authentication
// in just a few lines using experimental_withMcpAuth + WorkOS
const authHandler = experimental_withMcpAuth(
// in just a few lines using withMcpAuth + WorkOS
const authHandler = withMcpAuth(
handler,
async (request, token) => {
// If no token is provided, allow through for public tools (like ping)
Expand Down
4 changes: 2 additions & 2 deletions app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ const handler = createMcpHandler((server) => {
</div>
<div className="flex-1">
<h3 className="text-2xl font-bold text-gray-900 dark:text-white mb-4">
Wrap with `experimental_withMcpAuth`
Wrap with `withMcpAuth`
</h3>
<p className="text-gray-700 dark:text-neutral-300 mb-6 text-lg">
Transform your handler into an `authHandler` that
Expand Down Expand Up @@ -337,7 +337,7 @@ const handler = createMcpHandler((server) => {
>
{`// 🔐 THE AUTHHANDLER PATTERN 🔐
// Wrap your MCP handler with optional enterprise authentication
const authHandler = experimental_withMcpAuth(
const authHandler = withMcpAuth(
handler, // Your regular MCP handler from step 1
async (request, token) => {
// No token? Return undefined (allows public tools like ping)
Expand Down
2 changes: 1 addition & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ server.tool("userData", {}, async (args, extra) => {

### How It Works

1. **Wrap your handler** with `experimental_withMcpAuth`
1. **Wrap your handler** with `withMcpAuth`
2. **Verify JWT tokens** with WorkOS (automatic)
3. **Tools get user context** through our helper functions

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"@modelcontextprotocol/sdk": "^1.15.0",
"@tailwindcss/postcss": "^4.1.10",
"@types/react-syntax-highlighter": "^15.5.13",
"@vercel/mcp-adapter": "^0.11.2",
"@vercel/mcp-adapter": "^1.0.0",
"@workos-inc/authkit-nextjs": "^2.4.2",
"jose": "^6.0.11",
"mermaid": "^11.7.0",
Expand Down Expand Up @@ -54,5 +54,6 @@
},
"overrides": {
"prismjs": "1.30.0"
}
},
"packageManager": "[email protected]+sha512.5ea8b0deed94ed68691c9bad4c955492705c5eeb8a87ef86bc62c74a26b037b08ff9570f108b2e4dbd1dd1a9186fea925e527f141c648e85af45631074680184"
}
33 changes: 25 additions & 8 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.