Skip to main content
Glama

mcpstead

CI npm version Crates.io License

Puerta de enlace MCP

Un punto final /mcp descendente que sirve de interfaz para muchos servidores MCP ascendentes. Conexiones ascendentes persistentes con reconexión, registro de herramientas con nombres calificados, respuestas JSON o SSE basadas en el Accept del cliente, autenticación por servidor ascendente y métricas de Prometheus.

Instalación

# npm (macOS, Linux, WSL)
npm i -g @ahkohd/mcpstead

# homebrew (macOS, Linux)
brew install ahkohd/tap/mcpstead

# cargo
cargo install mcpstead --locked --force

# verify
mcpstead --version

Related MCP server: Mavryn

Inicio rápido

# 1. write a config
mkdir -p ~/.config/mcpstead
cat > ~/.config/mcpstead/config.yaml <<'EOF'
host: 0.0.0.0
port: 8766

mcp:
  auth:
    mode: none

servers:
  - name: example
    url: http://127.0.0.1:3000/mcp
    protocol: streamable
    auth: none
EOF

# 2. run
mcpstead --config ~/.config/mcpstead/config.yaml

Luego, apunta cualquier cliente MCP a http://127.0.0.1:8766/mcp.

Docker

docker build -t mcpstead .
docker run --rm \
  -p 8766:8766 \
  -v "$PWD/config:/etc/mcpstead:ro" \
  mcpstead

El Dockerfile se instala desde crates.io.

API HTTP

Método

Ruta

Propósito

POST

/mcp

MCP sobre HTTP JSON-RPC

GET

/mcp

devuelve 405

DELETE

/mcp

terminar sesión descendente

GET

/health

estado ascendente, recuento de herramientas, última vez visto, reconexiones

GET

/metrics

formato de texto de Prometheus

POST

/-/reload

recargar configuración sin reiniciar

Configuración del cliente MCP

Local, sin autenticación:

mcpstead:
  url: http://127.0.0.1:8766/mcp
  tools:
    resources: false
    prompts: false

Autenticación Bearer:

mcpstead:
  url: http://127.0.0.1:8766/mcp
  headers:
    Authorization: Bearer ${MCPSTEAD_BEARER_TOKEN}
  tools:
    resources: false
    prompts: false

Las herramientas aparecen con nombres calificados - <servidor>__<herramienta> - para que múltiples servidores ascendentes puedan ofrecer nombres de herramientas superpuestos sin colisiones.

Autenticación

Descendente (clientes a mcpstead)

Por defecto no hay autenticación:

mcp:
  auth:
    mode: none

Autenticación Bearer:

mcp:
  auth:
    mode: bearer

El token proviene de una variable de entorno:

export MCPSTEAD_BEARER_TOKEN='replace-with-strong-secret'
mcpstead --config ~/.config/mcpstead/config.yaml

Los clientes envían Authorization: Bearer <token>. Un token faltante o incorrecto devuelve 401. mcp.auth.bearer_token en la configuración es rechazado al inicio.

/health y /metrics permanecen abiertos independientemente del modo de autenticación, para monitoreo sin exponer el token.

Ascendente (mcpstead a servidores MCP)

Por servidor en la lista servers. Tres modos:

servers:
  - name: local
    url: http://127.0.0.1:3000/mcp
    auth: none

  - name: workflow
    url: https://workflow.example/mcp-server/http
    auth:
      type: bearer
      token_env: WORKFLOW_TOKEN

  - name: custom
    url: https://api.example/mcp
    headers:
      X-API-Key: '${EXAMPLE_KEY}'

token_env resuelve la variable de entorno nombrada al inicio y al recargar la configuración.

Configuración

Establece la ruta de configuración con --config <ruta> o la variable de entorno MCPSTEAD_CONFIG.

host: 0.0.0.0
port: 8766

mcp:
  auth:
    mode: none           # none | bearer
  session:
    idle_ttl_seconds: 3600
    gc_interval_seconds: 60
    shutdown_grace_seconds: 5

servers:
  - name: local
    url: http://127.0.0.1:3000/mcp
    protocol: streamable # streamable | sse | auto
    required: false      # if true, gateway won't start without this upstream
    auth: none
    reconnect:
      max_attempts: 0    # 0 = infinite
      backoff_base_ms: 1000
      backoff_max_ms: 30000
    tools:
      ttl_seconds: 300
    tls_skip_verify: false
    quirks:
      normalize_sse_events: true
      inject_accept_header: 'application/json, text/event-stream'

metrics:
  enabled: true

logging:
  level: info

Recarga en caliente

mcpstead recarga su configuración sin reiniciar al recibir:

  • SIGHUP (systemctl reload mcpstead o kill -HUP <pid>)

  • POST /-/reload (protegido por autenticación bearer en modo bearer)

Recargable en caliente:

  • lista de servidores ascendentes

  • autenticación, encabezados, peculiaridades, reconexión, herramientas, URL, protocolo y configuraciones TLS por servidor ascendente

  • mcp.auth.mode y MCPSTEAD_BEARER_TOKEN

  • metrics.enabled

Se requiere reinicio para:

  • host

  • port

  • logging.level

  • mcp.session.*

La recarga es de mejor esfuerzo. Una configuración incorrecta es rechazada e ignorada; la configuración en ejecución permanece vigente. Revisa los registros y mcpstead_config_reloads_total{result="error"} para ver fallos.

Claves de configuración de sesión MCP

  • mcp.session.idle_ttl_seconds - desalojar sesiones inactivas después de esta cantidad de segundos (por defecto 3600)

  • mcp.session.gc_interval_seconds - intervalo de activación del recolector de basura de sesiones inactivas (por defecto 60)

  • mcp.session.shutdown_grace_seconds - tiempo máximo de barrido de cierre (por defecto 5)

