MCP与Skills的辨析

MCP与Skills的辨析

Anthropic公司先推出了MCP协议,希望统一LLM与外部服务商通讯的方式;在一年后又推出claude skills功能,让claude code执行时拥有多种外挂载能力。

Claude 的各种应用(desktop、code cli、claude.ai 等)现在可以使用 "Skills" 来改进其执行特定任务的方式。"Skills"是包含指令、脚本和资源的文件夹,Claude 应用可以根据需要加载这些文件夹。

Claude 应用只会在 Skill 与当前任务相关时才会使用该 Skill。使用 Skill 后,克劳德可以更高效地完成特定任务,例如使用 Excel 或操作 pdf。

在执行任务时,Claude 应用会扫描可用 Skill 以查找相关匹配项。找到匹配项后,它只会加载所需的最少信息和文件------既保证了 Claude 的运行速度,又能让他快速获取专业知识。

mcp与skills的作用都是扩展外部能力,功能特点又近似,莫非Anthropic内部也在赛马?(/笑哭)

MCP

MCP已经是很广为人知的概念了,通过标准的通讯协议规定Agent与外部服务的通讯结构后,Agent可以构造参数请求服务端,得到结果并结合分析。过程:

  • 架构: Agent = LLM + MCP客户端 + 状态管理。
  • 远端服务需要支持MCP服务调用,可以手动支持或者在网关层面支持。
  • Agent在初始化MCP客户端时,通过调用服务端的tool_list接口得到服务列表信息,比如服务名称、作用、请求参数等
  • Agent收到客户的调用后,在请求参数中设置tools列表,由LLM的响应决定是否调用tool
  • 如果LLM判断需要调用tools,则Agent通过遍历响应结构的tools_call字段,解析调用参数与服务名称,通过mcp客户端调用mcp服务端。
  • Agent拿到mcp服务端的结果之后,填充到与LLM对话的上下文列表中,最终再发起一次相当于总结的LLM调用,包含了原始的问题与MCP工具执行结果,调用LLM后的响应作为最终的执行结果返回给用户

以上就是MCP调用的过程,实际通讯可以通过网络(streamable http)或者本地进程间通讯stdio,让Agent具有外部工具执行的能力。

Skills

claude skills一开始是在claude code中使用,可以在对话框中通过"."的方式选择skills执行,借此完成context engine(上下文工程,是一种优化普通Prompt工程的手段,引入更多专业知识与上下文,用来提升LLM输出结果的质量,实践:github.com/coleam00/co...) 。

skills本质上是一个文件夹,其中存放了markdown格式的Prompt、相关背景资料比如PDF、Excel、可执行的代码与模板、甚至可以放应用程序。

那么claude code是如何使用这些skills的呢?Claude 官方对 SKILL 的规范描述比较清楚,但是对于 LLM 怎么使用 SKILLs 并没有一个详细的描述。网络上的文章也都只是在介绍Skills如何使用而已,国内鸟窝大佬拆解了相关功能,得到一种实践方式: github.com/smallnest/g...

  • skills解析,通过规范skills中的md文件或者直接调用LLM解析,得到skills的信息------名称、作用等,将文件夹中的内容构造为内存中的skills对象
  • 用户在对话框输入问题并指定skills时,与MCP过程类似,程序会将skills对象转化为tool,初始调用一次让LLM决定是否调用tool,这个过程是skills选择阶段
  • 如果LLM决定调用tool,会返回tools_call字段,程序还是迭代这个字段来选择工具执行。比如,选择的skill包含python代码,程序需要通过cmd命令调用当前系统环境的python执行并得到结果,也就意味着这个skills的映射需要提前写入代码中,不过如果是编程能力较强的LLM,完全可以做到自己判断代码风险与实时生成shell来执行。
  • skills执行完毕后,得到的结果也是加入对话上下文中,传递给LLM得到最终的结果并返回给用户。

上述过程完全都是本地调用,依赖于本地系统环境------跨机器调度就会比较复杂。整体过程与MCP类似,都是通过tools让LLM选择工具、通过tools_call控制执行工具,区别是MCP规范了外部调用而skills更强调程序内部的扩展能力。

重点介绍goskills

更直观的skill的使用,可以参考go实现LLM使用skills的项目:github.com/smallnest/g...

这个项目提供了一个命令行工具,可以通过传递skills与提问内容,自动解析skills与自动调用得到结果。使用起来很简单,类似于:./goskills run --auto-approve --model deepseek-v3 --api-base qianfan.baidubce.com/v2 "使用markitdown 工具解析网页 baike.baidu.com/item/%E5%AD....

