Next.js MCP Server Template
Overview
This template provides a fully production-ready Model Context Protocol (MCP) server built with TypeScript and Next.js, designed to give AI assistants like Claude deep integration with Next.js application development workflows. Rather than a toy example, this server exposes real utility โ it helps developers analyze Next.js project structures, inspect route configurations, audit performance budgets, and query build metadata directly from their AI assistant.
The server uses HTTP transport with API key authentication, making it suitable for deployment as a standalone service accessible by multiple MCP clients simultaneously. Whether you are building an internal developer tooling platform or want Claude to have persistent context about your Next.js codebase, this template gives you a solid foundation with proper error handling, structured logging, health monitoring, and Docker deployment out of the box.
This template is aimed at intermediate TypeScript developers who are comfortable with Next.js and want to extend their AI workflows with custom tooling. You will learn how the MCP protocol works at the HTTP layer, how to structure a maintainable server with middleware, and how to deploy it reliably using Docker and container orchestration platforms like Railway or Fly.io.
What You'll Learn
- How to implement an MCP server using the
@modelcontextprotocol/sdkwith HTTP/SSE transport - API key authentication middleware patterns for securing MCP endpoints
- Tool registration with full Zod schema validation for type-safe inputs
- Structured JSON logging with request tracing using
pino - Multi-stage Docker builds optimised for minimal production image size
- Health check endpoint design that reflects real dependency status
- Environment variable management with runtime validation via
zod - Next.js project analysis tools: route detection, build manifest parsing, performance auditing
- Error handling patterns that return meaningful MCP error responses
- Docker Compose configuration for local development with live reload
- How to test MCP servers manually with
curland via Claude Desktop - Production deployment to Railway and Fly.io with persistent configuration
Architecture
Claude Desktop / Cursor / Claude Code
โ
โ HTTP POST /mcp (SSE stream)
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Next.js API Routes โ
โ app/api/mcp/route.ts โ
โ app/api/health/route.ts โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ API Key Auth Middleware โ
โ src/auth.ts โ
โโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ MCP Server Core โ
โ src/server.ts โ
โ Tool Router + Handler Registry โ
โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโบ analyze_nextjs_project โ filesystem / package.json
โโโโบ inspect_api_routes โ app/ dir traversal
โโโโบ audit_performance โ .next/build-manifest.json
Project Structure
nextjs-mcp-server/
โโโ app/
โ โโโ api/
โ โ โโโ mcp/
โ โ โ โโโ route.ts # MCP HTTP transport endpoint
โ โ โโโ health/
โ โ โโโ route.ts # Health check endpoint
โ โโโ layout.tsx # Minimal root layout
โโโ src/
โ โโโ server.ts # MCP server + tool implementations
โ โโโ auth.ts # API key authentication middleware
โ โโโ health.ts # Health check logic
โ โโโ config.ts # Environment config with Zod validation
โโโ public/
โ โโโ .gitkeep
โโโ Dockerfile # Multi-stage production build
โโโ docker-compose.yml # Local development stack
โโโ .env.example # All environment variables documented
โโโ .gitignore
โโโ next.config.ts # Next.js configuration
โโโ tsconfig.json
โโโ package.json
โโโ README.md
Prerequisites
- Node.js 20+ (LTS recommended)
- npm 10+ or pnpm 9+
- Docker 24+ and Docker Compose v2 (for containerised development)
- Basic familiarity with Next.js App Router and TypeScript
- An MCP client: Claude Desktop, Cursor, Windsurf, or Claude Code
Quick Start
# 1. Clone and enter the project
git clone https://github.com/your-org/nextjs-mcp-server
cd nextjs-mcp-server
# 2. Install dependencies
npm install
# 3. Configure environment
cp .env.example .env.local
# Edit .env.local and set MCP_API_KEY to a secure random string
# openssl rand -hex 32
# 4. Start the development server
npm run dev
# 5. Verify health endpoint
curl http://localhost:3000/api/health
# 6. Test MCP endpoint (SSE handshake)
curl -X POST http://localhost:3000/api/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
Features
- HTTP/SSE Transport โ Stateless MCP server compatible with all HTTP-capable MCP clients
- API Key Authentication โ Per-request key validation via
x-api-keyheader orAuthorization: Bearer - 3 Production-Grade Tools โ
analyze_nextjs_project,inspect_api_routes,audit_performance_budget - Zod Schema Validation โ All tool inputs are validated with descriptive error messages
- Structured Logging โ JSON logs with request IDs, tool names, durations via
pino - Health Monitoring โ
/api/healthendpoint with dependency status and uptime reporting - Multi-Stage Dockerfile โ Builder + runner stages, non-root user, minimal attack surface
- Docker Compose โ Local dev stack with hot reload and environment variable injection
- TypeScript Strict Mode โ Full type safety across all modules
- Graceful Error Handling โ MCP-compliant error responses with codes and context
Works With
| Client | Supported | Notes |
|---|---|---|
| Claude Desktop | โ | Add to claude_desktop_config.json as HTTP server |
| Claude Code | โ | Use --mcp-server flag with HTTP URL |
| Cursor | โ | Add via MCP settings panel |
| Windsurf | โ | HTTP transport supported natively |
| Continue | โ | Configure in config.json as HTTP MCP provider |
Claude Desktop Configuration
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"nextjs-tools": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:3000/api/mcp"],
"env": {
"MCP_API_KEY": "your_api_key_here"
}
}
}
}
Configuration
| Variable | Description | Required | Default |
|---|---|---|---|
MCP_API_KEY | Secret key for authenticating MCP requests | โ Required | โ |
MCP_SERVER_NAME | Display name shown to MCP clients | Optional | nextjs-mcp-server |
MCP_SERVER_VERSION | Server version string | Optional | 1.0.0 |
NODE_ENV | Runtime environment (development/production) | Optional | development |
PORT | HTTP port for the Next.js server | Optional | 3000 |
LOG_LEVEL | Pino log level (debug/info/warn/error) | Optional | info |
NEXTJS_PROJECT_PATH | Absolute path to the Next.js project to analyse | Optional | process.cwd() |
ALLOWED_ORIGINS | Comma-separated CORS origins | Optional | * |
RATE_LIMIT_RPM | Requests per minute per API key | Optional | 60 |
Deployment
Docker (Local)
# Build and run with Docker Compose
docker compose up --build
# Production build only
docker build -t nextjs-mcp-server .
docker run -p 3000:3000 \
-e MCP_API_KEY=your_secret_key \
-e NODE_ENV=production \
nextjs-mcp-server
Railway
# Install Railway CLI
npm install -g @railway/cli
# Login and deploy
railway login
railway init
railway up
# Set environment variables
railway variables set MCP_API_KEY=your_secret_key
railway variables set NODE_ENV=production
Fly.io
# Install flyctl
curl -L https://fly.io/install.sh | sh
# Launch app (uses Dockerfile automatically)
fly launch --name nextjs-mcp-server --region lhr
# Set secrets
fly secrets set MCP_API_KEY=your_secret_key
# Deploy
fly deploy
# Check logs
fly logs
Production Checklist
-
MCP_API_KEYis a cryptographically random string (minimum 32 characters) -
NODE_ENV=productionis set in your deployment environment - Health endpoint returns
200 OKbefore routing traffic:curl https://your-domain.com/api/health - Docker image uses non-root user (verify with
docker run --rm nextjs-mcp-server whoami) - All secrets are stored in platform secret manager, not in
.envcommitted to git -
ALLOWED_ORIGINSis restricted to known MCP client origins - Log level is set to
infoorwarn(notdebug) in production - Container memory and CPU limits are set in
docker-compose.ymlor platform config - Health checks are configured in your load balancer or platform (interval: 30s)
- Rate limiting (
RATE_LIMIT_RPM) is tuned for your expected client count -
.next/build artifacts are not committed to version control -
NEXTJS_PROJECT_PATHpoints to a read-only mount if analysing external projects - TLS/HTTPS is terminated at the load balancer or platform edge
- Graceful shutdown is handled (Next.js handles
SIGTERMby default) - Monitoring/alerting is set up on the
/api/healthendpoint status field
Testing
Manual Testing with curl
# List available tools
curl -s -X POST http://localhost:3000/api/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | jq
# Call analyze_nextjs_project
curl -s -X POST http://localhost:3000/api/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: your_api_key_here" \
-d '{
"jsonrpc":"2.0",
"id":2,
"method":"tools/call",
"params":{
"name":"analyze_nextjs_project",
"arguments":{"projectPath":"/path/to/your/nextjs/app"}
}
}' | jq
# Test authentication failure
curl -s -X POST http://localhost:3000/api/mcp \
-H "Content-Type: application/json" \
-H "x-api-key: wrong_key" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
# Health check
curl -s http://localhost:3000/api/health | jq
Testing with Claude Desktop
- Start the server:
npm run dev - Add the Claude Desktop config shown in the Works With section
- Restart Claude Desktop
- In a new conversation, type: "Use the nextjs-tools MCP server to analyze my project at /path/to/project"
- Claude should call
analyze_nextjs_projectand return structured results
Running Type Checks
# TypeScript type check
npm run type-check
# Lint
npm run lint
# Build (catches compile errors)
npm run build