mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-19 20:14:17 +02:00
fix: preserve tool decorator metadata (#4072)
Generated with Codex. Co-authored-by: lawrence3699 <lawrence3699@users.noreply.github.com>
This commit is contained in:
parent
f5dea2a17c
commit
2ffe68cfa1
2 changed files with 35 additions and 2 deletions
|
|
@ -24,7 +24,7 @@ from pydantic import Field
|
|||
from pydantic.json_schema import SkipJsonSchema
|
||||
|
||||
import fastmcp
|
||||
from fastmcp.decorators import resolve_task_config
|
||||
from fastmcp.decorators import get_fastmcp_meta, resolve_task_config
|
||||
from fastmcp.exceptions import FastMCPDeprecationWarning
|
||||
from fastmcp.server.auth.authorization import AuthCheck
|
||||
from fastmcp.server.dependencies import without_injected_parameters
|
||||
|
|
@ -169,6 +169,11 @@ class FunctionTool(Tool):
|
|||
"Use metadata alone or individual parameters alone."
|
||||
)
|
||||
|
||||
if metadata is None and not individual_params_provided:
|
||||
fmeta = get_fastmcp_meta(fn)
|
||||
if isinstance(fmeta, ToolMeta):
|
||||
metadata = fmeta
|
||||
|
||||
# Build metadata from kwargs if not provided
|
||||
if metadata is None:
|
||||
metadata = ToolMeta(
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ import pytest
|
|||
from fastmcp import FastMCP
|
||||
from fastmcp.client import Client
|
||||
from fastmcp.tools import tool
|
||||
from fastmcp.tools.function_tool import DecoratedTool, ToolMeta
|
||||
from fastmcp.tools.base import Tool
|
||||
from fastmcp.tools.function_tool import DecoratedTool, FunctionTool, ToolMeta
|
||||
|
||||
|
||||
class TestToolDecorator:
|
||||
|
|
@ -89,6 +90,33 @@ class TestToolDecorator:
|
|||
assert decorated.__fastmcp__.tags == {"greeting", "demo"}
|
||||
assert decorated.__fastmcp__.meta == {"custom": "value"}
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"factory", [Tool.from_function, FunctionTool.from_function]
|
||||
)
|
||||
def test_from_function_preserves_decorator_metadata(self, factory):
|
||||
"""Direct from_function calls should respect @tool metadata."""
|
||||
|
||||
@tool(
|
||||
name="custom-greet",
|
||||
version="v1",
|
||||
title="Greeting Tool",
|
||||
description="Greets people",
|
||||
tags={"greeting", "demo"},
|
||||
meta={"custom": "value"},
|
||||
)
|
||||
def greet(name: str) -> str:
|
||||
"""Fallback description."""
|
||||
return f"Hello, {name}!"
|
||||
|
||||
created_tool = factory(greet)
|
||||
|
||||
assert created_tool.name == "custom-greet"
|
||||
assert created_tool.version == "v1"
|
||||
assert created_tool.title == "Greeting Tool"
|
||||
assert created_tool.description == "Greets people"
|
||||
assert created_tool.tags == {"greeting", "demo"}
|
||||
assert created_tool.meta == {"custom": "value"}
|
||||
|
||||
async def test_tool_function_still_callable(self):
|
||||
"""Decorated function should still be directly callable."""
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue