
最近很多做 AI Agent 的同学都在讨论一个话题Skills和MCP到底有什么区别什么时候该用Skills什么时候该接MCP社区里相关的帖子非常多但大部分介绍都比较零散。有些朋友甚至产生了一个错觉觉得“MCP 是标准协议Skills 只是临时方案”其实不是这么回事。本文想从概念、机制、适用场景、代码示例和工程实践几个角度把Skills和MCP完整对比一遍。无论你是在做 Claude Code 插件开发、Dify 工作流编排还是在设计企业级 Agent 平台这篇文章都值得收藏备用。1. 背景与核心概念1.1 AI Agent 的“技能扩展”需求从哪里来我们先从一个很常见的场景说起。假设你正在用一个大模型开发一个客服机器人。模型本身懂自然语言但它不知道你公司内部的订单数据存在哪张表里也不知道怎么调用你们现有的库存接口。为了让模型完成这些具体任务你通常需要给模型“加装”一些能力比如读取数据库中的订单记录调用公司内部的 REST API查询某个 Excel 文件中的产品信息操作浏览器完成自动化测试生成一份格式固定的 PDF 报表。这些能力本质上就是 AI Agent 的外挂模块。问题在于这些模块怎么编写怎么被模型发现怎么被模型调用不同厂商、不同框架给出的答案并不统一于是就有了Skills和MCP这两类主流方案。1.2 什么是 SkillsSkills从字面上理解就是“技能”它的核心形式通常是一组描述性文件 可执行脚本或提示词组合。在 Claude Code 等工具中一个 Skill 通常由一个SKILL.md文件来声明里面包含技能的用途说明触发条件需要执行的操作步骤依赖的外部命令或脚本使用示例。本质上Skills更偏向“把某类任务的完成方法打包给 Agent”让 Agent 在需要的时候读取这段说明然后按照步骤去执行。以 Claude Code Skills 为例它的典型目录结构如下skills/ pdf-report/ SKILL.md generate_report.py templates/ report_template.html当 Agent 在处理“生成 PDF 报表”这类任务时会读取SKILL.md知道应该调用generate_report.py并用templates目录下的模板来完成输出。1.3 什么是 MCPMCP全称是Model Context Protocol即“模型上下文协议”。它由 Anthropic 提出并开源目标是标准化 AI 应用与外部数据源、工具之间的连接方式。你可以把 MCP 理解成“AI 世界的 USB 接口”。设备厂商不需要为每一台电脑单独定制接口只需要按照 USB 标准生产设备电脑就能即插即用。MCP 做的事情类似工具提供方按照 MCP 协议实现一个 ServerAI 应用作为 MCP Client 连接这个 Server双方通过统一的 JSON-RPC 格式通信。一个 MCP 架构通常包含三个角色角色说明示例MCP Host用户使用的 AI 应用Claude Desktop、Dify、Cursor 等MCP ClientHost 内部与 Server 建立会话的组件负责发送请求、接收结果MCP Server暴露工具、数据能力的独立服务数据库 MCP、Playwright MCP、支付宝 MCP 等1.4 两者的核心差异简单总结Skills和MCP的目标都是“增强 Agent 能力”但侧重点不同。Skills强调的是“给 Agent 一份操作手册”它的输入是文本指令输出是让 Agent 自己按步骤完成任务MCP强调的是“给 Agent 一个标准接口”它的输入是结构化调用请求输出是工具执行结果。换句话说Skills更适合封装“过程性知识”MCP更适合暴露“原子能力”。2. 环境准备与版本说明2.1 本文示例环境由于 AI Agent 工具链迭代非常快不同版本的依赖和配置可能存在差异。本文的示例以当前主流环境为例重点演示思路并不代表所有版本完全一致。操作系统macOS / Linux / WindowsWSL2 均可 运行时Node.js 18 / Python 3.10 AI 工具Claude Code / Dify / Codex CLI / Cursor 等 MCP SDKmodelcontextprotocol/sdk如果你的环境版本不同需要根据实际情况调整命令和配置。2.2 当前生态里的常见组合从最近社区的热门讨论来看大家常遇到这些组合场景常用方案Claude Code 内编写技能Claude Code SkillsCodex CLI 扩展能力Codex SkillsDify 中接入本地工具Dify 本地 MCP 服务浏览器自动化测试Playwright MCP数据库直接查询Workbuddy / 自定义 MCP Server前端设计稿转代码Figma MCP、蓝湖 MCP可以看到Skills更多出现在“代码编辑器/CLI Agent”场景MCP则更多出现在“平台化、产品化”场景。3. 核心机制拆解3.1 Skills 的工作机制一个 Skill 要生效通常要经历三个阶段。第一阶段发现Agent 在启动时会扫描配置的 Skills 目录读取每个 Skill 的元信息比如名称、描述、适用任务类型。这个过程类似于搜索引擎建立索引目的是让 Agent 知道“我有哪些技能可用”。第二阶段选择当用户提出一个任务时Agent 会根据任务描述匹配最合适的 Skill。匹配依据通常是SKILL.md中的描述信息。如果描述写得模糊Agent 可能选错 Skill所以“写清楚触发条件”非常重要。第三阶段执行Agent 读取 Skill 文件中的详细步骤逐步执行。这里的“执行”并不一定是调代码也可能是一系列提示词引导让 Agent 按特定思维方式完成分析。下面是一个典型SKILL.md的内容示例--- name: excel-data-analysis description: 用于处理 Excel 数据的分析与统计适合读取 xlsx 文件、计算汇总指标、生成图表。 triggers: - 分析 Excel - 统计表格数据 - 读取 xlsx --- # Excel 数据分析技能 ## 步骤 1. 使用 pandas 读取 Excel 文件。 2. 查看数据列名和缺失值。 3. 根据用户需求计算汇总统计量。 4. 如果用户需要图表使用 matplotlib 生成图片。 ## 示例 输入分析销售表 输出读取 sales.xlsx返回总销售额和 top 5 商品。这种设计的好处是不需要提前启动任何服务Agent 读取文本即可完成动态决策。坏处是没有校验机制Skill 内的脚本如果写错Agent 不一定能及时发现。3.2 MCP 的工作机制MCP 采用客户端-服务器模式。通信过程遵循 JSON-RPC 2.0 规范以下是简化版的交互流程初始化Client 向 Server 发送initialize请求协商协议版本和能力工具列表获取Client 调用tools/list获取 Server 提供的工具清单工具调用Client 根据用户意图调用tools/call传入工具名和参数结果返回Server 执行完操作后把结果返回给 Client。一个最简单的 MCP Server 示例Node.js 版如下import { McpServer } from modelcontextprotocol/sdk/server/mcp.js; import { StdioServerTransport } from modelcontextprotocol/sdk/server/stdio.js; const server new McpServer({ name: demo-server, version: 1.0.0 }); server.tool( get_time, 获取当前服务器时间, async () { const now new Date().toISOString(); return { content: [{ type: text, text: 当前时间${now} }] }; } ); const transport new StdioServerTransport(); await server.connect(transport);启动之后AI 应用可以通过 stdio 或 SSE 方式连接这个 Server把get_time暴露给模型调用。MCP 的最大价值在于它定义了一套标准协议工具开发一次可以在多个 Agent 平台复用。比如你写了一个“查询 MySQL 数据库”的 MCP Server那么 Claude Desktop、Dify、Cursor 都可以连接它。但 MCP 也有学习成本。你需要理解协议、初始化握手、工具定义格式、错误处理等概念而且调试 MCP 连接比调试普通脚本要复杂。3.3 什么时候优先选择 Skills根据实践经验以下场景选择 Skills 更合适第一任务是“过程型”而不是“接口型”。比如你想让 Agent 按照一套固定的步骤做数据分析读取文件、清洗数据、计算指标、输出报告。这个流程涉及多个环节每个环节的输入输出并不严格。用 Skill 把整个流程写清楚Agent 可以灵活执行。第二你希望扩展包只需一个文件夹。Skills 可以直接放到 Git 仓库里团队成员拉下来就能用。不需要启动额外进程不依赖运行时版本。第三任务本身并不需要“实时数据”。如果 Agent 只需要根据文本描述生成代码、解释概念、编写文档那 Skills 完全够用。你不需要为了一个离线任务专门起一个 MCP Server。3.4 什么时候优先选择 MCP反过来下面几种场景优先选择 MCP第一需要访问实时业务数据。比如客服 Agent 需要实时查询订单状态。这类场景需要稳定的接口调用而不是让模型“读取说明然后猜测”。通过 MCP Server 把查询逻辑封装起来可以保证每次返回的都是真实数据。第二同一个工具需要被多个平台复用。假设你开发了一个“SSH 远程执行命令”工具。如果写成 Skill它可能只适用于某一个 Agent 平台如果写成 MCP Server则所有支持 MCP 的客户端都能连接。第三需要更严格的权限和审计。MCP Server 作为独立服务可以在服务层做身份认证、操作日志、限流控制。这是纯文本 Skill 无法做到的。4. 实战案例4.1 用 Skills 实现一个自动周报生成 Agent首先我们创建一个 Skills 目录编写一个周报技能。skills/ weekly-report/ SKILL.md generate_report.pySKILL.md的内容如下--- name: weekly-report description: 根据本周工作记录生成结构化周报适合项目周会前使用。 triggers: - 生成周报 - 写周报 - weekly report --- # 周报生成技能 ## 输入要求 用户需要提供本周完成事项列表可以是文本或 Markdown 列表。 ## 执行步骤 1. 解析用户提供的工作记录。 2. 按模块归类需求开发、Bug 修复、技术调研、团队协作。 3. 使用 generate_report.py 生成 Markdown 周报。 4. 输出周报到终端方便用户复制粘贴。 ## 输出格式 ## 本周工作 ### 需求开发 - 事项 1 - 事项 2 ### Bug 修复 - 事项 1 ## 下周计划 - 待用户补充generate_report.py的简化实现如下import sys def generate_weekly_report(work_items: list[str]) - str: categories { 需求开发: [], Bug 修复: [], 技术调研: [], 团队协作: [], } for item in work_items: if 修复 in item or bug in item.lower(): categories[Bug 修复].append(item) elif 调研 in item or 学习 in item: categories[技术调研].append(item) elif 会议 in item or 评审 in item: categories[团队协作].append(item) else: categories[需求开发].append(item) lines [## 本周工作] for category, items in categories.items(): if items: lines.append(f### {category}) for it in items: lines.append(f- {it}) lines.append(\n## 下周计划) lines.append(- 待补充) return \n.join(lines) if __name__ __main__: items sys.argv[1:] print(generate_weekly_report(items))这个案例展示的是“过程性知识”的封装。Agent 只需读取 Skill 说明就能决定什么时候运行脚本、如何组织输出。4.2 用 MCP 接入数据库查询能力现在我们换一个思路使用 MCP Server 暴露一个订单查询工具。完整示例使用 Python 编写from mcp.server.fastmcp import FastMCP import sqlite3 mcp FastMCP(order-server) mcp.tool() def query_order(order_id: str) - str: 根据订单ID查询订单信息 conn sqlite3.connect(orders.db) cur conn.cursor() cur.execute(SELECT id, customer, amount, status FROM orders WHERE id ?, (order_id,)) row cur.fetchone() conn.close() if row: return f订单 {row[0]}客户 {row[1]}金额 {row[2]}状态 {row[3]} return 未找到订单 if __name__ __main__: mcp.run(transportstdio)对应 Dify 中配置本地 MCP 服务时你需要填写服务类型stdio 命令python 参数order_server.py启动成功后Dify 会自动获取query_order这个工具Agent 就能在对话中直接调用它查询订单。注意到这里的关键区别了吗MCP 把“查询订单”变成了一个稳定的工具接口任何支持 MCP 的客户端都可以调用不需要关心底层是 SQLite、MySQL 还是 HTTP API。4.3 在 Claude Code 中同时使用 Skills 和 MCP实际项目中两者常常是组合使用的而不是二选一。例如你可以在 Claude Code 的项目配置里同时声明 Skills 目录和 MCP Server{ skills: { weekly-report: ./skills/weekly-report, excel-analysis: ./skills/excel-analysis }, mcpServers: { order-db: { command: python, args: [mcp_servers/order_server.py] }, playwright: { command: npx, args: [playwright/mcplatest] } } }这样做的好处是过程型、诊断型任务交给 Skills让 Agent 自主规划步骤原子型、实时型任务交给 MCP保证数据准确性和接口稳定性两种能力互相补充Agent 可以先通过 Skill 得到操作路径再通过 MCP 调用具体工具。5. 常见问题与排查思路在实际使用中大家经常会遇到下面这些问题。问题现象常见原因解决思路MCP Server 连接失败协议版本不匹配或 transport 配置错误检查 MCP SDK 版本确认使用 stdio 还是 SSE查看服务端日志Skills 未被模型调用SKILL.md 描述不清晰重写 description 和 triggers加入典型用户问法上下文过大导致 MCP 工具失效对话历史过长模型无法关注到工具结果启用会话自动归档精简上下文或把工具结果写入外部存储Agent 调用 Skills 后报权限错误脚本没有可执行权限或依赖缺失本地运行chmod x检查依赖包是否安装Dify 中添加本地 MCP 后看不到工具未正确刷新工具列表在 Dify 中重新连接 MCP 服务或重启 Dify 并确认服务端口可访问MCP Server 启动后进程退出stdio transport 下运行模式错误确认是否通过命令行启动脚本而不是直接双击运行6. 最佳实践与工程建议6.1 明确边界Skills 管流程MCP 管能力工程上最忌讳的是把两种方案混着用导致代码结构混乱。建议团队内部形成一条共识如果你要封装“怎么做”写成 Skill如果你要封装“能做什么”写成 MCP Server。例如“如何生成一份符合公司模板的项目总结” → Skill“获取某个订单的物流轨迹” → MCP Tool6.2 为 Skills 建立规范仓库Skills 可能很快变多建议统一维护。目录结构可以这样规划skills-repo/ skills/ frontend-develop/ >