Files
deer-flow/backend/packages/harness/deerflow/tools/mcp_metadata.py
T
Ryker_FengandGitHub 5ba25b06ec feat(mcp): add MCP routing hints (#4004)
* feat: add MCP routing hints

* test: isolate mcp routing prompt config

* fix: address mcp routing review feedback
2026-07-09 16:26:31 +08:00

53 lines
1.9 KiB
Python

"""Single source of truth for the MCP-tool metadata tag.
A tool is "MCP-sourced" when it carries the ``deerflow_mcp`` metadata flag.
The tag is *written* where MCP tools are loaded (``tools.py``) and *read* by
deferred-tool assembly (``tool_search.py``) and the agent build site
(``agent.py``). Keeping the key, the tagger, and the predicate here means the
magic string lives in exactly one place, and readers import a public predicate
instead of a private cross-module helper.
This is a leaf module by design: it depends only on ``BaseTool`` so that any
module (including the tool loader) can import it without an import cycle.
"""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from langchain.tools import BaseTool
MCP_TOOL_METADATA_KEY = "deerflow_mcp"
MCP_TOOL_ROUTING_METADATA_KEY = "deerflow_mcp_routing"
def tag_mcp_tool(tool: BaseTool) -> BaseTool:
"""Mark ``tool`` as MCP-sourced. Mutates in place and returns it for chaining."""
tool.metadata = {**(tool.metadata or {}), MCP_TOOL_METADATA_KEY: True}
return tool
def is_mcp_tool(tool: BaseTool) -> bool:
"""True when ``tool`` carries the MCP-source tag written by :func:`tag_mcp_tool`."""
return (getattr(tool, "metadata", None) or {}).get(MCP_TOOL_METADATA_KEY) is True
def tag_mcp_routing(tool: BaseTool, routing: Mapping[str, Any]) -> BaseTool:
"""Attach serialized MCP routing metadata to ``tool``."""
tool.metadata = {
**(tool.metadata or {}),
MCP_TOOL_ROUTING_METADATA_KEY: dict(routing),
}
return tool
def get_mcp_routing(tool: BaseTool) -> dict[str, Any] | None:
"""Return routing metadata only for MCP tools whose routing mode is active."""
if not is_mcp_tool(tool):
return None
routing = (getattr(tool, "metadata", None) or {}).get(MCP_TOOL_ROUTING_METADATA_KEY)
if not isinstance(routing, dict) or routing.get("mode") == "off":
return None
return routing