Treat `typing.Dict[str, X]` return annotations like `dict[str, X]`
Fixes #3745
-> typing.Dict[str, X] now gets the same output schema and structuredContent as -> dict[str, X], instead of being wrapped in {"result": ...}.
Motivation and Context
_create_output_model detected generics with isinstance(type_expr, types.GenericAlias). typing.Dict[str, X] is a typing._GenericAlias, so it fell through to the catch-all branch and got wrapped. Rewriting Dict to dict (e.g. ruff UP006) therefore silently changed a tool's output on the wire.
The branch now checks get_origin(type_expr) is not None.
How Has This Been Tested?
- Added a
typing.Dict[str, str]case totest_structured_output_dict_str_types; it fails without the fix. - Added a
NewTypecase totest_structured_output_generic_types, which is now what reaches the catch-all branch. func_metadata.pyat 100% coverage,strict-no-cover, ruff and pyright pass; test file passes on 3.11, 3.13 and 3.14.
Breaking Changes
Tools annotated -> typing.Dict[str, X] stop wrapping their result in {"result": ...}, matching the builtin spelling. Union, Optional, Literal and typing.List/Tuple now take the generic branch instead of the catch-all, but are still wrapped as before.
Types of changes
- Bug fix (non-breaking change which fixes an issue)
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to change)
- Documentation update
Checklist
- I am assigned to the linked issue (or it is labeled
help wanted, or I'm a maintainer) - I have disclosed any AI assistance and can explain the change in my own words
- I have read the MCP Documentation
- My code follows the repository's style guidelines
- New and existing tests pass locally
- I have added appropriate error handling
- I have added or updated documentation as needed
Additional context
Related: #3725 (bare dict/list/tuple), which touches the same function.
AI Disclaimer
This PR was developed with the assistance of either Claude or Codex. I've reviewed and verified the changes.