Skip to content

Commit c4dde51

Browse files
committed
fix(server): convert connector tool schema with Zod 4 native JSON Schema
zod-to-json-schema is Zod 3 only; under Zod 4 it silently returns an empty schema, so the connector tool lost its server_name argument and MCP clients could not discover connector selection. Use z.toJSONSchema, which reads the Zod 4 object correctly.
1 parent 7a2a1d3 commit c4dde51

1 file changed

Lines changed: 8 additions & 11 deletions

File tree

packages/browseros-agent/apps/server/src/api/services/klavis/tool-adapters.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import type { CallToolResult } from '@modelcontextprotocol/client'
99
import { fromJsonSchema, type McpServer } from '@modelcontextprotocol/server'
1010
import { jsonSchema, type ToolSet } from 'ai'
1111
import { z } from 'zod'
12-
import { zodToJsonSchema } from 'zod-to-json-schema'
1312
import { logger } from '../../../lib/logger'
1413
import { metrics } from '../../../lib/metrics'
1514
import { findConnector, getConnectorCatalogDescription } from './catalog'
@@ -240,20 +239,18 @@ export function buildKlavisToolSet(deps: KlavisToolAdapterDeps): ToolSet {
240239
return toolSet
241240
}
242241

243-
// Bridge a locally hand-built Zod v3 shape (the connector tool's schema) into a
244-
// v2 registerTool input schema. v2 derives a tools/list JSON schema only from
245-
// Zod v4, so convert the v3 shape to JSON Schema first, then wrap it. Remote
246-
// Strata tools do NOT use this path: their JSON schema goes straight to
247-
// fromJsonSchema (round-tripping through Zod drops every property under v3).
242+
// Bridge the locally hand-built Zod shape (the connector tool's schema) into a
243+
// v2 registerTool input schema. v2 derives a tools/list JSON schema from the
244+
// JSON Schema, so convert the object first, then wrap it. Remote Strata tools do
245+
// NOT use this path: their JSON schema goes straight to fromJsonSchema.
248246
function toV2InputSchema(rawShape: z.ZodRawShape) {
249247
// The bridged value is a StandardSchemaWithJSON; type it as a raw shape so
250248
// registerTool's overload and handler typing resolve as before. At runtime
251-
// v2 accepts the real object via the Standard Schema path.
252-
// zod-to-json-schema is typed for Zod v3; under v4 its generic return type
253-
// instantiates too deeply (TS2589), so call it through an `unknown` signature.
254-
const toJsonSchema = zodToJsonSchema as (schema: unknown) => unknown
249+
// v2 accepts the real object via the Standard Schema path. Use Zod's native
250+
// JSON Schema converter: the object is a Zod 4 schema, which the external
251+
// zod-to-json-schema (v3-only) silently converts to an empty schema.
255252
return fromJsonSchema(
256-
toJsonSchema(z.object(rawShape)) as never,
253+
z.toJSONSchema(z.object(rawShape)) as never,
257254
) as unknown as Record<string, never>
258255
}
259256

0 commit comments

Comments
 (0)