153 lines · 4.4 KB · TypeScript
RawDownload
import { test, expect, mock, beforeEach } from "bun:test" // Track what options were passed to each transport constructorconst transportCalls: Array<{  type: "streamable" | "sse"  url: string  options: { authProvider?: unknown; requestInit?: RequestInit }}> = [] // Mock the transport constructors to capture their argumentsmock.module("@modelcontextprotocol/sdk/client/streamableHttp.js", () => ({  StreamableHTTPClientTransport: class MockStreamableHTTP {    constructor(url: URL, options?: { authProvider?: unknown; requestInit?: RequestInit }) {      transportCalls.push({        type: "streamable",        url: url.toString(),        options: options ?? {},      })    }    async start() {      throw new Error("Mock transport cannot connect")    }  },})) mock.module("@modelcontextprotocol/sdk/client/sse.js", () => ({  SSEClientTransport: class MockSSE {    constructor(url: URL, options?: { authProvider?: unknown; requestInit?: RequestInit }) {      transportCalls.push({        type: "sse",        url: url.toString(),        options: options ?? {},      })    }    async start() {      throw new Error("Mock transport cannot connect")    }  },})) beforeEach(() => {  transportCalls.length = 0}) // Import MCP after mockingconst { MCP } = await import("../../src/mcp/index")const { Instance } = await import("../../src/project/instance")const { tmpdir } = await import("../fixture/fixture") test("headers are passed to transports when oauth is enabled (default)", async () => {  await using tmp = await tmpdir({    init: async (dir) => {      await Bun.write(        `${dir}/openscience.json`,        JSON.stringify({          $schema: "https://syntheticsciences.ai/config.json",          mcp: {            "test-server": {              type: "remote",              url: "https://example.com/mcp",              headers: {                Authorization: "Bearer test-token",                "X-Custom-Header": "custom-value",              },            },          },        }),      )    },  })   await Instance.provide({    directory: tmp.path,    fn: async () => {      // Trigger MCP initialization - it will fail to connect but we can check the transport options      await MCP.add("test-server", {        type: "remote",        url: "https://example.com/mcp",        headers: {          Authorization: "Bearer test-token",          "X-Custom-Header": "custom-value",        },      }).catch(() => {})       // Both transports should have been created with headers      expect(transportCalls.length).toBeGreaterThanOrEqual(1)       for (const call of transportCalls) {        expect(call.options.requestInit).toBeDefined()        expect(call.options.requestInit?.headers).toEqual({          Authorization: "Bearer test-token",          "X-Custom-Header": "custom-value",        })        // OAuth should be enabled by default, so authProvider should exist        expect(call.options.authProvider).toBeDefined()      }    },  })}) test("headers are passed to transports when oauth is explicitly disabled", async () => {  await using tmp = await tmpdir()   await Instance.provide({    directory: tmp.path,    fn: async () => {      transportCalls.length = 0       await MCP.add("test-server-no-oauth", {        type: "remote",        url: "https://example.com/mcp",        oauth: false,        headers: {          Authorization: "Bearer test-token",        },      }).catch(() => {})       expect(transportCalls.length).toBeGreaterThanOrEqual(1)       for (const call of transportCalls) {        expect(call.options.requestInit).toBeDefined()        expect(call.options.requestInit?.headers).toEqual({          Authorization: "Bearer test-token",        })        // OAuth is disabled, so no authProvider        expect(call.options.authProvider).toBeUndefined()      }    },  })}) test("no requestInit when headers are not provided", async () => {  await using tmp = await tmpdir()   await Instance.provide({    directory: tmp.path,    fn: async () => {      transportCalls.length = 0       await MCP.add("test-server-no-headers", {        type: "remote",        url: "https://example.com/mcp",      }).catch(() => {})       expect(transportCalls.length).toBeGreaterThanOrEqual(1)       for (const call of transportCalls) {        // No headers means requestInit should be undefined        expect(call.options.requestInit).toBeUndefined()      }    },  })})