Merge pull request #181 from zzstoatzz/update-fastmcp-server-typing

satisfy `pyright` untyped decorators in `mcp.server.fastmcp.server`
This commit is contained in:
David Soria Parra
2025-02-04 18:25:32 +00:00
committed by GitHub
3 changed files with 16 additions and 9 deletions

3
.gitignore vendored
View File

@@ -162,3 +162,6 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# vscode
.vscode/

View File

@@ -25,6 +25,7 @@ from mcp.server.sse import SseServerTransport
from mcp.server.stdio import stdio_server from mcp.server.stdio import stdio_server
from mcp.shared.context import RequestContext from mcp.shared.context import RequestContext
from mcp.types import ( from mcp.types import (
AnyFunction,
EmbeddedResource, EmbeddedResource,
GetPromptResult, GetPromptResult,
ImageContent, ImageContent,
@@ -165,7 +166,7 @@ class FastMCP:
return Context(request_context=request_context, fastmcp=self) return Context(request_context=request_context, fastmcp=self)
async def call_tool( async def call_tool(
self, name: str, arguments: dict self, name: str, arguments: dict[str, Any]
) -> Sequence[TextContent | ImageContent | EmbeddedResource]: ) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
"""Call a tool by name with arguments.""" """Call a tool by name with arguments."""
context = self.get_context() context = self.get_context()
@@ -214,7 +215,7 @@ class FastMCP:
def add_tool( def add_tool(
self, self,
fn: Callable, fn: AnyFunction,
name: str | None = None, name: str | None = None,
description: str | None = None, description: str | None = None,
) -> None: ) -> None:
@@ -230,7 +231,9 @@ class FastMCP:
""" """
self._tool_manager.add_tool(fn, name=name, description=description) self._tool_manager.add_tool(fn, name=name, description=description)
def tool(self, name: str | None = None, description: str | None = None) -> Callable: def tool(
self, name: str | None = None, description: str | None = None
) -> Callable[[AnyFunction], AnyFunction]:
"""Decorator to register a tool. """Decorator to register a tool.
Tools can optionally request a Context object by adding a parameter with the Tools can optionally request a Context object by adding a parameter with the
@@ -263,7 +266,7 @@ class FastMCP:
"Did you forget to call it? Use @tool() instead of @tool" "Did you forget to call it? Use @tool() instead of @tool"
) )
def decorator(fn: Callable) -> Callable: def decorator(fn: AnyFunction) -> AnyFunction:
self.add_tool(fn, name=name, description=description) self.add_tool(fn, name=name, description=description)
return fn return fn
@@ -284,7 +287,7 @@ class FastMCP:
name: str | None = None, name: str | None = None,
description: str | None = None, description: str | None = None,
mime_type: str | None = None, mime_type: str | None = None,
) -> Callable: ) -> Callable[[AnyFunction], AnyFunction]:
"""Decorator to register a function as a resource. """Decorator to register a function as a resource.
The function will be called when the resource is read to generate its content. The function will be called when the resource is read to generate its content.
@@ -328,7 +331,7 @@ class FastMCP:
"Did you forget to call it? Use @resource('uri') instead of @resource" "Did you forget to call it? Use @resource('uri') instead of @resource"
) )
def decorator(fn: Callable) -> Callable: def decorator(fn: AnyFunction) -> AnyFunction:
# Check if this should be a template # Check if this should be a template
has_uri_params = "{" in uri and "}" in uri has_uri_params = "{" in uri and "}" in uri
has_func_params = bool(inspect.signature(fn).parameters) has_func_params = bool(inspect.signature(fn).parameters)
@@ -376,7 +379,7 @@ class FastMCP:
def prompt( def prompt(
self, name: str | None = None, description: str | None = None self, name: str | None = None, description: str | None = None
) -> Callable: ) -> Callable[[AnyFunction], AnyFunction]:
"""Decorator to register a prompt. """Decorator to register a prompt.
Args: Args:
@@ -417,7 +420,7 @@ class FastMCP:
"Did you forget to call it? Use @prompt() instead of @prompt" "Did you forget to call it? Use @prompt() instead of @prompt"
) )
def decorator(func: Callable) -> Callable: def decorator(func: AnyFunction) -> AnyFunction:
prompt = Prompt.from_function(func, name=name, description=description) prompt = Prompt.from_function(func, name=name, description=description)
self.add_prompt(prompt) self.add_prompt(prompt)
return func return func

View File

@@ -1,4 +1,4 @@
from typing import Annotated, Any, Generic, Literal, TypeVar from typing import Annotated, Any, Callable, Generic, Literal, TypeAlias, TypeVar
from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel from pydantic import BaseModel, ConfigDict, Field, FileUrl, RootModel
from pydantic.networks import AnyUrl from pydantic.networks import AnyUrl
@@ -27,6 +27,7 @@ ProgressToken = str | int
Cursor = str Cursor = str
Role = Literal["user", "assistant"] Role = Literal["user", "assistant"]
RequestId = str | int RequestId = str | int
AnyFunction: TypeAlias = Callable[..., Any]
class RequestParams(BaseModel): class RequestParams(BaseModel):