Skip to content

Using xmcp with Next.js

Add an MCP server to an existing Next.js app with xmcp. Create typed tools, add authentication, and deploy to Vercel as a Vercel Function.

5 min read
Last updated June 13, 2026

xmcp is a TypeScript-first framework for building MCP (Model Context Protocol) servers. It handles registering tools, prompts, and resources automatically, so you can focus on writing tool logic instead of protocol plumbing. With the Next.js adapter, you can add an MCP endpoint to an existing Next.js app and expose your application's functionality to AI agents and MCP clients. When you deploy to Vercel, the endpoint runs as a Vercel Function with Fluid compute by default, with no extra configuration.

In this guide, you'll add xmcp to an existing Next.js project and expose an MCP endpoint through a Next.js route handler. You'll create a tool with a typed schema and metadata, add authentication to your MCP server, then run the server locally and deploy it to Vercel.

Before you begin, make sure you have:

  • A Vercel account
  • Node.js 20+ and a package manager (e.g., npm)
  • An existing Next.js project using the App Router
  • Vercel CLI installed (npm i -g vercel)

xmcp discovers tools, prompts, and resources from dedicated directories in your project and compiles them into a generated .xmcp folder. The @xmcp/adapter package exposes this compiled server as a standard Next.js route handler, so MCP requests flow through your app like any other API route. Because the adapter runs inside Next.js, xmcp's own middleware.ts and xmcp/headers features are not supported. Next.js already provides equivalents, and on Vercel, you can also use Routing Middleware to run code before a request reaches your app.

Run the initializer from the root of your Next.js project:

Terminal
npx init-xmcp@latest

The CLI detects your framework and package manager, then prompts you for directory paths:

Terminal
? Tools directory path: (tools)
? Prompts directory path: (prompts)
? Resources directory path: (resources)
? Route directory path: (app/mcp)

Accept the defaults unless your project has a different structure. The initializer creates the tools, prompts, and resources folders, adds the MCP route to your app, and updates your package.json scripts to run xmcp alongside Next.js:

package.json
{
"scripts": {
"dev": "xmcp dev & next dev",
"build": "xmcp build && next build"
}
}

The @xmcp/adapter import resolves against the generated .xmcp folder, which doesn't exist until the first build. Generate it now:

Terminal
npx xmcp build

Then add the path mapping to your tsconfig.json:

tsconfig.json
{
"compilerOptions": {
"paths": {
"@xmcp/*": ["./.xmcp/*"]
}
}
}

After both steps, TypeScript resolves the adapter import without errors.

The initializer creates a route handler at the path you chose (default app/mcp). It exports the xmcp handler for both GET and POST requests:

app/mcp/route.ts
import { xmcpHandler } from "@xmcp/adapter";
export { xmcpHandler as GET, xmcpHandler as POST };

This makes your MCP server available at /mcp on your app's domain. MCP clients connect to this endpoint over HTTP.

Each tool lives in its own file inside the tools directory. A tool file exports three things, including a Zod schema for parameters, a metadata object, and a default function that implements the logic:

tools/get-weather.ts
import { z } from "zod";
import { type InferSchema } from "xmcp";
export const schema = {
location: z.string().describe("City name"),
};
export const metadata = {
name: "get-weather",
description: "Get current weather for a location",
};
export default async function getWeather({
location,
}: InferSchema<typeof schema>) {
// Your implementation here
return `Weather in ${location}: 72°F, Sunny`;
}

xmcp registers the tool automatically based on the file. To add more tools, create additional files in the same directory with the same structure. The .describe() calls on schema fields become parameter descriptions that MCP clients show to users and AI models, so write them as you would API documentation.

Start the development server:

Terminal
npm run dev

This runs xmcp dev and next dev together. Your MCP endpoint is available at http://localhost:3000/mcp, and tool changes hot-reload as you edit files. You can connect any MCP client to this URL to test your tools.

If you deploy through Vercel, you can also use Vercel CLI for local development:

Terminal
vercel dev

To protect your MCP server, wrap the handler with withAuth and supply a token verification function. The function receives the request and bearer token, and returns auth information for valid tokens or undefined to reject the request:

app/mcp/route.ts
import { xmcpHandler, withAuth, VerifyToken } from "@xmcp/adapter";
const verifyToken: VerifyToken = async (req: Request, bearerToken?: string) => {
if (!bearerToken) return undefined;
// Validate the token against your auth service
const isValid = await checkToken(bearerToken);
if (!isValid) return undefined;
return {
token: bearerToken,
scopes: ["read:messages", "write:messages"],
clientId: "example-client",
};
};
const handler = withAuth(xmcpHandler, {
verifyToken,
required: true,
requiredScopes: ["read:messages"],
resourceMetadataPath: "/.well-known/oauth-protected-resource",
});
export { handler as GET, handler as POST };

Set required: true to reject unauthenticated requests, and use requiredScopes to enforce scope checks on every call. The resourceMetadataPath option exposes OAuth-protected resource metadata so compliant clients can discover your auth requirements.

Deploy by connecting your Git repository or with Vercel CLI:

Terminal
vercel deploy

Your MCP endpoint runs as a Vercel Function and uses Fluid compute by default. Fluid compute lets multiple requests share a single instance, which suits MCP workloads well since tool calls are often I/O-bound while waiting on APIs or databases.

Once deployed, your server is available at https://your-project.vercel.app/mcp.

The .xmcp folder hasn't been generated yet, or the path mapping is missing. Run npx xmcp build to generate the folder, then confirm your tsconfig.json includes the @xmcp/* path mapping from step 2.

The Next.js adapter doesn't support xmcp's middleware.ts or xmcp/headers. Use Next.js middleware for request processing in your app, or Routing Middleware on Vercel for rewrites, redirects, and headers before a request reaches your application.

Was this helpful?

supported.