test(mcp): replace module mocks with real servers (#35450)

This commit is contained in:
Aiden Cline
2026-07-05 12:49:31 -05:00
committed by GitHub
parent be73f465df
commit d3459eb740
7 changed files with 1036 additions and 1841 deletions
+70 -95
View File
@@ -1,126 +1,101 @@
import { describe, expect, mock, beforeEach } from "bun:test"
import { describe, expect } from "bun:test"
import { Server } from "@modelcontextprotocol/sdk/server/index.js"
import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js"
import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js"
import { LayerNode } from "@opencode-ai/core/effect/layer-node"
import { Effect } from "effect"
import { testEffect } from "../lib/effect"
import { MCP } from "../../src/mcp/index"
// Track what options were passed to each transport constructor
const transportCalls: Array<{
type: "streamable" | "sse"
url: string
options: { authProvider?: unknown; requestInit?: RequestInit }
}> = []
// Mock the transport constructors to capture their arguments
void mock.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")
}
},
}))
void 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 mocking
const { MCP } = await import("../../src/mcp/index")
const it = testEffect(LayerNode.compile(MCP.node))
const serve = Effect.acquireRelease(
Effect.promise(async () => {
const requests: Headers[] = []
const protocol = new Server({ name: "headers", version: "1.0.0" }, { capabilities: { tools: {} } })
protocol.setRequestHandler(ListToolsRequestSchema, () => Promise.resolve({ tools: [] }))
const transport = new WebStandardStreamableHTTPServerTransport({
sessionIdGenerator: () => crypto.randomUUID(),
enableJsonResponse: true,
})
await protocol.connect(transport)
const http = Bun.serve({
port: 0,
fetch(request) {
requests.push(new Headers(request.headers))
return transport.handleRequest(request)
},
})
return {
requests,
url: http.url.toString(),
close: async () => {
await http.stop(true)
await protocol.close()
},
}
}),
(server) => Effect.promise(server.close),
)
describe("mcp.headers", () => {
it.instance("headers are passed to transports when oauth is enabled (default)", () =>
Effect.gen(function* () {
const server = yield* serve
const mcp = yield* MCP.Service
yield* mcp
.add("test-server", {
type: "remote",
url: "https://example.com/mcp",
headers: {
Authorization: "Bearer test-token",
"X-Custom-Header": "custom-value",
},
})
.pipe(Effect.catch(() => Effect.void))
// 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({
const result = yield* mcp.add("test-server", {
type: "remote",
url: server.url,
headers: {
Authorization: "Bearer test-token",
"X-Custom-Header": "custom-value",
})
// OAuth should be enabled by default, so authProvider should exist
expect(call.options.authProvider).toBeDefined()
},
})
expect(result.status).toMatchObject({ "test-server": { status: "connected" } })
expect(server.requests.length).toBeGreaterThan(0)
for (const headers of server.requests) {
expect(headers.get("authorization")).toBe("Bearer test-token")
expect(headers.get("x-custom-header")).toBe("custom-value")
}
}),
)
it.instance("headers are passed to transports when oauth is explicitly disabled", () =>
Effect.gen(function* () {
const server = yield* serve
const mcp = yield* MCP.Service
yield* mcp
.add("test-server-no-oauth", {
type: "remote",
url: "https://example.com/mcp",
oauth: false,
headers: {
Authorization: "Bearer test-token",
},
})
.pipe(Effect.catch(() => Effect.void))
expect(transportCalls.length).toBeGreaterThanOrEqual(1)
for (const call of transportCalls) {
expect(call.options.requestInit).toBeDefined()
expect(call.options.requestInit?.headers).toEqual({
const result = yield* mcp.add("test-server-no-oauth", {
type: "remote",
url: server.url,
oauth: false,
headers: {
Authorization: "Bearer test-token",
})
// OAuth is disabled, so no authProvider
expect(call.options.authProvider).toBeUndefined()
},
})
expect(result.status).toMatchObject({ "test-server-no-oauth": { status: "connected" } })
expect(server.requests.length).toBeGreaterThan(0)
for (const headers of server.requests) {
expect(headers.get("authorization")).toBe("Bearer test-token")
}
}),
)
it.instance("no requestInit when headers are not provided", () =>
Effect.gen(function* () {
const server = yield* serve
const mcp = yield* MCP.Service
yield* mcp
.add("test-server-no-headers", {
type: "remote",
url: "https://example.com/mcp",
})
.pipe(Effect.catch(() => Effect.void))
const result = yield* mcp.add("test-server-no-headers", {
type: "remote",
url: server.url,
})
expect(transportCalls.length).toBeGreaterThanOrEqual(1)
for (const call of transportCalls) {
// No headers means requestInit should be undefined
expect(call.options.requestInit).toBeUndefined()
expect(result.status).toMatchObject({ "test-server-no-headers": { status: "connected" } })
expect(server.requests.length).toBeGreaterThan(0)
for (const headers of server.requests) {
expect(headers.has("authorization")).toBe(false)
expect(headers.has("x-custom-header")).toBe(false)
}
}),
)