Skip to content

McpServer toolkit registration drops declared tool service requirements #8843

Closed

Description

@brandon-julio-t

What version of Effect is running?

Observed downstream with effect@4.0.0-rc.117. The same declarations remain on current main at 723478668709ccefcec406522e2fce2431c653c9.

The before/after regression test used base commit e36abbba72674cfe366747ae52639448e48da1ec and fix commit 3ce953d1ffa21605b4fc4d210a96a258f7be3741, with TypeScript 5.9.3 and 6.0.3.

What steps can reproduce the bug?

Declare a tool service dependency, register its toolkit, and supply the MCP server and tool handlers. The declared tool service disappears from the remaining Effect requirements.

The executable reproduction covers handler and schema services across multiple tools. Its critical assertions are:

expect<Effect.Services<typeof withoutServices>>().type.toBe<Lookup | Decoder | Encoder>()
expect(Effect.runPromise).type.not.toBeCallableWith(withoutServices)

In a disposable checkout of the fix commit with dependencies installed, replace only the implementation with its original version:

git show e36abbba72674cfe366747ae52639448e48da1ec:packages/effect/src/ai/McpServer.ts > packages/effect/src/ai/McpServer.ts
pnpm test-types packages/effect/typetest/ai/McpServer.tst.ts

This fails on both compiler targets, including Error: Expression is callable with the given argument. Restore the fix and repeat:

git restore --source=3ce953d1ffa21605b4fc4d210a96a258f7be3741 -- packages/effect/src/ai/McpServer.ts
pnpm test-types packages/effect/typetest/ai/McpServer.tst.ts

The same tests pass: 98 assertions combined across both compiler targets, compared with 12 failed and 86 passed before the fix.

What is the expected behavior?

McpServer.registerToolkit and McpServer.toolkit should preserve the tool services required at registration. TypeScript should reject execution until the application supplies those services. The per-call McpRequestContext should remain excluded.

What do you see instead?

The remaining service type becomes never, so Effect.runPromise accepts the incomplete program. Our downstream HTTP tool failed with Service not found: effect/HttpClient, despite declaring dependencies: [HttpClient.HttpClient].

Additional information

Both APIs extract Tool.HandlerServices<Tools> from the entire tool record, instead of Tool.HandlerServices<Tools[keyof Tools]> from its values. The former resolves to never. Current source

Fix and full before/after evidence: #8842.

Related: #8526 concerns the outer Effect versus returned Stream requirements in Toolkit.handle. This report concerns service requirements lost during MCP registration.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions