fastmcp/tests/server
Jeremiah Lowin 41ec7ee06d
SEP-1577: Sampling with tools (#2551)
* MCP → SDK (vocab change only)

* WIP: Sampling API with SamplingResult[T] and result_type

* SEP-1577: Sampling with tools

- Add tools and result_type parameters to ctx.sample()
- Update OpenAI handler for tool content types
- Client advertises sampling.tools capability by default
- Collect tool results into single message with list content

* Fix tool result content handling in OpenAI handler

* Remove @sampling_tool decorator - pass functions directly to sample()

Functions passed to ctx.sample(tools=[...]) are now auto-converted
via SamplingTool.from_function(). Users can still use that method
directly for custom name/description overrides.

* Remove auto-conversion of MCP tools to sampling tools

Users want MCP tools passed to ctx.sample() to go through the full MCP
machinery (middleware, native responses) rather than being auto-converted
to direct function calls. Now only SamplingTool and plain callables are
accepted - passing a FastMCP Tool raises a clear TypeError.

Also bumps mcp dependency to >=1.24.0 for required sampling features.

* Refactor sampling API: replace sample_iter() with sample_step()

Replace the mutable SampleRun/sample_iter() pattern with a simpler stateless
sample_step() function. sample_step() makes a single LLM call and returns a
SampleStep with the response and history. sample() now loops sample_step()
internally.

Key changes:
- Add sample_step() for fine-grained control over the sampling loop
- Remove SampleRun class and sample_iter() method
- Structured output uses tool description only (no prompt modification)
- execute_tools parameter controls automatic vs manual tool execution

* Address CodeRabbit nitpicks

* Address CodeRabbit review feedback for sampling tools

- Fix temperature=0.0 being dropped due to falsy evaluation
- Add ToolChoice.name support for forcing specific tools
- Replace assert statements with explicit RuntimeError checks
- Add mask_error_details parameter to sample()/sample_step() with ToolError escape hatch
- Fix hasattr patterns with proper isinstance checks
- Document mask_error_details and add OpenAI prerequisites to docs

* Address additional CodeRabbit review feedback

- Catch ValidationError specifically instead of bare Exception
- Update result_type docs to mention dataclasses and basic types
- Raise ValueError for unknown tool_choice modes
- Validate sampling_handler_behavior to catch typos
- Remove ToolChoice.name handling (not part of MCP spec)
- Validate tool_choice string in sample_step()

* Review fixes for sampling tools PR

- Remove internal functions from sampling __init__.py exports
- Remove fragile is_text property, use not is_tool_use instead
- Inline call_client into context.py, remove from run.py
- Fix SamplingMessage docs to use TextContent
- Handle result.text being None in doc examples
- Simplify client sampling docs to recommend OpenAISamplingHandler
- Add sampling_capabilities override documentation
- Raise iteration limit from 50 to 100
- Remove _parse_model_preferences duplication
- Use AsyncOpenAI in OpenAISamplingHandler
- Fix tool_choice docstring

* Fix OpenAI handler tests to use AsyncOpenAI

* Address remaining CodeRabbit review comments

- Fix message ordering in OpenAI handler: tool results now correctly
  follow assistant message with tool_calls
- sample_step() now always includes assistant message in history
- Raise ValueError on JSON parse errors instead of silent {}
- Add has_sampling capability check when behavior is None
- Raise RuntimeError when structured output receives text response
- Wrap primitive result_type schemas in object wrapper
- Fix docs example using invalid SamplingMessage construction
- Add comprehensive client_sampling_test.py example

* Add return type annotation to OpenAISamplingHandler.__init__

* Use explicit 'is not None' check for sampling_capabilities defaulting

---------

Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Bill Easton <strawgate@users.noreply.github.com>
2025-12-14 13:51:05 -05:00
..
auth Add smart fallback for missing access token expiry (#2587) 2025-12-09 21:31:17 -05:00
http Fix type errors for ty 0.0.1-alpha.31 upgrade (#2561) 2025-12-05 21:29:14 -05:00
middleware SEP-1577: Sampling with tools (#2551) 2025-12-14 13:51:05 -05:00
openapi Switch to new OpenAPI parser as default (#2513) 2025-12-01 20:29:18 -05:00
proxy SEP-1577: Sampling with tools (#2551) 2025-12-14 13:51:05 -05:00
sampling SEP-1577: Sampling with tools (#2551) 2025-12-14 13:51:05 -05:00
tasks Remove TaskConfig and client from root exports (#2580) 2025-12-09 12:28:01 -05:00
__init__.py restore 1.x code 2025-04-09 11:54:42 -04:00
test_app_state.py Update docs and test 2025-06-20 13:06:48 -04:00
test_auth_integration.py Update FastMCP for MCP SDK 1.23.1 auth changes 2025-12-03 11:50:08 -05:00
test_context.py SEP-1577: Sampling with tools (#2551) 2025-12-14 13:51:05 -05:00
test_dependencies.py [2.14] SEP-1686 tasks (#2378) 2025-12-04 20:10:35 -05:00
test_event_store.py SEP-1699: Add SSE polling support with EventStore (#2564) 2025-12-09 09:55:51 -05:00
test_file_server.py Internal refactor of MCP handlers (#2005) 2025-10-05 08:45:10 -04:00
test_icons.py Implement icon support (#2121) 2025-10-17 17:28:08 -04:00
test_import_server.py 2.14 deprecation removals (#2329) 2025-12-01 14:11:00 -05:00
test_input_validation.py Add Pydantic-compatible input validation (#2073) 2025-10-14 11:49:30 -07:00
test_log_level.py Add log level support for stdio and HTTP transports (#1840) 2025-09-19 13:46:30 -04:00
test_logging.py Remove enable_docket setting; Docket is now always on 2025-12-05 11:40:04 -05:00
test_mount.py Fix nested server mount routing for 3+ levels deep (#2586) 2025-12-09 21:06:47 -05:00
test_run_server.py Update tests for prompts 2025-06-04 16:37:41 -04:00
test_server.py Revert "Refactor resource behavior and add meta support (#2598)" (#2609) 2025-12-13 15:02:18 -05:00
test_server_docket.py Fix type errors for ty 0.0.1-alpha.31 upgrade (#2561) 2025-12-05 21:29:14 -05:00
test_server_interactions.py Revert "Refactor prompt behavior and add meta support (#2600)" (#2608) 2025-12-13 14:57:50 -05:00
test_server_lifespan.py Fix type errors for ty 0.0.1-alpha.31 upgrade (#2561) 2025-12-05 21:29:14 -05:00
test_streamable_http_no_redirect.py Improve redirect handling to address 307's (#1387) 2025-08-08 11:55:30 -04:00
test_tool_annotations.py Add TaskConfig for SEP-1686 execution modes 2025-12-06 21:01:11 -05:00
test_tool_exclude_args.py Fix exclude_args with non-serializable types 2025-11-17 12:25:43 -05:00
test_tool_transformation.py Internal refactor of MCP handlers (#2005) 2025-10-05 08:45:10 -04:00