Tu primer servidor MCP en 90 minutos
Sin teoría, sin capítulo sobre la especificación del protocolo. Construyes un servidor, lo conectas, lo ves funcionar.
Los MCP servers son lo que convierte tu Claude o Codex de "chatbot con conocimiento" en "brazo extendido en mi sistema". La mayoría de tutoriales para principiantes intentan explicarte primero el protocolo. Resultado: nadie construye uno. Aquí lo hacemos al revés: construimos algo, funciona, y luego entiendes por qué.
Si lo haces completo, en 90 minutos tienes tu propio MCP server con una tarea concreta (resumir ficheros de una carpeta), conectado a Claude Desktop y corriendo en tu máquina. Es la base para todo lo que en el Nivel 6 se vuelve más complejo.
1. Aclarar requisitos
Necesitas: Node.js 20 o más nuevo (node --version en un terminal), un editor de texto (VS Code, Sublime, lo que tengas), y Claude Desktop instalado (claude.ai/download). Eso es todo. Sin cuenta cloud, sin Docker, sin conocimiento de TypeScript.
Un consejo: si nunca instalaste Node, usa nvm o el instalador de nodejs.org. No "brew install node" si más tarde quieres cambiar versiones, lleva a caos de versiones.
2. Carpeta de proyecto
Crea una carpeta nueva en algún sitio, por ejemplo ~/code/mi-primer-mcp. Dentro:
npm init -y
npm install @modelcontextprotocol/sdk
Eso instala el SDK oficial de Anthropic. No necesitas más.
Un consejo: cuando apuntes la ruta, escríbela absoluta (con /Users/TuNombre/... en Mac o C:\Users\TuNombre\... en Windows). Claude Desktop la quiere absoluta, no relativa.
3. Escribir el archivo del server
Crea server.js en la carpeta del proyecto. Contenido completo:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { readdir, readFile } from "node:fs/promises";
import { join } from "node:path";
const server = new Server(
{ name: "mi-primer-mcp", version: "1.0.0" },
{ capabilities: { tools: {} } }
);
server.setRequestHandler("tools/list", async () => ({
tools: [
{
name: "folder_summary",
description: "Cuenta archivos de una carpeta y muestra las primeras líneas de cada uno",
inputSchema: {
type: "object",
properties: {
path: { type: "string", description: "Ruta absoluta a la carpeta" }
},
required: ["path"]
}
}
]
}));
server.setRequestHandler("tools/call", async (request) => {
if (request.params.name !== "folder_summary") {
throw new Error("Tool desconocida");
}
const path = request.params.arguments.path;
const files = await readdir(path);
const summaries = await Promise.all(
files.slice(0, 10).map(async (file) => {
try {
const content = await readFile(join(path, file), "utf8");
const firstLines = content.split("\n").slice(0, 3).join("\n");
return `## ${file}\n${firstLines}`;
} catch {
return `## ${file}\n(no se puede leer)`;
}
})
);
return {
content: [
{ type: "text", text: `Carpeta: ${path}\nArchivos: ${files.length}\n\n${summaries.join("\n\n")}` }
]
};
});
const transport = new StdioServerTransport();
await server.connect(transport);
Es un MCP server completo. Hace exactamente una cosa: tomar una ruta de carpeta, listar archivos, mostrar las primeras tres líneas de cada uno.
Un consejo: copia 1:1. Sin cambios la primera vez. Cuando funcione, entiendes qué hace cada línea y puedes añadir cosas.
4. Ajustar package.json
Abre el package.json que creó npm init. Añade "type": "module" cerca del principio para que los import funcionen. Quedará algo así:
{
"name": "mi-primer-mcp",
"version": "1.0.0",
"type": "module",
"main": "server.js",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.0"
}
}
Un consejo: si más tarde ves errores de JSON, suele ser una coma faltante. Un validador online de JSON te ahorra cinco minutos de adivinar.
5. Test local
Antes de conectar Claude, comprueba si el server arranca. Terminal en la carpeta del proyecto:
node server.js
Si no pasa nada y el cursor parpadea: bien. Los MCP servers esperan input por stdin. Ctrl+C para abortar. Si aparece un error, léelo, normalmente es un import faltante o un typo.
Un consejo: los mensajes de error de Node son largos pero la primera línea es la importante. El resto es el stack trace que te dice exactamente dónde.
6. Que Claude Desktop lo encuentre
Ahora la conexión real. Abre Claude Desktop, ve a Settings, "Developer", "Edit Config". Eso abre claude_desktop_config.json. Añade el server, queda algo así:
{
"mcpServers": {
"mi-primer-mcp": {
"command": "node",
"args": ["/Users/TuNombre/code/mi-primer-mcp/server.js"]
}
}
}
Ajusta la ruta a la tuya. Absoluta, no relativa. Guarda, cierra Claude Desktop completamente (no solo la ventana. Cmd+Q en Mac, click derecho → Salir en Windows), reinicia.
Un consejo: si Claude no encuentra el server, en el 90 % de los casos es la ruta. Cópiala desde terminal con pwd en la carpeta del proyecto.
7. Primera llamada real en Claude
Abre un chat nuevo en Claude Desktop. Pregunta algo tipo: "¿Puedes resumirme qué hay en mi carpeta /Users/TuNombre/Documents/notas?" (Ajusta la ruta a una real.) Claude debería reconocer que folder_summary es la tool correcta y llamarla.
Ves un pequeño icono de tool-call, breve estado, después el resultado. Si funciona, acabas de poner tu primer MCP server en producción.
Un consejo: la primera vez parece magia. Es normal. Acabas de dar a Claude una capacidad nueva que OpenAI y Anthropic no entregan de fábrica.
8. Qué puede romperse y cómo arreglarlo
Errores típicos: ruta mal en config, versión Node demasiado vieja, no reiniciar Claude Desktop tras cambiar config, permisos de archivo en la carpeta. Claude Desktop tiene un log en ~/Library/Logs/Claude/mcp*.log en Mac que te muestra lo que dice el server al arrancar.
Un consejo: si algo no va, primera pregunta: ¿está el server en la config en el sitio correcto? Segunda: ¿lo ves en developer settings de Claude? Si ambas sí y no va, el bug está en el código. Lee logs, no adivines.
9. Por qué entiendes esto ya
Sin teoría de protocolo aprendiste lo que un MCP server realmente es: un programa local que espera en stdin, responde requests JSON y reporta tools que Claude puede llamar. Esa es la spec entera en una frase.
Todo lo que se construye alrededor en servers de producción (OAuth, HTTP transport, conexión a BD, types TypeScript, tests, logging, error handling, rate limiting) es decoración encima de este núcleo. Cuando entiendes el núcleo, entiendes el resto leyendo.
Un consejo: no construyas un server "bonito" como siguiente. Construye uno que resuelva una tarea real para ti. Un MCP server que resuma tu página Notion de la semana. Uno que lea tus últimas tres entradas de calendario. Uno que busque en tus notas Markdown locales. El valor de MCP es lo que te resuelve a ti, no cómo de profesional luce.
10. Seguir construyendo
Cuando tras estos 90 minutos tienes un server corriendo, has superado el muro que para al 95 % de los interesados. A partir de aquí es más fácil. Añadir tools (ampliar tools/list, ampliar tools/call en consonancia), construir una segunda. Profundizar en TypeScript y los types del SDK. Más tarde un server HTTP en lugar de stdio para que otros puedan usarlo. Aún más tarde: OAuth para que extraños puedan entrar de forma segura. Todo paso a paso, cada uno manejable.
Un consejo: tras los 90 minutos, anota tres ideas de tools que añadir al server. Eso mantiene el momentum. Si solo dices "tengo que volver a hacer MCP alguna vez", no vuelve nunca.
Cómo sigue
El Nivel 6 de la Academy recorre este camino estructuradamente: planificar tu server, esqueleto TypeScript, diseño de tools, deployment en dominio propio, venta vía marketplaces. Tras este sprint de 90 minutos estás ready para el Nivel 6.
Y si quieres tu setup aún más limpio: el Playbook "Memoria portable" muestra cómo tus servers caseros corren paralelos a memory servers existentes y todo está disponible simultáneamente en Claude, Codex y Cursor.
Por ahora: server corre, Claude habla con él. Esa es la prueba. Todo lo demás es solo más de eso.