From 169a9617c87d0033a054933eda5788b05d09b264 Mon Sep 17 00:00:00 2001 From: David Kaya Date: Sat, 28 Mar 2026 19:43:53 +0100 Subject: [PATCH] fix: improve MCP probe error reporting and SSE fallback When SSE fallback gets 405 (confirming a Streamable HTTP server), surface the original Streamable HTTP error instead of the misleading SSE 405. Extract HTTP status codes from SDK error objects to produce clearer log messages like 'HTTP 401: Streamable HTTP error: ...'. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/main/services/mcpToolProber.ts | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/main/services/mcpToolProber.ts b/src/main/services/mcpToolProber.ts index ab80063..3f2f069 100644 --- a/src/main/services/mcpToolProber.ts +++ b/src/main/services/mcpToolProber.ts @@ -73,7 +73,7 @@ export async function probeServer( status: 'success', }; } catch (error) { - const message = error instanceof Error ? error.message : String(error); + const message = formatProbeError(error); console.warn(`[aryx mcp-probe] ${server.name}: failed — ${message}`); return { serverId: server.id, @@ -102,10 +102,17 @@ async function probeServerCore( return await probeWithTransport( new StreamableHTTPClientTransport(new URL(server.url), headerOpts), ); - } catch { - return probeWithTransport( - new SSEClientTransport(new URL(server.url), headerOpts), - ); + } catch (streamableError) { + try { + return await probeWithTransport( + new SSEClientTransport(new URL(server.url), headerOpts), + ); + } catch (sseError) { + // SSE 405 means the server IS Streamable HTTP — surface the original error. + const sseCode = (sseError as { code?: number }).code; + if (sseCode === 405) throw streamableError; + throw sseError; + } } } @@ -177,6 +184,19 @@ function buildHeaders( }; } +function formatProbeError(error: unknown): string { + if (!(error instanceof Error)) return String(error); + + const httpCode = (error as { code?: number }).code; + const base = error.message; + + if (typeof httpCode === 'number' && httpCode >= 100) { + return `HTTP ${httpCode}: ${base}`; + } + + return base; +} + function withTimeout(promise: Promise, ms: number, message: string): Promise { return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error(message)), ms);