Files
openswarm/backend/apps/tools/discover_tools/discover_tools.py

44 lines
2.0 KiB
Python

from typing import Any
from swarm_debug import debug
from backend.apps.tools.discover_tools.DiscoveryError import DiscoveryError, DiscoveryConfigError
from backend.apps.tools.discover_tools.utils.discover_mcp_tools_stdio import discover_mcp_tools_stdio
from backend.apps.tools.discover_tools.utils.discover_mcp_tools_http import discover_mcp_tools_http
from backend.apps.tools.discover_tools.utils.discover_mcp_tools_sse import discover_mcp_tools_sse
from typeguard import typechecked
# TODO: better type specing of this whole func
@typechecked
async def discover_tools(config: dict[str, Any], tool_name: str = "") -> list[dict]:
"""Probe an MCP server using the appropriate transport and return discovered tools.
config is the raw mcp_config dict from a ToolDefinition (with credentials
already injected by the converter if needed).
Returns a list of dicts with keys: name, description, inputSchema.
"""
transport = config.get("type", "")
if transport == "stdio":
command = config.get("command", "")
if not command:
raise DiscoveryConfigError("stdio transport requires a 'command' in MCP config")
return await discover_mcp_tools_stdio(
command=command,
args=config.get("args"),
env=config.get("env"),
)
if transport in ("http", "sse") or config.get("url"):
url = config.get("url", "")
if not url:
raise DiscoveryConfigError("HTTP/SSE transport requires a 'url' in MCP config")
if transport == "sse":
return await discover_mcp_tools_sse(url, config.get("headers"))
try:
return await discover_mcp_tools_http(url, config.get("headers"))
except DiscoveryError:
debug(f"[discover_tools] Streamable HTTP failed for {tool_name}, retrying with SSE")
return await discover_mcp_tools_sse(url, config.get("headers"))
raise DiscoveryConfigError(f"Unsupported MCP transport type: '{transport}'")