Requisitos previos
Necesario antes de empezar
-
TypeScriptNode.js 18 o 20 o superior, gestor de paquetes npm/pnpm/bun y familiaridad básica con TypeScript y Zod
-
PythonPython 3.10 o superior, el gestor uv (o pip) y nociones de async/await y tipado
-
Cliente de pruebaClaude Desktop instalado localmente o la CLI MCP Inspector (mcp dev)
Configuración del entorno
Configurar el proyecto en TypeScript
Crea el directorio de trabajo e inicializa el proyecto Node.js.
mkdir mcp-servidor-ts
cd mcp-servidor-ts
npm init -y
Instala el SDK oficial de servidores MCP, las utilidades de Node.js y la librería de validación Zod.
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node
Configura package.json para soportar módulos ES2022 y el script de compilación.
{
"name": "mcp-servidor-ts",
"version": "1.0.0",
"type": "module",
"main": "build/index.js",
"scripts": {
"build": "tsc"
}
}
Crea tsconfig.json con la configuración de compilación.
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true
},
"include": ["src/**/*"]
}
Configurar el proyecto en Python
Usa uv para inicializar el proyecto y crear el entorno virtual.
# Inicializar el proyecto e instalar dependencias
uv init mcp-servidor-python
cd mcp-servidor-python
uv venv
source .venv/bin/activate # En Windows: .venv\Scripts\activate
Agrega el SDK oficial de Python con la CLI integrada.
uv add "mcp[cli]"
Implementación del servidor
Implementar el servidor en TypeScript
Crea src/index.ts. Este servidor expone una Tool para consultar métricas, un Resource con la política de alertas y un Prompt de diagnóstico guiado.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
// 1. Inicialización de la instancia del servidor MCP
const server = new McpServer({
name: "servidor-metricas-ts",
version: "1.0.0",
});
// 2. Definición de una Tool (Acción con parámetros validados por Zod)
server.registerTool(
"obtener_rendimiento",
{
description: "Obtiene el porcentaje de uso de CPU y memoria de un servidor remoto.",
inputSchema: z.object({
servidorId: z.string().describe("Identificador único del servidor (ej. srv-01)"),
}),
},
async ({ servidorId }) => {
// Registro de logs seguro enviado a stderr
console.error(`[INFO] Consultando métricas para: ${servidorId}`);
// Respuesta estructurada requerida por el protocolo
return {
content: [
{
type: "text",
text: `Servidor ${servidorId}: Uso de CPU al 42%, Memoria al 68%. Estado: Saludable.`,
},
],
};
}
);
// 3. Definición de un Resource (Datos de solo lectura)
server.registerResource(
"politica_alerta",
"config://politica-alerta",
{
name: "Política de Alertas",
description: "Límites estipulados para el disparo de alertas de infraestructura.",
mimeType: "text/plain",
},
async (uri) => ({
contents: [
{
uri: uri.href,
text: "Límite crítico CPU: 90%. Límite crítico Memoria: 85% sostenido por 5 min.",
},
],
})
);
// 4. Definición de un Prompt (Plantilla de usuario)
server.registerPrompt(
"diagnosticar_servidor",
{
description: "Genera un análisis guiado sobre la salud del servidor.",
args: {
servidorId: z.string().describe("ID del servidor a revisar"),
},
},
({ servidorId }) => ({
messages: [
{
role: "user",
content: {
type: "text",
text: `Por favor analiza las métricas del servidor ${servidorId}, verifica si excede la politica_alerta y recomienda acciones.`,
},
},
],
})
);
// 5. Conexión e inicio del transporte STDIO
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Servidor MCP TypeScript ejecutándose en STDIO");
}
main().catch((error) => {
console.error("Error fatal en main():", error);
process.exit(1);
});
Compila el código ejecutando npx tsc; el archivo resultante queda en build/index.js.
npx tsc
Implementar el servidor en Python
Crea servidor.py con la misma funcionalidad, usando el SDK de Python vía decoradores.
import logging
from typing import Any
from mcp.server.fastmcp import FastMCP
# Configuración de logs dirigidos strictly a stderr
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("servidor-python")
# 1. Inicialización de la instancia del servidor MCP con FastMCP
mcp = FastMCP("servidor-metricas-py")
# 2. Definición de Tool mediante decoradores sintácticos
@mcp.tool()
def obtener_rendimiento(servidor_id: str) -> str:
"""Obtiene el porcentaje de uso de CPU y memoria de un servidor remoto.
Args:
servidor_id: Identificador único del servidor (ej. srv-01)
"""
logger.error(f"[INFO] Consultando servidor Python: {servidor_id}")
return f"Servidor {servidor_id} (Py): Uso de CPU al 38%, Memoria al 55%. Estado: Óptimo."
# 3. Definición de Resource (Lectura de contexto estático)
@mcp.resource("config://politica-alerta")
def obtener_politica() -> str:
"""Devuelve las políticas de alerta predeterminadas del sistema."""
return "Regla Py: Notificar si el uso de disco supera el 95%."
# 4. Definición de Prompt reutilizable
@mcp.prompt("reporte_rapido")
def plantilla_reporte(servidor_id: str) -> str:
"""Plantilla para solicitar un informe ejecutivo rápido."""
return f"Genera un resumen ejecutivo de un párrafo sobre el estado actual de {servidor_id}."
# 5. Punto de entrada para ejecución en transporte STDIO
if __name__ == "__main__":
mcp.run(transport="stdio")
Extensiones: MCP Tasks y MCP Apps
La especificación publicada el 2026-07-28 añade dos extensiones opcionales sobre el núcleo del protocolo: MCP Tasks, para operaciones asíncronas de larga duración, y MCP Apps, para interfaces interactivas incrustadas en la ventana de chat.
Extensiones de la especificación
-
MCP Tasks (SEP-2663)Convierte una llamada larga en un objeto task con un taskId duradero y estado inicial working; el cliente sondea con tasks/get hasta completed, failed o cancelled, y usa tasks/update si entra en input_required
-
MCP Apps (SEP-1865)Vincula una herramienta a una interfaz mediante _meta.ui.resourceUri (esquema ui://); el host la renderiza en un iframe aislado, sin acceso a cookies, almacenamiento local ni al DOM del host
Pruebas y despliegue en Claude Desktop
Probar con MCP Inspector
Ejecuta el inspector apuntando al script de Python o al build de TypeScript.
# Para el servidor Python
uv run mcp dev servidor.py
# Para el servidor TypeScript
npx @modelcontextprotocol/inspector node build/index.js
El inspector abre una interfaz web local donde se puede ejecutar la herramienta obtener_rendimiento y revisar la respuesta JSON, sin escrituras accidentales en stdout.
Configurar Claude Desktop
Edita el archivo de configuración global claude_desktop_config.json. Las rutas predeterminadas son:
Ruta del archivo de configuración
-
macOS~/Library/Application Support/Claude/claude_desktop_config.json
-
Windows%APPDATA%\Claude\claude_desktop_config.json
Agrega la clave mcpServers con ambos servidores y sus rutas absolutas.
{
"mcpServers": {
"metricas-ts": {
"command": "node",
"args": [
"/RUTA/ABSOLUTA/A/mcp-servidor-ts/build/index.js"
]
},
"metricas-python": {
"command": "uv",
"args": [
"--directory",
"/RUTA/ABSOLUTA/A/mcp-servidor-python",
"run",
"servidor.py"
]
}
}
}
Nota: en Windows, escapa las barras invertidas de las rutas con doble barra (C:\\Ruta\\Al\\Proyecto).
Verificar el funcionamiento
Checklist de verificación
Cerrar Claude Desktop
Cierra completamente la aplicación desde la barra de estado o la bandeja del sistema.
Reabrir la aplicación
Inicia Claude Desktop nuevamente.
Revisar las herramientas
Abre el icono de herramientas del chat y confirma que aparecen obtener_rendimiento de ambos servidores.
Hacer una consulta de prueba
Realiza una consulta como "¿Cuál es el estado de rendimiento del servidor srv-01?".
Preguntas que podrían surgir durante el proceso de implementación:
¿Por qué no aparece el servidor en Claude Desktop?
Revisa la sintaxis de claude_desktop_config.json con un validador JSON y confirma que las rutas registradas sean absolutas.
¿Qué hacer si la llamada a la herramienta falla sin mostrar error?
Consulta los logs en ~/Library/Logs/Claude/mcp-server-<nombre>.log (macOS) o %APPDATA%\Claude\logs\ (Windows/Linux) para ver la salida enviada a stderr.
Seguridad en producción
Medidas defensivas mínimas
Sanear las entradas
Valida de forma estricta los argumentos de las herramientas para prevenir inyección de comandos en el transporte STDIO.
Aislar los procesos
Ejecuta los servidores MCP en contenedores con permisos de sistema de archivos limitados, bajo el principio de mínimo privilegio.
Asegurar el transporte remoto
Exige OAuth 2.1/OIDC y validación del emisor (RFC 9207) al migrar a Streamable HTTP.
Próximos pasos
Con el servidor corriendo en local, el siguiente paso natural es conectar herramientas reales a bases de datos SQL, Supabase o APIs de CRM, aprovechar MCP Tasks para procesos pesados y diseñar paneles con MCP Apps dentro del flujo de conversación.
Como práctica adicional, despliega un servidor en Streamable HTTP con Express o Fastify en TypeScript, o con FastMCP en Python, e integra autenticación centralizada para servicios empresariales.
Etiquetas
¿Te gustó este artículo? ¡Compártelo y suscríbete!