fix(voice-agent): warn on slow MCP doctor probe instead of failing

Use a 2s timeout for GET /api/mcp/servers and downgrade timeout-style
errors to warn so stdio MCP connect does not fail the whole doctor run.

Follow-up to #273 (example-only; no core SDK changes).

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
MervinPraisonandCursor committed 2026-09-14 14:51:08 +01:00
1 parent e6a346aa22
commit 8ce13a9fec
2 files changed
+40 -1

No files matched your search

@@ -17,6 +17,25 @@ def _tcp_open(host: str, port: int, timeout: float = 2.0) -> bool:
return False
_MCP_PROBE_TIMEOUT_SEC = 2.0
def _is_slow_mcp_probe(detail: str) -> bool:
lowered = detail.lower()
return any(token in lowered for token in ("timed out", "timeout", "temporarily unavailable"))
def _mcp_servers_probe(app_port: int) -> tuple[str, str]:
"""Probe MCP list endpoint; slow stdio connect must not fail the whole doctor run."""
status, detail = _http_status(
f"http://127.0.0.1:{app_port}/api/mcp/servers",
timeout=_MCP_PROBE_TIMEOUT_SEC,
)
if status == "fail" and _is_slow_mcp_probe(detail):
return "warn", detail
return status, detail
def _http_status(url: str, timeout: float = 5.0) -> tuple[str, str]:
try:
req = Request(url, headers={"User-Agent": "praisonai-voice-doctor"})
@@ -64,7 +83,7 @@ def run_voice_doctor(*, app_port: int = 8001, sidecar_port: int = 8002) -> dict[
checks.append({"name": "Speech Engine config", "status": status, "detail": detail})
status, detail = _http_status(f"http://127.0.0.1:{app_port}/api/voice/realtime/config")
checks.append({"name": "GPT Realtime config", "status": status, "detail": detail})
status, detail = _http_status(f"http://127.0.0.1:{app_port}/api/mcp/servers")
status, detail = _mcp_servers_probe(app_port)
checks.append({"name": "MCP servers API", "status": status, "detail": detail})
else:
checks.append(
+20
View File
@@ -478,6 +478,26 @@ def test_voice_doctor_report(monkeypatch):
assert report["summary"]["failed"] >= 1
def test_voice_doctor_mcp_probe_timeout_is_warn(monkeypatch):
monkeypatch.setenv("OPENAI_API_KEY", "sk-test-key-12345678")
def fake_http_status(url: str, timeout: float = 5.0):
if "/api/mcp/servers" in url:
assert timeout == 2.0
return "fail", "timed out"
return "pass", "HTTP 200"
with _voice_modules() as imp:
doctor = imp("integrations.voice.doctor")
monkeypatch.setattr(doctor, "_tcp_open", lambda *args, **kwargs: True)
monkeypatch.setattr(doctor, "_http_status", fake_http_status)
report = doctor.run_voice_doctor(app_port=8001, sidecar_port=59998)
mcp = next(c for c in report["checks"] if c["name"] == "MCP servers API")
assert mcp["status"] == "warn"
assert mcp["detail"] == "timed out"
def test_call_detail_ui_includes_analytics():
with _voice_modules() as imp:
ui = imp("integrations.voice.call_detail_ui")