UFO 项目 MCP 配置完全指南:从分层 YAML 结构到服务器生命周期管理
【免费下载链接】UFOUFO³: Weaving the Digital Agent Galaxy项目地址: https://gitcode.com/GitHub_Trending/uf/UFO
本篇技术指南系统讲解 UFO 项目中 MCP(Model Context Protocol)的配置文件设计与实战使用。UFO 通过一份位于config/ufo/mcp.yaml的分层 YAML 配置,将不同 Agent(如 HostAgent、AppAgent、HardwareAgent)映射到各自的 MCP 服务器,从而统一管理"数据采集"与"动作执行"两类工具。读完本文,你将掌握四层配置层级、local/http/stdio 三种服务器类型的字段语义、内置 Agent 的完整配置样例、加载与校验方式,以及从旧版配置迁移的完整路径,能够独立为自定义 Agent 编写可运行、可维护的 MCP 配置。
MCP 配置在 UFO 中的定位
MCP 是 UFO 中 Agent 与外部工具交互的统一协议层:Agent 负责决策"做什么",MCP 服务器负责实现"怎么做"。而mcp.yaml正是将两者绑定在一起的"映射表"——它为每个 Agent 声明可用的数据采集服务器(只读观察)与动作服务器(状态变更)。
配置文件的默认位置为:
config/ufo/mcp.yaml从源码结构看,该路径由两处共同确认:系统配置项的默认值mcp_servers_config: str = "config/ufo/mcp.yaml"(见 config/config_schemas.py),以及配置加载器ufo/config/__init__.py中"优先读取新位置config/ufo/mcp.yaml、回退到旧位置ufo/config/agent_mcp.yaml"的加载逻辑(见 ufo/config/init.py)。
配置结构:四层层级模型
MCP 配置采用层级 YAML 结构,自上而下共四层:
AgentName: # 第 1 层:Agent 名称 SubType: # 第 2 层:子类型(如 "default"、"WINWORD.EXE") data_collection: # 第 3 层:工具类型(数据采集服务器) - namespace: ... # 第 4 层:服务器列表 type: ... # 服务器类型(local/http/stdio) ... # 其他服务器配置 action: # 第 3 层:工具类型(动作服务器) - namespace: ... type: ... ...四层含义
- Agent Name(Agent 名称):顶层标识,例如
HostAgent、AppAgent、ConstellationAgent、HardwareAgent、LinuxAgent。仓库自带配置文件还包含MobileAgent(见 config/ufo/mcp.yaml),用于 Android 设备自动化。 - Sub-Type(子类型):上下文相关配置,例如
default(兜底)或具体的应用程序名WINWORD.EXE、EXCEL.EXE、POWERPNT.EXE、explorer.exe。 - Tool Type(工具类型):
data_collection(数据采集,框架自动调用、LLM 不可选)或action(动作执行,LLM 每步主动选择)。 - Server List(服务器列表):一个数组,包含若干 MCP 服务器配置,每个配置以
namespace唯一标识。
层级关系可以形象地表示为:
AgentName └─ SubType ├─ data_collection │ ├─ Server 1 │ ├─ Server 2 │ └─ ... └─ action ├─ Server 1 ├─ Server 2 └─ ...Default 子类型约定:始终定义一个default子类型作为兜底配置。如果找不到特定子类型,Agent 会自动回退到default。这一"继承默认、按需覆盖"的机制正是配置哲学中hierarchical原则的体现,也是 AppAgent 能同时服务 Word、Excel、PowerPoint 等多个应用场景的关键。
服务器配置字段详解
通用字段(所有服务器共享)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
namespace | string | ✅ 是 | 服务器唯一标识符 |
type | string | ✅ 是 | 服务器类型:local、http或stdio |
reset | boolean | ❌ 否 | 是否重置服务器状态(默认:false) |
start_args | array | ❌ 否 | 传递给服务器初始化的参数 |
在源码层面,MCPServerManager通过_server_type_mapping字典把type字段直接映射到三个实现类(见 ufo/client/mcp/mcp_server_manager.py):
_server_type_mapping: Dict[str, Callable[[Dict[str, Any]], BaseMCPServer]] = { "http": HTTPMCPServer, "local": LocalMCPServer, "stdio": StdioMCPServer, }三者都继承自抽象基类BaseMCPServer,统一实现start()、stop()、reset()三个生命周期方法,并暴露config、namespace、server三个属性。create_mcp_server()会根据type断言合法性后实例化对应类并调用start()(见 ufo/client/mcp/mcp_server_manager.py),type不在映射表中的配置会直接抛出Unsupported server type断言错误。
Local(进程内)服务器字段
- namespace: UICollector type: local start_args: [] reset: false| 字段 | 说明 |
|---|---|
start_args | 传递给服务器工厂函数的参数 |
Local 服务器从MCPRegistry中按namespace取出FastMCP实例,在 Agent 进程内运行(in-process),无 IPC 开销、启动最快。其启动逻辑见 ufo/client/mcp/mcp_server_manager.py:调用MCPRegistry.get(server_namespace, ...),若 registry 中没有对应名称则抛出KeyError并提示"本地服务器注册表中找不到该名称"。
MCPRegistry是集中的服务器注册表,支持两种注册方式(见 ufo/client/mcp/mcp_registry.py):
register_instance:直接注册已创建的FastMCP实例;register_factory:注册工厂函数,实现懒初始化——get()时若实例不存在,则调用工厂函数现场创建。工厂还可以通过@MCPRegistry.register_factory_decorator("server_name")装饰器注册。
UFO 内置的本地服务器模块位于 ufo/client/mcp/local_servers/,包括ui_mcp_server、word_wincom_mcp_server、excel_wincom_mcp_server、ppt_wincom_mcp_server、pdf_reader_mcp_server、cli_mcp_server、constellation_mcp_server等。注意:local_servers/__init__.py定义了WINDOWS_ONLY_SERVERS集合,ui_mcp_server及四个 Windows COM 服务器在非 Windows 平台上会被自动跳过(见 ufo/client/mcp/local_servers/init.py),因此 UI 类 local 服务器是 Windows 专属能力。
HTTP(远程)服务器字段
- namespace: HardwareCollector type: http host: "localhost" port: 8006 path: "/mcp" reset: false| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
host | string | ✅ 是 | 服务器主机名或 IP |
port | integer | ✅ 是 | 服务器端口号 |
path | string | ✅ 是 | MCP 端点的 URL 路径 |
HTTP 服务器运行在远程机器上,通过 REST API 访问。其start()实现会拼接http://{host}:{port}{path}生成 URL(默认值分别为localhost、8000、/mcp),并支持可选的auth字段:若auth包含未解析的环境变量占位符(如${UFO_MCP_API_KEY}),会抛出ValueError提示"HTTP MCP auth 包含未解析的环境变量";只有合法的非空字符串才会构建带认证的StreamableHttpTransport(见 ufo/client/mcp/mcp_server_manager.py)。仓库的MobileAgent配置就使用了auth: "${UFO_MCP_API_KEY}"的写法(见 config/ufo/mcp.yaml)。
由于 HTTP 服务器通常由外部进程托管,其stop()与reset()均为占位实现(reset 会打印"HTTP MCP server reset is not supported"提示),本质上被视为无状态服务。
Stdio(子进程)服务器字段
- namespace: CustomProcessor type: stdio command: "python" start_args: ["-m", "custom_mcp_server"] env: {"API_KEY": "secret"} cwd: "/path/to/server" reset: false| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
command | string | ✅ 是 | 可执行命令 |
start_args | array | ❌ 否 | 命令行参数 |
env | object | ❌ 否 | 环境变量 |
cwd | string | ❌ 否 | 工作目录 |
Stdio 服务器以子进程方式运行,通过 stdin/stdout 与 Agent 双向通信,实现进程隔离与干净的资源管理。其start()直接构造StdioTransport(command=command, args=start_args, env=env, cwd=cwd)(见 ufo/client/mcp/mcp_server_manager.py),默认命令为python、默认工作目录为.。适合需要沙箱隔离或语言无关的自定义服务器场景。
内置 Agent 的 MCP 配置
HostAgent(系统级 Agent)
面向操作系统全局自动化:
HostAgent: default: data_collection: - namespace: UICollector type: local start_args: [] reset: false action: - namespace: HostUIExecutor type: local start_args: [] reset: false - namespace: CommandLineExecutor type: local start_args: [] reset: false可用工具:
- 数据采集:UI 检测、截屏
- 动作:系统级点击、窗口管理、CLI 执行
AppAgent(应用级 Agent)
面向具体应用程序的自动化。同一 Agent 可通过不同 SubType 复用default基础能力并叠加专属执行器。
默认配置
AppAgent: default: data_collection: - namespace: UICollector type: local start_args: [] reset: false action: - namespace: AppUIExecutor type: local start_args: [] reset: false - namespace: CommandLineExecutor type: local start_args: [] reset: falseWord 专属配置
AppAgent: WINWORD.EXE: data_collection: - namespace: UICollector type: local start_args: [] reset: false action: - namespace: AppUIExecutor type: local start_args: [] reset: false - namespace: WordCOMExecutor type: local start_args: [] reset: true # 切换文档时重置 COM 状态可用工具:数据采集与 default 相同;动作包含 App UI 自动化 + Word COM API(insert_table、select_text等)。
Reset 标志:对有状态工具(如 COM 执行器)设置reset: true,防止跨上下文(如不同文档之间)的状态泄漏。
Excel 专属配置
AppAgent: EXCEL.EXE: data_collection: - namespace: UICollector type: local reset: false action: - namespace: AppUIExecutor type: local reset: false - namespace: ExcelCOMExecutor type: local reset: truePowerPoint 专属配置
AppAgent: POWERPNT.EXE: data_collection: - namespace: UICollector type: local reset: false action: - namespace: AppUIExecutor type: local reset: false - namespace: PowerPointCOMExecutor type: local reset: true文件资源管理器配置
AppAgent: explorer.exe: data_collection: - namespace: UICollector type: local reset: false action: - namespace: AppUIExecutor type: local reset: false - namespace: PDFReaderExecutor type: local reset: true以上配置与仓库中的 config/ufo/mcp.yaml 完全一致。从架构角度看,AppAgent 的每个 SubType 都采用了"GUI 自动化(AppUIExecutor)+ API 自动化(COM Executor)"双模式组合:LLM 在每一步根据可靠性、速度与可用性动态选择走 API(快、确定)还是走 GUI(处理 API 无法覆盖的视觉元素)。例如插入表格用WordCOMExecutor::insert_table,而切换到 Design 标签页则回退到AppUIExecutor::click_input。
ConstellationAgent(多设备协同 Agent)
ConstellationAgent: default: action: - namespace: ConstellationEditor type: local start_args: [] reset: false可用工具:创建任务、分配设备、查看任务状态。
HardwareAgent(远程硬件监控 Agent)
HardwareAgent: default: data_collection: - namespace: HardwareCollector type: http host: "localhost" port: 8006 path: "/mcp" reset: false action: - namespace: HardwareExecutor type: http host: "localhost" port: 8006 path: "/mcp" reset: false可用工具:
- 数据采集:CPU 信息、内存信息、磁盘信息
- 动作:硬件控制命令
远程部署:使用远程服务器时,需确保目标机器上已运行 HTTP MCP 服务器,部署指南见 Remote Servers。仓库中对应的服务端实现位于 ufo/client/mcp/http_servers/(hardware_mcp_server.py、linux_mcp_server.py、mobile_mcp_server.py)。
LinuxAgent(Linux 系统 Agent)
LinuxAgent: default: action: - namespace: BashExecutor type: http host: "localhost" port: 8010 path: "/mcp" reset: false可用工具:Bash 命令执行。
MobileAgent(Android 设备 Agent)
虽然配置文档正文未展开,但仓库自带的 config/ufo/mcp.yaml 已给出MobileAgent的完整配置:MobileDataCollector(HTTP,端口 8020,带${UFO_MCP_API_KEY}认证)负责 Android 设备观测,MobileActionExecutor(HTTP,端口 8021,同样带认证)负责点击、滑动、启动应用等控制操作。它是"HTTP 远程 + 环境变量认证"组合的现成范例。
配置示例:三种典型组合
示例 1:纯本地 Agent
SimpleAgent: default: data_collection: - namespace: UICollector type: local reset: false action: - namespace: SimpleExecutor type: local reset: false适用于完全依赖内置本地工具的场景,零网络依赖。
示例 2:混合 Agent(本地 + 远程)
HybridAgent: default: data_collection: # 本地 UI 检测 - namespace: UICollector type: local reset: false # 远程硬件监控 - namespace: HardwareCollector type: http host: "192.168.1.100" port: 8006 path: "/mcp" reset: false action: # 本地 UI 自动化 - namespace: UIExecutor type: local reset: false # 远程命令执行 - namespace: RemoteExecutor type: http host: "192.168.1.100" port: 8007 path: "/mcp" reset: false展示如何在同一 Agent 内同时挂载本地与远程服务器,实现"就近处理 + 分布式扩展"。
示例 3:多上下文 Agent
MultiContextAgent: # 默认配置 default: data_collection: - namespace: BasicCollector type: local action: - namespace: BasicExecutor type: local # Chrome 专属 chrome.exe: data_collection: - namespace: BasicCollector type: local - namespace: WebCollector type: local action: - namespace: BasicExecutor type: local - namespace: BrowserExecutor type: local reset: true # VS Code 专属 Code.exe: data_collection: - namespace: BasicCollector type: local - namespace: IDECollector type: local action: - namespace: BasicExecutor type: local - namespace: CodeExecutor type: local reset: true充分利用"default 兜底 + 子类型覆盖"机制:chrome.exe与Code.exe在default基础上各自追加专属采集器与执行器,且对有状态执行器开启reset。
最佳实践
1. 使用描述性命名空间
# ✅ 良好:清晰且具描述性 namespace: WindowsUICollector namespace: ExcelCOMExecutor namespace: LinuxBashExecutor # ❌ 糟糕:通用且含义不明 namespace: Collector1 namespace: Server namespace: Tools清晰的namespace不仅便于人类阅读维护,也直接影响调试日志的可读性(如Registered MCP server 'UICollector' ...)。
2. 按用途分组服务器
# ✅ 良好:逻辑分组 HostAgent: default: data_collection: - namespace: UICollector # 所有 UI 相关 - namespace: ScreenshotTaker action: - namespace: UIExecutor # 所有 UI 动作 - namespace: WindowManager # ❌ 糟糕:目的混杂 HostAgent: default: data_collection: - namespace: UICollector - namespace: HardwareMonitor # 用途不同3. 重置有状态服务器
# ✅ 良好:重置 COM 服务器 WordCOMExecutor: type: local reset: true # 防止状态泄漏 # ❌ 糟糕:不重置可能引发问题 WordCOMExecutor: type: local reset: false # 可能残留上一个文档的状态4. 验证远程服务器可用性
# 使用远程服务器时,确保其可达 HardwareCollector: type: http host: "192.168.1.100" # ✅ 验证该主机可达 port: 8006 # ✅ 验证端口开放 path: "/mcp" # ✅ 验证端点存在5. 用环境变量管理密钥
# ✅ 良好:使用环境变量 - namespace: SecureAPI type: http host: "${API_HOST}" port: "${API_PORT}" auth: token: "${API_TOKEN}" # ❌ 糟糕:硬编码密钥 - namespace: SecureAPI type: http host: "api.example.com" auth: token: "secret123" # 切勿提交到仓库!仓库对此有双重保障:MobileAgent的auth使用${UFO_MCP_API_KEY}占位符(见 config/ufo/mcp.yaml),而 ufo/client/mcp/mcp_server_manager.py 中定义了_UNRESOLVED_ENV_VAR_PATTERN正则,专门检测未解析的环境变量并拒绝启动——从配置到运行时都杜绝了密钥硬编码的隐患。
加载配置
从文件加载
import yaml from pathlib import Path # 加载 MCP 配置 config_path = Path("config/ufo/mcp.yaml") with open(config_path) as f: mcp_config = yaml.safe_load(f) # 访问 Agent 配置 host_agent_config = mcp_config["HostAgent"]["default"]以编程方式加载
from ufo.config import get_config # 获取完整配置 configs = get_config() # 访问 MCP 部分 mcp_config = configs.get("mcp", {}) # 获取指定 Agent host_agent = mcp_config.get("HostAgent", {}).get("default", {})注意:在get_config()中,MCP 配置是作为mcp键嵌入到整体配置字典中的。其加载逻辑见 ufo/config/init.py:优先读取config/ufo/mcp.yaml,若不存在则回退到旧位置ufo/config/agent_mcp.yaml。此外,系统级开关由 config/config_schemas.py 中的字段控制:
| 系统配置项 | 默认值 | 作用 |
|---|---|---|
use_mcp | true | 是否启用 MCP 工具 |
mcp_servers_config | config/ufo/mcp.yaml | MCP 配置文件路径 |
mcp_preferred_apps | 空列表 | 优先使用 MCP 的应用列表 |
mcp_fallback_to_ui | true | MCP 失败时是否回退到 UI 操作 |
mcp_instructions_path | ufo/config/mcp_instructions | MCP 使用说明文件路径 |
mcp_tool_timeout | 30 | MCP 工具调用超时(秒) |
mcp_log_execution | false | 是否记录工具执行日志 |
这些配置均可通过环境变量(如MCP_SERVERS_CONFIG、MCP_TOOL_TIMEOUT)覆盖,映射关系见 config/config_schemas.py。
配置校验
Schema 校验
UFO 在加载 MCP 配置时会进行校验:
from ufo.config.config_schemas import MCPConfigSchema # 校验配置 try: MCPConfigSchema.validate(mcp_config) print("✅ Configuration is valid") except ValidationError as e: print(f"❌ Configuration error: {e}")常见校验错误
| 错误 | 原因 | 解决方案 |
|---|---|---|
Missing required field: namespace | 服务器缺少命名空间 | 添加namespace字段 |
Invalid server type: unknown | 不支持的类型 | 使用local、http或stdio |
Missing host for http server | HTTP 服务器缺少 host | 添加host和port |
Duplicate namespace | 同一命名空间被使用两次 | 使用唯一命名空间 |
此外,运行时还有一层防线:MCPServerManager.create_mcp_server()对未知type的断言会直接中断启动(见 ufo/client/mcp/mcp_server_manager.py);LocalMCPServer.start()对未注册的 namespace 会抛出带明确提示的ValueError。
调试配置
启用调试日志
import logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger("ufo.client.mcp") # 将显示服务器创建与注册过程 # DEBUG: Creating MCP server 'UICollector' of type local # DEBUG: Registered MCP server 'UICollector' with 15 tools这两条日志分别对应MCPServerManager中的创建与注册流程:create_mcp_server()内调用server_instance.start()后,随即调用register_server(),后者会打印Registered MCP server '{namespace}' of type {type(server).__name__}(见 ufo/client/mcp/mcp_server_manager.py)。
查看已加载的服务器
from ufo.client.mcp.mcp_server_manager import MCPServerManager # 列出所有已注册服务器 servers = MCPServerManager._servers_mapping for namespace, server in servers.items(): print(f"Server: {namespace}, Type: {type(server).__name__}")_servers_mapping是MCPServerManager的类级字典,以 namespace 为键、BaseMCPServer实例为值;get_server(namespace)提供了无副作用的查询入口。
测试服务器连通性
async def test_server(config): """测试 MCP 服务器是否可访问。""" try: server = MCPServerManager.create_mcp_server(config) print(f"✅ Server '{config['namespace']}' is accessible") # 列出工具 if hasattr(server, 'server'): from fastmcp.client import Client async with Client(server.server) as client: tools = await client.list_tools() print(f" Tools: {[tool.name for tool in tools]}") except Exception as e: print(f"❌ Server '{config['namespace']}' failed: {e}")迁移指南:从旧版配置格式升级
如果正在从旧版 UFO 配置迁移:
旧格式(config.yaml):
MCP_SERVERS: - name: ui_collector module: ufo.mcp.ui_server新格式(mcp.yaml):
HostAgent: default: data_collection: - namespace: UICollector type: local新旧格式的关键差异:旧格式是"扁平列表 + module 引用",新格式是"按 Agent 分层的 namespace 映射"。仓库提供了两条迁移路径:
- 自动迁移工具:ufo/tools/convert_config.py 可将旧版
agent_mcp.yaml直接转换为mcp.yaml(文件内标注了agent_mcp.yaml → mcp.yaml的映射规则); - 运行时回退:即使未迁移,ufo/config/init.py 也会在找不到新路径时自动读取旧路径
ufo/config/agent_mcp.yaml,保证平滑过渡。
详细迁移说明见 Configuration Migration Guide。
相关文档
- MCP Overview — MCP 高层架构与概念
- Data Collection Servers — 数据采集服务器配置
- Action Servers — 动作服务器配置
- Local Servers — 内置本地 MCP 服务器清单
- Remote Servers — HTTP 与 Stdio 部署
- MCP Reference — 完整字段速查
- Creating Custom MCP Servers Tutorial — 构建自定义服务器
- Configuration Guide — 通用配置指南
- HostAgent Overview — HostAgent 配置示例
- AppAgent Overview — AppAgent 配置示例
配置哲学:
MCP 配置遵循约定优于配置(convention over configuration)原则:
- 合理的默认值— 最小化必需的配置项;
- 需要时显式— 需要定制时提供完全控制;
- 类型安全— 加载时即校验,尽早捕获错误;
- 层级化— 从默认配置继承,按需覆盖。
结合源码实现可以进一步看到这套哲学如何落地:配置通过config/ufo/mcp.yaml单文件声明,由ufo/config/__init__.py统一加载为mcp键;运行时由MCPServerManager依据type分派到LocalMCPServer/HTTPMCPServer/StdioMCPServer;本地服务器经由MCPRegistry的实例/工厂双通道按需获取,实现"声明式配置 + 懒加载实例化"的完整链路。掌握这一链路后,你可以轻松为新的 Agent 编写 MCP 配置,或将自定义 MCP 服务器无缝接入 UFO 的工具体系。
【免费下载链接】UFOUFO³: Weaving the Digital Agent Galaxy项目地址: https://gitcode.com/GitHub_Trending/uf/UFO
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考