Claves de configuración por servidor ascendente

  • name - requerido, usado como prefijo de herramienta

  • url - requerido, punto final MCP

  • protocol - streamable | sse | auto (por defecto auto)

  • required - bloquear el inicio si el servidor ascendente no logra inicializarse (por defecto false)

  • auth - none, bearer (con token_env), o mapa de headers

  • reconnect.max_attempts - 0 = infinito (por defecto)

  • reconnect.backoff_base_ms / backoff_max_ms - límites de retroceso exponencial

  • tools.ttl_seconds - actualizar tools/list en caché después de este intervalo

  • tls_skip_verify - deshabilitar comprobaciones de certificados TLS para este servidor ascendente (por defecto false, usar solo para redes locales confiables)

  • quirks.normalize_sse_events - eliminar líneas event: de las respuestas SSE ascendentes

  • quirks.inject_accept_header - anular el encabezado Accept enviado al servidor ascendente

Observabilidad

Métricas

/metrics expone contadores, indicadores e histogramas en formato Prometheus. La cardinalidad de las etiquetas asume un conjunto pequeño y limitado de servidores ascendentes y herramientas; las series de llamadas a herramientas están indexadas por (servidor, herramienta).

mcpstead_build_info{version="...",rust_version="...",git_sha="..."}
mcpstead_start_time_seconds
mcpstead_uptime_seconds
mcpstead_process_resident_memory_bytes
mcpstead_process_virtual_memory_bytes
mcpstead_process_cpu_seconds_total
mcpstead_process_open_fds
mcpstead_process_max_fds
mcpstead_process_threads
mcpstead_upstream_connected{server="..."}
mcpstead_upstream_tools_count{server="..."}
mcpstead_upstream_reconnects_total{server="..."}
mcpstead_upstream_last_seen_seconds{server="..."}
mcpstead_upstream_initialize_total{server="...",result="success|error"}
mcpstead_upstream_initialize_duration_seconds_bucket{server="...",le="..."}
mcpstead_upstream_health_checks_total{server="...",result="success|failure"}
mcpstead_upstream_reconnect_attempts_total{server="...",result="success|error"}
mcpstead_upstream_backoff_seconds_total{server="..."}
mcpstead_upstream_in_backoff{server="..."}
mcpstead_upstream_current_backoff_seconds{server="..."}
mcpstead_upstream_session_resets_total{server="...",reason="unknown_session|expired|terminated"}
mcpstead_upstream_tools_refresh_total{server="...",result="success|error"}
mcpstead_upstream_tools_refresh_duration_seconds_bucket{server="...",le="..."}
mcpstead_upstream_tools_last_refresh_timestamp_seconds{server="..."}
mcpstead_upstream_bytes_total{server="...",direction="sent|received"}
mcpstead_downstream_sessions_active
mcpstead_downstream_sessions_total
mcpstead_downstream_session_duration_seconds_bucket{le="..."}
mcpstead_downstream_session_terminations_total{reason="..."}
mcpstead_mcp_requests_total{method="...",result="success|error"}
mcpstead_mcp_request_duration_seconds_bucket{method="...",le="..."}
mcpstead_mcp_auth_attempts_total{result="success|failure"}
mcpstead_mcp_auth_failures_total{reason="..."}
mcpstead_config_reloads_total{result="success|error"}
mcpstead_config_last_reload_timestamp_seconds
mcpstead_tool_calls_total{server="...",tool="..."}
mcpstead_tool_call_errors_total{server="...",tool="...",reason="..."}
mcpstead_tool_call_duration_seconds_bucket{server="...",tool="...",le="..."}

Configuración de scrape

- job_name: mcpstead
  metrics_path: /metrics
  static_configs:
    - targets: ['mcpstead:8766']

Verificación de salud

curl http://127.0.0.1:8766/health

Devuelve JSON: estado de conexión por servidor ascendente, recuento de herramientas, último contacto exitoso, recuento de reconexiones, último error.

Solución de problemas

  • La lista de todas las herramientas está vacía - al menos un servidor ascendente falló al initialize. Revisa /health para el estado por servidor; verifica la URL ascendente, la autenticación y la accesibilidad.

  • SSE parse failed esporádico - el servidor ascendente envía un dialecto SSE que mcpstead no reconoce. Prueba quirks.normalize_sse_events: true para ese servidor, o establece quirks.inject_accept_header: 'application/json' para forzar JSON.

  • tools/call devuelve error de autenticación - el servidor ascendente rechazó el token bearer. Confirma que token_env se resuelve al valor correcto al inicio; verifica el nombre del encabezado esperado por el servidor ascendente.

  • Errores de handshake TLS contra un servidor ascendente autofirmado - establece tls_skip_verify: true en ese servidor. Solo es seguro en redes locales confiables.

  • 401 desde /mcp con modo bearer - al cliente le falta o está enviando un Authorization: Bearer <token> incorrecto. Verifica que MCPSTEAD_BEARER_TOKEN coincida con lo que envía el cliente.

  • El servidor ascendente se pone rojo en /health repetidamente - revisa mcpstead_upstream_reconnects_total y mcpstead_upstream_last_seen_seconds. Ajusta reconnect.backoff_max_ms si el servidor ascendente necesita una recuperación más larga.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A gateway that aggregates multiple MCP servers into a single endpoint, namespacing their tools and forwarding calls, so an agent connects to one MCP to access the entire stack.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Centralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.
    5 npm
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    A generic MCP gateway that aggregates multiple upstream MCP servers into a single FastMCP endpoint, configured via servers.json with support for tool subsetting, renaming, multi-instance routing, and pluggable authentication.
    -