Skip to content

Conversation

@nik-net
Copy link
Contributor

@nik-net nik-net commented Jun 13, 2025

… conversion

Description

This PR fixes a critical bug in the MCP Client node's listTools operation, where tool parameter schemas from the MCP server were being truncated and losing fidelity. The root cause was a lossy conversion from JSON Schema to Zod and back, resulting in the loss of nested object structures, enums, constraints, and defaults. The fix removes this conversion and passes the server's JSON Schema through unchanged, preserving all schema details for downstream consumers and UI.

Related Issue

Closes #129

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Other (please describe):

How Has This Been Tested?

  • Added a Jest-based test (nodes/McpClient/__tests__/listTools.schema.test.ts) that simulates a complex, deeply-nested tool schema from the MCP server and verifies that the schema is returned without modification or truncation.
  • Ran the full test suite with npm test to ensure all existing and new tests pass.
  • Manually reviewed the output of the listTools operation to confirm full fidelity of the schema.

Checklist

  • My code follows the code style of this project
  • I have updated the documentation accordingly (schemabug.md and PR template)
  • I have added tests to cover my changes
  • All new and existing tests passed

Release Notes

  • Fix: MCP Client now preserves and returns the full, original JSON Schema for tool parameters in listTools, enabling correct UI generation, validation, and downstream usage.

Screenshots (if applicable)

N/A (schema validation and passthrough tested via Jest)

Summary by CodeRabbit

  • Bug Fixes
    • Resolved an issue where complex or nested tool schemas were truncated in the listTools operation, ensuring the full original schema is now returned as provided by the server.
  • New Features
    • Added detailed debug-level logging for received and returned schemas to aid traceability.
  • Tests
    • Introduced new tests to verify that schemas are passed through without modification and to detect any schema truncation.
  • Documentation
    • Added documentation describing the schema truncation bug and the implemented solution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 13, 2025

Walkthrough

This change refactors the MCP Client's listTools operation to eliminate lossy schema conversions, ensuring the original JSON Schema from the MCP server is returned unaltered. It adds debug logging, error handling, and introduces new unit tests that verify schema passthrough integrity, while removing unnecessary Zod-related code.

Changes

File(s) Change Summary
nodes/McpClient/McpClient.node.ts Refactored listTools to remove Zod conversion, directly return original schemas, add logging and error handling.
nodes/McpClient/tests/listTools.schema.test.ts,
nodes/McpClient/listTools.schema.test.ts
Added Jest tests to verify schema passthrough and detect truncation.
docs/PR_TEMPLATE_mcp-schema-fix.md,
schemabug.md
Added documentation describing the bug, its solution, and test strategy.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant McpClient
    participant MCP_Server

    User->>McpClient: listTools()
    McpClient->>MCP_Server: fetch tools with schemas
    MCP_Server-->>McpClient: return tools with inputSchema
    McpClient->>McpClient: log received schemas (debug)
    McpClient->>McpClient: normalize and validate tools
    McpClient->>McpClient: log returned schemas (debug)
    McpClient-->>User: return tools with original inputSchema
Loading

Assessment against linked issues

