当前位置: 首页 > news >正文

S1-番外篇-03-MCP→Skill 自动转换:万悟真正的工具本地化魔法

番外03:MCP 与工具转换体系——从协议到 Skill

📌 本文是《从零吃透企业级 AI 平台:元景万悟源码学习手记》第一季·番外篇的第 3 篇
🔗 原理对照:回链第一季 06「MCP 协议实战」。06 讲了 MCP 协议标准(ListTools/CallTool/JSON-RPC)和万悟的 mcp-service。本篇深挖万悟的真正特色——MCP→Skill 和 OpenAPI→Skill 的自动转换引擎
🎯 读完本文:① 理解 mcp2skill 的 6 种使用模式 ② 看懂 OpenAPI→Skill 的分组/过滤/Schema 策略 ③ 掌握渐进式披露设计 ④ 理解万悟如何把外部工具"本地化"为 Skill
⏱️ 预计阅读时间:30 分钟 | 动手实践:30 分钟

⚠️ 诚实说明:本文基于 pkg/mcp2skill/ 和 pkg/openapi2skill/ 的完整 README(GitHub 已验证)。这两个包的文档极为详尽——含完整 API、数据结构、使用示例、对比表——可以写到代码级。


一、这篇文章要解决什么问题?

第一季 06 教了你 MCP 协议——"一个标准化的工具调用协议,让 AI 能用 GitHub、Slack、数据库等外部工具"。

但你有没有想过一个更深的问题:

接通了工具 ≠ Agent 会用工具。

MCP Server 可能暴露几十个、上百个工具。Agent 的 prompt 塞得下这么多工具描述吗?就算塞得下了,LLM 能从中准确选择吗?选错了怎么办?

万悟的做法不是"把所有工具平铺给 Agent",而是通过 mcp2skill 和 openapi2skill 两个转换引擎,把外部工具本地化为结构化 Skill——附带分类、渐进式加载、按需检索。

三个核心问题:

  1. mcp2skill 怎么把 MCP 工具转成 Skill? 生成的目录结构长什么样?6 种使用模式分别解决什么问题?

  2. openapi2skill 怎么处理庞大的 API 规范? 一个 OpenAPI spec 可能有几百个端点——怎么分组?怎么过滤?怎么生成 Skill 文档?

  3. 为什么这套转换比"直接把工具扔给 Agent"更好? 渐进式披露、按需加载、工具搜索——这些设计在代码中怎么体现?


二、核心概念

**MCP→Skill 转换链路图(MCP 协议 → 工具 Schema → Skill 注册)**

2.1 为什么需要转换?

**MCP 生态图(Server / Client / 工具市场 / 万悟集成点)**

直接让 Agent 调用 MCP 工具的痛点:

❌ 直接把 50 个 MCP 工具塞给 Agent→ System Prompt 暴涨→ LLM 混淆相似工具("get_user" vs "list_users" vs "search_users")→ Token 成本翻倍(每次对话都要传全套工具描述)→ 新工具上线要改 Agent prompt

转换后的 Skill 方案:

✅ mcp2skill/openapi2skill 把工具转为结构化 Skill→ SKILL.md 只写技能概览(~200 字)→ 每个工具一个独立 .md 文件(按需加载)→ Agent 先读概览 → 按关键词搜索具体工具 → 只加载需要的工具文件→ 新工具上线 = 重建 Skill,Agent prompt 不变

2.2 渐进式披露(Progressive Disclosure)

这是万悟 Skill 体系的核心设计理念。

Layer 1: SKILL.md              ← Agent 最先看到(概览,极小)↓ "我需要发个 Slack 消息"     ← Agent 按需求向下探索
Layer 2: references/operations/ ← 按工具名搜索(按需加载)↓ "send_message 的参数是什么"  ← Agent 找到具体工具文档
Layer 3: references/schemas/    ← 复杂类型需要看 Schema 定义

每一层只加载需要的信息,而不是把整个 Skill 一次性塞给 LLM。对比传统方式节省 70-90% 的 token。

2.3 mcp2skill vs openapi2skill

