Deploy MCP servers to Vercel

Deploy MCP servers to Vercel

Deploy your Model Context Protocol (MCP) servers on Vercel to take advantage of features like Vercel Functions, OAuth, and efficient scaling for AI applications.

Deploy a Template


HyperFrames on Vercel
Preview HTML video compositions in the browser and render MP4s server-side on Vercel Sandbox.](/content/templates/next.js/hyperframes-on-vercel/index.html)


ChatGPT app with Next.js \ Ship a ChatGPT app on Vercel with Next.js and Model Context Protocol (MCP).](/content/templates/next.js/chatgpt-app-with-next-js/index.html)


x402 AI Starter
A fullstack template for using x402 with MCP and AI SDK.](/content/templates/next.js/x402-ai-starter/index.html)

Deploy MCP servers efficiently

Vercel provides the following features for production MCP deployments:

Deploy an MCP server on Vercel

Use mcp-handler to create an MCP server in an existing Next.js App Router application. You'll need Node.js 20 or later.

Install mcp-handler v2, the MCP server SDK v2, and Zod v4:

pnpm i mcp-handler@2.1.1 @modelcontextprotocol/server@2 zod@4
yarn add mcp-handler@2.1.1 @modelcontextprotocol/server@2 zod@4
npm i mcp-handler@2.1.1 @modelcontextprotocol/server@2 zod@4
bun add mcp-handler@2.1.1 @modelcontextprotocol/server@2 zod@4

Create a route that exposes a tool for rolling an N-sided die:

app/api/mcp/route.ts

import { createMcpHandler } from 'mcp-handler';
import { z } from 'zod';

const handler = createMcpHandler((server) => {
  server.registerTool(
    'roll_dice',
    {
      description: 'Roll an N-sided die',
      inputSchema: z.object({ sides: z.number().int().min(2) }),
    },
    async ({ sides }) => {
      const value = 1 + Math.floor(Math.random() * sides);
      return {
        content: [{ type: 'text', text: `🎲 You rolled a ${value}!` }],
      };
    },
  );
});

export { handler as GET, handler as POST };

Clients connect to /api/mcp using Streamable HTTP. Your framework determines the route, so you don't need to configure a base path in mcp-handler.

Version 2 of mcp-handler uses @modelcontextprotocol/server instead of @modelcontextprotocol/sdk, changes tool registration, and removes legacy HTTP+SSE transport and Redis configuration. Follow the migration guide to update an existing server.

Test the MCP server locally

Start your Next.js development server at http://localhost:3000 before opening the MCP Inspector.

  1. Run the MCP inspector:
pnpm dlx @modelcontextprotocol/inspector@latest
yarn dlx @modelcontextprotocol/inspector@latest
npx @modelcontextprotocol/inspector@latest
bunx @modelcontextprotocol/inspector@latest
  1. Open the inspector interface:
    • Browse to http://127.0.0.1:6274 where the inspector runs by default
  2. Connect to your MCP server:
    • Select Streamable HTTP in the drop-down on the left
    • In the URL field, use http://localhost:3000/api/mcp
    • Expand Configuration
    • In the Proxy Session Token field, paste the token printed in the terminal where MCP Inspector is running
    • Click Connect
  3. Test the tools:
    • Click List Tools under Tools
    • Click on the roll_dice tool
    • Test it through the available options on the right of the tools section

When you deploy your application on Vercel, you will get a URL such as https://my-mcp-server.vercel.app.

Configure an MCP host

Using Cursor, add the URL of your MCP server to the configuration file in Streamable HTTP transport format.

cursor/mcp.json

{
  "mcpServers": {
    "server-name": {
      "url": "https://my-mcp-server.vercel.app/api/mcp"
    }
  }
}

You can now use your MCP roll dice tool in Cursor's AI chat or any other MCP client.

To call the same tool from your own application, follow the AI SDK or TanStack AI example. Explore MCP integrations for connection and authentication options, including eve.

Enabling authorization

mcp-handler includes helpers for verifying bearer tokens and publishing OAuth protected resource metadata. You provide an authorization server and the logic that validates its tokens. The package does not issue tokens or run an authorization server.

Secure your server with OAuth

Wrap your MCP handler with withMcpAuth and set required: true to require a valid token. Return the verified client's identity and scopes from verifyToken.

The following example uses a token from the MCP_DEMO_TOKEN environment variable for local testing. Set that variable in .env.local before starting your development server. For production, replace the comparison with your authorization server's token verification, including issuer, audience, expiration, and granted scopes.

Replace your MCP route with the following code:

app/api/mcp/route.ts

import type { AuthInfo } from '@modelcontextprotocol/server';
import { createMcpHandler, withMcpAuth } from 'mcp-handler';
import { z } from 'zod';

const verifyToken = async (
  _req: Request,
  bearerToken?: string,
): Promise<AuthInfo | undefined> => {
  if (!bearerToken || bearerToken !== process.env.MCP_DEMO_TOKEN) {
    return undefined;
  }

return {
    token: bearerToken,
    scopes: ['read:dice'],
    clientId: 'demo-client',
  };
};

const authHandler = withMcpAuth(handler, verifyToken, {
  required: true,
  requiredScopes: ['read:dice'],
  resourceMetadataPath: '/.well-known/oauth-protected-resource',
});

export { authHandler as GET, authHandler as POST };

With this configuration, requests without a valid token receive 401. If a verified token lacks a required scope, the handler returns 403.

Expose OAuth metadata endpoint

To comply with the MCP specification, your server must expose a metadata endpoint that provides OAuth configuration details.

How to add OAuth metadata endpoint

  1. In your app/ directory, create a .well-known folder.
  2. Inside this directory, create a subdirectory called oauth-protected-resource.
  3. In this subdirectory, create a route.ts or route.js file with the following code.
  4. Replace the https://example-authorization-server-issuer.com URL with your own Authorization Server (AS) Issuer URL.
  5. Set resourceUrl to the public URL of your MCP route, including /api/mcp.

app/.well-known/oauth-protected-resource/route.ts

import {
  protectedResourceHandler,
  metadataCorsOptionsRequestHandler,
} from 'mcp-handler';

const handler = protectedResourceHandler({
  authServerUrls: ['https://example-authorization-server-issuer.com'],
  resourceUrl: 'https://my-mcp-server.vercel.app/api/mcp',
});

const corsHandler = metadataCorsOptionsRequestHandler();

export { handler as GET, corsHandler as OPTIONS };

To view the full list of values available to be returned in the OAuth Protected Resource Metadata JSON, see the protected resource metadata RFC.

MCP clients that are compliant with the latest version of the MCP spec can now securely connect and invoke tools defined in your MCP server, when provided with a valid OAuth token.