Objective Addressed Explanation
Preserve complete, original JSON Schema from MCP server in listTools output (#129)
Remove double conversion (JSON Schema → Zod → JSON Schema) in listTools (#129)
Ensure all schema constraints, defaults, enums, and nested structures are retained in output (#129)
Add error handling and logging to listTools operation as per project standards (#129)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation

Possibly related PRs

  • bug: Zod returning in Json schema #124: Modifies listTools to convert Zod schemas to JSON Schema using zodToJsonSchema, which is the opposite approach to this PR's direct passthrough strategy.

Poem

In the warren where schemas would hide,
A bug snipped their branches, their leaves cast aside.
But now the full forest returns to the field,
With each nested twig and constraint unconcealed.
🐇 Debug logs burrow deep, tests hop with delight,
The MCP schema is whole—what a wonderful sight!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
nodes/McpClient/__tests__/listTools.schema.test.ts (1)

6-67: ⚠️ Potential issue

Test duplicates an identical suite elsewhere

There is an identical test file nodes/McpClient/listTools.schema.test.ts.
Running both doubles execution time and provides no additional coverage.
Delete one or move common helpers to a shared util to avoid redundancy.

♻️ Duplicate comments (1)
nodes/McpClient/listTools.schema.test.ts (1)

6-71: Same concern as above – duplicated and indirect tests

This file is an exact copy of __tests__/listTools.schema.test.ts.
Keep a single source-of-truth test and remove the copy to prevent maintenance drift.

🧹 Nitpick comments (5)
schemabug.md (2)

38-41: Avoid unnecessary bold-hyphen coupling

“deeply-nested” does not need a hyphen because “deeply” already ends with -ly.

-**Preserve the original JSON Schema from the MCP server.**  
+**Preserve the original JSON Schema from the MCP server.**

146-147: Tone – add “please” for reviewer friendliness

The sentence “If you need a PR template or further test scaffolding, let me know!” is flagged by LanguageTool.
Consider:

-If you need a PR template or further test scaffolding, let me know!
+If you need a PR template or further test scaffolding, please let me know!
🧰 Tools
🪛 LanguageTool

[style] ~147-~147: Consider using polite language here.
Context: ...R template or further test scaffolding, let me know!

(INSERT_PLEASE)

nodes/McpClient/McpClient.node.ts (2)

425-446: Large JSON pretty-prints may explode n8n logs

JSON.stringify(rawTools, null, 2) and the similar call for outputTools stringify full nested schemas.
On large tool catalogs this can flood n8n’s log buffer and degrade performance.

- this.logger.debug(`[MCP][listTools] Received tools from server: ${JSON.stringify(rawTools, null, 2)}`);
+ this.logger.debug(() => `[MCP][listTools] Received tools from server (count=${tools?.length ?? 0})`);

Most loggers (including n8n’s) accept a lazy-evaluated function/string. Consider logging only length or first N chars.


441-445: Variable reuse reduces readability

The alias tools is reused for the mapped array:

const tools = ;

const outputTools = tools.map()

toolsrawToolArray and outputToolsnormalizedTools would read clearer.

docs/PR_TEMPLATE_mcp-schema-fix.md (1)

22-25: Missing determiner

“Downstream consumers will now receive full, correct schema” → “the full, correct schema”.

-Downstream consumers will now receive the full, correct schema as provided by the MCP server.
+Downstream consumers will now receive the full, correct schema as provided by the MCP server.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~23-~23: You might be missing the article “the” here.
Context: ...ed. ## Impact - No breaking changes to API or interface. - Downstream consumers wi...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0358161 and 7a77583.

📒 Files selected for processing (5)
  • docs/PR_TEMPLATE_mcp-schema-fix.md (1 hunks)
  • nodes/McpClient/McpClient.node.ts (2 hunks)
  • nodes/McpClient/__tests__/listTools.schema.test.ts (1 hunks)
  • nodes/McpClient/listTools.schema.test.ts (1 hunks)
  • schemabug.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
docs/PR_TEMPLATE_mcp-schema-fix.md

[uncategorized] ~23-~23: You might be missing the article “the” here.
Context: ...ed. ## Impact - No breaking changes to API or interface. - Downstream consumers wi...

(AI_EN_LECTOR_MISSING_DETERMINER_THE)

schemabug.md

[uncategorized] ~13-~13: Although a hyphen is possible, it is not necessary in a compound modifier in which the first word is an adverb that ends in ‘ly’.
Context: ...aude Desktop) correctly fetch the full, deeply-nested schema from the same MCP server. ## 3....

(HYPHENATED_LY_ADVERB_ADJECTIVE)


[style] ~147-~147: Consider using polite language here.
Context: ...R template or further test scaffolding, let me know!

(INSERT_PLEASE)

🔇 Additional comments (1)
nodes/McpClient/McpClient.node.ts (1)

428-435: Defensive parsing could mis-detect object-shaped responses

typeof rawTools?.tools === 'object' && rawTools.tools !== null ? Object.values(rawTools.tools) : []
will treat a plain object with arbitrary keys as list of tools, losing the key names.

If the SDK guarantees rawTools.tools is either array or object keyed by name, that’s fine; otherwise you risk silently discarding data. Add an explicit fallback / validation.

@belfortmaycon
Copy link

Hi @havebeenfitz, @iamfiscus.

This PR solves a big issue I'm currently facing, as reported in #129. Do you think this can be merged/fixed?

Appreciate it.

Maycon

@iamfiscus iamfiscus merged commit bca4681 into nerding-io:main Nov 25, 2025
1 check 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.

# Bug: Massive schema information loss in listTools operation due to unnecessary double conversion

3 participants