主题
07 - 能力扩展:Skill 与 MCP 契约化接入
一句话:企业能力只要满足契约就能接入,Skill 交出 HubSkillSpec 与 SKILL.md、MCP 暴露标准端点,控制面按订阅档位批量 import、enable 并下发工具白名单;契约换来零定制,代价是它只保证“装得上”而不保证“跑得安全”,高风险工具要靠白名单与沙箱在实例侧兜底,而批量分发天然是异步且部分成功的,结果必须逐实例记账。
一、设计目标
企业数字分身的能力扩展必须满足两个要求:
- 接入方零定制:企业 Skill 开发者或 MCP Server 提供方只需满足契约规范,无需了解实例内部实现
- 控制面统一分发:Skill 安装、MCP 连接、工具白名单、版本管理全部由控制面按契约自动完成
本章定义 Skill 和 MCP 两类能力扩展的契约规范、分发流程、以及控制面的管理实现。
二、Skill 契约
2.1 HubSkillSpec 规范
每个 Skill 必须提供符合以下规范的元信息:
python
@dataclass
class HubSkillSpec:
slug: str # 唯一标识(如 "tavily-search")
name: str # 显示名称(如 "Tavily 搜索")
description: str # 能力描述
version: str # 语义化版本号(如 "1.2.0")
source_url: str # 包来源(市场 URL / Git 仓库 / bundle_url)
author: str # 作者/团队
icon_url: str # 图标 URL
source: str # 来源类型:"hub"(官方市场)| "customized"(企业私有)
tags: list[str] # 标签(用于搜索和分类)
min_runtime: str # 最低运行时版本要求2.2 Skill 包结构
my-skill/
├── SKILL.md # 必须:Skill 能力描述(Agent 读取此文件理解如何使用)
├── skill.yaml # 必须:元信息(对应 HubSkillSpec)
├── tools/ # 可选:工具定义
│ └── search.py
├── prompts/ # 可选:提示词模板
│ └── default.md
└── tests/ # 可选:测试用例
└── test_search.pySKILL.md 示例:
markdown
---
name: tavily-search
version: 1.2.0
description: 使用 Tavily API 进行网络搜索
tools:
- name: web_search
description: 搜索互联网获取信息
parameters:
query: string (required) - 搜索关键词
max_results: integer (optional, default=5) - 最大结果数
---
# Tavily 搜索技能
当用户需要查找互联网上的最新信息时,使用此技能。
## 使用场景
- 用户询问实时信息(新闻、天气、股价等)
- 用户需要验证某个事实
- 用户需要查找特定主题的参考资料
## 注意事项
- 搜索结果可能不完全准确,需要向用户说明
- 每次搜索消耗 API 配额,避免不必要的搜索2.3 Skill 来源与市场
| 来源类型 | 说明 | 管理方 |
|---|---|---|
| 官方市场(hub) | QwenPaw 社区 Skill 市场,经过审核 | QwenPaw 社区 |
| 企业私有市场 | 企业内部 Skill 仓库,管理员审核后上架 | 企业管理员 |
| 直接上传 | 管理员通过 zip 包直接安装到指定实例 | 企业管理员 |
企业私有市场架构:
三、Skill 分发流程
3.1 管理员分发(企业统一配置)
3.2 员工自助安装
员工可以在订阅允许的范围内自行安装市场中的 Skill:
员工在 Console UI 中:
1. 浏览市场(GET /api/skills/hub/search?q=搜索)
2. 点击安装(POST /api/skills/hub/install/start)
3. 控制面校验订阅权限 → 异步安装任务
4. 安装完成后通知员工3.3 Skill 版本管理
| 操作 | 说明 |
|---|---|
| 安装 | 从市场下载指定版本到 skill_pool |
| 更新 | 检查市场新版本 → 下载 → 替换本地 → 重新启用 |
| 回滚 | 从 skill_pool 历史版本目录恢复 |
| 卸载 | 从 skill_pool 删除 + 从 Agent 配置中移除 |
版本锁定:管理员可以为特定 Skill 锁定版本(如 tavily-search@1.2.0),锁定后员工不可自行更新。
四、MCP 契约
4.1 MCPClientCreateRequest 规范
python
@dataclass
class MCPClientCreateRequest:
transport: Literal["stdio", "streamable_http", "sse"]
# 远程连接(streamable_http / sse)
url: str | None = None # MCP Server 端点 URL
headers: dict[str, str] | None = None # HTTP 头(含认证信息)
# 本地连接(stdio)
command: str | None = None # 启动命令
args: list[str] | None = None # 命令参数
env: dict[str, str] | None = None # 环境变量
# 通用
tools_whitelist: list[str] | None = None # 可用工具白名单4.2 MCP 连接方式对比
| 传输协议 | 场景 | 优势 | 限制 |
|---|---|---|---|
streamable_http | 远程 MCP Server(企业内网/公网) | 标准 HTTP,防火墙友好 | 需要 Server 暴露 HTTP 端点 |
sse | 远程 MCP Server(流式场景) | 实时推送 | 连接维护成本高 |
stdio | 本地命令行工具 | 无需网络配置 | 工具必须预装在实例镜像中 |
4.3 工具白名单
MCP Server 可能暴露大量工具,但企业通常只允许员工使用其中一部分。白名单机制实现细粒度控制:
MCP Server 提供的工具:
- search (网络搜索)
- query_db (数据库查询)
- delete_record (删除记录) ← 高风险
- export_data (导出数据) ← 敏感
- list_tables (列出表结构)
管理员配置的白名单:
tools_whitelist: ["search", "list_tables"]
结果:
实例中该 MCP Client 只能调用 search 和 list_tables
query_db / delete_record / export_data 不可见白名单粒度:
| 粒度 | 说明 | 适用场景 |
|---|---|---|
| 全局白名单 | 所有实例统一 | 企业安全基线 |
| 订阅档白名单 | 按订阅计划差异化 | 基础档/标准档/增强档 |
| 实例白名单 | 管理员为特定实例定制 | 特殊岗位需求 |
五、MCP 分发流程
5.1 控制面分发
5.2 凭证安全
MCP Server 的访问凭证(API Key、Token)由 Vault 统一管理:
- 凭证不入实例配置:MCP Client 创建时,控制面从 Vault 取出凭证注入请求 header,凭证不落实例配置文件
- 凭证不进备份:
include_secrets=false - 凭证定期轮换:控制面定时任务按策略轮换(默认 90 天)
- 凭证泄露即吊销:审计发现异常 → 控制面立即吊销 → 网关缓存失效 → 实例下次请求被拒
六、Skill 与 MCP 的协同
一个完整的业务能力通常需要 Skill + MCP 配合:
场景:员工让数字分身"查一下竞品最新动态并生成分析报告"
所需能力:
1. Skill: web-research(定义如何搜索、如何总结)
2. MCP: tavily-search(提供网络搜索工具)
3. MCP: enterprise-knowledge(提供内部知识库查询)
4. Skill: report-generator(定义报告格式和模板)
执行流程:
Agent 接收指令
→ 调用 web-research Skill(理解任务)
→ 通过 tavily-search MCP 搜索竞品信息
→ 通过 enterprise-knowledge MCP 查询内部资料
→ 调用 report-generator Skill 生成报告
→ 产物写入 projects/{task_id}/report.md七、市场分发审计
所有分发操作记录审计日志:
json
{
"event_type": "skill_install",
"timestamp": "2026-10-25T10:30:00Z",
"operator": "admin@company.com",
"target_instances": ["inst_abc123", "inst_def456"],
"skill_slug": "tavily-search",
"skill_version": "1.2.0",
"source": "enterprise_market",
"result": {"success": 2, "failed": 0, "skipped": 0},
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}