"""根据配置文件构造 MCP runner。""" from __future__ import annotations import logging from pathlib import Path from .logging_utils import json_for_log from .mcp_client import ( HttpMcpToolClient, McpClientConfig, OAuthTokenProvider, StdioMcpToolClient, load_mcp_client_config, ) from .mcp_runner import McpActionRunner logger = logging.getLogger(__name__) def build_mcp_runner_from_config(path: str | Path) -> McpActionRunner: """读取 MCP 配置文件,并构造可直接给 Agent 使用的 runner。""" logger.info("开始构建 MCP runner config_path=%s", path) config = load_mcp_client_config(path) client = build_mcp_client(config) runner = McpActionRunner(client=client, tool_names=config.tool_names or None) logger.info( "MCP runner 构建完成 config_path=%s transport=%s server_url=%s client=%s tool_names=%s", path, config.transport, config.server_url, type(client).__name__, json_for_log(config.tool_names), ) return runner def build_mcp_client(config: McpClientConfig): """根据 transport 类型创建 MCP client。""" logger.info( "开始构建 MCP client transport=%s server_url=%s command=%s has_auth=%s headers=%s", config.transport, config.server_url, config.command, config.auth is not None, json_for_log(config.headers), ) if config.transport == "stdio": return StdioMcpToolClient( command=config.command, args=config.args, env=config.env, cwd=config.cwd or None, timeout_seconds=config.timeout_seconds, ) if config.transport in ("streamable_http", "sse"): auth_provider = ( OAuthTokenProvider(config.auth, timeout_seconds=config.timeout_seconds) if config.auth is not None else None ) return HttpMcpToolClient( url=config.server_url, transport=config.transport, headers=config.headers, auth_provider=auth_provider, timeout_seconds=config.timeout_seconds, sse_read_timeout_seconds=config.sse_read_timeout_seconds, ) raise ValueError(f"不支持的 MCP transport: {config.transport}")