Cómo crear tu propio servidor MCP
Aprende a construir un servidor MCP desde cero usando el SDK oficial de Anthropic. Tools, resources y despliegue paso a paso.
¿Qué necesitas?
Node.js 18+— cualquier versión LTS reciente- TypeScript — el SDK está escrito en TS, aunque puedes usarlo desde JS
npmopnpmpara gestionar dependencias- Un editor de código (VS Code, Cursor, etc.)
Proyecto desde cero
Crea una carpeta para tu servidor e inicializa el proyecto:
mkdir mi-servidor-mcp
cd mi-servidor-mcp
npm init -yInstala las dependencias necesarias:
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/nodeCrea un tsconfig.json con la configuración básica:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"esModuleInterop": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}La estructura final del proyecto será:
mi-servidor-mcp/
├── package.json
├── tsconfig.json
├── src/
│ └── index.ts
└── dist/Tu primer servidor MCP
Vamos a crear un servidor que exponga un tool de saludo. Abre src/index.ts y escribe:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "mi-servidor",
version: "1.0.0",
});
server.tool(
"greet",
"Saluda a una persona por su nombre",
{ name: z.string().describe("El nombre de la persona") },
async ({ name }) => {
return {
content: [{ type: "text", text: "Hola, " + name + "! Bienvenido a MCP." }],
};
},
);
const transport = new StdioServerTransport();
await server.connect(transport);Añade los scripts al package.json:
"scripts": {
"build": "tsc",
"start": "node dist/index.js"
}Compila y prueba:
npm run build
node dist/index.jsEl servidor se queda escuchando por stdio. No verás nada en la terminal porque espera mensajes JSON-RPC del cliente. Para probarlo necesitas un cliente MCP como OpenCode o el Inspector.
z.string().describe() para que la IA entienda qué debe pasar en cada parámetro. La descripción es clave para que el modelo use bien tu tool.Añadir un Resource
Los resources permiten que la IA lea datos estructurados desde tu servidor. Vamos a exponer proyectos ficticios usando una plantilla URI:
server.resource(
"project",
"file://projects/{id}",
async (uri) => {
const id = uri.pathname.split("/").pop();
return {
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify({
id,
name: `Proyecto ${id}`,
status: "activo",
createdAt: new Date().toISOString(),
}, null, 2),
},
],
};
},
);El cliente puede solicitar file://projects/42 y recibirá un JSON con los datos del proyecto. El URI se parsea automáticamente y el handler recibe el objeto URI completo.
Tu src/index.ts completo debería verse así:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "mi-servidor",
version: "1.0.0",
});
server.tool(
"greet",
"Saluda a una persona por su nombre",
{ name: z.string().describe("El nombre de la persona") },
async ({ name }) => {
return {
content: [{ type: "text", text: `Hola, ${name}! Bienvenido a MCP.` }],
};
},
);
server.resource(
"project",
"file://projects/{id}",
async (uri) => {
const id = uri.pathname.split("/").pop();
return {
contents: [
{
uri: uri.href,
mimeType: "application/json",
text: JSON.stringify({
id,
name: `Proyecto ${id}`,
status: "activo",
createdAt: new Date().toISOString(),
}, null, 2),
},
],
};
},
);
const transport = new StdioServerTransport();
await server.connect(transport);Probar con MCP Inspector
Anthropic provee una herramienta interactiva para depurar servidores MCP sin necesidad de un cliente IA.
Primero compila tu servidor y luego ejecuta:
npx @modelcontextprotocol/inspector node dist/index.jsEsto abre una UI en el navegador donde puedes:
- Ver la lista de tools y resources disponibles
- Ejecutar tools con parámetros personalizados
- Inspeccionar la respuesta JSON-RPC completa
- Probar la resolución de resources por URI
Configurar en OpenCode
Una vez que tu servidor funciona, añádelo a opencode.json en la raíz de tu proyecto:
{
"mcpServers": {
"mi-servidor": {
"command": "node",
"args": ["dist/index.js"]
}
}
}Si prefieres que el servidor se compile automáticamente antes de ejecutarse, usa npm run build como pre-callback o apunta directamente al source con tsx:
{
"mcpServers": {
"mi-servidor": {
"command": "npx",
"args": ["tsx", "src/index.ts"]
}
}
}Con esta configuración, OpenCode cargará tu servidor al iniciar sesión y podrás usar el tool greet y el resource file://projects/ directamente desde el chat.
Publicar tu servidor
Si quieres compartir tu servidor con la comunidad, puedes publicarlo en npm:
npm publishAsegúrate de tener un package.json completo con name, version, main apuntando a dist/index.js, y los bin si quieres que se ejecute con npx.
También puedes crear un template en GitHub para que otros hagan fork. Incluye un README con instrucciones claras y ejemplos de configuración.