MCP Hub
Un MCP Hub ligero para centralizar tus servidores M
Documentación
MCP-Hub
Un hub basado en Go que agrega múltiples servidores MCP (Model Context Protocol) y expone sus herramientas a través de una API HTTP unificada.
Características
- Protocolo MCP estándar: Soporte completo para la especificación MCP 2024-11-05
- Múltiples tipos de transporte:
- Stdio: Para servidores MCP locales (Node.js, Python, etc.)
- HTTP/SSE: Para servidores MCP remotos
- Basado en configuración: Configuración JSON compatible con el formato de Cursor/VSCode
- Listo para Docker: Despliegue fácil en contenedores con montajes de volúmenes
- Agregación de herramientas: Combina herramientas de múltiples servidores MCP en un solo lugar
- API HTTP: Endpoints RESTful para descubrimiento y ejecución de herramientas
Inicio Rápido
1. Compilar
cd cmd/mcp-hub
go build -o ../../mcp-hub
2. Crear Configuración
Crea un archivo config.json (consulta config.example.json para una plantilla):
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
3. Ejecutar
# Using default config.json
./mcp-hub
# Or specify a config file
./mcp-hub --config /path/to/config.json
Notas:
- La dirección de escucha HTTP se puede sobrescribir con la variable de entorno
MCP_HUB_PORToPORT. Si el valor contiene dos puntos, se trata como una dirección completa (por ejemplo,0.0.0.0:8080); de lo contrario, se trata como un puerto y se le antepone dos puntos. - El binario acepta un flag
--config(por defecto:config.json).
4. Usar la API
Listar todas las herramientas disponibles:
curl http://localhost:8080/mcp/tools
Ejecutar una herramienta:
curl -X POST http://localhost:8080/mcp/execute \
-H 'Content-Type: application/json' \
-d '{
"plugin_id": "filesystem",
"tool_name": "read_file",
"arguments": {"path": "/tmp/test.txt"}
}'
Listar servidores conectados:
curl http://localhost:8080/mcp/servers
Formato de Configuración
El archivo de configuración utiliza el formato estándar mcpServers compatible con Cursor, VSCode y Claude Desktop.
Servidores Stdio (Locales)
Para servidores MCP que se ejecutan como procesos locales:
{
"mcpServers": {
"server-name": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-package"],
"env": {
"API_KEY": "${YOUR_API_KEY}"
},
"timeout": 30
}
}
}
Campos:
command: Ejecutable a ejecutar (requerido)args: Argumentos de línea de comandos (opcional)env: Variables de entorno (opcional, admite expansión de${VAR})timeout: Tiempo de espera de solicitud en segundos (opcional, por defecto: 30)disabled: Establecer entruepara deshabilitar un servidor (opcional)
Servidores HTTP (Remotos)
Para servidores MCP accesibles vía HTTP:
{
"mcpServers": {
"remote-server": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
},
"timeout": 45
}
}
}
Campos:
type: Establecer en"http"para transporte HTTP (o auto-detectado desdeurl)url: URL del endpoint HTTP (requerido)headers: Cabeceras HTTP a incluir (opcional, admite expansión de${VAR})timeout: Tiempo de espera de solicitud en segundos (opcional, por defecto: 30)
Variables de Entorno
Las variables de entorno en la configuración se expanden usando la sintaxis ${VAR_NAME}. Por ejemplo:
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
Luego ejecuta:
GITHUB_TOKEN=your_token_here ./mcp-hub
Despliegue con Docker
Variantes de Imagen
El repositorio proporciona dos variantes de imagen Docker, optimizadas para diferentes casos de uso:
1. Imagen Estándar (Dockerfile / mcp-hub:latest)
- Tamaño: ~47MB
- Incluye: Alpine Linux + CLI de Docker + binario mcp-hub
- Úsala cuando: Necesites transporte Docker para ejecutar servidores MCP en contenedores, o transportes mixtos
- Mejor para: Despliegues de producción con servidores MCP basados en contenedores
2. Imagen de Servidores MCP Locales (Dockerfile.local / mcp-hub:local)
- Tamaño: ~800MB
- Incluye: Node.js 20, Python 3, uv, curl, git y binario mcp-hub
- Úsala cuando: Quieras ejecutar servidores MCP locales basados en stdio (Node.js, Python) en el mismo contenedor
- Mejor para: Despliegues autocontenidos donde el hub y todos los servidores MCP se ejecutan juntos
Compilar Imagen Docker
Para compilar una imagen específica localmente:
# Standard image (with Docker CLI)
docker build -t mcp-hub:latest .
# Local MCP servers image (with Node.js, Python, uv)
docker build -f Dockerfile.local -t mcp-hub:local .
Ejecutar con Docker
# Create a config directory
mkdir -p config
# Put your config.json in the config directory
cp config.json config/
# Run the container
docker run -d \
-p 8080:8080 \
-v $(pwd)/config:/config:ro \
-e GITHUB_TOKEN=${GITHUB_TOKEN} \
mcp-hub
Docker Compose
version: '3.8'
services:
mcp-hub:
build: .
ports:
- "8080:8080"
volumes:
- ./config:/config:ro
- ./plugins:/plugins:ro # Optional: mount custom plugins
environment:
- GITHUB_TOKEN=${GITHUB_TOKEN}
- BRAVE_API_KEY=${BRAVE_API_KEY}
Referencia de la API HTTP
GET /mcp/tools
Lista todas las herramientas disponibles de todos los servidores MCP conectados.
Respuesta:
[
{
"id": "read_file",
"name": "read_file",
"description": "Read contents of a file",
"plugin_id": "filesystem"
}
]
POST /mcp/execute
Ejecuta una herramienta en un servidor MCP específico.
Solicitud:
{
"plugin_id": "filesystem",
"tool_name": "read_file",
"arguments": {
"path": "/tmp/test.txt"
}
}
Respuesta: Resultado de la llamada a la herramienta MCP (el formato depende de la herramienta)
GET /mcp/servers
Lista todos los servidores MCP conectados.
Respuesta:
{
"servers": ["filesystem", "github", "brave-search"]
}
GET /mcp/stream
Flujo de eventos enviados por el servidor (Server-Sent Events) de actualizaciones del registro de herramientas (para descubrimiento de herramientas en tiempo real).
Ejemplos
Ejemplo 1: Usando Servidores MCP Oficiales
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"brave-search": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
"env": {
"BRAVE_API_KEY": "${BRAVE_API_KEY}"
}
}
}
}
Ejemplo 2: Servidor MCP Python Personalizado
{
"mcpServers": {
"custom-tools": {
"command": "python3",
"args": ["/app/plugins/custom_mcp_server.py"]
}
}
}
Ejemplo 3: Servidores Mixtos Locales y Remotos
{
"mcpServers": {
"local-filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
},
"remote-api": {
"type": "http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}
Desarrollo
Estructura del Proyecto
.
├── cmd/
│ └── mcp-hub/
│ └── main.go # Entry point
├── internal/
│ ├── config/
│ │ └── config.go # Configuration parsing
│ ├── mcp/
│ │ └── protocol.go # MCP protocol structures
│ ├── plugin/
│ │ └── manager.go # Server management
│ ├── registry/
│ │ └── registry.go # Tool registry
│ ├── server/
│ │ └── server.go # HTTP server
│ └── transport/
│ ├── transport.go # Transport interface
│ ├── stdio.go # Stdio transport
│ └── http.go # HTTP transport
├── config.example.json # Example configuration
└── README.md
Agregar Nuevos Tipos de Transporte
Implementa la interfaz Transport en internal/transport/:
type Transport interface {
Start(ctx context.Context) error
SendRequest(ctx context.Context, req interface{}) (json.RawMessage, error)
SendNotification(ctx context.Context, notification interface{}) error
Close() error
IsConnected() bool
}
Solución de Problemas
El servidor no se inicia
Revisa los registros para mensajes de error específicos. Problemas comunes:
- Falta
npxopython3en PATH - Nombres de paquetes de servidor MCP inválidos
- Variables de entorno faltantes
- Rutas de archivo incorrectas en la configuración
La ejecución de herramientas falla
- Verifica que el servidor MCP esté correctamente inicializado (revisa
/mcp/servers) - Asegúrate de que los argumentos de la herramienta coincidan con el esquema esperado
- Revisa los registros del servidor (la salida de stderr es visible en los registros del hub)
Errores de tiempo de espera
Aumenta el valor de timeout en la configuración del servidor:
{
"mcpServers": {
"slow-server": {
"command": "...",
"timeout": 120
}
}
}
Licencia
MIT
Servidores Docker (Contenedorizados)
Para servidores MCP que se ejecutan en contenedores Docker:
{
"mcpServers": {
"containerized-server": {
"type": "docker",
"image": "my-mcp-server:latest",
"args": ["--option", "value"],
"env": {
"API_KEY": "${YOUR_API_KEY}"
},
"volumes": {
"/host/path": "/container/path",
"${HOME}/data": "/data"
},
"network": "mcp-network",
"timeout": 60
}
}
}
Campos:
type: Establecer en"docker"para transporte Docker (o auto-detectado desdeimage)image: Nombre de la imagen Docker (requerido)args: Argumentos de comando para pasar al entrypoint del contenedor (opcional)env: Variables de entorno (opcional, admite expansión de${VAR})volumes: Montajes de volúmenes como asignaciones dehost:container(opcional, admite expansión de${VAR})network: Red Docker a la que conectarse (opcional)timeout: Tiempo de espera de solicitud en segundos (opcional, por defecto: 30)
Beneficios del Transporte Docker:
- No es necesario instalar Node.js, Python u otros runtimes en el host del hub
- Dependencias aisladas por servidor MCP
- Gestión de versiones fácil con etiquetas Docker
- Entorno consistente en todos los despliegues
Compilación de Imágenes Docker para Servidores MCP
Puedes contenerizar cualquier servidor MCP para evitar instalar sus dependencias en el host del hub.
Ejemplo: Dockerizando un Servidor MCP Python
Dockerfile:
FROM python:3.11-slim
WORKDIR /app
# Install dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy MCP server code
COPY mcp_server.py .
# Run as non-root user
RUN useradd -m -u 1000 mcpuser && chown -R mcpuser:mcpuser /app
USER mcpuser
# The server should read from stdin and write to stdout
ENTRYPOINT ["python", "-u", "mcp_server.py"]
Compilar y usar:
# Build the image
docker build -t my-mcp-server:latest .
# Add to config.json
{
"mcpServers": {
"my-server": {
"image": "my-mcp-server:latest"
}
}
}
Ejemplo: Dockerizando un Servidor MCP Node.js
Dockerfile:
FROM node:20-alpine
WORKDIR /app
# Install dependencies
COPY package*.json ./
RUN npm ci --production
# Copy server code
COPY . .
# Run as non-root user
RUN addgroup -g 1000 mcpuser && \
adduser -D -u 1000 -G mcpuser mcpuser && \
chown -R mcpuser:mcpuser /app
USER mcpuser
ENTRYPOINT ["node", "server.js"]
Notas Importantes para Servidores MCP Docker
- Usa el flag
-i: El hub ejecuta contenedores condocker run -ipara stdin/stdout interactivo - Salida sin buffer: Asegúrate de que las salidas de tu servidor no tengan buffer (usa
python -uoflush()) - Solo stdin/stdout: El protocolo MCP usa stdin para entrada y stdout para salida
- stderr para registros: Usa stderr para registro (visible en los registros del hub)
- Limpieza: Los contenedores se ejecutan con
--rmpara limpieza automática
Imágenes de Servidores MCP Precompiladas
Crea un registro de imágenes Docker para servidores MCP comunes:
# Example: Build an echo server image
cd examples/plugins
cat > Dockerfile << 'DOCKERFILE'
FROM python:3.11-slim
COPY mcp_echo.py /app/server.py
WORKDIR /app
RUN chmod +x server.py
ENTRYPOINT ["python", "-u", "server.py"]
DOCKERFILE
docker build -t mcp-echo:latest .
Luego úsalo:
{
"mcpServers": {
"echo": {
"image": "mcp-echo:latest"
}
}
}
Comparación de Transportes
| Transporte | Caso de Uso | Ventajas | Desventajas |
|---|---|---|---|
| stdio | Servidores MCP locales con acceso directo | Rápido, baja sobrecarga | Requiere runtime (Node.js/Python) instalado |
| Docker | Servidores MCP aislados y reproducibles | Sin dependencias de runtime, versionado fácil | Sobrecarga ligeramente mayor, requiere Docker |
| HTTP | Servidores MCP remotos/alojados en la nube | Escalable, puede equilibrarse la carga | Latencia de red, requiere infraestructura de servidor |
Cuándo Usar Transporte Docker
Elige transporte Docker cuando:
- ✅ Quieras evitar instalar Node.js, Python u otros runtimes en tu host del hub
- ✅ Necesites entornos consistentes y reproducibles en todos los despliegues
- ✅ Quieras gestión de versiones fácil con etiquetas Docker
- ✅ Estés ejecutando el hub en un entorno contenerizado (Kubernetes, Docker Compose)
- ✅ Necesites aislar dependencias de servidores
- ✅ Quieras usar imágenes de servidores MCP precompiladas de un registro
Elige transporte stdio cuando:
- ✅ Estés desarrollando localmente y quieras iteración más rápida
- ✅ Las dependencias de runtime ya estén instaladas
- ✅ Necesites la latencia más baja posible
Elige transporte HTTP cuando:
- ✅ Los servidores MCP estén alojados remotamente
- ✅ Necesites escalar servidores de forma independiente
- ✅ Quieras usar servicios de servidores MCP gestionados
Ejemplo: Configuración Docker Completa
Aquí hay un ejemplo completo ejecutando múltiples servidores MCP en Docker:
# 1. Build your custom MCP server image
docker build -t my-mcp-server:v1.0 ./my-server
# 2. Create Docker network for inter-container communication
docker network create mcp-network
# 3. Configure servers
cat > config.json << 'JSON'
{
"mcpServers": {
"echo": {
"image": "mcp-echo:latest"
},
"custom-tools": {
"image": "my-mcp-server:v1.0",
"env": {
"API_KEY": "${MY_API_KEY}"
},
"volumes": {
"/host/data": "/data"
}
}
}
}
JSON
# 4. Run the hub
MY_API_KEY=secret123 ./mcp-hub --config config.json
Esta configuración te ofrece:
- ✨ Sin dependencias de runtime en el host del hub
- ✨ Entornos aislados para cada servidor MCP
- ✨ Actualizaciones fáciles cambiando etiquetas de imágenes Docker
- ✨ Despliegues reproducibles
Despliegue Contenerizado
El propio mcp-hub puede ejecutarse en un contenedor Docker. Consulta DOCKER_DEPLOYMENT.md para la guía de despliegue completa.
Despliegue Docker Rápido
# Build the image
docker build -t mcp-hub:latest .
# Run with your config
docker run -d \
--name mcp-hub \
-p 8080:8080 \
-v $(pwd)/config.json:/app/config.json:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
-e GITHUB_TOKEN=${GITHUB_TOKEN} \
mcp-hub:latest
O usa Docker Compose
docker-compose up -d
Tamaños de Imagen:
- Estándar (con CLI de Docker): ~47MB
- Mínima (solo stdio/HTTP): ~6MB
Las variables de entorno se pasan automáticamente y se expanden en tu configuración.
Vigilancia del Archivo de Configuración
El MCP Hub vigila automáticamente el archivo de configuración para detectar cambios y actualiza el registro en consecuencia. Cuando modificas config.json, el hub:
- Agrega nuevos servidores: Inicia automáticamente cualquier servidor MCP recién agregado
- Elimina servidores: Detiene servidores que se eliminan de la configuración o se deshabilitan
- Recarga servidores: Reinicia servidores cuya configuración ha cambiado
- Actualiza el registro: Mantiene el registro de herramientas sincronizado con los servidores activos
Cómo Funciona
El vigilante usa fsnotify para monitorear el archivo de configuración en busca de eventos de escritura. Cuando se detectan cambios:
- Se carga y valida la nueva configuración
- Se comparan los cambios con la configuración anterior
- Se toman las acciones apropiadas (iniciar/detener/recargar servidores)
- El registro se actualiza automáticamente
- Los cambios se registran para visibilidad
Debounce
Para evitar procesar cambios rápidos sucesivos (por ejemplo, cuando los editores escriben múltiples veces), el vigilante incluye un retraso de debounce de 500ms. Esto asegura que la configuración solo se recargue una vez después de que termines de editar.
Ejemplo
# Start mcp-hub
./mcp-hub --config=config.json
# In another terminal, edit config.json
vim config.json
# The hub will automatically detect changes and log:
# "config file changed, reloading..."
# "adding server: new-server"
# "loaded MCP server: new-server (stdio transport)"
Manejo de Errores
Si la nueva configuración contiene errores:
- JSON inválido: Los cambios se rechazan, el hub continúa con la configuración anterior
- Campos requeridos faltantes: Los cambios se rechazan con error de validación
- Fallos de inicio de servidores: Se registran como advertencias, otros servidores continúan ejecutándose