Просмотр исходного кода

test(mcp): migrate lifecycle tests to Effect runner (#27205)

Kit Langton 3 месяцев назад
Родитель
Сommit
68c4951318
1 измененных файлов с 390 добавлено и 362 удалено
  1. 390 362
      packages/opencode/test/mcp/lifecycle.test.ts

+ 390 - 362
packages/opencode/test/mcp/lifecycle.test.ts

@@ -1,7 +1,7 @@
-import { test, expect, mock, beforeEach } from "bun:test"
-import { InstanceRuntime } from "../../src/project/instance-runtime"
-import { Effect } from "effect"
+import { expect, mock, beforeEach } from "bun:test"
+import { Effect, Exit } from "effect"
 import type { MCP as MCPNS } from "../../src/mcp/index"
+import { testEffect } from "../lib/effect"
 
 // --- Mock infrastructure ---
 
@@ -179,39 +179,9 @@ beforeEach(() => {
 
 // Import after mocks
 const { MCP } = await import("../../src/mcp/index")
-const { Instance } = await import("../../src/project/instance")
-const { WithInstance } = await import("../../src/project/with-instance")
-const { tmpdir } = await import("../fixture/fixture")
-
-// --- Helper ---
-
-function withInstance(
-  config: Record<string, unknown>,
-  fn: (mcp: MCPNS.Interface) => Effect.Effect<void, unknown, never>,
-) {
-  return async () => {
-    await using tmp = await tmpdir({
-      init: async (dir) => {
-        await Bun.write(
-          `${dir}/opencode.json`,
-          JSON.stringify({
-            $schema: "https://opencode.ai/config.json",
-            mcp: config,
-          }),
-        )
-      },
-    })
-
-    await WithInstance.provide({
-      directory: tmp.path,
-      fn: async () => {
-        await Effect.runPromise(MCP.Service.use(fn).pipe(Effect.provide(MCP.defaultLayer)))
-        // dispose instance to clean up state between tests
-        await InstanceRuntime.disposeInstance(Instance.current)
-      },
-    })
-  }
-}
+const { McpOAuthCallback } = await import("../../src/mcp/oauth-callback")
+
+const it = testEffect(MCP.defaultLayer)
 
 function statusName(status: Record<string, MCPNS.Status> | MCPNS.Status, server: string) {
   if ("status" in status) return status.status
@@ -222,82 +192,82 @@ function statusName(status: Record<string, MCPNS.Status> | MCPNS.Status, server:
 // Test: tools() are cached after connect
 // ========================================================================
 
-test(
+it.instance(
   "tools() reuses cached tool definitions after connect",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "my-server"
-      const serverState = getOrCreateClientState("my-server")
-      serverState.tools = [
-        { name: "do_thing", description: "does a thing", inputSchema: { type: "object", properties: {} } },
-      ]
-
-      // First: add the server successfully
-      const addResult = yield* mcp.add("my-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
-      expect((addResult.status as any)["my-server"]?.status ?? (addResult.status as any).status).toBe("connected")
-
-      expect(serverState.listToolsCalls).toBe(1)
-
-      const toolsA = yield* mcp.tools()
-      const toolsB = yield* mcp.tools()
-      expect(Object.keys(toolsA).length).toBeGreaterThan(0)
-      expect(Object.keys(toolsB).length).toBeGreaterThan(0)
-      expect(serverState.listToolsCalls).toBe(1)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "my-server"
+        const serverState = getOrCreateClientState("my-server")
+        serverState.tools = [
+          { name: "do_thing", description: "does a thing", inputSchema: { type: "object", properties: {} } },
+        ]
+
+        // First: add the server successfully
+        const addResult = yield* mcp.add("my-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
+        expect((addResult.status as any)["my-server"]?.status ?? (addResult.status as any).status).toBe("connected")
+
+        expect(serverState.listToolsCalls).toBe(1)
+
+        const toolsA = yield* mcp.tools()
+        const toolsB = yield* mcp.tools()
+        expect(Object.keys(toolsA).length).toBeGreaterThan(0)
+        expect(Object.keys(toolsB).length).toBeGreaterThan(0)
+        expect(serverState.listToolsCalls).toBe(1)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: tool change notifications refresh the cache
 // ========================================================================
 
-test(
+it.instance(
   "tool change notifications refresh cached tool definitions",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "status-server"
-      const serverState = getOrCreateClientState("status-server")
-
-      yield* mcp.add("status-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
-
-      const before = yield* mcp.tools()
-      expect(Object.keys(before).some((key) => key.includes("test_tool"))).toBe(true)
-      expect(serverState.listToolsCalls).toBe(1)
-
-      serverState.tools = [{ name: "next_tool", description: "next", inputSchema: { type: "object", properties: {} } }]
-
-      const handler = Array.from(serverState.notificationHandlers.values())[0]
-      expect(handler).toBeDefined()
-      yield* Effect.promise(() => handler?.())
-
-      const after = yield* mcp.tools()
-      expect(Object.keys(after).some((key) => key.includes("next_tool"))).toBe(true)
-      expect(Object.keys(after).some((key) => key.includes("test_tool"))).toBe(false)
-      expect(serverState.listToolsCalls).toBe(2)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "status-server"
+        const serverState = getOrCreateClientState("status-server")
+
+        yield* mcp.add("status-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
+
+        const before = yield* mcp.tools()
+        expect(Object.keys(before).some((key) => key.includes("test_tool"))).toBe(true)
+        expect(serverState.listToolsCalls).toBe(1)
+
+        serverState.tools = [
+          { name: "next_tool", description: "next", inputSchema: { type: "object", properties: {} } },
+        ]
+
+        const handler = Array.from(serverState.notificationHandlers.values())[0]
+        expect(handler).toBeDefined()
+        yield* Effect.promise(() => handler?.())
+
+        const after = yield* mcp.tools()
+        expect(Object.keys(after).some((key) => key.includes("next_tool"))).toBe(true)
+        expect(Object.keys(after).some((key) => key.includes("test_tool"))).toBe(false)
+        expect(serverState.listToolsCalls).toBe(2)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: connect() / disconnect() lifecycle
 // ========================================================================
 
-test(
+it.instance(
   "disconnect sets status to disabled and removes client",
-  withInstance(
-    {
-      "disc-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "disc-server"
         getOrCreateClientState("disc-server")
@@ -315,24 +285,27 @@ test(
         const statusAfter = yield* mcp.status()
         expect(statusAfter["disc-server"]?.status).toBe("disabled")
 
-        // Tools should be empty after disconnect
         const tools = yield* mcp.tools()
         const serverTools = Object.keys(tools).filter((k) => k.startsWith("disc-server"))
         expect(serverTools.length).toBe(0)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "disc-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
-test(
+it.instance(
   "connect() after disconnect() re-establishes the server",
-  withInstance(
-    {
-      "reconn-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "reconn-server"
         const serverState = getOrCreateClientState("reconn-server")
@@ -348,70 +321,71 @@ test(
         yield* mcp.disconnect("reconn-server")
         expect((yield* mcp.status())["reconn-server"]?.status).toBe("disabled")
 
-        // Reconnect
         yield* mcp.connect("reconn-server")
         expect((yield* mcp.status())["reconn-server"]?.status).toBe("connected")
 
         const tools = yield* mcp.tools()
         expect(Object.keys(tools).some((k) => k.includes("my_tool"))).toBe(true)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "reconn-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
 // ========================================================================
 // Test: add() closes existing client before replacing
 // ========================================================================
 
-test(
+it.instance(
   "add() closes the old client when replacing a server",
   // Don't put the server in config — add it dynamically so we control
   // exactly which client instance is "first" vs "second".
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "replace-server"
-      const firstState = getOrCreateClientState("replace-server")
-
-      yield* mcp.add("replace-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
-
-      expect(firstState.closed).toBe(false)
-
-      // Create new state for second client
-      clientStates.delete("replace-server")
-      const secondState = getOrCreateClientState("replace-server")
-
-      // Re-add should close the first client
-      yield* mcp.add("replace-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
-
-      expect(firstState.closed).toBe(true)
-      expect(secondState.closed).toBe(false)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "replace-server"
+        const firstState = getOrCreateClientState("replace-server")
+
+        yield* mcp.add("replace-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
+
+        expect(firstState.closed).toBe(false)
+
+        // Create new state for second client
+        clientStates.delete("replace-server")
+        const secondState = getOrCreateClientState("replace-server")
+
+        // Re-add should close the first client
+        yield* mcp.add("replace-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
+
+        expect(firstState.closed).toBe(true)
+        expect(secondState.closed).toBe(false)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: state init with mixed success/failure
 // ========================================================================
 
-test(
+it.instance(
   "init connects available servers even when one fails",
-  withInstance(
-    {
-      "good-server": {
-        type: "local",
-        command: ["echo", "good"],
-      },
-      "bad-server": {
-        type: "local",
-        command: ["echo", "bad"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         // Set up good server
         const goodState = getOrCreateClientState("good-server")
@@ -443,77 +417,88 @@ test(
         const tools = yield* mcp.tools()
         expect(Object.keys(tools).some((k) => k.includes("good_tool"))).toBe(true)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "good-server": {
+          type: "local",
+          command: ["echo", "good"],
+        },
+        "bad-server": {
+          type: "local",
+          command: ["echo", "bad"],
+        },
+      },
+    },
+  },
 )
 
-test(
+it.instance(
   "falls back when MCP output schema refs fail SDK tool discovery",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "stitch-like-server"
-      const serverState = getOrCreateClientState("stitch-like-server")
-      serverState.listToolsShouldFail = true
-      serverState.listToolsError = "can't resolve reference #/$defs/ScreenInstance from id #"
-      serverState.tools = [
-        {
-          name: "render_screen",
-          description: "renders a screen",
-          inputSchema: { type: "object", properties: { prompt: { type: "string" } }, required: ["prompt"] },
-          outputSchema: { type: "object", properties: { screen: { $ref: "#/$defs/ScreenInstance" } } },
-        },
-      ]
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "stitch-like-server"
+        const serverState = getOrCreateClientState("stitch-like-server")
+        serverState.listToolsShouldFail = true
+        serverState.listToolsError = "can't resolve reference #/$defs/ScreenInstance from id #"
+        serverState.tools = [
+          {
+            name: "render_screen",
+            description: "renders a screen",
+            inputSchema: { type: "object", properties: { prompt: { type: "string" } }, required: ["prompt"] },
+            outputSchema: { type: "object", properties: { screen: { $ref: "#/$defs/ScreenInstance" } } },
+          },
+        ]
 
-      const addResult = yield* mcp.add("stitch-like-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
+        const addResult = yield* mcp.add("stitch-like-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
 
-      expect(statusName(addResult.status, "stitch-like-server")).toBe("connected")
+        expect(statusName(addResult.status, "stitch-like-server")).toBe("connected")
 
-      const tools = yield* mcp.tools()
-      expect(Object.keys(tools).some((key) => key.includes("render_screen"))).toBe(true)
-      expect(serverState.listToolsCalls).toBe(1)
-      expect(serverState.requestCalls).toBe(1)
-    }),
-  ),
+        const tools = yield* mcp.tools()
+        expect(Object.keys(tools).some((key) => key.includes("render_screen"))).toBe(true)
+        expect(serverState.listToolsCalls).toBe(1)
+        expect(serverState.requestCalls).toBe(1)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
-test(
+it.instance(
   "does not fall back for non-schema MCP tool discovery errors",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "broken-server"
-      const serverState = getOrCreateClientState("broken-server")
-      serverState.listToolsShouldFail = true
-      serverState.listToolsError = "transport closed"
-
-      const addResult = yield* mcp.add("broken-server", {
-        type: "local",
-        command: ["echo", "test"],
-      })
-
-      expect(statusName(addResult.status, "broken-server")).toBe("failed")
-      expect(serverState.listToolsCalls).toBe(1)
-      expect(serverState.requestCalls).toBe(0)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "broken-server"
+        const serverState = getOrCreateClientState("broken-server")
+        serverState.listToolsShouldFail = true
+        serverState.listToolsError = "transport closed"
+
+        const addResult = yield* mcp.add("broken-server", {
+          type: "local",
+          command: ["echo", "test"],
+        })
+
+        expect(statusName(addResult.status, "broken-server")).toBe("failed")
+        expect(serverState.listToolsCalls).toBe(1)
+        expect(serverState.requestCalls).toBe(0)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: disabled server via config
 // ========================================================================
 
-test(
+it.instance(
   "disabled server is marked as disabled without attempting connection",
-  withInstance(
-    {
-      "disabled-server": {
-        type: "local",
-        command: ["echo", "test"],
-        enabled: false,
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         const countBefore = clientCreateCount
 
@@ -529,23 +514,28 @@ test(
         const status = yield* mcp.status()
         expect(status["disabled-server"]?.status).toBe("disabled")
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "disabled-server": {
+          type: "local",
+          command: ["echo", "test"],
+          enabled: false,
+        },
+      },
+    },
+  },
 )
 
 // ========================================================================
 // Test: prompts() and resources()
 // ========================================================================
 
-test(
+it.instance(
   "prompts() returns prompts from connected servers",
-  withInstance(
-    {
-      "prompt-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "prompt-server"
         const serverState = getOrCreateClientState("prompt-server")
@@ -562,19 +552,23 @@ test(
         expect(key).toContain("prompt-server")
         expect(key).toContain("my-prompt")
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "prompt-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
-test(
+it.instance(
   "resources() returns resources from connected servers",
-  withInstance(
-    {
-      "resource-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "resource-server"
         const serverState = getOrCreateClientState("resource-server")
@@ -591,19 +585,23 @@ test(
         expect(key).toContain("resource-server")
         expect(key).toContain("my-resource")
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "resource-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
-test(
+it.instance(
   "prompts() skips disconnected servers",
-  withInstance(
-    {
-      "prompt-disc-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "prompt-disc-server"
         const serverState = getOrCreateClientState("prompt-disc-server")
@@ -619,67 +617,77 @@ test(
         const prompts = yield* mcp.prompts()
         expect(Object.keys(prompts).length).toBe(0)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "prompt-disc-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
 // ========================================================================
 // Test: connect() on nonexistent server
 // ========================================================================
 
-test(
+it.instance(
   "connect() on nonexistent server does not throw",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      // Should not throw
-      yield* mcp.connect("nonexistent")
-      const status = yield* mcp.status()
-      expect(status["nonexistent"]).toBeUndefined()
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        // Should not throw
+        yield* mcp.connect("nonexistent")
+        const status = yield* mcp.status()
+        expect(status["nonexistent"]).toBeUndefined()
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: disconnect() on nonexistent server
 // ========================================================================
 
-test(
+it.instance(
   "disconnect() on nonexistent server does not throw",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      yield* mcp.disconnect("nonexistent")
-      // Should complete without error
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        yield* mcp.disconnect("nonexistent")
+        // Should complete without error
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: tools() with no MCP servers configured
 // ========================================================================
 
-test(
+it.instance(
   "tools() returns empty when no MCP servers are configured",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      const tools = yield* mcp.tools()
-      expect(Object.keys(tools).length).toBe(0)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        const tools = yield* mcp.tools()
+        expect(Object.keys(tools).length).toBe(0)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: connect failure during create()
 // ========================================================================
 
-test(
+it.instance(
   "server that fails to connect is marked as failed",
-  withInstance(
-    {
-      "fail-connect": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "fail-connect"
         getOrCreateClientState("fail-connect")
@@ -701,51 +709,55 @@ test(
         const tools = yield* mcp.tools()
         expect(Object.keys(tools).length).toBe(0)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "fail-connect": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
 // ========================================================================
 // Bug #5: McpOAuthCallback.cancelPending uses wrong key
 // ========================================================================
 
-test("McpOAuthCallback.cancelPending is keyed by mcpName but pendingAuths uses oauthState", async () => {
-  const { McpOAuthCallback } = await import("../../src/mcp/oauth-callback")
-
-  // Register a pending auth with an oauthState key, associated to an mcpName
-  const oauthState = "abc123hexstate"
-  const callbackPromise = McpOAuthCallback.waitForCallback(oauthState, "my-mcp-server")
-
-  // cancelPending is called with mcpName — should find the entry via reverse index
-  McpOAuthCallback.cancelPending("my-mcp-server")
-
-  // The callback should still be pending because cancelPending looked up
-  // "my-mcp-server" in a map keyed by "abc123hexstate"
-  let rejected = false
-  callbackPromise.then(() => {}).catch(() => (rejected = true))
-
-  // Give it a tick
-  await new Promise((r) => setTimeout(r, 50))
-
-  // cancelPending("my-mcp-server") should have rejected the pending callback
-  expect(rejected).toBe(true)
+it.live("McpOAuthCallback.cancelPending is keyed by mcpName but pendingAuths uses oauthState", () =>
+  Effect.acquireUseRelease(
+    Effect.sync(() => McpOAuthCallback.waitForCallback("abc123hexstate", "my-mcp-server")),
+    (callback) =>
+      Effect.gen(function* () {
+        McpOAuthCallback.cancelPending("my-mcp-server")
+
+        const exit = yield* Effect.tryPromise({
+          try: () => callback,
+          catch: (error) => (error instanceof Error ? error : new Error(String(error))),
+        }).pipe(
+          Effect.timeoutOrElse({
+            duration: "1 second",
+            orElse: () => Effect.fail(new Error("timed out waiting for OAuth cancellation")),
+          }),
+          Effect.exit,
+        )
 
-  await McpOAuthCallback.stop()
-})
+        expect(Exit.isFailure(exit)).toBe(true)
+      }),
+    () => Effect.promise(() => McpOAuthCallback.stop()).pipe(Effect.ignore),
+  ),
+)
 
 // ========================================================================
 // Test: multiple tools from same server get correct name prefixes
 // ========================================================================
 
-test(
+it.instance(
   "tools() prefixes tool names with sanitized server name",
-  withInstance(
-    {
-      "my.special-server": {
-        type: "local",
-        command: ["echo", "test"],
-      },
-    },
-    (mcp) =>
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
       Effect.gen(function* () {
         lastCreatedClientName = "my.special-server"
         const serverState = getOrCreateClientState("my.special-server")
@@ -768,87 +780,103 @@ test(
         expect(keys.some((k) => k.endsWith("tool_b"))).toBe(true)
         expect(keys.length).toBe(2)
       }),
-  ),
+    ),
+  {
+    config: {
+      mcp: {
+        "my.special-server": {
+          type: "local",
+          command: ["echo", "test"],
+        },
+      },
+    },
+  },
 )
 
 // ========================================================================
 // Test: transport leak — local stdio timeout (#19168)
 // ========================================================================
 
-test(
+it.instance(
   "local stdio transport is closed when connect times out (no process leak)",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "hanging-server"
-      getOrCreateClientState("hanging-server")
-      connectShouldHang = true
-
-      const addResult = yield* mcp.add("hanging-server", {
-        type: "local",
-        command: ["node", "fake.js"],
-        timeout: 100,
-      })
-
-      const serverStatus = (addResult.status as any)["hanging-server"] ?? addResult.status
-      expect(serverStatus.status).toBe("failed")
-      expect(serverStatus.error).toContain("timed out")
-      // Transport must be closed to avoid orphaned child process
-      expect(transportCloseCount).toBeGreaterThanOrEqual(1)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "hanging-server"
+        getOrCreateClientState("hanging-server")
+        connectShouldHang = true
+
+        const addResult = yield* mcp.add("hanging-server", {
+          type: "local",
+          command: ["node", "fake.js"],
+          timeout: 100,
+        })
+
+        const serverStatus = (addResult.status as any)["hanging-server"] ?? addResult.status
+        expect(serverStatus.status).toBe("failed")
+        expect(serverStatus.error).toContain("timed out")
+        // Transport must be closed to avoid orphaned child process
+        expect(transportCloseCount).toBeGreaterThanOrEqual(1)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: transport leak — remote timeout (#19168)
 // ========================================================================
 
-test(
+it.instance(
   "remote transport is closed when connect times out",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "hanging-remote"
-      getOrCreateClientState("hanging-remote")
-      connectShouldHang = true
-
-      const addResult = yield* mcp.add("hanging-remote", {
-        type: "remote",
-        url: "http://localhost:9999/mcp",
-        timeout: 100,
-        oauth: false,
-      })
-
-      const serverStatus = (addResult.status as any)["hanging-remote"] ?? addResult.status
-      expect(serverStatus.status).toBe("failed")
-      // Transport must be closed to avoid leaked HTTP connections
-      expect(transportCloseCount).toBeGreaterThanOrEqual(1)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "hanging-remote"
+        getOrCreateClientState("hanging-remote")
+        connectShouldHang = true
+
+        const addResult = yield* mcp.add("hanging-remote", {
+          type: "remote",
+          url: "http://localhost:9999/mcp",
+          timeout: 100,
+          oauth: false,
+        })
+
+        const serverStatus = (addResult.status as any)["hanging-remote"] ?? addResult.status
+        expect(serverStatus.status).toBe("failed")
+        // Transport must be closed to avoid leaked HTTP connections
+        expect(transportCloseCount).toBeGreaterThanOrEqual(1)
+      }),
+    ),
+  { config: { mcp: {} } },
 )
 
 // ========================================================================
 // Test: transport leak — failed remote transports not closed (#19168)
 // ========================================================================
 
-test(
+it.instance(
   "failed remote transport is closed before trying next transport",
-  withInstance({}, (mcp) =>
-    Effect.gen(function* () {
-      lastCreatedClientName = "fail-remote"
-      getOrCreateClientState("fail-remote")
-      connectShouldFail = true
-      connectError = "Connection refused"
-
-      const addResult = yield* mcp.add("fail-remote", {
-        type: "remote",
-        url: "http://localhost:9999/mcp",
-        timeout: 5000,
-        oauth: false,
-      })
-
-      const serverStatus = (addResult.status as any)["fail-remote"] ?? addResult.status
-      expect(serverStatus.status).toBe("failed")
-      // Both StreamableHTTP and SSE transports should be closed
-      expect(transportCloseCount).toBeGreaterThanOrEqual(2)
-    }),
-  ),
+  () =>
+    MCP.Service.use((mcp: MCPNS.Interface) =>
+      Effect.gen(function* () {
+        lastCreatedClientName = "fail-remote"
+        getOrCreateClientState("fail-remote")
+        connectShouldFail = true
+        connectError = "Connection refused"
+
+        const addResult = yield* mcp.add("fail-remote", {
+          type: "remote",
+          url: "http://localhost:9999/mcp",
+          timeout: 5000,
+          oauth: false,
+        })
+
+        const serverStatus = (addResult.status as any)["fail-remote"] ?? addResult.status
+        expect(serverStatus.status).toBe("failed")
+        // Both StreamableHTTP and SSE transports should be closed
+        expect(transportCloseCount).toBeGreaterThanOrEqual(2)
+      }),
+    ),
+  { config: { mcp: {} } },
 )