diff --git a/.changeset/evil-things-check.md b/.changeset/evil-things-check.md index 541b341..fd82b78 100644 --- a/.changeset/evil-things-check.md +++ b/.changeset/evil-things-check.md @@ -1,5 +1,5 @@ --- -"@vercel/mcp-adapter": minor +"mcp-handler": minor --- Refactor packaging and make withMcpAuth stable diff --git a/.changeset/ripe-mails-doubt.md b/.changeset/ripe-mails-doubt.md index 8bf41d2..e893cf6 100644 --- a/.changeset/ripe-mails-doubt.md +++ b/.changeset/ripe-mails-doubt.md @@ -1,5 +1,5 @@ --- -"@vercel/mcp-adapter": minor +"mcp-handler": minor --- Add RFC 9728 OAuth Protected Resource Metadata handler diff --git a/.changeset/violet-squids-camp.md b/.changeset/violet-squids-camp.md new file mode 100644 index 0000000..6aa4140 --- /dev/null +++ b/.changeset/violet-squids-camp.md @@ -0,0 +1,5 @@ +--- +"mcp-handler": major +--- + +Move package from @vercle/mcp-adapter to mcp-handler diff --git a/CHANGELOG.md b/CHANGELOG.md index 42d6933..fe23a19 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# @vercel/mcp-adapter +# mcp-handler ## 0.11.2 diff --git a/README.md b/README.md index dd5620d..d56da64 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,24 @@ -# @vercel/mcp-adapter +# mcp-handler A Vercel adapter for the Model Context Protocol (MCP), enabling real-time communication between your applications and AI models. Currently supports Next.js with more framework adapters coming soon. ## Installation ```bash -npm install @vercel/mcp-adapter @modelcontextprotocol/sdk +npm install mcp-handler @modelcontextprotocol/sdk # or -yarn add @vercel/mcp-adapter @modelcontextprotocol/sdk +yarn add mcp-handler @modelcontextprotocol/sdk # or -pnpm add @vercel/mcp-adapter @modelcontextprotocol/sdk +pnpm add mcp-handler @modelcontextprotocol/sdk # or -bun add @vercel/mcp-adapter @modelcontextprotocol/sdk +bun add mcp-handler @modelcontextprotocol/sdk ``` ## Next.js Usage ```typescript // app/api/[transport]/route.ts -import { createMcpHandler } from "@vercel/mcp-adapter"; +import { createMcpHandler } from "mcp-handler"; const handler = createMcpHandler( (server) => { server.tool( @@ -159,7 +159,7 @@ The MCP adapter supports the [MCP Authorization Specification](https://modelcont ```typescript // app/api/[transport]/route.ts -import { createMcpHandler, withMcpAuth } from "@vercel/mcp-adapter"; +import { createMcpHandler, withMcpAuth } from "mcp-handler"; // Create your handler as normal const handler = createMcpHandler( @@ -235,7 +235,7 @@ Create a new file at `app/.well-known/oauth-protected-resource/route.ts`: import { protectedResourceHandler, metadataCorsOptionsRequestHandler, -} from "@vercel/mcp-adapter"; +} from "mcp-handler"; const handler = protectedResourceHandler({ // Specify the Issuer URL of the associated Authorization Server diff --git a/examples/auth/route.ts b/examples/auth/route.ts index a0b6a77..5908664 100644 --- a/examples/auth/route.ts +++ b/examples/auth/route.ts @@ -1,22 +1,29 @@ import { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types"; -import { createMcpHandler, experimental_withMcpAuth as withMcpAuth } from "@vercel/mcp-adapter"; +import { + createMcpHandler, + experimental_withMcpAuth as withMcpAuth, +} from "mcp-handler"; import { z } from "zod"; // Define the handler with proper parameter validation const handler = createMcpHandler( - server => { + (server) => { server.tool( - 'echo', - 'Echo a message back with authentication info', + "echo", + "Echo a message back with authentication info", { - message: z.string().describe('The message to echo back') + message: z.string().describe("The message to echo back"), }, async ({ message }, extra) => { return { content: [ { - type: 'text', - text: `Echo: ${message}${extra.authInfo?.token ? ` (from ${extra.authInfo.clientId})` : ''}`, + type: "text", + text: `Echo: ${message}${ + extra.authInfo?.token + ? ` (from ${extra.authInfo.clientId})` + : "" + }`, }, ], }; @@ -27,17 +34,17 @@ const handler = createMcpHandler( { capabilities: { auth: { - type: 'bearer', + type: "bearer", required: true, }, }, }, // Route configuration { - streamableHttpEndpoint: '/mcp', - sseEndpoint: '/sse', - sseMessageEndpoint: '/message', - basePath: '/api/mcp', + streamableHttpEndpoint: "/mcp", + sseEndpoint: "/sse", + sseMessageEndpoint: "/message", + basePath: "/api/mcp", redisUrl: process.env.REDIS_URL, } ); @@ -46,38 +53,37 @@ const handler = createMcpHandler( * Verify the bearer token and return auth information * In a real implementation, this would validate against your auth service */ -const verifyToken = async (req: Request, bearerToken?: string): Promise => { - if (!bearerToken) return undefined; - - // TODO: Replace with actual token verification logic - // This is just an example implementation - const isValid = bearerToken.startsWith('__TEST_VALUE__'); - - if (!isValid) return undefined; - - return { - token: bearerToken, - scopes: ['read:messages', 'write:messages'], - clientId: 'example-client', - extra: { - userId: 'user-123', - // Add any additional user/client information here - permissions: ['user'], - timestamp: new Date().toISOString() - } - }; -} +const verifyToken = async ( + req: Request, + bearerToken?: string +): Promise => { + if (!bearerToken) return undefined; + + // TODO: Replace with actual token verification logic + // This is just an example implementation + const isValid = bearerToken.startsWith("__TEST_VALUE__"); + + if (!isValid) return undefined; + + return { + token: bearerToken, + scopes: ["read:messages", "write:messages"], + clientId: "example-client", + extra: { + userId: "user-123", + // Add any additional user/client information here + permissions: ["user"], + timestamp: new Date().toISOString(), + }, + }; +}; // Create the auth handler with required scopes -const authHandler = withMcpAuth( - handler, - verifyToken, - { - required: true, - requiredScopes: ['read:messages'], - resourceMetadataPath: '/.well-known/oauth-protected-resource' - } -); +const authHandler = withMcpAuth(handler, verifyToken, { + required: true, + requiredScopes: ["read:messages"], + resourceMetadataPath: "/.well-known/oauth-protected-resource", +}); // Export the handler for both GET and POST methods export { authHandler as GET, authHandler as POST }; diff --git a/package.json b/package.json index 08836d5..dca1263 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "@vercel/mcp-adapter", + "name": "mcp-handler", "version": "0.11.2", "description": "Vercel MCP Adapter for Next.js and other frameworks", "main": "dist/index.js", @@ -7,6 +7,7 @@ "type": "commonjs", "bin": { "create-mcp-route": "./dist/cli/index.js", + "mcp-handler": "./dist/cli/index.js", "@vercel/mcp-adapter": "./dist/cli/index.js" }, "exports": { diff --git a/src/cli/index.ts b/src/cli/index.ts index 22c068f..e3d27ca 100644 --- a/src/cli/index.ts +++ b/src/cli/index.ts @@ -7,7 +7,7 @@ import chalk from "chalk"; const program = new Command(); -const ROUTE_TEMPLATE = `import { createMcpHandler } from '@vercel/mcp-adapter'; +const ROUTE_TEMPLATE = `import { createMcpHandler } from 'mcp-handler'; import { z } from 'zod'; const handler = createMcpHandler( @@ -66,7 +66,7 @@ async function installDependencies( packageManager: "npm" | "pnpm" | "yarn" | "bun" ) { const execSync = (await import("node:child_process")).execSync; - const dependencies = ["@vercel/mcp-adapter", "zod"]; + const dependencies = ["mcp-handler", "zod"]; const commands = { npm: `npm install ${dependencies.join(" ")}`, @@ -125,7 +125,7 @@ async function init() { } program - .name("@vercel/mcp-adapter") + .name("mcp-handler") .description("Initialize MCP route handler in your Next.js project") .action(init);