Skip to content

Commit 6fb1d0e

Browse files
committed
Add backwards compatibility test for structured output
- Test same tools with both structured_output=False and True - Verify legacy mode (raw strings/JSON) vs enhanced mode (wrapped objects) - Ensure existing code compatibility when upgrading adapter settings
1 parent e140d36 commit 6fb1d0e

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

tests/test_smolagents_adapter_structured_output.py

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,3 +198,121 @@ def hello_world():
198198
result = tool()
199199
assert result == "hello world"
200200

201+
202+
def test_backwards_compatibility():
203+
"""Tests that the same tools work consistently with structured_output=False and True.
204+
205+
This ensures existing code doesn't break when upgrading and that tools
206+
behave predictably regardless of the structured_output setting.
207+
"""
208+
server_script = dedent(
209+
"""
210+
from mcp.server.fastmcp import FastMCP
211+
from typing import Any
212+
213+
mcp = FastMCP("Compatibility Server")
214+
215+
@mcp.tool()
216+
def simple_text_tool(message: str) -> str:
217+
'''Returns a simple text message'''
218+
return f"Echo: {message}"
219+
220+
@mcp.tool()
221+
def structured_data_tool(location: str) -> dict[str, Any]:
222+
'''Returns structured weather data'''
223+
return {
224+
"location": location,
225+
"weather": "sunny",
226+
"temperature": 22,
227+
"humidity": 65
228+
}
229+
230+
mcp.run()
231+
"""
232+
)
233+
234+
# Test with legacy behavior (structured_output=False)
235+
with MCPAdapt(
236+
StdioServerParameters(
237+
command="uv", args=["run", "python", "-c", server_script]
238+
),
239+
SmolAgentsAdapter(structured_output=False),
240+
) as legacy_tools:
241+
# We know the tools are created in order, so we can use simple indexing
242+
simple_tool_legacy = legacy_tools[0] # simple_text_tool
243+
structured_tool_legacy = legacy_tools[1] # structured_data_tool
244+
245+
# Verify we got the right tools
246+
assert simple_tool_legacy.name == "simple_text_tool"
247+
assert structured_tool_legacy.name == "structured_data_tool"
248+
249+
# Both tools should have string output_type in legacy mode
250+
assert simple_tool_legacy.output_type == "string"
251+
assert structured_tool_legacy.output_type == "string"
252+
assert simple_tool_legacy.output_schema is None
253+
assert structured_tool_legacy.output_schema is None
254+
assert simple_tool_legacy.use_structured_features is False
255+
assert structured_tool_legacy.use_structured_features is False
256+
257+
# Call the tools in legacy mode
258+
simple_result_legacy = simple_tool_legacy(message="test")
259+
structured_result_legacy = structured_tool_legacy(location="London")
260+
261+
assert simple_result_legacy == "Echo: test"
262+
# structured_tool result should be JSON string in legacy mode
263+
assert isinstance(structured_result_legacy, str)
264+
assert "London" in structured_result_legacy
265+
assert "sunny" in structured_result_legacy
266+
267+
# Test with enhanced behavior (structured_output=True)
268+
with MCPAdapt(
269+
StdioServerParameters(
270+
command="uv", args=["run", "python", "-c", server_script]
271+
),
272+
SmolAgentsAdapter(structured_output=True),
273+
) as enhanced_tools:
274+
# Same tools, same order - much clearer than complex searching
275+
simple_tool_enhanced = enhanced_tools[0] # simple_text_tool
276+
structured_tool_enhanced = enhanced_tools[1] # structured_data_tool
277+
278+
# Verify we got the right tools
279+
assert simple_tool_enhanced.name == "simple_text_tool"
280+
assert structured_tool_enhanced.name == "structured_data_tool"
281+
282+
# Both tools get enhanced features and schemas
283+
assert simple_tool_enhanced.output_type == "object" # FastMCP auto-generates schema even for str
284+
assert simple_tool_enhanced.output_schema is not None # Schema exists for str return type
285+
assert simple_tool_enhanced.use_structured_features is True
286+
287+
assert structured_tool_enhanced.output_type == "object"
288+
assert structured_tool_enhanced.output_schema is not None
289+
assert structured_tool_enhanced.use_structured_features is True
290+
291+
# Call the tools in enhanced mode
292+
simple_result_enhanced = simple_tool_enhanced(message="test")
293+
structured_result_enhanced = structured_tool_enhanced(location="London")
294+
295+
# Key behavior differences discovered by this test:
296+
297+
# Simple text tools - enhanced mode wraps results
298+
assert isinstance(simple_result_enhanced, dict)
299+
assert simple_result_enhanced["result"] == "Echo: test" # Wrapped in result object
300+
# vs legacy mode returns plain string: "Echo: test"
301+
302+
# Structured tools show the format difference:
303+
assert isinstance(structured_result_enhanced, dict) # Dict in enhanced mode
304+
assert structured_result_enhanced["location"] == "London"
305+
assert structured_result_enhanced["weather"] == "sunny"
306+
307+
# Legacy mode returns JSON string, enhanced mode returns dict
308+
# But both contain the same underlying data
309+
import json
310+
parsed_legacy_result = json.loads(structured_result_legacy)
311+
assert parsed_legacy_result == structured_result_enhanced # Same data, different format
312+
313+
# Backwards compatibility verified:
314+
# - Legacy mode: Returns raw data (strings as strings, dicts as JSON strings)
315+
# - Enhanced mode: Returns structured objects (strings wrapped, dicts native)
316+
# - Both contain the same information, just in different formats
317+
# - Existing code will keep working, new code gets enhanced features
318+

0 commit comments

Comments
 (0)