维度 mcp2skill openapi2skill
输入 MCP Server 的 SSE URL OpenAPI 3.x spec(JSON/YAML)
输出来源 运行时调用 list_tools() 静态解析 spec 文件
适用 已有 MCP Server(GitHub/Slack/数据库) 已有 OpenAPI 文档的 REST API
工具数量 通常 5-30 个 可能 50-500+ 个
分组策略 按 tool annotations 分组 按 resource + operation 分组

三、源码拆解

3.1 mcp2skill:MCP → Skill 自动转换

目录结构

pkg/mcp2skill/
├── cmd/               # CLI 入口:mcp2skill convert
├── auth.go            # URL Key 脱敏(安全)
├── converter.go       # 核心转换逻辑
└── README.md          # 详细的文档# 生成的 Skill 目录:
{outputDir}/{skillName}/
├── SKILL.md                          # 技能入口概览
├── scripts/
│   └── mcp_client.py                 # 自动生成的 Python MCP 客户端
└── references/operations/├── {tool-name-1}.md              # 工具 1 详情├── {tool-name-2}.md              # 工具 2 详情└── ...

6 种使用模式

# 模式 命令/参数 适用场景
1 基础模式 mcp2skill --url <SSE_URL> 最简单,自动发现所有工具
2 过滤模式 mcp2skill --url <URL> --include "send,create" --exclude "delete" 只想暴露部分工具给 Agent
3 认证模式 mcp2skill --url <URL> --auth-header "Bearer xxx" MCP Server 需要认证
4 自定义输出 mcp2skill --url <URL> --output ./skills/github 指定输出目录
5 重命名 mcp2skill --url <URL> --skill-name "github-tools" 自定义 Skill 名称
6 批量转换 mcp2skill --config config.yaml 批量处理多个 MCP Server

💡 过滤模式是最常用的:你不需要把所有 GitHub MCP 工具都给 Agent——"delete_repo" 这种危险工具应该在 Skill 创建时就排除,而不是等 Agent 调用了再拦截。

converter.go 核心逻辑(教学重建版)

// 教学重建版(真实实现:pkg/mcp2skill/converter.go)
type Converter struct {input      string               // MCP Server SSE URLoutputDir  string               // 输出目录skillName  string               // Skill 名称includes   []string             // 白名单excludes   []string             // 黑名单authHeader string               // 认证头
}func (c *Converter) Convert(ctx context.Context) error {// Step 1: 连接 MCP Server,调用 list_tools()client := mcp.NewClient(c.input)tools, err := client.ListTools(ctx)if err != nil {return fmt.Errorf("list tools: %w", err)}// Step 2: 过滤工具tools = c.filterTools(tools)// 按 annotations 分组:readOnly / destructive / idempotenttools = c.groupByAnnotation(tools)// Step 3: 生成 SKILL.md(概览文件)c.generateSkillMD(tools)// Step 4: 生成 mcp_client.py(Python MCP 客户端)c.generatePythonClient(tools)// Step 5: 为每个工具生成独立 .md 文件for _, tool := range tools {c.generateToolMD(tool)}return nil
}

生成的 SKILL.md 示例

# GitHub Tools一个通过 Model Context Protocol (MCP) 连接 GitHub API 的技能。## 可用工具| 工具名 | 说明 | 类型 |
|--------|------|------|
| search_issues | 搜索 Issues | readOnly |
| create_issue | 创建新 Issue | destructive |
| list_repos | 列出仓库列表 | readOnly |
| get_pull_request | 获取 PR 详情 | readOnly |
| create_pr_comment | 在 PR 上添加评论 | destructive |## 使用说明本技能连接 GitHub API v3。所有操作基于当前认证账号的权限范围。详细工具文档见 `references/operations/`。

生成的工具详情文件示例(references/operations/search_issues.md)

