diff --git a/ui/ruvocal/src/lib/server/mcp/clientPool.ts b/ui/ruvocal/src/lib/server/mcp/clientPool.ts index 2f78ddd9..becb2a32 100644 --- a/ui/ruvocal/src/lib/server/mcp/clientPool.ts +++ b/ui/ruvocal/src/lib/server/mcp/clientPool.ts @@ -16,7 +16,19 @@ function keyOf(server: McpServerConfig) { export async function getClient(server: McpServerConfig, signal?: AbortSignal): Promise { const key = keyOf(server); const existing = pool.get(key); - if (existing) return existing; + if (existing) { + // Verify the cached client is still alive by checking transport state + try { + // If the transport is closed/errored, evict and reconnect + if ((existing as unknown as { _transport?: { readyState?: number } })._transport?.readyState === 2) { + pool.delete(key); + } else { + return existing; + } + } catch { + return existing; + } + } let firstError: unknown; const client = new Client({ name: "chat-ui-mcp", version: "0.1.0" }); diff --git a/ui/ruvocal/src/lib/server/mcp/httpClient.ts b/ui/ruvocal/src/lib/server/mcp/httpClient.ts index eb862157..de629c69 100644 --- a/ui/ruvocal/src/lib/server/mcp/httpClient.ts +++ b/ui/ruvocal/src/lib/server/mcp/httpClient.ts @@ -4,7 +4,17 @@ import { config } from "$lib/server/config"; function isConnectionClosedError(err: unknown): boolean { const message = err instanceof Error ? err.message : String(err); - return message.includes("-32000") || message.toLowerCase().includes("connection closed"); + const lower = message.toLowerCase(); + return ( + message.includes("-32000") || + lower.includes("connection closed") || + lower.includes("404") || + lower.includes("not found") || + lower.includes("session") || + lower.includes("fetch failed") || + lower.includes("econnreset") || + lower.includes("econnrefused") + ); } export interface McpServerConfig {