Skip to content
This repository was archived by the owner on May 18, 2026. It is now read-only.

fix: tool-retrieval MCP server crashes on startup (plain-object schema bug)#3

Merged
GusCayresMindsight merged 1 commit into
masterfrom
fix/tool-retrieval-mcp-server-startup
May 15, 2026
Merged

fix: tool-retrieval MCP server crashes on startup (plain-object schema bug)#3
GusCayresMindsight merged 1 commit into
masterfrom
fix/tool-retrieval-mcp-server-startup

Conversation

@GusCayresMindsight

Copy link
Copy Markdown
Owner

Problem

`opencode-workspace mcp-serve` exited immediately on every invocation with:

```
tool-retrieval-server: fatal error: Schema is missing a method literal
MCP error -32000: Connection closed local mcp startup failed
```

`Server.setRequestHandler()` in `@modelcontextprotocol/sdk` requires a Zod schema as its first argument. The code was passing a plain JavaScript object instead:

```js
// Before — crashes the server on startup
server.setRequestHandler({ method: 'tools/list' }, handler);
server.setRequestHandler({ method: 'tools/call' }, handler);
```

The SDK calls `getObjectShape(schema)` on the first argument. A plain object has no `.shape` or `._zod` property, so `shape?.method` is `undefined` and the SDK throws synchronously — killing the process before it can serve a single request.

Fix

Use the correct Zod schemas exported by the SDK:

```js
const { ListToolsRequestSchema, CallToolRequestSchema } =
await import('@modelcontextprotocol/sdk/types.js');

server.setRequestHandler(ListToolsRequestSchema, handler);
server.setRequestHandler(CallToolRequestSchema, handler);
```

Refactor (enables the new tests)

  • Extract server setup into `createMcpServer({ Server, ListToolsRequestSchema, CallToolRequestSchema })` — accepts its SDK dependencies explicitly so it can be unit-tested with a mock `Server` without binding to stdio.
  • Remove the module-level `startServer()` auto-call; export `startServer()` and call it from `bin/cli.js`. This makes `require()`ing the module in tests safe.

Tests added

All previously existing 50 scenarios still pass. Three new scenarios cover the layer that was completely untested:

Scenario What it catches
Zod schema validation `setRequestHandler` is called with proper Zod schemas; each schema `.safeParse`s a valid request — would have failed with the old plain-object code
list-tools wire protocol Full `Client↔Server` round-trip via `InMemoryTransport`; asserts `search_tools` appears in the manifest with `query` in `required`
call-tool wire protocol Same in-process transport; asserts a valid `{ content, isError }` envelope is returned (uses empty corpus path — no embedder needed)

53/53 scenarios pass, 234/234 steps pass.

… schema

setRequestHandler() in @modelcontextprotocol/sdk requires a Zod schema as
its first argument (ListToolsRequestSchema / CallToolRequestSchema), not a
plain object like { method: 'tools/list' }.  Passing a plain object caused
the SDK to throw 'Schema is missing a method literal' synchronously during
server construction, so the process exited immediately on every mcp-serve
invocation.

Fixes:
- Use ListToolsRequestSchema and CallToolRequestSchema from the SDK's
  types module in both setRequestHandler calls.
- Extract server setup into createMcpServer({ Server, ListToolsRequestSchema,
  CallToolRequestSchema }) so it can be unit-tested without a real stdio
  transport.
- Remove the module-level startServer() auto-call; export startServer()
  explicitly and call it from bin/cli.js so requiring the module in tests
  is safe.

Tests added (docs/tool-retrieval-mcp.feature + step-definitions):
- Zod schema validation: asserts setRequestHandler is called with proper
  Zod schemas (not plain objects) using a mock Server + safeParse checks.
- list-tools wire protocol: full Client<->Server round-trip via
  InMemoryTransport; asserts search_tools appears in the manifest.
- call-tool wire protocol: same in-process transport; asserts a valid
  CallToolResult envelope is returned (empty corpus path, no embedder needed).

All 53 scenarios pass (234 steps).
@GusCayresMindsight GusCayresMindsight merged commit 022a986 into master May 15, 2026
4 checks passed
@GusCayresMindsight GusCayresMindsight deleted the fix/tool-retrieval-mcp-server-startup branch May 15, 2026 20:04
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant