Busca "Next.js MCP server" y te encuentras con dos tareas distintas que comparten nombre. Algunas personas quieren que su agente de programación vea el interior de la app de Next.js que están creando: los errores en la página, las rutas, los problemas de compilación. Otras quieren convertir su app de Next.js en un MCP server, para que Claude o ChatGPT puedan llamar a herramientas que ofrece su sitio. La mayoría de las páginas que leímos cubren una y difuminan la otra, y muchas todavía muestran la versión antigua de la librería para la segunda tarea.
Esta guía cubre ambas. Ejecutamos cada comando y ejemplo de código a continuación el 14 de noviembre de 2026, en Next.js 16.4.6, next-devtools-mcp 0.4.0, mcp-handler 2.4.0, @modelcontextprotocol/server 2.4.0 y zod 4.6.7, en macOS. Donde el resultado difirió de la documentación, lo indicamos.
¿Cuál necesitas?
| Quieres | Usa | Se ejecuta | La IA obtiene |
|---|---|---|---|
| Que Claude Code, Cursor o Codex depuren la app que estás escribiendo | El /_next/mcp integrado más next-devtools-mcp |
Tu máquina, solo con next dev |
Errores en vivo, rutas, logs, comprobaciones de compilación, documentación acorde a tu versión |
| Dar a apps de IA herramientas de tu producto (búsqueda, pedidos, documentación) | Tu propia ruta con mcp-handler |
Donde sea que esté desplegada la app | Las herramientas que escribas, nada más |
| Ambas | Ambas, no entran en conflicto |
Si no lo tienes claro, probablemente quieras la primera. Requiere un solo comando y nada de código.
Parte 1: conecta tu agente de código a una app de Next.js en ejecución
Qué expone Next.js 16 en /_next/mcp
Desde Next.js 16, next dev responde a las solicitudes MCP en /_next/mcp. Está activado por defecto. Enviamos tools/list con curl y obtuvimos nueve herramientas:
| Herramienta | Qué devuelve | Necesita |
|---|---|---|
get_errors |
Errores actuales: validación de next.config, errores de runtime del navegador, errores de build con stacks mapeados a las fuentes |
La página abierta en un navegador para los errores de runtime |
get_logs |
Ruta al archivo de log del dev server con la consola del navegador y la salida del servidor | |
get_page_metadata |
Qué contribuyó al render de la página actual | La página abierta en un navegador |
get_project_metadata |
Ruta del proyecto y URL del dev server | |
get_routes |
Todas las rutas agrupadas por appRouter y pagesRouter, con los segmentos dinámicos como [param] |
|
get_server_action_by_id |
Archivo fuente y nombre del export de una Server Action | |
get_compilation_issues |
Errores de resolución, módulos faltantes y errores de transformación en todas las rutas | Turbopack |
compile_route |
Compila una ruta sin solicitarla | Turbopack |
get_request_insights |
Líneas de tiempo de solicitudes recientes, fetches y comportamiento de la caché | experimental.requestInsights |
El servidor se identificó como "Next.js MCP Server" versión 0.2.0. En nuestra app de prueba de dos páginas, get_routes devolvió exactamente lo que teníamos: / y /api/mcp.
Las herramientas de compilación son la ventaja silenciosa. Un agente que acaba de editar tres archivos puede preguntarle al dev server en ejecución si compilan, en lugar de lanzar un next build completo con el código a medio terminar.
Hay dos límites que conviene conocer antes de confiar en esto. Solo existe en desarrollo: compilamos la misma app y ejecutamos next start, y /_next/mcp devolvió 404. Y requiere Next.js 16. En la 15 no hay nada en esa ruta; npx @next/codemod@latest upgrade latest es la vía de actualización que sugiere el propio tooling.
Para desactivarlo, pon experimental.mcpServer en false en next.config.
Instala next-devtools-mcp
Tu agente no habla directamente con /_next/mcp. El paquete next-devtools-mcp es un pequeño servidor stdio que encuentra los dev servers en ejecución y les reenvía las llamadas. Desde la versión 0.4.0 es un conector ligero con cuatro herramientas:
nextjs_indexlista los dev servers de Next.js en ejecución y las herramientas que expone cada uno.nextjs_callejecuta una de esas herramientas en un servidor, dados suportytoolName.nextjs_docsapunta al agente a la documentación que viene dentro de tu Next.js instalado, ennode_modules/next/dist/docs/, para que las respuestas coincidan con tu versión.browser_evalapunta al agente al CLIagent-browserpara revisar páginas en un navegador real.
Necesita Node.js 20.19 o superior. Elige tu cliente:
Claude Code
claude mcp add next-devtools npx next-devtools-mcp@latest
Codex
codex mcp add next-devtools -- npx next-devtools-mcp@latest
En Windows 11, según el README, Codex también necesita env = { SystemRoot="C:\\Windows", PROGRAMFILES="C:\\Program Files" } y startup_timeout_ms = 20_000 en .codex/config.toml.
Gemini CLI
gemini mcp add next-devtools npx next-devtools-mcp@latest
Agrega -s user para instalarlo en todos los proyectos en lugar de solo en el actual.
VS Code con Copilot
code --add-mcp '{"name":"next-devtools","command":"npx","args":["-y","next-devtools-mcp@latest"]}'
Cursor, o cualquier cliente que lea un archivo JSON
{
"mcpServers": {
"next-devtools": {
"command": "npx",
"args": ["-y", "next-devtools-mcp@latest"]
}
}
}
Ponlo en .mcp.json en la raíz del proyecto para compartirlo con el equipo a través de git, o en ~/.cursor/mcp.json solo para Cursor.
Todos los agentes a la vez
npx add-mcp next-devtools-mcp@latest
add-mcp escribe la entrada para cada agente de código que encuentra en la máquina.
Comprueba que funciona
Primero inicia el dev server. Luego abre en el navegador la página en la que estás trabajando, porque get_errors y get_page_metadata leen de sesiones de navegador activas. Ahora pregúntale al agente algo que solo la app en ejecución sabe:
- "¿Qué errores tiene la app ahora mismo?"
- "Lista las rutas y dime cuáles son dinámicas."
- "¿Compila
/blog/[slug]?"
En Claude Code verás llamadas como nextjs_index y luego nextjs_call con toolName: "get_errors". Si el agente responde leyendo tus archivos, no se ha conectado.
También puedes comprobar el endpoint sin ningún agente:
curl -s -X POST http://localhost:3000/_next/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
Una lista de herramientas significa que Next.js está bien y que cualquier problema está entre el agente y next-devtools-mcp.
Lo que nos encontramos: dev servers en otros puertos
Nuestra app de prueba corría en el puerto 3417, porque el 3000 estaba ocupado. nextjs_index no la encontró. Encontró otro proyecto que estaba corriendo en el 3000.
Leer el código del paquete explicó por qué. En macOS y Linux, next-devtools-mcp 0.4.0 primero busca procesos llamados exactamente next-server. En nuestro Mac el proceso se llama next-server (v16.4.6), así que esa coincidencia falló, y el paquete recurrió a sondear los puertos 3000 a 3010. Un dev server en cualquier otro puerto es invisible para él.
La solución es simple. nextjs_call recibe el puerto directamente, y funcionó en el 3417 en cuanto se lo pasamos:
{ "port": 3417, "toolName": "get_routes" }
Así que si ejecutas más de un proyecto, o usas un puerto personalizado, díselo al agente una vez: "el dev server está en el puerto 3417". Llamará a la herramienta con ese puerto. Mantener los proyectos dentro del 3000 al 3010 también evita el problema.
Parte 2: crea tu propio MCP server dentro de una app de Next.js
Este es el otro significado: tu app de Next.js se convierte en algo a lo que Claude, Cursor o ChatGPT pueden conectarse por URL. Las herramientas típicas son la búsqueda sobre tu contenido, una consulta a tu base de datos o una acción como crear un ticket de soporte.
El mcp-handler de Vercel se encarga del trabajo del protocolo. Convierte la definición de un servidor en una función simple (Request) => Response, que es exactamente lo que exporta un Route Handler de Next.js.
La versión 2 cambió mucho
La mayoría de los tutoriales todavía muestran la versión 1, con Redis, un endpoint SSE y una ruta dinámica [transport]. La versión 2 es más simple, y los fragmentos antiguos no funcionan con ella:
| mcp-handler 1.x | mcp-handler 2.x | |
|---|---|---|
| Paquete del SDK | @modelcontextprotocol/sdk 1.x |
@modelcontextprotocol/server 2.x |
| zod | 3 | 4.2 o posterior |
| Node.js | 20 o posterior | |
| Transportes | Streamable HTTP y SSE | Solo Streamable HTTP, sin estado |
| Redis | Necesario para SSE | No se usa |
| Opciones de enrutamiento | basePath, maxDuration, redisUrl y más |
Eliminadas: monta el handler en la ruta que quieras |
Si te quedas en 1.x, mantén @modelcontextprotocol/sdk en 1.26.0 o posterior. El README de mcp-handler señala que las versiones anteriores del SDK tienen una vulnerabilidad de seguridad.
Instalación
npm install mcp-handler@^2 @modelcontextprotocol/server@^2 zod@^4
La ruta
Crea app/api/mcp/route.ts. Esta ruta les da a los clientes de IA una búsqueda sobre las entradas del blog. Cambia el array por tu base de datos o CMS.
import { createMcpHandler } from "mcp-handler";
import { z } from "zod";
const posts = [
{ slug: "edge-caching", title: "Caching at the edge", body: "How we cache HTML at the edge for 10 minutes." },
{ slug: "image-sizes", title: "Picking image sizes", body: "Three widths cover most layouts." },
];
const handler = createMcpHandler(
(server) => {
server.registerTool(
"search_posts",
{
title: "Search posts",
description: "Find blog posts whose title or body contains the query.",
inputSchema: z.object({ query: z.string().min(2) }),
},
async ({ query }) => {
const q = query.toLowerCase();
const hits = posts.filter((p) => `${p.title} ${p.body}`.toLowerCase().includes(q));
return {
content: [{ type: "text", text: hits.length ? hits.map((p) => `${p.title} (/blog/${p.slug})`).join("\n") : "No posts found." }],
};
},
);
},
{ serverInfo: { name: "my-blog", version: "1.0.0" } },
);
export { handler as GET, handler as POST };
/api/mcp es solo una convención. El handler nunca mira la ruta, así que app/mcp/route.ts funciona igual de bien. Dale a los clientes la URL completa de la ruta que elijas.
Define serverInfo. Sin él, nuestro servidor se presentaba a los clientes como "mcp-typescript server on vercel", que es lo que los usuarios ven en la lista de servidores de su cliente.
Pruébalo con curl
Con npm run dev en ejecución, estas tres peticiones son un ciclo completo. Las ejecutamos contra la ruta de arriba:
curl -s -X POST http://localhost:3000/api/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"curl","version":"1"}}}'
La respuesta llegó como un solo server-sent event con "serverInfo":{"name":"my-blog","version":"1.0.0"}. Reemplaza el cuerpo por {"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}} para ver search_posts con su JSON Schema, y por este para ejecutar la herramienta:
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"search_posts","arguments":{"query":"edge"}}}
Obtuvimos Caching at the edge (/blog/edge-caching). Un GET simple a la ruta respondió 405, que es lo esperado: la versión 2 no tiene estado y no tiene un stream de larga duración que abrir.
Si prefieres una vista para hacer clic en lugar de curl, el MCP Inspector también funciona: npx @modelcontextprotocol/inspector, luego conéctate a http://localhost:3000/api/mcp con el transporte Streamable HTTP.
Conecta un cliente
Los clientes que hablan Streamable HTTP se conectan por URL.
Claude Code
claude mcp add --transport http my-blog http://localhost:3000/api/mcp
Cursor (~/.cursor/mcp.json)
{
"mcpServers": {
"my-blog": { "url": "http://localhost:3000/api/mcp" }
}
}
VS Code (.vscode/mcp.json)
{
"servers": {
"my-blog": { "type": "http", "url": "http://localhost:3000/api/mcp" }
}
}
Claude Desktop lee los servidores remotos desde Settings › Connectors. Para una URL local en claude_desktop_config.json, conéctala con mcp-remote:
{
"mcpServers": {
"my-blog": { "command": "npx", "args": ["-y", "mcp-remote", "http://localhost:3000/api/mcp"] }
}
}
Después de desplegar, cambia la URL de localhost por la real, como https://your-app.vercel.app/api/mcp. Nuestro generador de configuración escribe estos fragmentos para 15 clientes si registras tu servidor ahí.
Protégelo antes de desplegar
Una ruta desplegada es pública. Cualquiera que encuentre la URL puede llamar a tus herramientas, así que agrega autenticación antes del primer despliegue, no después.
withMcpAuth envuelve el handler. Esta es la versión que probamos, con un token compartido desde una variable de entorno:
import { createMcpHandler, withMcpAuth } from "mcp-handler";
// createMcpHandler(...) as above
const verifyToken = async (_req: Request, bearerToken?: string) => {
if (!bearerToken || bearerToken !== process.env.MCP_TOKEN) return undefined;
return { token: bearerToken, clientId: "team", scopes: ["posts:read"] };
};
const authed = withMcpAuth(handler, verifyToken, { required: true });
export { authed as GET, authed as POST };
required: true importa. Sin él, una petición sin un token válido igual pasa. Con él, nuestra llamada sin autenticar obtuvo:
HTTP/1.1 401 Unauthorized
www-authenticate: Bearer error="invalid_token", error_description="No authorization provided", resource_metadata="http://localhost:3417/.well-known/oauth-protected-resource"
y la misma llamada con Authorization: Bearer <token> obtuvo 200.
Ese enlace resource_metadata es cómo los clientes compatibles con OAuth encuentran tu inicio de sesión. Sírvelo desde app/.well-known/oauth-protected-resource/route.ts:
import { metadataCorsOptionsRequestHandler, protectedResourceHandler } from "mcp-handler";
const handler = protectedResourceHandler({ authServerUrls: ["https://auth.example.com"] });
const corsHandler = metadataCorsOptionsRequestHandler();
export { handler as GET, corsHandler as OPTIONS };
Respondió {"resource":"http://localhost:3417","authorization_servers":["https://auth.example.com"]}. Apunta authServerUrls a tu proveedor de identidad real. Para usuarios reales, reemplaza el token compartido por la verificación de los tokens de ese proveedor, y revisa requiredScopes por ruta. La revisión actual de la especificación, 2026-07-28, mueve el registro de clientes de Dynamic Client Registration a Client ID Metadata Documents; ese trabajo ocurre en tu servidor de autorización, y tu ruta de Next.js no cambia.
Dentro de una herramienta, la identidad verificada está en ctx.http?.authInfo, así que una herramienta puede filtrar resultados por la cuenta del llamador.
Problemas y soluciones
| Lo que ves | Causa | Solución |
|---|---|---|
[error] No server info found desde next-devtools-mcp |
No hay un servidor de desarrollo de Next.js 16 en ejecución, o está fuera de los puertos 3000 a 3010 | Ejecuta npm run dev; si usas otro puerto, indícale al agente el puerto para nextjs_call |
ERR_MODULE_NOT_FOUND para next-devtools-mcp/dist |
Caché de npx obsoleta | Limpia la caché de npx y reinicia el cliente |
404 en /_next/mcp |
Next.js 15 o anterior, next start, o experimental.mcpServer: false |
Actualiza, usa next dev o elimina la flag |
| El agente responde a partir de los archivos y nunca llama a las herramientas | El cliente no cargó el servidor | Reinicia el cliente y revisa su lista de MCP; en Claude Code ejecuta /mcp |
405 en GET /api/mcp |
Es normal en mcp-handler 2 | No hay nada que corregir; los clientes usan POST |
401 con una cabecera WWW-Authenticate |
withMcpAuth con required: true y sin token |
Envía Authorization: Bearer ... o inicia sesión mediante el flujo OAuth del cliente |
El código de tutoriales antiguos falla en redisUrl o basePath |
Está escrito para mcp-handler 1 | Elimina esas opciones y monta la ruta donde quieras |
| "The module was automatically converted to an EcmaScript module" en un proyecto nuevo | npm init añadió "type": "commonjs" a package.json |
Borra el campo type; Next.js gestiona los módulos por su cuenta |
El último nos costó cinco minutos en un proyecto de prueba en blanco. create-next-app no tiene ese problema.
Servidores MCP de Next.js en nuestro directorio
El 14 de noviembre de 2026, el catálogo de HostedMCP tenía 19 servidores activos con Next.js en el nombre, y 4 de ellos pasaron nuestras reglas de indexación. Los dos que importan para esta guía:
| Servidor | Estrellas | Puntuación de comprobaciones | Qué es |
|---|---|---|---|
| vercel/next-devtools-mcp | 836 | 89 | El conector de la Parte 1 |
| vercel-labs/mcp-handler | 699 | 86 | La librería de la Parte 2 |
Los recuentos de estrellas provienen de GitHub en nuestra última actualización; la puntuación de comprobaciones es nuestra revisión automatizada del repositorio, la licencia, el mantenimiento, la cadena de suministro y las descripciones de las herramientas, con la evidencia en el informe de comprobaciones de cada servidor. La mayoría de los otros 17 son plantillas de inicio o herramientas de un solo propósito con pocas estrellas. Revísalos de la misma forma antes de instalar uno.
Notas de seguridad
El endpoint de desarrollo es solo para desarrollo, pero no es privado. Mientras next dev está en ejecución, cualquier proceso que pueda alcanzar el puerto puede leer la ruta de tu proyecto, las rutas y la ubicación del log. No vincules el servidor de desarrollo a una dirección de red compartida mientras tenga secretos en su entorno.
Tu propia ruta es una API pública desde el día en que la despliegas. Trata cada herramienta como un endpoint: valida la entrada con el esquema, devuelve solo lo que el llamador puede ver y nunca pongas secretos ni URLs internas en las descripciones de las herramientas, porque el modelo lee esas descripciones y también cualquiera que liste tus herramientas. Nuestra guía de seguridad de MCP repasa los riesgos en orden.
A dónde ir ahora
Si quieres los detalles del protocolo que hay detrás de la ruta, cómo crear un MCP server explica cómo construir uno en TypeScript y Python sin más. Cuando tu servidor esté en marcha, envía el repositorio y HostedMCP lo listará con fragmentos de instalación para cada cliente y ejecutará sus comprobaciones.