From 1ddae51afbd8ec097ca9b8c0c9b6bfd4c0e9c636 Mon Sep 17 00:00:00 2001 From: Theodore Li Date: Mon, 5 Oct 2026 19:39:51 -0700 Subject: [PATCH] fix(mcp): treat different URL credentials as a new destination --- apps/sim/lib/mcp/utils.test.ts | 7 +++++++ apps/sim/lib/mcp/utils.ts | 11 ++++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/sim/lib/mcp/utils.test.ts b/apps/sim/lib/mcp/utils.test.ts index 251ab3b7063..8d0a26369ba 100644 --- a/apps/sim/lib/mcp/utils.test.ts +++ b/apps/sim/lib/mcp/utils.test.ts @@ -63,6 +63,13 @@ describe('isSameMcpServerDestination', () => { expect(isSameMcpServerDestination(url, 'https://mcp.example.com/MCP')).toBe(false) expect(isSameMcpServerDestination(url, `${url}/`)).toBe(false) }) + + it('treats different embedded credentials as a new destination', () => { + const url = 'https://user:pass@mcp.example.com/mcp' + expect(isSameMcpServerDestination(url, 'https://mcp.example.com/mcp')).toBe(false) + expect(isSameMcpServerDestination(url, 'https://other:pass@mcp.example.com/mcp')).toBe(false) + expect(isSameMcpServerDestination(url, 'https://user:other@mcp.example.com/mcp')).toBe(false) + }) }) describe('categorizeError', () => { diff --git a/apps/sim/lib/mcp/utils.ts b/apps/sim/lib/mcp/utils.ts index 4745a83a269..23f5637594a 100644 --- a/apps/sim/lib/mcp/utils.ts +++ b/apps/sim/lib/mcp/utils.ts @@ -244,15 +244,20 @@ export function generateMcpServerId(workspaceId: string, url: string): string { } /** - * Whether two URLs name the same MCP server destination: the same origin and - * exact path. Only the query string and fragment may differ — paths can be + * Whether two URLs name the same MCP server destination: the same origin, + * credentials, and exact path. Only the query string and fragment may differ — paths can be * case-sensitive, so this is stricter than the id hash. */ export function isSameMcpServerDestination(a: string, b: string): boolean { try { const parsedA = new URL(a) const parsedB = new URL(b) - return parsedA.origin === parsedB.origin && parsedA.pathname === parsedB.pathname + return ( + parsedA.origin === parsedB.origin && + parsedA.username === parsedB.username && + parsedA.password === parsedB.password && + parsedA.pathname === parsedB.pathname + ) } catch { return a === b }