项目文件夹

文件
2026-07-13 13:22:34 +08:00

75 行
2.0 KiB
Python

"""
Decorator for exposing MLflow CLI commands as MCP tools.
Usage:
from mlflow.mcp.decorator import mlflow_mcp
@commands.command("search")
@mlflow_mcp(tool_name="search_traces")
@click.option(...)
def search_traces(...):
...
The decorator attaches MCP metadata to the Click command, which is then
used by the MCP server to register the tool with the specified name.
"""
from typing import Callable, TypeVar
import click
# Attribute name used to store MCP metadata on Click commands
MCP_METADATA_ATTR = "_mlflow_mcp_metadata"
F = TypeVar("F", bound=Callable)
def mlflow_mcp(tool_name: str) -> Callable[[F], F]:
"""
Decorator to expose a Click command as an MCP tool with a curated name.
Args:
tool_name: The name to use for the MCP tool. This should be a clear,
agent-friendly name that describes what the tool does.
Convention: action_entity (e.g., "search_traces", "get_experiment")
Example:
@commands.command("search")
@mlflow_mcp(tool_name="search_traces")
def search(...):
'''Search for traces in the specified experiment.'''
...
The decorator stores metadata on the function that the MCP server reads
when registering tools. Commands without this decorator are not exposed
as MCP tools.
"""
def decorator(fn: F) -> F:
# Store MCP metadata on the function
setattr(fn, MCP_METADATA_ATTR, {"tool_name": tool_name})
return fn
return decorator
def get_mcp_tool_name(cmd: click.Command) -> str | None:
"""
Get the MCP tool name from a Click command, if it has been decorated.
Args:
cmd: The Click command to check.
Returns:
The MCP tool name if the command has been decorated with @mlflow_mcp,
None otherwise.
"""
if cmd.callback is None:
return None
metadata = getattr(cmd.callback, MCP_METADATA_ATTR, None)
if metadata is None:
return None
return metadata.get("tool_name")