Primeros Pasos con MCP: Guía para Desarrolladores
Introducción
Si ya conoces los fundamentos de MCP, es hora de ensuciarnos las manos. En este tutorial, aprenderás a construir tu primer servidor MCP desde cero.
Requisitos previos
Antes de comenzar, asegúrate de tener instalado:
# Node.js v18 o superior
node --version # v18.0.0 o mayor
# npm o pnpm
npm --version # 8.0.0 o mayor
Instalación del SDK
MCP proporciona SDKs oficiales para diferentes lenguajes. Comenzaremos con TypeScript:
# Crear nuevo proyecto
mkdir mi-servidor-mcp
cd mi-servidor-mcp
# Inicializar proyecto
npm init -y
# Instalar SDK de MCP
npm install @modelcontextprotocol/sdk
# Instalar TypeScript y tipos
npm install -D typescript @types/node
Configuración de TypeScript
Crea un archivo tsconfig.json:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}
Tu primer servidor MCP
Estructura básica
Crea el archivo src/index.ts:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
// Crear instancia del servidor
const server = new Server(
{
name: "mi-primer-servidor-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
Definir herramientas (Tools)
Las herramientas son funciones que la IA puede ejecutar. Vamos a crear una calculadora simple:
// Registrar handler para listar herramientas
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "sumar",
description: "Suma dos números",
inputSchema: {
type: "object",
properties: {
a: {
type: "number",
description: "Primer número",
},
b: {
type: "number",
description: "Segundo número",
},
},
required: ["a", "b"],
},
},
{
name: "multiplicar",
description: "Multiplica dos números",
inputSchema: {
type: "object",
properties: {
a: { type: "number" },
b: { type: "number" },
},
required: ["a", "b"],
},
},
],
};
});
Implementar la lógica
Ahora implementamos qué hace cada herramienta:
// Registrar handler para ejecutar herramientas
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "sumar": {
const { a, b } = args as { a: number; b: number };
const resultado = a + b;
return {
content: [
{
type: "text",
text: `El resultado de sumar ${a} + ${b} es: ${resultado}`,
},
],
};
}
case "multiplicar": {
const { a, b } = args as { a: number; b: number };
const resultado = a * b;
return {
content: [
{
type: "text",
text: `El resultado de multiplicar ${a} × ${b} es: ${resultado}`,
},
],
};
}
default:
throw new Error(`Herramienta desconocida: ${name}`);
}
});
Iniciar el servidor
// Conectar servidor con transporte stdio
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Servidor MCP iniciado en stdio");
}
main().catch((error) => {
console.error("Error fatal:", error);
process.exit(1);
});
Servidor completo
Aquí está el código completo de src/index.ts:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
const server = new Server(
{
name: "calculadora-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Lista de herramientas
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "sumar",
description: "Suma dos números",
inputSchema: {
type: "object",
properties: {
a: { type: "number", description: "Primer número" },
b: { type: "number", description: "Segundo número" },
},
required: ["a", "b"],
},
},
{
name: "multiplicar",
description: "Multiplica dos números",
inputSchema: {
type: "object",
properties: {
a: { type: "number" },
b: { type: "number" },
},
required: ["a", "b"],
},
},
],
};
});
// Implementación de herramientas
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "sumar": {
const { a, b } = args as { a: number; b: number };
return {
content: [
{
type: "text",
text: `El resultado es: ${a + b}`,
},
],
};
}
case "multiplicar": {
const { a, b } = args as { a: number; b: number };
return {
content: [
{
type: "text",
text: `El resultado es: ${a * b}`,
},
],
};
}
default:
throw new Error(`Herramienta desconocida: ${name}`);
}
});
// Iniciar servidor
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Servidor MCP iniciado");
}
main().catch(console.error);
Compilar y ejecutar
Añade scripts a tu package.json:
{
"name": "mi-servidor-mcp",
"version": "1.0.0",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node dist/index.js",
"dev": "tsc && node dist/index.js"
},
"dependencies": {
"@modelcontextprotocol/sdk": "latest"
},
"devDependencies": {
"@types/node": "^20.0.0",
"typescript": "^5.3.0"
}
}
Compila y ejecuta:
# Compilar TypeScript
npm run build
# Ejecutar servidor
npm start
Conectar con Claude Desktop
Para usar tu servidor con Claude Desktop, añádelo a la configuración:
En macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
En Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"calculadora": {
"command": "node",
"args": ["/ruta/a/tu/proyecto/dist/index.js"]
}
}
}
Reinicia Claude Desktop y tu servidor estará disponible.
Ejemplo con recursos
Además de herramientas, puedes exponer recursos (datos):
import { ListResourcesRequestSchema, ReadResourceRequestSchema } from "@modelcontextprotocol/sdk/types.js";
// Listar recursos disponibles
server.setRequestHandler(ListResourcesRequestSchema, async () => {
return {
resources: [
{
uri: "config://settings",
name: "Configuración de la app",
mimeType: "application/json",
},
],
};
});
// Leer un recurso específico
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;
if (uri === "config://settings") {
return {
contents: [
{
uri,
mimeType: "application/json",
text: JSON.stringify({
theme: "dark",
language: "es",
version: "1.0.0",
}, null, 2),
},
],
};
}
throw new Error(`Recurso no encontrado: ${uri}`);
});
Debugging
Para debug, usa console.error() (no console.log, que interfiere con el protocolo):
server.setRequestHandler(CallToolRequestSchema, async (request) => {
console.error("Recibida petición:", request.params);
// ... tu código
});
Mejores prácticas
1. Validación de entrada
function validateNumber(value: any): number {
if (typeof value !== "number" || isNaN(value)) {
throw new Error(`Valor inválido: ${value}`);
}
return value;
}
2. Manejo de errores
try {
const result = await operacionRiesgosa();
return { content: [{ type: "text", text: result }] };
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${error instanceof Error ? error.message : "Desconocido"}`,
},
],
isError: true,
};
}
3. Logging estructurado
console.error(JSON.stringify({
timestamp: new Date().toISOString(),
level: "info",
message: "Herramienta ejecutada",
tool: name,
}));
Próximos pasos
Ahora que tienes tu primer servidor MCP funcionando, puedes:
- Añadir más herramientas complejas
- Conectar con bases de datos
- Integrar con APIs externas
- Publicar tu servidor en el MCP Registry
Conclusión
Has aprendido a:
- ✅ Instalar y configurar el SDK de MCP
- ✅ Crear un servidor MCP básico
- ✅ Definir herramientas y recursos
- ✅ Conectar con Claude Desktop
- ✅ Implementar mejores prácticas
En el próximo artículo exploraremos el MCP Registry y cómo compartir tus servidores con la comunidad.
Post anterior: Introducción al Model Context Protocol
Próximo post: El Registry de MCP: Descubre Servidores Públicos
Recursos: