-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Labels
P3Nice to haves, rare edge casesNice to haves, rare edge casesenhancementRequest for a new feature that's not currently supportedRequest for a new feature that's not currently supportedready for workEnough information for someone to start working onEnough information for someone to start working on
Description
Issue: Decorator type signatures lose parameter types
Summary
The MCP server decorators (@server.call_tool(), @server.list_tools(), etc.) use Callable[..., Awaitable[...]] which discards parameter type information, preventing static type checkers from validating decorated functions.
Current Behavior
# In mcp/server/lowlevel/server.py
def call_tool(self, *, validate_input: bool = True):
def decorator(
func: Callable[
..., # <-- Ellipsis loses parameter types!
Awaitable[UnstructuredContent | StructuredContent | ...],
],
):
# ...When decorating a function:
@server.call_tool() # type: ignore # <-- Required!
async def call_tool(name: str, arguments: dict[str, object]) -> list[TextContent]:
...Mypy cannot verify:
- Parameter names/types are correct
- Arguments are passed correctly to decorated function
- Return type matches decorator constraints
Expected Behavior
Decorators should preserve parameter types using ParamSpec:
from typing import ParamSpec, TypeVar, Callable, Awaitable
P = ParamSpec('P')
R = TypeVar('R')
def call_tool(self, *, validate_input: bool = True):
def decorator(
func: Callable[P, Awaitable[R]]
) -> Callable[P, Awaitable[R]]:
# ... wrapper implementation
return func # Type signature preservedThis would:
- ✅ Preserve parameter types through decoration
- ✅ Enable static type checking
- ✅ Eliminate need for
# type: ignore - ✅ Improve IDE autocomplete/hints
Environment
- mcp version: 1.24.0
- Python version: 3.14 (but affects 3.10+)
- Type checker: mypy (strict mode)
Impact
The package includes py.typed marker claiming type support, but decorators break type checking. Projects using strict mypy must either:
- Disable type checking for entire MCP server modules
- Add
# type: ignoreto every decorated function - Create local type stubs to work around the issue
Workaround
Currently using broad mypy overrides:
[[tool.mypy.overrides]]
module = "myproject.mcp_server"
disable_error_code = ["misc", "no-untyped-call", "explicit-any"]This defeats the purpose of having py.typed.
Related
- Python typing docs: https://docs.python.org/3/library/typing.html#typing.ParamSpec
- Similar issue in other libraries: Making a decorator which preserves function signature python/mypy#1927
Metadata
Metadata
Assignees
Labels
P3Nice to haves, rare edge casesNice to haves, rare edge casesenhancementRequest for a new feature that's not currently supportedRequest for a new feature that's not currently supportedready for workEnough information for someone to start working onEnough information for someone to start working on