Cómo construir tu propio servidor MCP desde cero
Tutorial técnico para construir un servidor MCP (Model Context Protocol): qué expone, su arquitectura, código mínimo en Python y TypeScript con el SDK oficial, cómo probarlo con MCP Inspector y conectarlo a Claude.
Un servidor MCP (Model Context Protocol) es la forma estándar de darle a Claude —o a cualquier cliente compatible— acceso a tus datos y acciones: una base de datos, una API interna, un sistema de archivos. En Cognitiva, agencia chilena de IA, construimos servidores MCP para conectar agentes a los sistemas reales de nuestros clientes, y la buena noticia es que un servidor mínimo se levanta en menos de 50 líneas. Este tutorial parte de cero: qué expone un servidor MCP (tools, resources y prompts), cómo es su arquitectura (JSON-RPC sobre stdio o HTTP), el código mínimo con el SDK oficial en Python y TypeScript, y cómo probarlo con MCP Inspector y conectarlo a Claude Desktop y Claude Code. Todo el código es fiel a la documentación oficial vigente (especificación 2025-11-25). Para el concepto de negocio detrás de MCP, complementa con nuestro artículo de MCP para CIO.
Qué expone un servidor MCP: tres primitivas
Un servidor MCP ofrece funcionalidad mediante tres primitivas. La distinción clave es quién las controla:
| Primitiva | Qué es | Quién la controla |
|---|---|---|
| Tools | Funciones que el modelo puede invocar para ejecutar acciones (consultar BD, llamar API, escribir archivos) | El modelo |
| Resources | Datos de solo lectura para dar contexto (archivos, esquemas, documentación) | La aplicación |
| Prompts | Plantillas de instrucción reutilizables que el usuario dispara (slash commands) | El usuario |
Regla práctica: si el modelo necesita hacer algo con efecto (crear, modificar, llamar), es una tool. Si solo necesita leer contexto, es un resource. Si quieres ofrecer un flujo de trabajo que el usuario invoca explícitamente, es un prompt. La mayoría de los servidores empiezan exponiendo una o dos tools.
Arquitectura en dos minutos
MCP sigue un modelo host–cliente–servidor. El **host** es la aplicación de IA (Claude Desktop, Claude Code, una IDE); crea un **cliente** por cada servidor, con conexión dedicada; el **servidor** —el que vas a construir— provee las capacidades.
La comunicación usa **JSON-RPC 2.0** y es con estado: hay un handshake de inicialización que negocia capacidades. Sobre eso corren dos transportes estándar:
- **stdio**: el cliente lanza tu servidor como subproceso y se comunican por entrada/salida estándar. Ideal para servidores locales; máximo rendimiento, sin red. Es por donde conviene empezar.
- **Streamable HTTP**: un endpoint HTTP único (con SSE opcional para streaming) para servidores remotos, con autenticación estándar. Reemplazó al antiguo transporte HTTP+SSE.
Para un primer servidor local, stdio es todo lo que necesitas.
Los SDK oficiales
Hay SDK oficiales que hacen el trabajo pesado del protocolo. Los dos más usados:
- **TypeScript**: paquete `@modelcontextprotocol/sdk` (instala también `zod` para los esquemas). La clase de alto nivel es `McpServer`.
- **Python**: paquete `mcp`, que incluye `FastMCP`. Genera la definición de la tool a partir de los type hints y el docstring de tu función.
Nota de versión: existe una v2 modular en preparación, pero a la fecha la versión estable y recomendada para producción es la línea v1 que usa el quickstart oficial. Este tutorial usa la API v1 estable.
Un servidor mínimo en Python (FastMCP)
Instala con `pip install "mcp[cli]"` (o `uv add "mcp[cli]"`). Un servidor con una tool y transporte stdio:
from mcp.server.fastmcp import FastMCP
# Inicializa el servidor
mcp = FastMCP("clima")
@mcp.tool()
async def alertas(estado: str) -> str:
"""Entrega alertas de clima para un estado.
Args:
estado: codigo de dos letras (ej. CA, NY)
"""
# ... aqui va la logica real: consultar una API, una BD, etc.
return "Sin alertas para " + estado
if __name__ == "__main__":
# Arranca el servidor sobre stdio
mcp.run(transport="stdio")Lo importante: FastMCP infiere el esquema de entrada de los type hints (`estado: str`) y la descripción de la tool del docstring. Regla crítica de stdio: **nunca escribas a stdout** (un `print` corrompe el protocolo JSON-RPC); usa `logging` o escribe a stderr.
El mismo servidor en TypeScript
Instala con `npm install @modelcontextprotocol/sdk zod` y usa `"type": "module"` en tu `package.json`:
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: "clima", version: "1.0.0" });
server.registerTool(
"alertas",
{
description: "Entrega alertas de clima para un estado",
inputSchema: {
estado: z.string().length(2).describe("Codigo de dos letras, ej. CA"),
},
},
async ({ estado }) => {
// ... logica real (API, BD) ...
return { content: [{ type: "text", text: "Sin alertas para " + estado }] };
},
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Servidor MCP de clima corriendo en stdio");
}
main().catch((e) => {
console.error("Error fatal:", e);
process.exit(1);
});Toda tool devuelve un objeto con un array `content` (cada item con su `type`, por ejemplo `"text"`), que es lo que el cliente entrega al modelo. Misma regla de stdio: usa `console.error` (stderr), nunca `console.log`.
Probarlo y conectarlo a Claude
MCP Inspector (debug local)
Antes de conectarlo a un cliente real, pruébalo con el inspector oficial, que corre sin instalación:
# TypeScript ya compilado
npx @modelcontextprotocol/inspector node ruta/al/servidor/index.js
# Python con uv
npx @modelcontextprotocol/inspector uv --directory ruta/al/proyecto run servidor.pyEl inspector lista tus tools, resources y prompts, muestra sus esquemas y te deja ejecutarlos con inputs de prueba. Prueba siempre los casos borde (inputs inválidos, faltantes).
Claude Desktop
Edita el archivo de configuración (`claude_desktop_config.json`) y usa rutas absolutas:
{
"mcpServers": {
"clima": {
"command": "node",
"args": ["/RUTA/ABSOLUTA/clima/build/index.js"]
}
}
}Guarda y reinicia Claude Desktop.
Claude Code (CLI)
El separador `--` divide las opciones de Claude del comando que lanza tu servidor:
claude mcp add --transport stdio clima -- node ruta/al/servidor/index.js
claude mcp list # ver servidores y estado de conexionBuenas prácticas y seguridad
- **Nombres y descripciones claras.** El modelo decide cuándo llamar una tool a partir de su descripción; sé explícito sobre qué hace y cuándo usarla.
- **Valida los inputs.** Define el esquema con precisión (tipos, longitudes, enums) y rechaza lo malformado.
- **Nunca escribas a stdout en stdio.** Rompe el protocolo. Usa stderr o logging.
- **Las tools son ejecución de código.** Pide consentimiento del usuario para acciones con efecto y trata las descripciones de servidores externos como no confiables.
- **No al token passthrough.** Un servidor MCP no debe aceptar tokens que no fueron emitidos para él; valida emisor, expiración, scopes y audiencia.
- **Secretos por variables de entorno**, nunca en el código. Para servidores locales, prefiere stdio para limitar el acceso al cliente.
- **Errores como contenido**, no excepciones sin control: devuelve el error dentro del resultado de la tool para que el modelo pueda reaccionar.
¿Cuándo construir uno propio?
Antes de programar, revisa si ya existe un servidor MCP para lo que necesitas (hay servidores oficiales y de la comunidad para GitHub, Postgres, Slack, sistemas de archivos y más). Construye uno propio cuando: necesitas conectar un sistema interno o propietario, requieres lógica de negocio específica, o necesitas control fino sobre seguridad y permisos.
En proyectos reales, el servidor MCP propio es el puente entre un agente y los sistemas que ninguna integración genérica cubre: tu ERP, tu base de conocimiento, tu API interna. Empieza con una tool, pruébala en el inspector y crece desde ahí.
Construir un servidor MCP en 5 pasos
De cero a un servidor conectado a Claude.
- Paso 1
Preparar
Entorno y SDK.
- Elegir lenguaje (Python o TypeScript)
- Instalar el SDK oficial
- Decidir qué tool expondrá
- Paso 2
Implementar
La tool y el transporte.
- Definir la tool con su esquema de entrada
- Escribir la lógica (API, BD)
- Arrancar el transporte stdio
- Paso 3
Probar
Validar antes de conectar.
- Lanzar MCP Inspector
- Ejecutar la tool con inputs de prueba
- Probar casos borde y errores
- Paso 4
Conectar
Al cliente real.
- Registrar en Claude Desktop o Claude Code
- Verificar el estado de conexión
- Paso 5
Endurecer
Producción.
- Validación de inputs y manejo de errores
- Secretos por entorno y control de acceso
Preguntas frecuentes
Da el siguiente paso
Hablemos
Cuéntanos sobre tu negocio. Respondemos en 24 horas.
Otros canales
Escríbenos por WhatsApp o agenda una llamada de 30 minutos.