Skip to main content
Glama

mcpstead

CI npm version Crates.io License

MCP-Gateway

Ein Downstream-/mcp-Endpunkt, der als Frontend für viele Upstream-MCP-Server fungiert. Persistente Upstream-Verbindungen mit automatischer Wiederverbindung, Tool-Registry mit qualifizierten Namen, JSON- oder SSE-Antworten basierend auf dem Accept-Header des Clients, Authentifizierung pro Upstream sowie Prometheus-Metriken.

Installation

# 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

Schnelleinstieg

# 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

Verweisen Sie dann einen beliebigen MCP-Client auf 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

Das Dockerfile installiert die Anwendung von crates.io.

HTTP-API

Methode

Pfad

Zweck

POST

/mcp

MCP über HTTP JSON-RPC

GET

/mcp

gibt 405 zurück

DELETE

/mcp

beendet die Downstream-Sitzung

GET

/health

Upstream-Status, Tool-Anzahl, zuletzt gesehen, Wiederverbindungen

GET

/metrics

Prometheus-Textformat

POST

/-/reload

Konfiguration ohne Neustart neu laden

Einrichtung des MCP-Clients

Lokal, ohne Authentifizierung:

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

Bearer-Authentifizierung:

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

Tools erscheinen mit qualifizierten Namen – <server>__<tool> –, sodass mehrere Upstreams sich überschneidende Tool-Namen ohne Kollision bereitstellen können.

Authentifizierung

Downstream (Clients zu mcpstead)

Standardmäßig ohne Authentifizierung:

mcp:
  auth:
    mode: none

Bearer-Authentifizierung:

mcp:
  auth:
    mode: bearer

Das Token stammt aus einer Umgebungsvariablen:

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

Clients senden Authorization: Bearer <token>. Ein fehlendes oder falsches Token führt zu einem 401-Fehler. mcp.auth.bearer_token in der Konfiguration wird beim Start abgelehnt.

/health und /metrics bleiben unabhängig vom Authentifizierungsmodus offen – für Monitoring, ohne das Token preiszugeben.

Upstream (mcpstead zu MCP-Servern)

Pro Server in der servers-Liste. Drei Modi:

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 löst die benannte Umgebungsvariable beim Start und beim Neuladen der Konfiguration auf.

Konfiguration

Legen Sie den Konfigurationspfad mit --config <path> oder der Umgebungsvariablen MCPSTEAD_CONFIG fest.

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

Hot-Reload

mcpstead lädt seine Konfiguration ohne Neustart neu bei:

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

  • POST /-/reload (geschützt durch Bearer-Authentifizierung im Bearer-Modus)

Hot-Reload-fähig:

  • Upstream-Liste

  • Authentifizierung pro Upstream, Header, Quirks, Wiederverbindung, Tools, URL, Protokoll und TLS-Einstellungen

  • mcp.auth.mode und MCPSTEAD_BEARER_TOKEN

  • metrics.enabled

Neustart erforderlich:

  • host

  • port

  • logging.level

  • mcp.session.*

Das Neuladen erfolgt nach dem Best-Effort-Prinzip. Eine fehlerhafte Konfiguration wird abgelehnt und ignoriert; die laufende Konfiguration bleibt bestehen. Überprüfen Sie die Protokolle und mcpstead_config_reloads_total{result="error"} auf Fehler.

Konfigurationsschlüssel für MCP-Sitzungen

  • mcp.session.idle_ttl_seconds - inaktive Sitzungen nach dieser Anzahl von Sekunden entfernen (Standard 3600)

  • mcp.session.gc_interval_seconds - GC-Intervall für inaktive Sitzungen (Standard 60)

  • mcp.session.shutdown_grace_seconds - maximale Zeit für den Abschluss des Herunterfahrens (Standard 5)

Konfigurationsschlüssel pro Upstream

  • name - erforderlich, wird als Tool-Präfix verwendet

  • url - erforderlich, MCP-Endpunkt

  • protocol - streamable | sse | auto (Standard auto)

  • required - Start blockieren, wenn der Upstream nicht initialisiert werden kann (Standard false)

  • auth - none, bearer (mit token_env) oder headers-Map

  • reconnect.max_attempts - 0 = unendlich (Standard)

  • reconnect.backoff_base_ms / backoff_max_ms - Grenzen für exponentielles Backoff

  • tools.ttl_seconds - zwischengespeicherte tools/list nach diesem Intervall aktualisieren

  • tls_skip_verify - TLS-Zertifikatsprüfung für diesen Upstream deaktivieren (Standard false, nur für vertrauenswürdige lokale Netzwerke verwenden)

  • quirks.normalize_sse_events - event:-Zeilen aus Upstream-SSE-Antworten entfernen

  • quirks.inject_accept_header - den an den Upstream gesendeten Accept-Header überschreiben

Beobachtbarkeit

Metriken

/metrics stellt Zähler, Gauges und Histogramme im Prometheus-Format bereit. Die Kardinalität der Labels geht von einer kleinen, begrenzten Menge an Upstreams und Tools aus; Tool-Call-Serien sind nach (server, tool) indiziert.

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="..."}

Scrape-Konfiguration

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

Gesundheitsprüfung

curl http://127.0.0.1:8766/health

Gibt JSON zurück: Verbindungsstatus pro Upstream, Tool-Anzahl, letzter erfolgreicher Kontakt, Anzahl der Wiederverbindungen, letzter Fehler.

Fehlerbehebung

  • Liste aller Tools ist leer - mindestens ein Upstream konnte nicht initialisiert werden. Überprüfen Sie /health auf den Status pro Server; prüfen Sie die Upstream-URL, Authentifizierung und Erreichbarkeit.

  • Sporadische SSE parse failed - der Upstream sendet einen SSE-Dialekt, den mcpstead nicht erkennt. Versuchen Sie quirks.normalize_sse_events: true für diesen Server oder setzen Sie quirks.inject_accept_header: 'application/json', um JSON zu erzwingen.

  • tools/call gibt Authentifizierungsfehler zurück - der Upstream hat das Bearer-Token abgelehnt. Bestätigen Sie, dass token_env beim Start in den richtigen Wert aufgelöst wird; prüfen Sie den erwarteten Headernamen des Upstreams.

  • TLS-Handshake-Fehler bei einem Upstream mit selbstsigniertem Zertifikat - setzen Sie tls_skip_verify: true für diesen Server. Nur in vertrauenswürdigen lokalen Netzwerken sicher.

  • 401 von /mcp im Bearer-Modus - Client sendet kein oder ein falsches Authorization: Bearer <token>. Überprüfen Sie, ob MCPSTEAD_BEARER_TOKEN mit dem übereinstimmt, was der Client sendet.

  • Upstream wird in /health wiederholt rot - prüfen Sie mcpstead_upstream_reconnects_total und mcpstead_upstream_last_seen_seconds. Passen Sie reconnect.backoff_max_ms an, falls der Upstream eine längere Wiederherstellungszeit benötigt.

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.
    -