具体的实践文章:mp.weixin.qq.com/s/W1DjPNWjk...

工具提供了skill发现与管理、skill执行、会话管理等功能。可以通过brew安装,到通用的skills仓库中下载想要的skills,再配置好LLM的api_key之后,就可以直接使用。

perl 复制代码
goskills run --auto-approve --model deepseek-v3 --api-base https://qianfan.baidubce.com/v2 --skills-dir=~/.claude/skills "使用markitdown 工具解析网页 https://baike.baidu.com/item/%E5%AD%94%E5%AD%90/1584"

Go:

go 复制代码
package main

import (
 "fmt"
 "os"
 "os/exec"
 "path/filepath"
)

func main() {
 prompt := "使用markitdown 工具解析网页 https://baike.baidu.com/item/%E5%AD%94%E5%AD%90/1584"

 // 获取用户主目录
 homeDir, err := os.UserHomeDir()
 if err != nil {
  fmt.Printf("无法获取主目录: %v\n", err)
  return
 }
 // 构建技能目录的完整路径
 skillsDirPath := filepath.Join(homeDir, ".claude", "skills")
 skillsDirArg := "--skills-dir=" + skillsDirPath

 cmd := exec.Command("goskills", "run",
  "--auto-approve",
  "--model", "deepseek-v3",
  "--api-base", "https://qianfan.baidubce.com/v2",
  skillsDirArg, // 使用构建的路径参数
  prompt)

 // CombinedOutput 运行命令并返回其组合的标准输出和标准错误
 output, err := cmd.CombinedOutput()
 if err != nil {
  fmt.Printf("执行命令时出错: %v\n", err)
  fmt.Printf("输出:\n%s\n", string(output))
  return
 }

 fmt.Printf("命令输出:\n%s\n", string(output))
}

辨析

同样是为了提供外部扩展的能力,除了MCP与Skills,似乎也可以通过API网关插件做到这些功能,到底有何区别?为什么有了MCP还要出现Skills?

殊途同归,假设要提供外部搜索能力,实现思路:

  • 思路1:定义一个搜索功能的MCP,让Agent调用MCP服务得到结果;
  • 思路2:也可以基于搜索引擎实现搜索功能,挂载在API网关中,请求达到时检查意图,调用搜索模块,得到搜索结构并附加到提示词中;
  • 思路3:定义一个搜索功能的skills------比如python代码,程序选择skills并调用本地执行,得到结果

核心在于选择,就像选择技术栈一样,某些特点就决定了整体的基础设施。

不管mcp与skills是赛马的结果,还是大方向演进下的细节填充,在应用层面上,skills属于内聚的存在------整体比较简单;而MCP是属于外部的存在------整体比较规范且复杂。这可以类比于高射机枪与高射炮面向的不同的场景,高射机枪的核心优势在于其轻便性、机动性和成本效益,而高射炮则更专注于构建中低空防空屏障。skills强调轻量快捷,与本地耦合;MCP强调解耦,更加全面。

总而言之,

  • 如果在构建一个外部扩展服务,可以先写成skills,逐步验证需求,等到探索完毕且流量压力升高时,再更换为标准MCP服务。
  • 如果外部功能属于临时且通用性不高,首选了skills。skills适合单体架构。
  • skills的生态目前不如mcp生态,选择的时候需要自己适配。
相关推荐
a程序小傲9 分钟前
京东Java面试被问:Fork/Join框架的使用场景
java·开发语言·后端·postgresql·面试·职场和发展
想用offer打牌12 分钟前
面试官问Redis主从延迟导致脏数据读怎么解决?
redis·后端·面试
appearappear1 小时前
Mac 上重新安装了Cursor 2.2.30,重新配置 springboot 过程记录
java·spring boot·后端
谷哥的小弟1 小时前
Spring Framework源码解析——RequestContext
java·后端·spring·框架·源码
IT_陈寒1 小时前
Vite 5大优化技巧:让你的构建速度飙升50%,开发者都在偷偷用!
前端·人工智能·后端
鹿角片ljp2 小时前
Spring Boot Web入门:从零开始构建web程序
前端·spring boot·后端
程序员阿鹏2 小时前
SpringBoot自动装配原理
java·开发语言·spring boot·后端·spring·tomcat·maven
程序员爱钓鱼2 小时前
Node.js 编程实战:CSV&JSON &Excel 数据处理
前端·后端·node.js
老华带你飞2 小时前
工会管理|基于springboot 工会管理系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·后端·spring
Echo flower2 小时前
Spring Boot WebFlux 实现流式数据传输与断点续传
java·spring boot·后端