fix: update MergeAgentHandlerTool to rightly handle MCP protocol#4255
fix: update MergeAgentHandlerTool to rightly handle MCP protocol#4255mplacona wants to merge 11 commits intocrewAIInc:mainfrom
Conversation
…l correctly
## Problem
The MergeAgentHandlerTool was not correctly handling the Agent Handler MCP protocol's parameter format:
1. Agent Handler wraps all parameters in an `input` object
2. MCP protocol uses `inputSchema` instead of `parameters` for tool schemas
3. Schema parsing didn't handle `anyOf` nullable type definitions
4. Pydantic schema exposed the wrapper object instead of actual parameters
This caused tools to fail when called by CrewAI agents.
## Solution
### Parameter Wrapping
- Wrap all arguments in an `{"input": kwargs}` structure before sending to Agent Handler
- Add backwards compatibility to detect pre-wrapped input and pass through as-is
### Schema Parsing
- Updated to parse `inputSchema` from MCP responses (not `parameters`)
- Automatically unwrap the `input` object to expose actual tool parameters in Pydantic schema
- This ensures CrewAI agents see the real parameters (e.g., `title`, `description`) instead of just `input`
### Nullable Type Support
- Added support for `anyOf` type definitions commonly used for nullable fields
- Properly marks nullable fields as optional with `None` default values
- Correctly infers the primary type from `anyOf` definitions
### Debugging Improvements
- Added debug logging when `inputSchema` is missing from responses
- Better error messages for schema parsing failures
## Testing
- Updated all test mocks to use `inputSchema` format matching real MCP responses
- Added tests for schema parsing from `inputSchema`
- Added tests for `anyOf` nullable type handling
- Added tests for backwards compatibility with pre-wrapped input
- Verified all tests pass with new parameter wrapping logic
## Impact
- Tools now work correctly with Agent Handler MCP protocol
- Pydantic schemas correctly represent actual tool parameters
- CrewAI agents can properly invoke Agent Handler tools
- Backwards compatible with any existing code that pre-wraps parameters
Separate nullable type annotation from optional default value in schema parsing. Previously, required nullable fields were incorrectly given a None default, allowing callers to omit them. This caused API errors when backends distinguish between missing fields and explicit null values. Changes: - Split nullable (type accepts None) from optional (has default) - Required nullable fields now require explicit value (can be None) - Improve input parameter wrapping check with isinstance guard - Add comprehensive tests for all field type combinations All 27 tests pass, confirming fix works without breaking existing functionality.
lib/crewai-tools/src/crewai_tools/tools/merge_agent_handler_tool/merge_agent_handler_tool.py
Show resolved
Hide resolved
|
@lorenzejay could you please help me get this past the finish line? Thanks |
|
any chance you can send a loom video of this working or help me build a way to test this out? |
| "name": "linear__create_issue", | ||
| "description": "Creates a new issue in Linear", | ||
| "parameters": { | ||
| "inputSchema": { |
There was a problem hiding this comment.
function calling expects paramters. Why are we changing this to inputScheme?
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
This PR is being reviewed by Cursor Bugbot
Details
Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.
To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.
| elif json_type == "array": | ||
| field_type = list[Any] | ||
| elif json_type == "object": | ||
| field_type = dict[str, Any] |
There was a problem hiding this comment.
Duplicated JSON-to-Python type mapping logic blocks
Low Severity
The JSON schema type-to-Python type mapping logic (mapping "string" → str, "integer" → int, etc.) is fully duplicated: once inside the anyOf branch and once in the else branch. Extracting this into a small helper function or dict lookup would reduce the maintenance burden and ensure any future type mapping changes are applied consistently in both paths.


Disclosure: I worked with Merge on getting this PR together
Problem
The MergeAgentHandlerTool was not correctly handling the Agent Handler MCP protocol's parameter format:
inputobjectinputSchemainstead ofparametersfor tool schemasanyOfnullable type definitionsThis caused tools to fail when called by CrewAI agents.
Solution
Parameter Wrapping
{"input": kwargs}structure before sending to Agent HandlerSchema Parsing
inputSchemafrom MCP responses (notparameters)inputobject to expose actual tool parameters in Pydantic schematitle,description) instead of justinputNullable Type Support
anyOftype definitions commonly used for nullable fieldsNonedefault valuesanyOfdefinitionsDebugging Improvements
inputSchemais missing from responsesTesting
inputSchemaformat matching real MCP responsesinputSchemaanyOfnullable type handlingImpact
Note
Medium Risk
Changes affect how all Agent Handler tool calls are serialized and how Pydantic argument schemas are inferred, which can break integrations if assumptions differ from real MCP responses. Coverage is strong, but runtime behavior depends on external schema variations.
Overview
Fixes
MergeAgentHandlerToolto match Agent Handler’s MCP protocol by wrapping tool call arguments underinput(with pass-through support for legacy pre-wrapped calls) and by parsing tool schemas frominputSchemainstead ofparameters.Schema generation now unwraps the top-level
inputobject soargs_schemaexposes real tool parameters, and adds handling for nullable JSON Schema definitions viaanyOf(including keeping required-but-nullable fields required). Tests were updated to useinputSchema, assertinput-wrapped requests, and add coverage for nullable/required/optional schema edge cases and backwards-compat behavior.Written by Cursor Bugbot for commit ab16c4b. This will update automatically on new commits. Configure here.