mirror of
https://github.com/PrefectHQ/fastmcp.git
synced 2026-08-09 15:19:10 +02:00
Engine modules (keys, context snapshot, docket lifespan, worker CLI, client handles) move intact; SEP-1686 wire modules park in _legacy_wire for adaptation to SEP-2663. Core keeps task=True declaration on tools only and raises at serve time until the tasks extension is registered. Co-Authored-By: Claude <noreply@anthropic.com>
41 lines
1.3 KiB
Python
41 lines
1.3 KiB
Python
"""Shared decorator utilities for FastMCP."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import inspect
|
|
from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
|
|
|
|
if TYPE_CHECKING:
|
|
from fastmcp.prompts.function_prompt import PromptMeta
|
|
from fastmcp.resources.function_resource import ResourceMeta
|
|
from fastmcp.tools.function_tool import ToolMeta
|
|
from fastmcp.utilities.tasks import TaskConfig
|
|
|
|
FastMCPMeta = ToolMeta | ResourceMeta | PromptMeta
|
|
|
|
|
|
def resolve_task_config(task: bool | TaskConfig | None) -> bool | TaskConfig:
|
|
"""Resolve task config, defaulting None to False."""
|
|
return task if task is not None else False
|
|
|
|
|
|
@runtime_checkable
|
|
class HasFastMCPMeta(Protocol):
|
|
"""Protocol for callables decorated with FastMCP metadata."""
|
|
|
|
__fastmcp__: Any
|
|
|
|
|
|
def get_fastmcp_meta(fn: Any) -> Any | None:
|
|
"""Extract FastMCP metadata from a function, handling bound methods and wrappers."""
|
|
if hasattr(fn, "__fastmcp__"):
|
|
return fn.__fastmcp__
|
|
if hasattr(fn, "__func__") and hasattr(fn.__func__, "__fastmcp__"):
|
|
return fn.__func__.__fastmcp__
|
|
try:
|
|
unwrapped = inspect.unwrap(fn)
|
|
if unwrapped is not fn and hasattr(unwrapped, "__fastmcp__"):
|
|
return unwrapped.__fastmcp__
|
|
except ValueError:
|
|
pass
|
|
return None
|