Skip to content

Commit b65bb16

Browse files
fix(mistralai): handle both Zod and JSON schemas in tool conversion
The _convertToolToMistralTool function was attempting to convert all tool schemas using zodToJsonSchema(), but MCP tools already provide JSON schemas. This caused a "Cannot read properties of undefined (reading 'typeName')" error when using MCP tools with ChatMistralAI. Now checks if schema is a Zod schema before conversion, allowing both Zod schemas (from standard LangChain tools) and JSON schemas (from MCP tools) to work correctly. Fixes compatibility issue between @langchain/mistralai and @langchain/mcp-adapters.
1 parent d29e16a commit b65bb16

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

libs/langchain-mistralai/src/chat_models.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -503,12 +503,17 @@ function _convertToolToMistralTool(
503503
}
504504

505505
const description = tool.description ?? `Tool: ${tool.name}`;
506+
// Check if schema is a Zod schema or already a JSON schema
507+
const parameters = isZodSchema(tool.schema)
508+
? zodToJsonSchema(tool.schema)
509+
: tool.schema;
510+
506511
return {
507512
type: "function",
508513
function: {
509514
name: tool.name,
510515
description,
511-
parameters: zodToJsonSchema(tool.schema),
516+
parameters,
512517
},
513518
};
514519
});

libs/langchain-mistralai/src/tests/chat_models.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { z } from "zod";
2+
import { DynamicStructuredTool } from "@langchain/core/tools";
13
import { ChatMistralAI } from "../chat_models.js";
24
import {
35
_isValidMistralToolCallId,
@@ -30,6 +32,55 @@ describe("Mistral Tool Call ID Conversion", () => {
3032
});
3133
});
3234

35+
test("Tool conversion handles both Zod schemas and JSON schemas", () => {
36+
const model = new ChatMistralAI({ apiKey: "test" });
37+
const zodTool = {
38+
name: "zodTool",
39+
description: "A tool with Zod schema",
40+
schema: z.object({
41+
input: z.string().describe("Input parameter"),
42+
}),
43+
};
44+
const jsonSchemaTool = {
45+
name: "jsonSchemaTool",
46+
description: "A tool with JSON schema",
47+
schema: {
48+
type: "object",
49+
properties: {
50+
input: {
51+
type: "string",
52+
description: "Input parameter"
53+
}
54+
},
55+
required: ["input"]
56+
},
57+
};
58+
59+
expect(() => {
60+
const modelWithTools = model.bindTools([zodTool, jsonSchemaTool]);
61+
expect(modelWithTools).toBeDefined();
62+
}).not.toThrow();
63+
64+
const mcpLikeTool = new DynamicStructuredTool({
65+
name: "mcpLikeTool",
66+
description: "Tool similar to MCP tools",
67+
schema: {
68+
type: "object",
69+
properties: {
70+
city: { type: "string" },
71+
},
72+
required: ["city"],
73+
},
74+
func: async () => "test result",
75+
});
76+
77+
// This should also not throw an error
78+
expect(() => {
79+
const modelWithMcpTool = model.bindTools([mcpLikeTool]);
80+
expect(modelWithMcpTool).toBeDefined();
81+
}).not.toThrow();
82+
});
83+
3384
test("Serialization", () => {
3485
const model = new ChatMistralAI({
3586
apiKey: "foo",

0 commit comments

Comments
 (0)