Skip to content

MCP gateway health check ignores tools.startup-timeout, and serial backend launches let one hung server block all others #69297

Closed

Description

@MattSkala

Summary

The gateway's health check gives up after a fixed ~149s, no matter what tools.startup-timeout is set to. startup-timeout: 300 is passed through as the backend startup timeout, but GH_AW_MCP_GATEWAY_HEALTH_MAX_ATTEMPTS stays at its default of 150. The health check therefore stops long before the configured timeout is reached.

On top of that, awmg launches stdio backends one after another even though it logs Parallel server launching enabled (default) / sequentialLaunch=false. A single backend that hangs therefore blocks every backend queued behind it. The step fails with Gateway failed to become ready and the agent never starts.

Environment

  • gh-aw CLI v0.91.12 (github/gh-aw-actions/setup@2f6729681c34eb94a2f94d533d4b6492de0d8a19)
  • ghcr.io/github/gh-aw-mcpg:v0.4.30, AWF v0.28.56
  • Engine: claude
  • Six MCP servers. Three are container: servers or built-in (github, atlassian, safeoutputs). Three are command: npx on node:lts-alpine (figma-developer-mcp, firebase-tools, @growthbook/mcp).
  • Frontmatter: tools.startup-timeout: 300

Observed

The "Start MCP Gateway" step fails. The resulting failure issue classifies it as agent_startup_failure:

[warning] MCP gateway health retry budget is 149s, which is below the 325s needed for the 300s backend startup timeout plus cleanup and registration; the health check may give up before the gateway is ready
...
[info] Total attempts: 150
[error] ERROR: Gateway failed to become ready
[error] Last HTTP code: 0
[error] Gateway process (PID: 6161) is still running

From the gateway stderr: only safeoutputs and then growthbook were ever launched. The growthbook container (npx -y @growthbook/mcp@2.2.0) was still Up 2 minutes and had not finished its handshake. atlassian, figma, firebase and github never logged Launching new server. When the step tore the gateway down, all of them failed together:

Failed to register tools from atlassian (took 2m25.16s): failed to connect: ... context canceled
Failed to register tools from figma (took 2m25.26s): ... context canceled
Failed to register tools from firebase (took 2m25.18s): ... context canceled
Failed to register tools from github (took 2m25.20s): ... context canceled
Failed to register tools from growthbook (took 2m25.15s): ... context canceled

The github image was pre-pulled by "Download container images" and normally connects in about 2s. It timed out only because it was queued behind growthbook.

Launches are serial despite sequentialLaunch=false

A successful run of the same workflow on the same commit 9 minutes later logged Creating new unified server: sequentialLaunch=false. Its mcp-gateway.log still shows each launch beginning only after the previous connection was established:

20:18:26.550 Launching new server: serverID=growthbook
20:18:34.119 Connection established: serverID=growthbook
20:18:34.126 Launching new server: serverID=figma
20:18:44.686 Connection established: serverID=figma
20:18:44.692 Launching new server: serverID=atlassian
20:18:53.119 Connection established: serverID=atlassian
20:18:53.129 Launching new server: serverID=github
20:18:55.378 Connection established: serverID=github
20:18:55.385 Launching new server: serverID=firebase
20:19:58.782 Connection established: serverID=firebase
20:19:58.798 Launching new server: serverID=safeoutputs
20:20:00.914 Connection established: serverID=safeoutputs

Startup time is therefore the sum of every backend's time, not the slowest one. Across 9 successful runs, the gateway became ready after 55–97 health-check attempts (about 55–97s). Only ~50s of the 149s budget is left as headroom, before any backend misbehaves.

Expected

  1. Setting tools.startup-timeout should make the health check wait at least startup-timeout + registration margin. tool_timeouts.cjs already maps GH_AW_STARTUP_TIMEOUT into GH_AW_MCP_GATEWAY_BACKEND_STARTUP_TIMEOUT_MS. Today the mismatch only produces a warning, and the user's startup-timeout has no effect beyond ~149s.
  2. With sequentialLaunch=false, backends should launch concurrently. Then a slow or hung backend delays only itself, and the gateway can come up with that server marked failed instead of failing the whole run.

Suggested fixes

  • Derive the health-check attempt count from the backend startup timeout. Either the compiler emits GH_AW_MCP_GATEWAY_HEALTH_MAX_ATTEMPTS, or resolveGatewayHealthRetryConfig raises maxTotalAttempts until retryBudgetMs >= backendStartupTimeoutMs + MCP_GATEWAY_HEALTH_REGISTRATION_MARGIN_MS when the env var isn't set explicitly. The startupDeadline already computed in start_mcp_gateway.cjs would then be the real limit.
  • The serialization itself is an awmg bug: its launcher holds one global write lock for the whole launch and handshake. Filed separately as Parallel backend launch is serialized by the launcher's global write lock, so one hung backend blocks every other server gh-aw-mcpg#14978.

Workaround

Set GH_AW_MCP_GATEWAY_HEALTH_MAX_ATTEMPTS (e.g. 330) as a workflow-level env so the health check outlasts startup-timeout.

Activity

  1. locked and limited conversation to collaborators on Oct 16, 2026
  2. unlocked this conversation on Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions