Skip to content

Conversation

@Viicos
Copy link
Contributor

@Viicos Viicos commented Oct 18, 2025

Motivation and Context

This is a first step in adding support for Pydantic 2.12 and Python 3.14. It avoids relying on patterns that we discourage using in Pydantic (mostly around the FieldInfo class), and removes usage of private utilities.

How Has This Been Tested?

Breaking Changes

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 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

Comment on lines +36 to +38
"typing-extensions>=4.9.0",
"typing-inspection>=0.4.1",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typing-extensions is already used in the project, but not declared as an explicit dependency. 4.9.0 is the oldest version with (proper) support for typing_extensions.deprecated.

typing-inspection is already a Pydantic dependency, so nothing new added here.

Comment on lines -471 to -515
def _get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
"""Get function signature while evaluating forward references"""
signature = inspect.signature(call)
globalns = getattr(call, "__globals__", {})
typed_params = [
inspect.Parameter(
name=param.name,
kind=param.kind,
default=param.default,
annotation=_get_typed_annotation(param.annotation, globalns),
)
for param in signature.parameters.values()
]
typed_return = _get_typed_annotation(signature.return_annotation, globalns)
typed_signature = inspect.Signature(typed_params, return_annotation=typed_return)
return typed_signature
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed, we can just use inspect.get_annotations() with eval_str=True.

It also enables more use cases to be supported, e.g.:

from __future__ import annotations

def func[T](a: T): ...

from_metadata(func)  # Used to raise

Let me know if I should add a test for this.

Kludex
Kludex previously approved these changes Oct 22, 2025
Copy link
Member

@Kludex Kludex left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR keeps the support for Pydantic 2.11.

@Viicos is maintaining Pydantic, so he knows stuff.

@Viicos Viicos force-pushed the refactor-func-metadata branch 2 times, most recently from 5dff9fa to cf3ae5c Compare October 22, 2025 14:52
Comment on lines 267 to 270
if return_type_expr is UNKNOWN and structured_output is True:
# `return_type_expr` is `UNKNOWN` when a bare type qualifier is used (unlikely to happen as a return annotation
# because it doesn't make any sense, but technically possible).
raise InvalidSignature(f"Function {func.__name__}: return annotation required for structured output")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we already have a unit test that covers this? otherwise would be good to add one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll add one.

Comment on lines 288 to 301
# Reconstruct the original annotation, by preserving the remaining metadata,
# i.e. from `Annotated[CallToolResult, ReturnType, Gt(1)]` to
# `Annotated[ReturnType, Gt(1)]`:
original_annotation = Annotated[(return_type_expr, *inspected_return_ann.metadata[1:])]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I'm reading this right, does that mean the current code on main would strip the extra metadata and cause different Pydantic models to be created? if so a unit test for this seems like a good idea

Copy link
Contributor Author

@Viicos Viicos Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code on main behaves as expected (in most cases, see here where it doesn't on main and on this PR), because it is constructing a FieldInfo instance from the annotation, and passing it again as Annotated[ann, field_info_instance], which is an undocumented pattern although kind of works.

I'll add tests related to this.

@felixweinberger felixweinberger added enhancement needs more work Not ready to be merged yet, needs additional follow-up from the author(s). labels Oct 23, 2025
@Viicos Viicos force-pushed the refactor-func-metadata branch from 961b3cc to 2b607bc Compare November 7, 2025 09:36
@felixweinberger felixweinberger added enhancement Request for a new feature that's not currently supported and removed enhancement deprecated labels Nov 12, 2025
@maxisbey maxisbey force-pushed the refactor-func-metadata branch from 2b607bc to 1e0e002 Compare November 13, 2025 19:58
maxisbey
maxisbey previously approved these changes Nov 13, 2025
@maxisbey maxisbey enabled auto-merge (squash) November 13, 2025 20:15
@maxisbey maxisbey merged commit 116c13e into modelcontextprotocol:main Nov 13, 2025
18 checks passed
@Viicos Viicos deleted the refactor-func-metadata branch November 13, 2025 20:22
@Viicos
Copy link
Contributor Author

Viicos commented Nov 13, 2025

Thanks @maxisbey (sorry I'm out for some days couldn't rebase).

LucaButBoring pushed a commit to LucaButBoring/mcp-python-sdk that referenced this pull request Nov 17, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Request for a new feature that's not currently supported needs more work Not ready to be merged yet, needs additional follow-up from the author(s).

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants