How do I make an MCP server with auth in Next.js?

main
31cdb9eworkos plugin workflow
This post might have stale content, as main is 1 commit ahead.
Avatar of KollerKollerposted

How can I make an MCP server? I want to have AUTH and I am using nextjs

Avatar of Claude Haiku 4.5Claude Haiku 4.5commented

I'll help you understand how to create an MCP server with authentication using Next.js. Let me first explore the repository to see what resources and examples are available.

Great! I can see there are excellent examples in the repository. Let me look at the relevant documentation and examples for building an MCP server with Next.js and authentication.

Let me explore the structure of these directories:

Now let me look at the actual code for these examples:

Let me look at the actual MCP route files and configuration:

Now let me look at the xmcp.config.ts and the better-auth setup:

Perfect! Now let me look at the Next.js adapter documentation:

Perfect! Now let me check the documentation for the Next.js adapter:

Perfect! Now let me also check the Better Auth integration documentation:

Excellent! Now I have all the information I need. Let me create a comprehensive response for the user.

##How to Create an MCP Server with AUTH in Next.js

Great question! The xmcp framework makes it easy to add authentication to your MCP server when using Next.js. I'll show you three different approaches based on what the repository offers:

###Option 1: Custom Bearer Token Authentication (Simplest)

This is the built-in withAuth wrapper from xmcp:

import { xmcpHandler, withAuth, VerifyToken } from "@xmcp/adapter";

/**
 * Verify the bearer token and return auth information
 * In a real implementation, this would validate against your auth service
 */
const verifyToken: VerifyToken = async (req: Request, bearerToken?: string) => {
  if (!bearerToken) return undefined;

  // Validate token against your database, JWT service, etc.
  const isValid = await validateTokenWithYourService(bearerToken);

  if (!isValid) return undefined;

  return {
    token: bearerToken,
    scopes: ["read:messages", "write:messages"],
    clientId: "example-client",
    extra: {
      userId: "user-123",
      permissions: ["user"],
      timestamp: new Date().toISOString(),
    },
  };
};

const options = {
  verifyToken,
  required: true, // Make auth mandatory
  requiredScopes: ["read:messages"], // Require specific scopes
};

const handler = withAuth(xmcpHandler, options);

export { handler as GET, handler as POST };

Key Features:

  • OAuth 2.0 Bearer token support
  • Scope validation
  • Token expiration checking
  • RFC 9728 OAuth Protected Resource Metadata

###Option 2: Better Auth Integration (Recommended for Full Auth)

This is the most comprehensive solution with email/password and OAuth support:

1. Install dependencies:

npm install better-auth pg
npm install -D @types/pg

2. Set up your auth configuration (src/lib/auth.ts):

import { betterAuth } from "better-auth";
import { mcp } from "better-auth/plugins";
import { Pool } from "pg";

export const auth = betterAuth({
  database: new Pool({
    connectionString: process.env.DATABASE_URL,
  }),
  baseURL: "http://localhost:3000",
  plugins: [
    mcp({
      loginPage: "/login",
    }),
  ],
  emailAndPassword: {
    enabled: true,
  },
});

3. Create your MCP route (app/mcp/route.ts):

import { xmcpHandler } from "@xmcp/adapter";
import { withMcpAuth } from "better-auth/plugins";
import { auth } from "@/lib/auth";

const handler = withMcpAuth(auth, (req) => {
  return xmcpHandler(req);
});

export { handler as GET, handler as POST };

4. Set up environment variables:

DATABASE_URL=postgresql://username:password@localhost:5432/your_database

See the full example: examples/better-auth-nextjs in the repository


###Option 3: API Key Authentication (Simple & Lightweight)

For simpler use cases without OAuth:

import { apiKeyAuthMiddleware, type Middleware } from "xmcp";

const middleware: Middleware = [
  apiKeyAuthMiddleware({
    headerName: "x-api-key",
    validateApiKey: async (apiKey) => {
      return apiKey === process.env.MCP_API_KEY;
    },
  }),
];

export default middleware;

Then connect with the API key in headers:

{
  "mcpServers": {
    "my-project": {
      "url": "http://localhost:3001/mcp",
      "headers": {
        "x-api-key": "your-api-key"
      }
    }
  }
}

###Setup Steps for Next.js

  1. Initialize xmcp in your Next.js project:
npx init-xmcp@latest
  1. Update your xmcp.config.ts:
import { XmcpConfig } from "xmcp";

const config: XmcpConfig = {
  http: true,
  experimental: {
    adapter: "nextjs",
  },
};

export default config;
  1. Update your tsconfig.json:
{
  "compilerOptions": {
    "paths": {
      "@xmcp/*": ["./.xmcp/*"]
    }
  }
}
  1. Update your package.json scripts:
{
  "scripts": {
    "dev": "xmcp dev & next dev",
    "build": "xmcp build && next build"
  }
}

###Which Option to Choose?

OptionBest ForComplexity
Bearer Token (Option 1)Custom auth logic, existing auth servicesLow
Better Auth (Option 2)Full auth system with email/OAuth/sessionsMedium-High
API Key (Option 3)Simple access control, internal toolsVery Low

Check out the working examples in the repo:

  • examples/auth-nextjs - Bearer token auth
  • examples/better-auth-nextjs - Full Better Auth setup
  • examples/with-nextjs - Basic Next.js setup without auth

All three patterns use OAuth 2.0 RFC 9728 Protected Resource Metadata, which MCP clients understand natively!


END OF POST

Log in to add a comment
Claude Haiku 4.5
How do I make an MCP server with auth in Next.js? — basementstudio/xmcp