mcpstead
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcpsteadshow me the health status of all upstream servers"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcpstead
MCP Gateway
One downstream /mcp endpoint that fronts many upstream MCP servers. Persistent upstream connections with reconnect, tool registry with qualified names, JSON or SSE responses based on client Accept, per-upstream auth, Prometheus metrics.
Install
# 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 --versionQuick start
# 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.yamlThen point any MCP client at http://127.0.0.1:8766/mcp.
Docker
docker build -t mcpstead .
docker run --rm \
-p 8766:8766 \
-v "$PWD/config:/etc/mcpstead:ro" \
mcpsteadThe Dockerfile installs from crates.io.
HTTP API
Method | Path | Purpose |
|
| MCP over HTTP JSON-RPC |
|
| returns 405 |
|
| terminate downstream session |
|
| upstream status, tool counts, last-seen, reconnects |
|
| Prometheus text format |
|
| reload config without restart |
MCP client setup
Local, no-auth:
mcpstead:
url: http://127.0.0.1:8766/mcp
tools:
resources: false
prompts: falseBearer auth:
mcpstead:
url: http://127.0.0.1:8766/mcp
headers:
Authorization: Bearer ${MCPSTEAD_BEARER_TOKEN}
tools:
resources: false
prompts: falseTools appear with qualified names - <server>__<tool> - so multiple upstreams can ship overlapping tool names without collision.
Auth
Downstream (clients to mcpstead)
Default is no auth:
mcp:
auth:
mode: noneBearer auth:
mcp:
auth:
mode: bearerToken comes from env:
export MCPSTEAD_BEARER_TOKEN='replace-with-strong-secret'
mcpstead --config ~/.config/mcpstead/config.yamlClients send Authorization: Bearer <token>. Missing or wrong token returns 401. mcp.auth.bearer_token in config is rejected at startup.
/health and /metrics stay open regardless of auth mode - for monitoring without exposing the token.
Upstream (mcpstead to MCP servers)
Per-server in the servers list. Three modes:
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 resolves the named env var at startup and on config reload.
Config
Set the config path with --config <path> or the MCPSTEAD_CONFIG env var.
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: infoHot reload
mcpstead reloads its config without restart on:
SIGHUP (
systemctl reload mcpsteadorkill -HUP <pid>)POST /-/reload(gated by bearer auth in bearer mode)
Hot-reloadable:
upstream list
per-upstream auth, headers, quirks, reconnect, tools, URL, protocol, and TLS settings
mcp.auth.modeandMCPSTEAD_BEARER_TOKENmetrics.enabled
Restart required:
hostportlogging.levelmcp.session.*
Reload is best-effort. Bad config is rejected and ignored; the running config stays in place. Check logs and mcpstead_config_reloads_total{result="error"} for failures.
MCP session config keys
mcp.session.idle_ttl_seconds- evict inactive sessions after this many seconds (default3600)mcp.session.gc_interval_seconds- idle-session GC wake interval (default60)mcp.session.shutdown_grace_seconds- max shutdown accounting sweep time (default5)
Per-upstream config keys
name- required, used as tool prefixurl- required, MCP endpointprotocol-streamable | sse | auto(defaultauto)required- block startup if upstream fails to initialize (defaultfalse)auth-none,bearer(withtoken_env), orheadersmapreconnect.max_attempts-0= infinite (default)reconnect.backoff_base_ms/backoff_max_ms- exponential backoff boundstools.ttl_seconds- refresh cachedtools/listafter this intervaltls_skip_verify- disable TLS cert checks for this upstream (defaultfalse, use only for trusted local nets)quirks.normalize_sse_events- stripevent:lines from upstream SSE responsesquirks.inject_accept_header- override the Accept header sent upstream
Observability
Metrics
/metrics exposes Prometheus-format counters, gauges, and histograms. Label cardinality assumes a small bounded set of upstreams and tools; tool-call series are keyed by (server, tool).
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 config
- job_name: mcpstead
metrics_path: /metrics
static_configs:
- targets: ['mcpstead:8766']Health check
curl http://127.0.0.1:8766/healthReturns JSON: per-upstream connection state, tool counts, last successful contact, reconnect counts, last error.
Troubleshooting
All tools list empty - at least one upstream failed to
initialize. Check/healthfor per-server status; check upstream URL, auth, and reachability.Sporadic
SSE parse failed- upstream sends an SSE dialect mcpstead doesn't recognize. Tryquirks.normalize_sse_events: truefor that server, or setquirks.inject_accept_header: 'application/json'to force JSON.tools/callreturns auth error - upstream rejected the bearer token. Confirmtoken_envresolves to the right value at startup; check upstream's expected header name.TLS handshake errors against a self-signed upstream - set
tls_skip_verify: trueon that server. Only safe on trusted local networks.401 from
/mcpwith mode bearer - client missing or sending wrongAuthorization: Bearer <token>. VerifyMCPSTEAD_BEARER_TOKENmatches what the client sends.Upstream goes red in
/healthrepeatedly - checkmcpstead_upstream_reconnects_totalandmcpstead_upstream_last_seen_seconds. Tunereconnect.backoff_max_msif the upstream needs longer recovery.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ahkohd/mcpstead'
If you have feedback or need assistance with the MCP directory API, please join our Discord server