From 4e03d899b3db0251e73fe445604dfefb11698b44 Mon Sep 17 00:00:00 2001 From: dhananjai1729 Date: Sun, 22 Mar 2026 10:23:56 +0530 Subject: [PATCH] fix: handle Headers instances in SSE fetch and redact invalid URLs - Properly convert Headers instances to plain objects in eventSourceInit.fetch so SDK-generated headers (e.g. Accept: text/event-stream) are preserved while user-configured headers still take precedence. - Redact potential credentials from invalid URLs in error reasons to prevent secret leakage in log output. Co-Authored-By: Claude Opus 4.6 --- src/agents/mcp-sse.ts | 4 +++- src/agents/pi-bundle-mcp-tools.ts | 22 ++++++++++++++++++---- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/agents/mcp-sse.ts b/src/agents/mcp-sse.ts index 30fd4a73a91..fa903fcf909 100644 --- a/src/agents/mcp-sse.ts +++ b/src/agents/mcp-sse.ts @@ -51,7 +51,9 @@ export function resolveSseMcpServerLaunchConfig( try { parsed = new URL(url); } catch { - return { ok: false, reason: `its url is not a valid URL: ${url}` }; + // Redact potential credentials from the invalid URL before including in reason. + const redactedUrl = url.replace(/\/\/([^@]+)@/, "//***:***@"); + return { ok: false, reason: `its url is not a valid URL: ${redactedUrl}` }; } if (parsed.protocol !== "http:" && parsed.protocol !== "https:") { return { diff --git a/src/agents/pi-bundle-mcp-tools.ts b/src/agents/pi-bundle-mcp-tools.ts index ef164da49bd..ef46d002fd2 100644 --- a/src/agents/pi-bundle-mcp-tools.ts +++ b/src/agents/pi-bundle-mcp-tools.ts @@ -170,13 +170,27 @@ function resolveTransport( // Apply headers to POST requests (tool calls, listTools, etc.). requestInit: hasHeaders ? { headers } : undefined, // Apply headers to the initial SSE GET handshake (required for auth). + // Apply headers to the initial SSE GET handshake (required for auth). + // Note: init?.headers may be a Headers instance; convert to plain object + // so SDK defaults are preserved and user-configured headers take precedence. eventSourceInit: hasHeaders ? { - fetch: (url, init) => - fetch(url, { + fetch: (url, init) => { + const sdkHeaders: Record = {}; + if (init?.headers) { + if (init.headers instanceof Headers) { + init.headers.forEach((v, k) => { + sdkHeaders[k] = v; + }); + } else { + Object.assign(sdkHeaders, init.headers); + } + } + return fetch(url, { ...init, - headers: { ...(init?.headers as Record), ...headers }, - }), + headers: { ...sdkHeaders, ...headers }, + }); + }, } : undefined, });