* fix: OpenAPI request director content-type dispatch and cookie params
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Stringify multipart form values and cookie params for httpx
httpx rejects non-string scalars in files= and cookies=.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add tests for non-string multipart values and cookie stringification
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Consolidate to single httpx.Request construction point
Eliminate early returns by using variables for files/data kwargs.
All httpx body kwargs accept None, so we set exactly one and
pass all to a single Request() call.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Use _query_scalar_to_str for multipart booleans, add tuple passthrough test
Reuse existing boolean serialization (true/false not True/False) for
multipart form fields. Add test for file-like tuple passthrough.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Normalize media type for dispatch, use OpenAPI serialization for cookies
- Strip content-type parameters (e.g. "; charset=utf-8") and lowercase
before matching, so variants like "Multipart/Form-Data" match correctly
- Use _query_scalar_to_str for cookie values (true/false not True/False)
- Add boolean cookie test
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Preserve media-type parameters in Content-Type header
Use raw_content_type (with charset etc.) for the outgoing header,
normalized form only for dispatch matching.
🤖 Generated with Claude Code
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Pass bytes/file-like values directly in multipart, add charset preservation test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Object-typed query parameters with explode=true (the default) were
passed as raw Python dicts to httpx, which called str() on them —
producing Python repr syntax (single quotes, capitalized booleans)
instead of proper query parameter serialization.
Per the OpenAPI specification, style=form with explode=true on objects
expands each property as a separate query parameter (e.g.
?myAttribute=true). This change handles dict values in both the
explode=true and explode=false branches of _serialize_query_params,
using the existing _query_scalar_to_str helper for correct boolean
formatting.
Fixes#2857
* fix: URL-encode path params in OpenAPI provider to prevent SSRF/path traversal
Co-authored-by: Claude <noreply@anthropic.com>
* Exempt too-long from core-category requirement in triage
* fix: also encode dots in path params to prevent bare .. traversal
* fix: only encode .. (not all dots) to preserve valid dotted values
* fix: encode all dots in path params to prevent single-dot normalization
* fix: check decoded path stays within prefix in double-encoding test
---------
Co-authored-by: Claude <noreply@anthropic.com>
* Bump ty to >=0.0.1a25 with type fixes
Follow-up to #2295. Updates ty and fixes compatibility issues with alpha 25, including:
- Updated ignore comment syntax (possibly-unbound-attribute → possibly-missing-attribute)
- Fixed async generator type handling with anext()
- Fixed type narrowing for timeout parameters
- Converted base_url assignments to AnyHttpUrl after string manipulation
- Added CallToolResult to return type annotations
- Removed redundant type casts
- Fixed test form data to use strings instead of bytes
ty alpha 25 has limitations with isinstance() narrowing on unions (see pyproject.toml for details), requiring some targeted type ignores.
* Pin ty to ==0.0.1a25
Alpha releases can have breaking changes, so pin to the tested version.
* Add output schema support for OpenAPI tools
Implement automatic output schema extraction from OpenAPI responses for
FastMCP tools, addressing issue #1070. Tools generated from OpenAPI specs
now have meaningful output schemas instead of null, improving agent
efficiency when working with structured API responses.
- Add extract_output_schema_from_responses() function to parse response schemas
- Enhance OpenAPITool to accept and use output schemas with proper wrapping
- Automatically wrap non-object responses to comply with MCP requirements
- Include schema definitions and compress unused ones
- Add comprehensive test suite covering object, array, and primitive responses
- Update existing tests to handle structured output with proper typing
- Maintain backward compatibility for specs without response schemas
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
* Move output schema tests to dedicated test file
Reorganize output schema tests into test_openapi_output_schemas.py to keep
the main test_openapi.py file focused and smaller, as requested. Added two
additional tests for schema definitions handling.
- Move all extract_output_schema_from_responses() tests to new file
- Add tests for schema definitions inclusion
- Remove output schema imports from main test file
---------
Co-authored-by: Claude <noreply@anthropic.com>
- Add extensions field to HTTPRoute class to store x-* fields
- Extract extensions from operation's model_extra in parser
- Add test to verify extensions are properly parsed
Previously, external schema references (URLs) in OpenAPI schemas were
silently passed through and only failed during JSON schema validation
with confusing "failed to match exactly one schema" errors.
This change:
- Detects external references in _replace_ref_with_defs() and raises clear error messages
- Updates exception handlers to propagate external reference errors while preserving other error handling
- Adds comprehensive test coverage for external reference detection
- Provides helpful error messages explaining that FastMCP only supports local schema references
Fixes#926🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>