# search_issues在 GitHub 仓库中搜索 Issues。## 参数
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `query` | string | 是 | 搜索关键词,支持 GitHub 搜索语法 |
| `repo` | string | 是 | 仓库名(格式:owner/name) |
| `state` | string | 否 | 状态:open/closed/all,默认 open |
| `labels` | string[] | 否 | 按标签过滤 |## 返回
- 匹配的 Issue 列表(标题、编号、状态、创建者、URL)## 示例
```json
{"tool": "search_issues", "params": {"query": "bug", "repo": "myorg/myrepo", "state": "open"}}
#### auth.go:URL Key 脱敏```go
// 教学重建版(真实实现:pkg/mcp2skill/auth.go)
// 如果 MCP Server URL 含 API Key,自动脱敏
// 例如: https://api.github.com?key=ghp_xxxx  →  https://api.github.com?key=***
func sanitizeURL(rawURL string) string {u, _ := url.Parse(rawURL)q := u.Query()for k := range q {if strings.Contains(strings.ToLower(k), "key") ||strings.Contains(strings.ToLower(k), "token") ||strings.Contains(strings.ToLower(k), "secret") {q.Set(k, "***")}}u.RawQuery = q.Encode()return u.String()
}

3.2 openapi2skill:OpenAPI → Skill 转换

处理的是 REST API(有 OpenAPI 文档),输出结构更丰富。

目录结构

pkg/openapi2skill/
├── cmd/               # CLI 入口
├── README.md          # 详细文档
└── (转换逻辑)# 生成的 Skill 目录:
{outputDir}/{skillName}/
├── SKILL.md                          # API 入口概览
└── references/├── resources/                    # 按资源分组的操作索引│   ├── users.md                  # 用户资源的所有操作│   ├── orders.md                 # 订单资源的所有操作│   └── ...├── operations/                   # 每个操作一个详情文件│   ├── users.list.md│   ├── users.create.md│   └── ...├── schemas/                      # 按命名前缀分组的 Schema│   ├── user.md                   # User 类型的 Schema 展开│   ├── order.md                  # Order 类型的 Schema 展开│   └── ...└── authentication.md             # 认证方案文档

分组策略

openapi2skill 的分组比 mcp2skill 更精细——因为 API 的端点数量可能很大:

OpenAPI Spec│├─ 按 resource 分(/users → user resource)│   ├─ 按 operation 分(list/create/get/update/delete)│   └─ 同 resource 的相关 schema 放一起│├─ 按 schema 分(命名前缀相同的放一起)│   └─ User / UserCreate / UserUpdate → user schema 组│└─ 认证信息单独提取

Schema 策略

