flipped-aurora/gin-vue-admin · error
MCP 健康检查失败: %s
Error message
MCP 健康检查失败: %s
What it means
checkMCPHealth reports failure when the health-check HTTP request to the standalone MCP process succeeded at transport level but returned a non-2xx status code; the error carries the raw resp.Status (e.g. '503 Service Unavailable'). 2xx (200-299) is treated as healthy.
Source
Thrown at server/mcp/standalone_manager.go:266
timeoutCtx, cancel := context.WithTimeout(ctx, mcpHealthCheckTimeout)
defer cancel()
req, err := http.NewRequestWithContext(timeoutCtx, http.MethodGet, ResolveMCPHealthURL(), nil)
if err != nil {
return false, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}
defer resp.Body.Close()
if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusMultipleChoices {
return true, nil
}
return false, fmt.Errorf("MCP 健康检查失败: %s", resp.Status)
}
func waitForManagedProcess(ctx context.Context, meta *managedProcessMeta) (ManagedStandaloneStatus, error) {
deadline := time.NewTimer(mcpStartWaitTimeout)
ticker := time.NewTicker(300 * time.Millisecond)
defer deadline.Stop()
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return GetManagedStandaloneStatus(context.Background()), ctx.Err()
case <-deadline.C:
return GetManagedStandaloneStatus(context.Background()), fmt.Errorf("等待 MCP 独立服务启动超时,请查看日志: %s", meta.LogPath)
case <-ticker.C:
current := GetManagedStandaloneStatus(context.Background())
if current.Reachable {
return current, nilView on GitHub (pinned to 3136500ef3)
Solutions
- Wait briefly and retry — transient 503 during startup is common; the caller waitForManagedProcess already retries on a 300ms ticker.
- Compare resp.Status in the error: 401/403 -> fix auth token; 404 -> health endpoint path changed; 5xx -> inspect the MCP log file.
- Confirm the health URL/port in GVA_MCP_CONFIG matches the standalone server's actual listener.
- If 5xx persists, check MCP logs for panics or failed dependency init.
Example fix
// defensive polling wrapper
func healthyEventually(url string, within time.Duration) error {
deadline := time.Now().Add(within)
for time.Now().Before(deadline) {
ok, err := checkMCPHealth(url)
if err == nil && ok { return nil }
time.Sleep(300 * time.Millisecond)
}
return fmt.Errorf("health check still failing after %s", within)
} Defensive patterns
Strategy: retry
Validate before calling
// pre-validate the health endpoint manually
resp, err := http.Get(healthURL)
if err != nil { return err }
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
return fmt.Errorf("health endpoint returned %s", resp.Status)
} Try / catch
ok, err := checkMCPHealth(url)
if err != nil && strings.Contains(err.Error(), "503") {
time.Sleep(500 * time.Millisecond) // still initializing; retry
ok, err = checkMCPHealth(url)
} Prevention
- Allow a warm-up window before requiring healthy status after start.
- Keep the health route path stable across versions; document it.
- Check the MCP log file whenever the status code is 5xx.
- Pin auth tokens used by the health checker and rotate on a schedule.
When it happens
Trigger: GET to the MCP standalone health endpoint returns 401/404/429/5xx: process still initializing, auth token mismatch, wrong health route, or the process is overloaded/degraded.
Common situations: Polling during startup before the HTTP server is fully ready; health endpoint path changed between versions; reverse proxy in front returning 502/503; rate limiting returning 429.
Related errors
AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31).
Data as JSON: /api/errors/b9bbde8ecab07cbd.
Report an issue: GitHub.