chore: remove unused runtime dependencies (10 -> 4) - #346
Open
K4bain wants to merge 2 commits into
Open
Conversation
…f injecting an arbitrary type
## Problem
For a request body field typed as a union of two real types (e.g. `dict[str, list[str]] | list[str]`), the projected MCP tool schema gets a single arbitrary `"type"` injected alongside `anyOf`. The MCP server's jsonschema validator then enforces that `"type"` strictly and rejects every call using the variant that lost the pick, with a misleading error like:
```
Input validation error: {'Skills': [...]} is not of type 'array'
```
The injected type is also non-deterministic (`next(iter(set))`), so which variant breaks can differ per run. Fixes tadata-org#307.
## Root cause
In `convert_openapi_to_mcp_tools`, both the query-param and body-param loops do:
```python
if "type" not in properties[param_name]:
properties[param_name]["type"] = get_single_param_type_from_schema(param_schema)
```
For `T | U` (both real types) Pydantic emits `{"anyOf": [...]}` with no top-level `"type"`, so the branch fires and one arbitrary variant type wins.
## Fix
Only fall back to `get_single_param_type_from_schema` when the union has at most one non-null variant. `T | None` (nullable) keeps the existing collapse behavior — its existing tests still pass unchanged — while `T | U` keeps `anyOf` verbatim, which the JSON Schema validator at the MCP layer handles correctly.
## Verification
- New test `test_union_type_schema_not_collapsed` asserts `anyOf` is preserved with no injected `"type"` and both `object`/`array` variants present.
- Repro from the issue validated with `jsonschema`: both the dict variant and the list variant pass validation (previously one of them always failed).
- Full suite: 70 passed (the 20 `test_sse_real_transport` errors are the pre-existing Windows `os.fork` limitation tracked in tadata-org#332).
The package itself imports none of these: - typer, rich: never referenced anywhere in fastapi_mcp/ - requests: zero imports (httpx is used everywhere) - tomli: zero imports - pydantic-settings: zero imports (mcp already depends on it anyway) - uvicorn: not needed at runtime (mcp itself pulls it for its own transports); kept as a 'deploy' extra and in the dev group for the real-transport tests and the examples Runtime deps go from 10 to 4: fastapi, mcp, pydantic, httpx. Verified: 78/78 tests, ruff clean, mypy clean, wheel metadata confirmed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
The library declares 10 runtime dependencies, but several are never imported by the package itself. This adds install weight and friction for downstream adopters (raised in #275 —
richin particular impacts log output configuration of host apps).Audit results
fastapi_mcp/server.py,auth/proxy.pymcpitself pulls it for its own transportsdeployextra + dev groupRuntime dependencies go from 10 to 4.
Notes
uvicornremains reachable:pip install fastapi-mcp[deploy], and the dev dependency group keeps it fortests/test_http_real_transport.py/tests/test_sse_real_transport.py.uv.lockregenerated; typer/rich/requests/urllib3/pygments/shellingham and friends drop out of the resolved graph entirely.fastapi,httpx,mcp,pydantic(+uvicorn; extra == 'deploy').Verification
uv run pytest tests/: 78 passed (real-transportos.forkerrors are the pre-existing Windows limitation tracked in test: skip real-transport tests on Windows (they require os.fork) #332, identical on unpatched main).uv run ruff check fastapi_mcp+ruff format --check: clean.uv run mypy fastapi_mcp: no issues in 12 source files.uv build+ METADATA inspection of the built wheel.Fixes #275