From 05288fc507b02f60f94b2c1efa65d95b7619fe7c Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 09:08:24 -0400 Subject: [PATCH 1/3] Fix handling tools without descriptions --- src/fastmcp/resources/template.py | 2 +- src/fastmcp/tools/tool.py | 4 ++-- tests/server/test_proxy.py | 9 +++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/fastmcp/resources/template.py b/src/fastmcp/resources/template.py index b7adb9481..5077a910b 100644 --- a/src/fastmcp/resources/template.py +++ b/src/fastmcp/resources/template.py @@ -148,7 +148,7 @@ class ResourceTemplate(BaseModel): f"URI parameters {uri_params} must be a subset of the function arguments: {func_params}" ) - description = description or fn.__doc__ or "" + description = description or fn.__doc__ if not inspect.isroutine(fn): fn = fn.__call__ diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index e92eda26b..0658a0dad 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -36,7 +36,7 @@ class Tool(BaseModel): fn: Callable[..., Any] name: str = Field(description="Name of the tool") - description: str = Field(description="Description of what the tool does") + description: str | None = Field(description="Description of what the tool does") parameters: dict[str, Any] = Field(description="JSON schema for tool parameters") tags: Annotated[set[str], BeforeValidator(_convert_set_defaults)] = Field( default_factory=set, description="Tags for the tool" @@ -74,7 +74,7 @@ class Tool(BaseModel): if func_name == "": raise ValueError("You must provide a name for lambda functions") - func_doc = description or fn.__doc__ or "" + func_doc = description or fn.__doc__ # if the fn is a callable class, we need to get the __call__ method from here out if not inspect.isroutine(fn): diff --git a/tests/server/test_proxy.py b/tests/server/test_proxy.py index b77db9b38..f310fa505 100644 --- a/tests/server/test_proxy.py +++ b/tests/server/test_proxy.py @@ -30,6 +30,10 @@ def fastmcp_server(): """Greet someone by name.""" return f"Hello, {name}!" + @server.tool() + def tool_without_description() -> str: + return "Hello?" + @server.tool() def add(a: int, b: int) -> int: """Add two numbers together.""" @@ -110,6 +114,11 @@ class TestTools: assert "greet" in tools assert "add" in tools assert "error_tool" in tools + assert "tool_without_description" in tools + + async def test_tool_without_description(self, proxy_server): + tools = await proxy_server.get_tools() + assert tools["tool_without_description"].description is None async def test_list_tools_same_as_original(self, fastmcp_server, proxy_server): assert ( From 4671741d42a06c33c85c0d14b6008d89e8029174 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 13:03:15 -0400 Subject: [PATCH 2/3] Update src/fastmcp/tools/tool.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/fastmcp/tools/tool.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index 0658a0dad..f9beaeea9 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -36,7 +36,7 @@ class Tool(BaseModel): fn: Callable[..., Any] name: str = Field(description="Name of the tool") - description: str | None = Field(description="Description of what the tool does") + description: str | None = Field(default=None, description="Description of what the tool does") parameters: dict[str, Any] = Field(description="JSON schema for tool parameters") tags: Annotated[set[str], BeforeValidator(_convert_set_defaults)] = Field( default_factory=set, description="Tags for the tool" From 32f6945336eb9b3ee989445cceebc4a21d41b7f7 Mon Sep 17 00:00:00 2001 From: Jeremiah Lowin <153965+jlowin@users.noreply.github.com> Date: Tue, 27 May 2025 13:04:17 -0400 Subject: [PATCH 3/3] Update tool.py --- src/fastmcp/tools/tool.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/fastmcp/tools/tool.py b/src/fastmcp/tools/tool.py index f9beaeea9..f556bafa7 100644 --- a/src/fastmcp/tools/tool.py +++ b/src/fastmcp/tools/tool.py @@ -36,7 +36,9 @@ class Tool(BaseModel): fn: Callable[..., Any] name: str = Field(description="Name of the tool") - description: str | None = Field(default=None, description="Description of what the tool does") + description: str | None = Field( + default=None, description="Description of what the tool does" + ) parameters: dict[str, Any] = Field(description="JSON schema for tool parameters") tags: Annotated[set[str], BeforeValidator(_convert_set_defaults)] = Field( default_factory=set, description="Tags for the tool"