OpenAPI spec 中的嵌套 schema 对 LLM 来说是灾难——User { address: { street, city, zip }, orders: [{ id, items: [{ sku, qty }] }] } 展开后极长。openapi2skill 的做法:

  1. 按命名前缀分组User/UserCreate/UserUpdateuser.md
  2. 展开第一层引用:展开直接引用($ref: '#/components/schemas/User'
  3. 深度引用留链接:第三层以上的嵌套不展开,留链接"详见 orders.md"
  4. 去重:同一 schema 被多个端点引用时只在 schemas/ 出现一次

3.3 工具注解类型(DeepWiki 揭示)

MCP 协议定义了四种工具注解,mcp2skill 在生成 Skill 时利用它们做分组:

注解 含义 分组行为
readOnlyHint 只读操作 安全工具,默认全部包含
destructiveHint 破坏性操作(删除/修改) 高危工具,生成警告标注
idempotentHint 幂等操作(可安全重试) 标注"失败可重试"
openWorldHint 开放世界操作 标注"结果可能不完整"

💡 这四种注解是 MCP 协议的一部分。但不是所有 MCP Server 都正确设置了。mcp2skill 在生成 Skill 时会检查——如果 tools 缺少注解,会在 SKILL.md 标注"⚠️ 工具未声明安全级别,请手动审查"。

3.4 MCP Square:前端集成

转换只是第一步。万悟的 MCP 能力还通过前端市场(MCP Square)展示:

web/src/views/mcpManagementPublic/
├── square.vue          # MCP 工具市场——浏览、搜索、安装
├── detail.vue          # MCP Server 详情页(工具列表 + 参数 + 描述)
└── sendDialog.vue      # 测试工具调用

MCP Square 让非开发者也能发现和安装 MCP 工具——搜索一个工具(如"发邮件"),点"安装",mcp2skill 在后台自动生成 Skill,Agent 立即可用。


四、动手实操

1. 用 mcp2skill 转换一个 GitHub MCP 工具

# 假设你有一个 GitHub MCP Server 跑在本地
mcp2skill convert \--url http://localhost:8080/sse \--skill-name "github-tools" \--include "search_issues,create_issue,list_repos,get_pr" \--exclude "delete_repo,delete_branch" \--output ./skills/

观察生成的 Skill 结构:

ls -R ./skills/github-tools/
# SKILL.md                      ← 概览
# scripts/mcp_client.py         ← Python 客户端
# references/operations/        ← 每个工具一个文件

2. 用 openapi2skill 转换一个 REST API

openapi2skill convert \--spec https://api.example.com/openapi.json \--skill-name "example-api" \--resource-filter "users,orders" \--auth-header "Bearer xxx" \--output ./skills/

3. 验证渐进式披露的效果

对比两种方式的 token 消耗:

  • 方式 A:把原始 OpenAPI spec 的全部端点描述塞入 System Prompt
  • 方式 B:用 Skill(先加载 SKILL.md,按需加载 operations/)

方式 B 在工具数 > 10 时通常节省 70%+ token。


五、Mini 版 / 踩坑录

Mini 版:简易 MCP 客户端(~30 行 Python)

# 教学重建版——连接 MCP Server 并列出工具
import json, requestsclass MCPClient:def __init__(self, url: str):self.url = urlself.req_id = 0def _call(self, method: str, params: dict = None) -> dict:self.req_id += 1payload = {"jsonrpc": "2.0","id": self.req_id,"method": method,"params": params or {}}resp = requests.post(self.url, json=payload)return resp.json()def list_tools(self) -> list:result = self._call("tools/list")return result.get("result", {}).get("tools", [])def call_tool(self, name: str, arguments: dict) -> dict:return self._call("tools/call", {"name": name,"arguments": arguments})# 使用
client = MCPClient("http://localhost:8080/sse")
tools = client.list_tools()
for t in tools:print(f"{t['name']}: {t['description']}")

踩坑录

踩坑 现象 原因 解法
工具名冲突 两个 MCP Server 的 search 重名 mcp2skill 默认用工具原名 --prefix 参数加前缀
Schema 展开过长 openapi2skill 生成的文件几百 KB 嵌套 schema 全展开了 限制展开深度=2
SSE 连接超时 mcp2skill 调用 list_tools 超时 MCP Server 响应慢 --timeout 参数
认证信息泄露 生成的 SKILL.md 里含 API Key auth.go 没拦截自定义 header --sanitize 强制脱敏

六、总结 & 延伸阅读

⏱️ 30 秒速览

这篇你只需要记住 3 件事:

  1. 万悟特色是 MCP→Skill 和 OpenAPI→Skill 自动转换(pkg/mcp2skill、pkg/openapi2skill)
  2. 转换 = 协议适配 + 工具 Schema 生成 + 运行时注入,第三方 API 秒变 Agent 工具
  3. 两个 MCP 库:ThinkInAIXYZ/go-mcp + mark3labs/mcp-go

想深挖?

  • 转换引擎实现:§2 核心概念;完整转换器见 GitHub pkg/mcp2skillpkg/openapi2skill

本文要点回顾

  1. ✅ mcp2skill 把 MCP 工具转为结构化 Skill——SKILL.md 概览 + 每个工具一个独立 .md 文件
  2. ✅ 6 种使用模式覆盖:基础/过滤/认证/自定义输出/重命名/批量——过滤模式最常用
  3. ✅ openapi2skill 处理 REST API,按 resource/operation/schema 三级分组
  4. 渐进式披露:概览 → 按需搜索 → 具体工具文档,节省 70-90% token
  5. ✅ MCP 工具的 4 种注解(readOnly/destructive/idempotent/openWorld)用于安全分组
  6. ✅ MCP Square 前端市场让非开发者也能发现和安装工具——搜索→安装→Agent 立即可用

架构决策回顾

决策 选了 理由
输出格式 Markdown Skill LLM 最擅长的格式,人类也可读
存储策略 独立文件 /references/operations/ 支持按需加载,不一次性塞给 LLM
Schema 深度 展开最多 2 层 平衡完整性和 token 消耗
工具过滤 include/exclude 白名单+黑名单 危险工具在 Skill 层就排除,不等 Agent 调用
URL 脱敏 自动检测 + 替换 *** 安全第一,默认行为

延伸阅读

  • 第一季 06「MCP 协议实战」—— MCP 协议基础(ListTools/CallTool/JSON-RPC)
  • 第一季 05「Agent 推理引擎」—— Agent 如何使用 Skill 中的工具
  • pkg/mcp2skill/README.md —— 万悟仓库中 mcp2skill 的完整文档(非常详尽)
  • pkg/openapi2skill/README.md —— openapi2skill 的完整文档
  • Model Context Protocol —— MCP 官方规范

📱 关注公众号,追更不迷路

本系列文章首发于微信公众号「农夫三拳有点癫」,每周更新源码拆解与架构实战。

在微信扫描下方二维码即可关注:

账号二维码

http://www.jsqmd.com/news/1387558/

相关文章:

  • 如何用Scrapling实现智能网页抓取:新手完整指南与实战技巧
  • 欧富洛家具|藏于宋式风骨,栖于自然风雅 - 优选案例分享
  • 2026年临沂蒙阴县保暖服饰源头工厂靠谱推荐:马员外服饰全产业链实力解析 - 科技快讯
  • 远程会议录音转写怎么选?自测5款高口碑会议记录工具对比
  • 1分钟语音克隆:GPT-SoVITS零基础入门完整指南
  • DeepSeek V4 Pro 正式版深夜突袭:0.1分差距,60倍价差,AI价格战打到新高度
  • FDE 接手一个 AI 项目后,先看哪五类现场信息
  • 2026武汉汉阳区楼顶漏水避坑指南,本地老牌公司,质保可查 - 企业资讯
  • 如何快速掌握AI视频生成:开源工具的完整指南
  • CAD2020自学教程:从安装到精通的112课完整学习路径
  • Vue 3 集成 intro.js 实现新手引导:从原理到最佳实践
  • 2026青岛市南区楼顶漏水避坑指南,本地老牌公司,质保可查 - 企业资讯
  • 2026年临沂蒙阴县保暖服饰源头工厂靠谱推荐:马员外服饰全产业链实力解析 - 子柔传媒
  • AI模型稳定性监控:PSI指标原理、计算与业务应用全解析
  • 计算机专业现状分析:从劝退现象看行业挑战与个人应对策略
  • 163MusicLyrics:你的音乐库歌词缺失问题的终极解决方案
  • Embabel Agent:终极JVM智能体流程编排框架完整指南
  • Thorsten-Voice情感语音合成指南:8种情绪效果实战演示
  • OM-036 台式频谱分析仪在煤矿能源电磁信号监测中的应用探究
  • Ring编程语言完全指南:如何用多范式语言快速开发跨平台应用
  • 开源Agent可视化引擎:基于DAG实现AI智能体全链路可观测性
  • AI技能管理与上下文优化:提升模型响应质量与成本效益
  • 深度复盘:从零开始的电子商务网站建设实训过程全流程解析与避坑指南
  • Macro:一体化工作空间革新办公,多模块协同提升团队效率!
  • 2026青岛市北区楼顶漏水避坑指南,本地老牌公司,质保可查 - 企业资讯
  • Krokiet:终极跨平台重复文件清理工具,快速释放硬盘空间
  • 2026济南章丘区楼顶漏水避坑指南,本地老牌公司,质保可查 - 企业资讯
  • iOS系统个性化定制:Cowabunga工具箱与MacDirtyCow漏洞原理详解
  • 东南亚知识产权问题律所怎么选?中国企业出海法律服务指南 - 产品推荐官
  • Blazor国际化与本地化:csharp_with_csharpfritz多语言应用解决方案