Skip to content

fix(mcp): preserve tool input schema types and required fields#6248

Merged
HenryHengZJ merged 4 commits intomainfrom
bugfix/mcp-inputschema-zod-conversion
Apr 21, 2026
Merged

fix(mcp): preserve tool input schema types and required fields#6248
HenryHengZJ merged 4 commits intomainfrom
bugfix/mcp-inputschema-zod-conversion

Conversation

@HenryHengZJ
Copy link
Copy Markdown
Contributor

Summary

  • MCP tools were losing all type information and required fields because createSchemaModel mapped every property to z.any()
  • Rather than reimplement a JSON-Schema-to-Zod converter (lossy for $ref, allOf, anyOf, enums, nested objects), pass the MCP server's inputSchema straight through to LangChain's tool() — the JsonSchema7Type overload has been supported since @langchain/core 1.1.x.
  • Downstream tool serializers (Agent, Tool, OpenAIAssistant) to uptake these changes

Before / After

Example 1 — typed params with required fields

MCP server with the following inputSchema for a create_issue tool:

{
  "type": "object",
  "properties": {
    "owner":      { "type": "string",  "description": "Repo owner" },
    "repo":       { "type": "string",  "description": "Repo name" },
    "title":      { "type": "string" },
    "project_id": { "type": "integer" },
    "draft":      { "type": "boolean" }
  },
  "required": ["owner", "repo", "title"]
}

Before — what the LLM saw after createSchemaModel:

{
  "type": "object",
  "properties": {
    "owner":      {},
    "repo":       {},
    "title":      {},
    "project_id": {},
    "draft":      {}
  }
}

LLM response:

{ "name": "create_issue", "arguments": {} }

Tool call fails — owner, repo, title missing. OpenAI strict mode rejects the schema outright because property type keys are absent.

After — we straightaway pass the raw inputSchema and preserve everything. LLM response:

{
  "name": "create_issue",
  "arguments": {
    "owner": "flowiseai",
    "repo":  "Flowise",
    "title": "Fix MCP schema handling"
  }
}

Example 2 — enum constraints

{
  "type": "object",
  "properties": {
    "priority": { "type": "string", "enum": ["low", "medium", "high"] }
  },
  "required": ["priority"]
}

Before: priority was z.any() — LLM would pass "urgent", "P1", or anything else.
After: the enum is preserved; the model provider enforces one of low | medium | high.

Example 3 — nested object

{
  "type": "object",
  "properties": {
    "filter": {
      "type": "object",
      "properties": {
        "status": { "type": "string" },
        "since":  { "type": "string", "format": "date-time" }
      },
      "required": ["status"]
    }
  },
  "required": ["filter"]
}

Before: nested filter became z.any() — the LLM received no guidance on inner structure and commonly sent "filter": "open" as a string.
After: full nested schema reaches the model; inner required and format are preserved.

Example 4 — no input schema

A tool like get_current_time with no params.

Before: createSchemaModel threw Invalid schema type or missing properties; the tool was silently dropped from the toolkit because Promise.allSettled swallowed the rejection.
After: tool registers correctly with an empty object schema.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request modifies how tool schemas are handled across several components, specifically by checking for Zod definitions before applying zodToJsonSchema or falling back to a plain object. It also removes the createSchemaModel utility and its associated Zod dependencies in MCP-related files, opting to pass the raw inputSchema instead. A critical issue was identified in OpenAIAssistant.ts where using a shallow copy for the schema can lead to unintended global side effects due to subsequent deep mutations; a deep clone is recommended instead.

Comment thread packages/components/nodes/agents/OpenAIAssistant/OpenAIAssistant.ts Outdated
Comment thread packages/components/src/utils.ts
Comment thread packages/components/src/utils.ts
@HenryHengZJ HenryHengZJ merged commit ea68f9a into main Apr 21, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OpenAI Agent Node Strict Tool Calling Mode fails on json schema validation with Custom MCP Tool

2 participants