From 6470b875add61b0b4c17a7bb165b3ded66872db2 Mon Sep 17 00:00:00 2001 From: Ben Senescu <44480372+bensenescu@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:41:44 -0400 Subject: [PATCH] Allow SurfMind Chrome extension MCP origin (#513) --- src/server/mcp/transport-v2.test.ts | 41 ++++++++++++++++++++++++++++- src/server/mcp/transport.test.ts | 23 +++++++++++++++- src/server/mcp/transport.ts | 3 +++ 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/server/mcp/transport-v2.test.ts b/src/server/mcp/transport-v2.test.ts index 4aa22b0..3262193 100644 --- a/src/server/mcp/transport-v2.test.ts +++ b/src/server/mcp/transport-v2.test.ts @@ -9,13 +9,18 @@ const ctx: ExecutionContext = { props: {}, }; -function request(method: string, body?: unknown) { +function request( + method: string, + body?: unknown, + headers?: Record, +) { return new Request("https://open-seo.test/mcp", { method, headers: { Host: "open-seo.test", Accept: "application/json, text/event-stream", "Content-Type": "application/json", + ...headers, }, body: body === undefined ? undefined : JSON.stringify(body), }); @@ -97,4 +102,38 @@ describe("Agents SDK v2 MCP transport", () => { expect(responseText).toContain('\\"scopes\\":[\\"mcp\\"]'); expect(responseText).toContain('\\"organizationId\\":\\"org-1\\"'); }); + + it("accepts the SurfMind extension origin and rejects other browser origins", async () => { + const handler = createMcpHandler( + () => new McpServer({ name: "test", version: "1.0.0" }), + { + route: "/mcp", + allowedOriginHostnames: [ + "open-seo.test", + "pghallcbnfabbgfijhbcldaapmgidnaa", + ], + }, + ); + const body = { + jsonrpc: "2.0", + id: 1, + method: "tools/list", + }; + + const surfMindResponse = await handler( + request("POST", body, { + Origin: "chrome-extension://pghallcbnfabbgfijhbcldaapmgidnaa", + }), + {}, + ctx, + ); + const unrelatedOriginResponse = await handler( + request("POST", body, { Origin: "https://evil.com" }), + {}, + ctx, + ); + + expect(surfMindResponse.status).toBe(200); + expect(unrelatedOriginResponse.status).toBe(403); + }); }); diff --git a/src/server/mcp/transport.test.ts b/src/server/mcp/transport.test.ts index 2b14a99..961ec87 100644 --- a/src/server/mcp/transport.test.ts +++ b/src/server/mcp/transport.test.ts @@ -215,7 +215,10 @@ describe("handleAuthenticatedOpenSeoMcpRequest", () => { expect(response.headers.get("connection")).not.toBe("keep-alive"); expect(selfHostedAuthMocks.createMcpHandler).toHaveBeenCalledWith( expect.objectContaining({ - allowedOriginHostnames: ["open-seo.test"], + allowedOriginHostnames: [ + "open-seo.test", + "pghallcbnfabbgfijhbcldaapmgidnaa", + ], legacy: "reject", }), ); @@ -255,6 +258,24 @@ describe("handleAuthenticatedOpenSeoMcpRequest", () => { expect(selfHostedAuthMocks.createOpenSeoMcpServer).not.toHaveBeenCalled(); }); + it("accepts a legacy request from the SurfMind Chrome extension", async () => { + const props = hostedProps(); + + const response = await handleAuthenticatedOpenSeoMcpRequest( + createMcpRequest({ + Origin: "chrome-extension://pghallcbnfabbgfijhbcldaapmgidnaa", + }), + props, + {}, + { ...ctx, props }, + ); + + expect(response.status).toBe(200); + expect(selfHostedAuthMocks.createOpenSeoMcpServer).toHaveBeenCalledWith( + props, + ); + }); + it("rejects provider props missing the OAuth client identity", async () => { // Hosted tokens always carry clientId/scopes; a token without them must // fail closed rather than skip scope enforcement. diff --git a/src/server/mcp/transport.ts b/src/server/mcp/transport.ts index c2cacbb..196db45 100644 --- a/src/server/mcp/transport.ts +++ b/src/server/mcp/transport.ts @@ -32,6 +32,8 @@ const MCP_CORS_HEADERS = { "Access-Control-Max-Age": "86400", } as const; +const SURFMIND_CHROME_EXTENSION_HOSTNAME = "pghallcbnfabbgfijhbcldaapmgidnaa"; + function withMcpCors(response: Response) { const headers = new Headers(response.headers); for (const [name, value] of Object.entries(MCP_CORS_HEADERS)) { @@ -158,6 +160,7 @@ export async function handleAuthenticatedOpenSeoMcpRequest( return createRequestHandler(result.data, [ new URL(getHostedBaseUrl()).hostname, + SURFMIND_CHROME_EXTENSION_HOSTNAME, ])(request, env, ctx); }