Skip to content

[Code Quality] Replace Fixed time.Sleep with Context-Based Polling in MCP Inspector #11879

@github-actions

Description

@github-actions

Description

The MCP inspector startup code uses hardcoded time.Sleep(2 * time.Second) delays instead of polling for actual server readiness, adding 2+ seconds of unnecessary latency to every MCP inspector launch.

Problem

In pkg/cli/mcp_inspect.go:864, the spawnMCPInspector function waits 2 full seconds after starting stdio servers:

// ❌ Hardcoded 2-second delay
time.Sleep(2 * time.Second)

Impact:

  • Fast servers: Waste 1.5+ seconds (ready in 500ms, wait 2s anyway)
  • Slow servers: May fail (need 3s, only get 2s)
  • User experience: Every gh aw mcp inspect waits 2s minimum

Other Affected Files

Fixed time.Sleep() calls found in 10 locations:

  • pkg/cli/mcp_inspect.go:864 - 2s hardcoded delay (CRITICAL UX issue)
  • pkg/cli/mcp_inspect.go:897 - 100ms cleanup delay in loop
  • pkg/cli/mcp_inspect.go (waitForServerReady) - 200ms polling
  • pkg/cli/trial_repository.go - 2s hardcoded delay
  • pkg/cli/docker_images.go - Variable sleep in validation
  • pkg/workflow/docker_validation.go - Variable sleep in validation
  • pkg/cli/run_workflow_tracking.go - Variable sleep with delay
  • pkg/cli/update_check.go - 100ms delay

Suggested Changes

Replace fixed delays with context-based polling using exponential backoff:

// Poll for server readiness with exponential backoff
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

ready := make(chan bool, len(stdioServers))
for _, config := range stdioServers {
    go func(cfg parser.MCPServerConfig) {
        ticker := time.NewTicker(100 * time.Millisecond)
        defer ticker.Stop()
        
        backoff := 100 * time.Millisecond
        maxBackoff := 2 * time.Second
        
        for {
            select {
            case <-ctx.Done():
                ready <- false
                return
            case <-ticker.C:
                if serverIsReady(cfg) {
                    ready <- true
                    return
                }
                
                // Exponential backoff
                backoff = min(backoff*2, maxBackoff)
                ticker.Reset(backoff)
            }
        }
    }(config)
}

// Wait for all servers or timeout
for range stdioServers {
    if !<-ready {
        return fmt.Errorf("server failed to start within 10s")
    }
}

Benefits

  • Fast servers: Complete in <500ms (vs current 2s) - 75% faster
  • Slow servers: Graceful timeout at 10s (vs current 2s crash)
  • Responsive: Exponential backoff avoids tight polling loops

Files to Update

Priority 1 (User-facing):

  • pkg/cli/mcp_inspect.go (3 instances) - CRITICAL

Priority 2 (Internal):

  • pkg/cli/trial_repository.go
  • pkg/cli/docker_images.go
  • pkg/workflow/docker_validation.go
  • pkg/cli/run_workflow_tracking.go
  • pkg/cli/update_check.go

Success Criteria

  • MCP inspector startup completes in <500ms for fast servers (vs current 2s)
  • Graceful 10s timeout for slow/failing servers
  • Context-based polling with exponential backoff implemented
  • All existing tests pass: go test ./pkg/cli/... -run TestMCP
  • New test added: concurrent server startup polling
  • Benchmark shows latency improvement: go test -bench=BenchmarkMCPInspector
  • No busy-wait CPU spikes (backoff working)
  • make agent-finish passes

Priority

High - Directly impacts user experience on every MCP inspector command

Estimated Effort: Medium (3-5 hours across multiple files)

Source

Extracted from Sergo Performance Optimization Analysis - Discussion #11840

Analysis Quote:

"10 fixed time.Sleep() calls in production code adding 2+ seconds of unnecessary latency to critical user-facing commands"

Performance Impact:

"Impact: 2+ seconds latency reduction in MCP inspector startup"

References:

AI generated by Discussion Task Miner - Code Quality Improvement Agent

  • expires on Feb 9, 2026, 2:09 PM UTC

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions