fix: fix mcp tool parameter extract (#33258)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
wangxiaolei
2026-03-11 13:46:38 +08:00
committed by GareArc
parent 6625828246
commit 0f938d453c
2 changed files with 175 additions and 5 deletions

View File

@ -7,7 +7,7 @@ import pytest
from core.mcp.types import Tool as MCPTool
from core.tools.entities.api_entities import ToolApiEntity, ToolProviderApiEntity
from core.tools.entities.common_entities import I18nObject
from core.tools.entities.tool_entities import ToolProviderType
from core.tools.entities.tool_entities import ToolParameter, ToolProviderType
from models.tools import MCPToolProvider
from services.tools.tools_transform_service import ToolTransformService
@ -175,6 +175,137 @@ class TestMCPToolTransform:
# The actual parameter conversion is handled by convert_mcp_schema_to_parameter
# which should be tested separately
def test_convert_mcp_schema_to_parameter_preserves_anyof_object_type(self):
"""Nullable object schemas should keep the object parameter type."""
schema = {
"type": "object",
"properties": {
"retrieval_model": {
"anyOf": [{"type": "object"}, {"type": "null"}],
"description": "检索模型配置",
}
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 1
assert result[0].name == "retrieval_model"
assert result[0].type == ToolParameter.ToolParameterType.OBJECT
assert result[0].input_schema == schema["properties"]["retrieval_model"]
def test_convert_mcp_schema_to_parameter_preserves_oneof_object_type(self):
"""Nullable oneOf object schemas should keep the object parameter type."""
schema = {
"type": "object",
"properties": {
"retrieval_model": {
"oneOf": [{"type": "object"}, {"type": "null"}],
"description": "检索模型配置",
}
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 1
assert result[0].name == "retrieval_model"
assert result[0].type == ToolParameter.ToolParameterType.OBJECT
assert result[0].input_schema == schema["properties"]["retrieval_model"]
def test_convert_mcp_schema_to_parameter_handles_null_type(self):
"""Schemas with only a null type should fall back to string."""
schema = {
"type": "object",
"properties": {
"null_prop_str": {"type": "null"},
"null_prop_list": {"type": ["null"]},
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 2
param_map = {parameter.name: parameter for parameter in result}
assert "null_prop_str" in param_map
assert param_map["null_prop_str"].type == ToolParameter.ToolParameterType.STRING
assert "null_prop_list" in param_map
assert param_map["null_prop_list"].type == ToolParameter.ToolParameterType.STRING
def test_convert_mcp_schema_to_parameter_preserves_allof_object_type_with_multiple_object_items(self):
"""Property-level allOf with multiple object items should still resolve to object."""
schema = {
"type": "object",
"properties": {
"config": {
"allOf": [
{
"type": "object",
"properties": {
"enabled": {"type": "boolean"},
},
"required": ["enabled"],
},
{
"type": "object",
"properties": {
"priority": {"type": "integer", "minimum": 1, "maximum": 10},
},
"required": ["priority"],
},
],
"description": "Config must match all schemas (allOf)",
}
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 1
assert result[0].name == "config"
assert result[0].type == ToolParameter.ToolParameterType.OBJECT
assert result[0].input_schema == schema["properties"]["config"]
def test_convert_mcp_schema_to_parameter_preserves_allof_object_type(self):
"""Composed property schemas should keep the object parameter type."""
schema = {
"type": "object",
"properties": {
"retrieval_model": {
"allOf": [
{"type": "object"},
{"properties": {"top_k": {"type": "integer"}}},
],
"description": "检索模型配置",
}
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 1
assert result[0].name == "retrieval_model"
assert result[0].type == ToolParameter.ToolParameterType.OBJECT
assert result[0].input_schema == schema["properties"]["retrieval_model"]
def test_convert_mcp_schema_to_parameter_limits_recursive_schema_depth(self):
"""Self-referential composed schemas should stop resolving after the configured max depth."""
recursive_property: dict[str, object] = {"description": "Recursive schema"}
recursive_property["anyOf"] = [recursive_property]
schema = {
"type": "object",
"properties": {
"recursive_config": recursive_property,
},
}
result = ToolTransformService.convert_mcp_schema_to_parameter(schema)
assert len(result) == 1
assert result[0].name == "recursive_config"
assert result[0].type == ToolParameter.ToolParameterType.STRING
assert result[0].input_schema is None
def test_mcp_provider_to_user_provider_for_list(self, mock_provider_full):
"""Test mcp_provider_to_user_provider with for_list=True."""
# Set tools data with null description