fix(mcp): make search_tools query optional to fix null content on tool discovery#40906
fix(mcp): make search_tools query optional to fix null content on tool discovery#40906aminghadersohi wants to merge 1 commit into
Conversation
…covery
BM25SearchTransform._make_search_tool() declared query: str (required).
When an LLM calls search_tools({}) for tool discovery, TypeAdapter raises
ValidationError, which StructuredContentStripperMiddleware catches and
returns as error text instead of the tool catalog.
Override _make_search_tool() in both _FixedBM25SearchTransform and
_FixedRegexSearchTransform to make query optional (str | None = None).
When omitted, returns all visible tools directly; when provided, runs the
configured search strategy.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #40906 +/- ##
==========================================
- Coverage 64.13% 64.12% -0.01%
==========================================
Files 2653 2653
Lines 143601 143615 +14
Branches 33132 33133 +1
==========================================
- Hits 92104 92099 -5
- Misses 49884 49901 +17
- Partials 1613 1615 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Code Review Agent Run #21bbd5Actionable Suggestions - 0Additional Suggestions - 2
Filtered by Review RulesBito filtered these suggestions based on rules created automatically for your feedback. Manage rules.
Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
gabotorresruiz
left a comment
There was a problem hiding this comment.
Nice fix, search_tools({}) failing closed is a real footgun for any MCP client that enumerate tools with no args.
One related thought for a follow-up (not this PR):
StructuredContentStripperMiddleware.on_list_tools catches all exceptions and returns [], so a transient error in the tools/list pipeline is indistinguishable from "this server has no tools." MCP clients that cache tools/list then treat it as an empty catalog rather than a retryable failure (similar to the empty-result problem this PR fixes for search_tools, but at the tools/list layer). Might be worth surfacing those as real protocol errors so clients can retry.
| query: Annotated[ | ||
| str | None, | ||
| "Natural language query. Omit to list all available tools.", | ||
| ] = None, |
There was a problem hiding this comment.
One thing on the schema: query: str | None renders as {"anyOf": [{"type":"string"},{"type":"null"}]} with no top-level type, same shape as call_tool's arguments, which is exactly what _fix_call_tool_arguments flattens (its docstring notes mcp-remote/Claude Desktop strip anyOf and leave the field typeless). So we'd be reintroducing an unflattened anyOf for those bridges.
Probably milder than the call_tool case (query is optional and usually omitted, so it may not actually break) but it's the same shape that bit us before, and flattening to a plain {"type": "string"} is cheap. Might also be worth having test_search_tool_query_is_optional_in_schema assert query has a concrete type, since that's what the bridges trip on.
|
The concern regarding the superset/mcp_service/server.py |
Summary
BM25SearchTransform._make_search_tool()declaresquery: str(required). When an LLM callssearch_tools({})for tool discovery,TypeAdapter.validate_python({})raisesValidationErrorbecause the required field is missing.StructuredContentStripperMiddlewarecatches this and returns error text instead of the tool catalog — so the LLM receives null/empty content._make_search_tool()in both_FixedBM25SearchTransformand_FixedRegexSearchTransformto acceptquery: str | None = None. When omitted, returns all visible tools directly; when provided, runs the configured search strategy as before.queryas optional, calling with no args returns all tools (BM25 + regex strategies).Test plan
pytest tests/unit_tests/mcp_service/test_tool_search_transform.py::test_search_tool_query_is_optional_in_schemapytest tests/unit_tests/mcp_service/test_tool_search_transform.py::test_search_tool_with_no_query_returns_all_visible_toolspytest tests/unit_tests/mcp_service/test_tool_search_transform.py::test_search_tool_regex_with_no_query_returns_all_visible_tools