从“只会聊天”到“真正干活”,这是每个AI Agent使用者都会遇到的坎。
很多人在试用Agent之后会有一个共同困惑:模型本身的智商不差,写代码、写文案、做分析都能聊得头头是道,但要让它“真的动手干活”就立刻露馅——让它查数据库,它说没有访问权限;让它操作设计工具,它说无法调用外部软件;让它按照一套固定的规范执行任务,它每次都要你把规则重新讲一遍。
问题不在于大模型,而在于Agent缺了两样东西:连接外部工具的能力,和固化工作流程的能力。
前者叫MCP,后者叫Skill。这篇文章的选题在技术社区里非常热门,很多人已经在B站、公众号、技术博客里见过这两个词,但真正能说清楚“MCP解决什么问题、Skill解决什么问题、两者怎么配合、实际项目里怎么落地”的内容仍然稀缺。多数教程只讲概念,不讲场景;只给一个Demo,不给全链路实践。
这篇文章的目标很明确:用一套完整的最小示例,带你从零理解MCP和Skill的原理,然后在本地跑通一个可扩展的Agent能力架构。读完你可以判断自己项目里该用MCP、该用Skill,还是两者结合,也能直接动手改造你自己的Agent。
1. AI Agent能力扩展到底扩展的是什么
先说一个容易踩的误区:很多人以为Agent能力扩展就是“给模型加提示词”。
实际上,Agent能力的核心是三个维度:
- 感知能力:Agent能否读取外部数据,比如数据库、文件、API返回结果。
- 行动能力:Agent能否调用外部工具,比如发送邮件、操作浏览器、执行命令行。
- 经验能力:Agent能否按照你沉淀的固定流程完成任务,而不是每次都重新推理一遍。
普通对话模型只具备“推理能力”,它可以在上下文中理解你给出的信息,但无法主动获取新信息,也无法对外部世界产生影响。
AI Agent的本质,是在模型外面包了一圈“能力层”。这个能力层负责接收模型发出的请求,转化成真实世界的操作,再把操作结果返回给模型,让模型继续决策。
问题就出在这一圈“能力层”上。
早期做法是每个项目自己写调用逻辑:调用数据库就写JDBC代码,调用浏览器就写Selenium脚本,调用设计软件就找对应SDK。结果是每个Agent项目都有一堆“手写工具”,零散、不可复用、换一个客户端就全部失效。
MCP和Skill的出现,就是为了解决这种碎片化问题,但它们的发力点不同:
- MCP解决“工具怎么被调用”的问题,它是一套标准化协议,让Agent可以统一连接外部数据源和工具,不用为每个工具单独写集成代码。
- Skill解决“任务怎么做”的问题,它是一套可复用的流程和知识封装,把某个特定任务的最佳实践、脚本、注意事项打包,让Agent一遇到同类任务就能按成熟流程执行。
用一句话概括:MCP管“连接”,Skill管“流程”。
这两者不是竞争关系,而是分工关系。MCP负责让Agent连接到数据库、设计软件、浏览器、业务系统;Skill负责在Agent连接好工具之后,告诉它“这个任务应该按什么步骤、用什么脚本、输出什么格式”。
这才是往“通用Agent”方向走的核心路径。
2. MCP与Skill核心概念深度解析
2.1 MCP:模型上下文协议
MCP全称Model Context Protocol,模型上下文协议。它是由Anthropic在2024年底提出并开源的一套开放协议,目的是标准化AI应用与外部数据源、工具之间的通信方式。
如果你理解了USB-C接口,就理解了MCP。
USB-C统一了充电口和数据口,让手机、电脑、显示器、扩展坞之间可以即插即用。MCP做的事情类似,它定义了AI应用(Host)如何连接外部能力(Server)。有了这个统一标准,开发者只需要把能力封装成MCP Server,任何支持MCP的客户端都能直接调用。
MCP架构里通常有三个角色:
| 角色 | 说明 | 类比 |
|---|---|---|
| MCP Host | 运行Agent和模型的客户端,比如Claude Desktop、Claude Code、Cursor | 电脑操作系统 |
| MCP Client | 客户端内部负责与Server建立连接的组件,一个Host可以连多个Client | 操作系统里的驱动框架 |
| MCP Server | 提供具体能力的服务,比如数据库服务、文件服务、外部API服务 | 外接设备 |
从通信层面看,MCP基于JSON-RPC 2.0协议,支持stdio和Streamable HTTP两种传输方式:
- stdio:Server作为客户端子进程运行,适合本地工具,启动快,数据不经过网络。
- HTTP/SSE:Server以远程服务方式运行,适合跨机器、多客户端共享能力。
MCP Server本质上是一个可以被Agent“发现”的工具集合。Server端会向客户端发送工具列表、工具描述、参数Schema;当Agent决定调用某个工具时,客户端把模型生成的参数传给Server,Server执行真实逻辑,返回结构化结果。
2.2 Skill:技能包
Skill这个概念在不同产品里有不同实现,但核心思想一致:把完成某个任务所需的指令、流程、脚本、示例、注意事项打包成一个可复用的“技能包”。
你可以把Skill理解为Agent岗位的“员工手册”。
一个新员工入职后,如果只有智商没有培训,他需要很长时间才能按公司规范完成任务。但如果有一份详细的手册,里面写着:接到这个任务后第一步做什么、用什么工具模板、遇到异常怎么处理、输出格式是什么,他就能快速上手。Skill就是给Agent用的“员工手册”。
以Claude Skills为例,一个Skill通常是一个带固定结构的目录:
skill-name/ ├── SKILL.md # 技能说明主文件 ├── scripts/ # 可执行脚本 ├── references/ # 参考资料、模板、示例子文件 └── assets/ # 其他静态资源SKILL.md文件里有技能的名称、描述、使用场景、执行步骤、注意事项、依赖环境等结构化信息。当Agent遇到的用户问题与Skill描述匹配时,系统会自动把对应Skill内容加载进上下文,Agent就“学会了”这个任务应该怎么做。
2.3 MCP和Skill的区别到底在哪里
先看对比表:
| 对比维度 | MCP | Skill |
|---|---|---|
| 解决核心问题 | 工具和数据的连接标准化 | 任务流程和知识的结构化封装 |
| 本质 | 一套通信协议/接口标准 | 一套提示词+脚本+资源的组合包 |
| 主要组成 | Server、Client、JSON-RPC、工具定义 | SKILL.md、脚本、参考文档 |
| 作用位置 | Agent的外部,连接真实世界 | Agent的上下文,指导行为方式 |
| 能否独立执行 | 不能,必须由Host调用 | 不能,必须由Agent加载后执行 |
| 典型场景 | 查询数据库、调API、操作浏览器 | 代码审查、数据处理、标准报告生成 |
| 有没有代码 | 必须有Server实现代码 | 可以有脚本,也可以纯文档 |
| 复用方式 | 跨客户端复用 | 跨任务复用 |
这里要强调一个关键判断:MCP和Skill不是二选一,而是上下游关系。
一个复杂任务往往需要两者配合。
以“数据库巡检”为例:Agent通过MCP Server连接数据库,获得执行SQL的能力;然后通过一个“数据库巡检Skill”学会巡检流程,包括先查慢查询日志、再查表空间占比、最后生成巡检报告。MCP提供“手”,Skill提供“操作手册”。
初学者最容易犯的错误是:把所有任务逻辑都塞进MCP工具,导致Server代码又长又难维护;或者把所有工具调用细节都写进Skill的提示词里,导致上下文窗口被占满、模型理解混乱。
正确的做法是:能用协议标准化的连接动作交给MCP,能用文档和脚本固化的经验流程交给Skill。
2.4 Computer Use、MCP、Skill三者关系
开发圈里还有一个高频搜索词是Computer Use。很多人把它和MCP放在一起比较,其实它们是不同层面的东西。
Computer Use是让AI像人一样操作电脑界面的能力,通过截图识别界面元素、模拟鼠标键盘操作来完成任务。它不依赖对方提供API,因为它是从“界面”层面操作。
MCP则是从“接口”层面连接能力,它要求对方提供符合协议的工具或数据服务。MCP调用更稳定、更可靠,因为它走的是结构化接口,不是视觉识别;Computer Use的优点是通用,缺点是慢、不稳定、容易被界面变化影响。
Skill在这两者之上,它决定“要不要用MCP、要不要用Computer Use、按照什么顺序用”。真正完整的Agent架构,是三者叠加:Skill负责流程编排,MCP负责调用结构化工具,Computer Use负责兜底处理没有接口的遗留系统。
3. 环境准备与前置条件
在开始动手之前,先确认你的环境具备哪些条件。
3.1 软件环境清单
本文的实践示例采用“通用工程思路”,不绑定某个特定商业产品。你只需要满足以下基础条件即可:
| 依赖 | 用途 | 版本建议 |
|---|---|---|
| Python 3.9+ | 编写MCP Server和Skill脚本 | 建议3.10及以上,版本以实际环境为准 |
| Node.js 18+ | 部分MCP SDK需要 | 建议18及以上 |
| Claude Desktop或Claude Code | 作为MCP Host和Agent运行环境 | 以官方最新版本为准 |
| uv或pip | Python依赖管理 | 最新稳定版 |
需要注意的是,我这里不会写死某个具体SDK版本,因为MCP和Skill生态处在快速迭代期,版本变化很快。你完全可以使用其他支持MCP的客户端,比如Cursor、JetBrains IDE插件等。核心原理是一样的,配置文件名和位置可能有差异。
3.2 前置知识要求
阅读本文建议具备以下基础:
- 了解Python基础语法,能读懂函数定义和异步调用。
- 了解JSON、Markdown基本语法。
- 用过至少一个AI对话客户端,知道Prompt是什么。
- 理解“工具调用”(Function Calling / Tool Use)的基本概念。
如果你完全不懂编程,本文的代码部分可以照抄运行,但要理解原理还需要补充一点Python基础。
3.3 安全提醒
本文会涉及通过MCP访问外部工具和数据库的示例。所有示例均使用模拟数据或演示数据,不会操作真实生产数据库。你在自己项目里接入数据库、文件系统、支付接口等敏感能力时,务必遵守最小权限原则,给Agent分配只读账号或专用低权限账号,不要使用管理员账号。
4. 核心流程拆解:MCP与Skill的分工模型
在写代码前,先想清楚整体流程。
一个标准的“Agent能力扩展”建设过程分为五个阶段:
- 能力盘点:列出Agent需要连接的资源,比如哪些数据库、哪些API、哪些本地工具。
- 连接层建设(MCP):为每个资源编写MCP Server,或选用现成Server。
- 流程封装(Skill):把高频任务写成Skill,沉淀标准操作步骤。
- 联调验证:在真实场景中验证Agent能否正确选择工具、按Skill流程执行。
- 安全加固:配置权限边界、日志审计、超时控制。
下面两章分别完成MCP和Skill的最小示例,然后在第6章把它们串起来。
5. 完整示例一:用MCP给Agent接上“数据库查询”能力
这一节从零实现一个最小MCP Server,功能是让Agent查询一张演示用的用户表。我们用一个本地SQLite数据库做演示,模拟“Agent通过MCP连接数据库”的真实场景。
5.1 初始化Python项目和安装依赖
mkdir mcp-demo-server cd mcp-demo-server python3 -m venv .venv source .venv/bin/activate安装MCP官方Python SDK和SQLite驱动:
pip install mcp sqlite3-utilsmcp是官方Python SDK,sqlite3-utils是为了方便操作SQLite演示数据。SQLite本身是Python内置库,你也可以直接用sqlite3。
5.2 创建演示数据库
python3 -c " import sqlite3 conn = sqlite3.connect('demo.db') c = conn.cursor() c.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, email TEXT, role TEXT)') c.execute(\"INSERT INTO users (name, email, role) VALUES ('张三', 'zhangsan@example.com', 'admin')\") c.execute(\"INSERT INTO users (name, email, role) VALUES ('李四', 'lisi@example.com', 'editor')\") c.execute(\"INSERT INTO users (name, email, role) VALUES ('王五', 'wangwu@example.com', 'viewer')\") conn.commit() conn.close() print('demo.db created') "这里用了两条INSERT语句插入演示数据。真实项目中,SQLite数据应该来自业务系统,这里只是为了有数据可查。
5.3 编写MCP Server
文件路径:mcp-demo-server/server.py
import sqlite3 from pathlib import Path from typing import Any from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.server.models import InitializationOptions import mcp.server.notification as notification import mcp.types as types DB_PATH = Path(__file__).parent / "demo.db" app = Server("demo-db-server") @app.list_tools() async def list_tools() -> list[types.Tool]: """声明Agent可见的工具列表。""" return [ types.Tool( name="query_users", description="查询users表中的用户数据,支持按姓名模糊搜索。", inputSchema={ "type": "object", "properties": { "keyword": { "type": "string", "description": "按姓名模糊搜索的关键字,可为空。", }, "limit": { "type": "integer", "description": "最多返回多少条,默认10。", }, }, }, ) ] @app.call_tool() async def call_tool(name: str, arguments: dict[str, Any]) -> list[types.TextContent]: """执行Agent请求的工具调用。""" if name != "query_users": raise ValueError(f"Unknown tool: {name}") conn = sqlite3.connect(DB_PATH) cursor = conn.cursor() keyword = arguments.get("keyword", "") limit = int(arguments.get("limit", 10)) if keyword: cursor.execute( "SELECT id, name, email, role FROM users WHERE name LIKE ? LIMIT ?", (f"%{keyword}%", limit), ) else: cursor.execute( "SELECT id, name, email, role FROM users LIMIT ?", (limit,), ) rows = cursor.fetchall() conn.close() lines = ["id|name|email|role"] for row in rows: lines.append("|".join(str(col) for col in row)) return [types.TextContent(type="text", text="\n".join(lines))] async def main() -> None: """启动stdio模式的MCP Server。""" async with stdio_server() as (read_stream, write_stream): await app.run( read_stream, write_stream, InitializationOptions( server_name="demo-db-server", server_version="0.1.0", ), ) if __name__ == "__main__": import asyncio asyncio.run(main())这段代码有四个关键部分:
list_tools():向Agent声明这个Server提供哪些工具。Agent看到的是工具名、描述和参数Schema,并不会看到你的数据库连接细节。call_tool():Agent决定调用工具后,客户端会把参数传到这里,由这个函数执行真实数据库查询。query_users工具的inputSchema:告诉模型它需要哪些参数、参数类型是什么,这决定了模型能否正确生成调用参数。stdio_server():使用标准输入输出作为MCP通信管道,这是本地MCP Server最常见的运行方式。
5.4 配置MCP客户端
不同客户端配置方式不同,这里给出两个主流示例。
Claude Desktop的配置文件位于claude_desktop_config.json,Windows和macOS路径不同。常见路径是:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
{ "mcpServers": { "demo-db": { "command": "python3", "args": [ "/absolute/path/to/mcp-demo-server/server.py" ] } } }Claude Code的配置方式类似,可以在项目根目录创建.mcp.json:
{ "mcpServers": { "demo-db": { "command": "python3", "args": [ "/absolute/path/to/mcp-demo-server/server.py" ] } } }配置完成后,重启客户端,让MCP Server随客户端启动。注意,/absolute/path/to/必须替换成你机器上server.py的真实绝对路径,否则客户端找不到Server。
5.5 运行与验证MCP Server
在终端直接运行Server,看它能否正常启动:
python3 server.py如果代码无误,进程会一直挂着等待输入,说明Server已经启动。这不是卡死,是stdio模式在等待客户端通过标准输入发送JSON-RPC请求。
在Claude Desktop中,你可以直接询问:
帮我查一下users表里所有名字带“张”的用户如果配置成功,模型会调用query_users工具,返回:
id|name|email|role 1|张三|zhangsan@example.com|admin如果你在对话中看到工具调用过程,说明MCP连接已经打通。
这里有个判断标准:模型是否真的把查询参数传给了工具,而不是自己在上下文里编造数据。可以通过让模型查询一个数据库里不存在的用户来验证,比如“查一下名字叫测试用户的人”,如果模型老实地返回空结果,说明它真的在执行SQL,不是猜答案。
6. 完整示例二:用Skill封装“标准代码审查”流程
MCP解决了Agent能不能调用数据库的问题,但“怎么高效地完成一次代码审查”这类流程问题,还需要Skill来解决。
6.1 Skill目录结构
我们创建一个名为code-review-skill的技能包:
code-review-skill/ ├── SKILL.md ├── scripts/ │ └── check_security.py └── references/ └── review_checklist.md6.2 编写SKILL.md
文件路径:code-review-skill/SKILL.md
--- name: code-review-skill description: 对代码变更执行结构化安全审查。当用户要求审查代码、检查Pull Request、评估提交质量时使用此技能。 --- # 代码审查技能 ## 技能目标 按照统一标准对代码变更进行审查,输出结构化的审查报告,重点发现安全漏洞、性能隐患和逻辑错误。 ## 适用场景 - 用户要求审查一段代码、一个Commit或一个Pull Request - 用户要求评估提交安全性 - 用户要求检查SQL注入、命令注入、敏感信息泄露等风险 ## 执行步骤 1. 定位需要审查的代码范围和语言类型。 2. 读取代码内容,重点关注用户输入入口、数据库操作、系统命令调用、文件读写、认证授权逻辑。 3. 运行安全检查脚本,提取当前变更的关键风险点。 4. 按严重级别分类输出:严重 / 警告 / 建议。 5. 每个问题必须给出:问题描述、代码位置、风险解释、修复建议。 ## 输出格式 审查报告必须使用以下格式: ### 审查范围 - 文件: - 语言: - 变更概述: ### 发现的问题 #### [严重级] 问题标题 - 位置:文件:行号 - 风险说明:... - 修复建议:... ### 审查结论 - 是否建议合并: - 需要修改的内容:SKILL.md的结构很重要。description字段决定了Skill是否会被自动触发,所以要写清楚“什么时候该用”“什么时候不该用”。执行步骤不要写模糊指令,要写“定位→读取→执行脚本→分类→输出”这种可执行动作。
6.3 编写Skill配套脚本
文件路径:code-review-skill/scripts/check_security.py
#!/usr/bin/env python3 """简单的代码安全扫描脚本,用于Skill辅助检查。""" import re import sys from pathlib import Path PATTERNS = { "SQL拼接": r"(?:SELECT|INSERT|UPDATE|DELETE).*f[\"']|=.*\+.*(?:cursor|execute)", "命令注入": r"os\.system|subprocess.*shell=True", "硬编码密码": r"password\s*=\s*[\"'][^\"']+[\"']", "eval执行": r"\beval\(|\bexec\(", "危险反序列化": r"pickle\.loads|yaml\.load\s*\([^)]*Loader\s*=\s*yaml\.Loader", } def scan_file(path: Path) -> list[dict]: findings = [] try: lines = path.read_text(encoding="utf-8", errors="ignore").splitlines() except Exception: return findings for idx, line in enumerate(lines, 1): for rule_name, pattern in PATTERNS.items(): if re.search(pattern, line, re.IGNORECASE): findings.append({ "file": str(path), "line": idx, "rule": rule_name, "code": line.strip(), }) return findings def main() -> None: target = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(".") if target.is_dir(): files = filter(lambda p: p.suffix in {".py", ".js", ".java", ".go", ".ts"}, target.rglob("*")) else: files = [target] all_findings = [] for f in files: all_findings.extend(scan_file(f)) if not all_findings: print("未发现匹配的安全风险模式。") return for item in all_findings: print(f"{item['file']}:{item['line']} [{item['rule']}] {item['code']}") if __name__ == "__main__": main()这个脚本是一个最小风险评估示例,它通过正则匹配代码里的危险模式。真实项目中,Skill配套脚本可以调用SonarQube API、Bandit、Semgrep等专业工具,返回结构化JSON给Agent。脚本的价值是:让Agent不只是凭印象审查代码,而是真正运行静态检查工具。
6.4 让Skill被Agent加载
Skill的加载方式取决于你使用的客户端。
以Claude Code为例,你可以把code-review-skill放到项目的.claude/skills/目录下:
your-project/ ├── .claude/ │ └── skills/ │ └── code-review-skill/ │ ├── SKILL.md │ ├── scripts/ │ │ └── check_security.py │ └── references/ │ └── review_checklist.md然后在对话中请求:
请审查src/目录下的Python代码变更Agent会根据Skill的description匹配任务,加载SKILL.md内容,并按技能步骤执行。你可以让Agent在审查前先运行脚本:
先运行check_security.py扫描src/,再结合扫描结果输出审查报告有两点需要注意。
第一,Skill不是插件,不需要“安装”,它本质上是目录和文档。Agent是你把Skill的内容“喂”给它,它再按文档执行。因此Skill内容的质量直接决定执行质量。
第二,同一个Skill可以被多个项目复用。你可以把通用技能放到用户全局skills目录,把项目特定技能放到项目级skills目录,形成两级复用结构。
6.5 验证Skill执行效果
执行后你应该看到模型输出一份结构整齐的审查报告,并且提到脚本扫描结果。如果模型只是泛泛而谈“这段代码存在安全风险”,没有具体文件、行号和修复建议,说明SKILL.md里的输出格式约束不够严格,需要增强格式指令。
这里有一个验证技巧:准备一段包含明显SQL拼接和硬编码密码的测试代码,然后让Agent审查。如果它能在报告中准确指出这两个问题并给出具体行号,说明Skill的流程生效了。
6.6 把MCP和Skill组合起来
单独跑通MCP和Skill之后,试着组合成一个真实任务:“对数据库进行安全巡检并输出报告”。
这个任务需要用到你前面写的两个能力:
- 通过MCP工具
query_users读取数据库数据。 - 通过Skill的流程模板,把巡检步骤和报告格式固定下来。
你可以创建一个新的db-inspection-skill/SKILL.md,执行步骤里明确写:先列出当前MCP Server提供的数据库工具,再调用工具读取表结构和抽样数据,检查是否存在空密码、弱权限、敏感字段明文等问题,最后按统一格式输出巡检报告。
这样你就得到了一套可以复用的Agent工程架构:MCP连接数据能力,Skill管控任务流程。
7. 运行结果与效果验证的完整路径
7.1 验证MCP是否配置成功
在支持MCP的客户端里,通常有一个工具列表界面。判断标准是:
- 启动客户端时,Server进程是否被拉起。
- 工具列表是否能看到
query_users。 - 向Agent提问时,是否出现“正在调用工具”的交互提示。
如果Agent回答“我没有权限访问数据库”,最可能的原因是MCP Server没有启动成功,而不是模型拒绝执行。先回到终端确认Server是否有报错。
7.2 验证Skill是否被正确触发
Skill触发的判断标准是:
- Agent是否按照SKILL.md里的执行步骤输出,而不是自由发挥。
- Agent是否主动运行了scripts/里的脚本。
- 输出格式是否和SKILL.md要求一致。
如果Agent完全没提Skill内容,可能是description写得不准确,模型没有把当前任务和Skill关联起来。试着调整描述,加入更多触发关键词,比如“代码审查”“Pull Request检查”“安全扫描”。
8. 常见问题与排查方法
下表总结了实践中最常遇到的几种情况。
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
| 客户端启动时MCP连接失败 | server.py路径不正确或Python环境不对 | 查看客户端日志,确认command和args路径 | 改用绝对路径,用which python3确认解释器位置 |
| Server在终端正常启动,但Agent看不到工具 | 客户端没重启,或配置格式错误 | 检查配置文件JSON格式,确认mcpServers层级 | 修改后完全退出客户端再重启 |
| Agent调用工具时报参数错误 | inputSchema参数类型和call_tool函数处理不一致 | 在call_tool里打印arguments内容 | 统一参数命名,增加类型转换和默认值 |
| Agent不调用工具,直接编造答案 | 工具描述不清晰,模型不清楚该工具适用场景 | 检查Tool的description和inputSchema描述 | 重写描述,加入触发条件和参数示例 |
| Skill没触发 | description关键词覆盖不够 | 查看客户端日志,确认Skill加载情况 | 增加关键词,补充负面触发条件 |
| Skill脚本执行失败 | 脚本依赖未安装或路径不对 | 在终端手动运行脚本验证 | 在SKILL.md的依赖项里写明安装命令 |
| 数据库查询暴露敏感信息 | 权限配置过大 | 检查数据库账号权限 | 为Agent创建只读账号,限制可查询表 |
| 调用外部API超时 | MCP Server未设置超时时间或外部服务慢 | 查看Server日志 | 在工具调用中增加超时控制,重试机制 |
这里重点说一个新手最容易忽略的点:MCP工具不是越多越好。
每个工具都会占用Agent的上下文空间。工具描述、参数Schema都会作为系统提示的一部分传给模型。如果你在一个Server里注册了50个工具,模型在做决策时反而更容易选错。更合理的做法是每个Server聚焦一个领域,比如db-server只连接数据库,http-server只提供HTTP请求工具。
9. 最佳实践与工程建议
9.1 选型:什么时候用MCP,什么时候用Skill
如果你的需求是“让Agent访问一个外部资源”,优先考虑MCP。数据库连接、第三方API调用、文件系统读取、搜索服务,都是MCP的典型场景。
如果你的需求是“让Agent规范化完成一类任务”,优先考虑Skill。代码审查、数据清洗、日报生成、测试用例编写,这些有固定流程和经验沉淀的任务,适合写成Skill。
如果需求两者都有,可以采用组合模式:MCP提供通用工具,Skill在工具之上定义流程。不要让Skill直接承载工具实现细节,不要让MCP Server承载业务流程逻辑。
9.2 安全边界:Agent连接外部能力时必须守住底线
MCP看起来是纯技术问题,实际上是权限问题。
给Agent接入数据库时,强烈建议使用专用只读账号,通过视图限制可访问字段。以MySQL为例:
CREATE USER 'agent_ro'@'localhost' IDENTIFIED BY 'strong_password'; GRANT SELECT ON biz_db.* TO 'agent_ro'@'localhost';这样Agent最多只能查询,不能修改、删除、创建表。如果业务上确实需要写操作,也应该通过一个受控的MCP工具实现,工具内部做参数白名单校验,而不是把写权限直接交给Agent。
文件操作也是一样。给Agent的文件访问范围应该限定在特定目录,不要在Server里暴露整个家目录。
9.3 上下文管理:控制Skill的加载成本
SKILL.md不是越长越好。一个几百行的Skill文档每次触发都会占用上下文Token,Agent理解核心步骤的难度也会增加。
经验是:SKILL.md主文件控制在100-200行,把补充资料放到references/子文件,需要时才让Agent读取。脚本放到scripts/目录,不要直接粘在主文件里。
9.4 团队协作:把Skill当代码管理
Skill是一堆Markdown和脚本文件,完全可以用Git管理。
建议在团队仓库里创建一个skills/目录,每个Skill一个子目录,通过Pull Request评审Skill内容变更。Skill更新应该和代码更新走同样的流程,否则会出现“技能过期”问题——Skill里的命令还在用旧参数,但实际业务接口已经变了。
9.5 日志审计
生产环境使用MCP连接真实业务系统后,一定要记录工具调用日志。记录内容至少包括:
- 调用时间
- 调用Agent会话ID
- 工具名称
- 传入参数
- 返回结果摘要
- 耗时
这样即使Agent误调用了某个工具,也能快速定位责任链。
10. 从Demo到生产:你的下一步行动清单
看完文章,建议按这套路径从Demo迈向生产:
第一步,复现本文两个示例,确保MCP Server能启动、Skill能被触发。这一步通常需要半天时间,目的是建立“连接”和“流程”两个心智模型。
第二步,盘点你自己的真实高频任务。不要一上来就想做一个通用Agent,先选出1到2个重复性最高的任务,比如“查询业务报表”“代码提交前自检”“生成测试数据”。
第三步,把任务的工具访问层用MCP封装,把流程规则用Skill封装。跑通一个“单一任务全流程”,再扩展下一个。
第四步,做安全审计。检查MCP Server绑定的权限、日志是否完整、工具调用是否有超时和熔断。
第五步,和团队一起维护Skill仓库,把个人经验变成团队资产。这一步的工程价值,往往比优化模型Prompt大得多。
MCP和Skill不是万能药,但它们确实把AI Agent从“依赖模型临场发挥”推进到了“可装配、可复用、可治理”的工程阶段。真正拉开Agent能力差距的,从来不只是一个更强的模型,而是你围绕模型建了多少条可靠的“连接”、沉淀了多少套高质量的“流程”。