1. 深夜那个问题:MCP 和 Skill 到底谁在干活
先说我当时卡在哪。用 Claude Code 写自动化脚本有一阵子了,.claude/skills/下面塞了好几个 Markdown 技能文件,.mcp.json里也挂了两个 MCP Server。两边都能让 Claude 帮我干活,用起来手感差不多,于是脑子里冒出一个很自然的念头:既然 Skill 里可以写「遇到这种情况就执行一段 Python 脚本」,那 MCP 是不是纯属多余?脚本什么都能干,开浏览器、连数据库、发请求,为什么还要多写一层 Server 包装?
这个问题不搞清楚,配置就会乱写。我见过不少人把该做成 MCP 的东西硬塞进 Skill,结果每次调用都要重新登录、重新启动进程;也见过把纯提示词流程硬包成 MCP Server,白白多维护几百行代码。所以这篇文章不聊概念空转,直接拆职责边界,再给你一套能复制进项目的配置骨架,最后用日志验证调用路径到底走的是哪条。
先把结论摆前面,方便你对号入座:MCP 是给模型用的结构化工具接口,Skill 是给模型看的流程指令。一个解决「能不能稳定调到外部能力」,一个解决「知不知道按什么步骤做」。两者不是替代关系,是上下游关系。你一个人自用、流程固定、脚本自己熟,Skill + 脚本能覆盖八成场景;一旦要分享给别人、要高频调用、要跨编辑器复用、要保持常驻状态,MCP 那层壳就从「多余」变成「临界点」。
下面按「问题场景 → 前置准备 → 可复制配置 → 验证请求 → 报错排查 → 按需分流」的顺序走,每一步都给命令和文件片段,你可以边看边在自己项目里落地。
2. 前置准备:TaoToken 接入 Claude Code 的模型与密钥
在拆 MCP 和 Skill 之前,得先让 Claude Code 能跑起来。Claude Code 默认走 Anthropic 官方通道,但很多人在国内网络环境下配置模型端点时会遇到连通性和鉴权问题。我这边统一用 TaoToken 做模型接入层,它提供 Anthropic 兼容的 API 端点,Claude Code 只要改 Base URL 和 Key 就能接上,MCP 和 Skill 的调试都不受影响。
你需要准备三样东西:一个可用的 API Key、正确的 Base URL、以及要调用的 Model ID。这三件套在 Claude Code、Cline、Codex 这类工具里是通用的,缺一个都会报鉴权或模型不存在。
第一步,拿到 API Key。打开 TaoToken 控制台的 API Keys 页面创建:
https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite创建后复制那串sk-开头的密钥,只显示一次,丢了就重建。这里提醒一句,Key 不要提交到 Git,放进环境变量或者本地 settings 文件,并且把该文件加进.gitignore。
第二步,确认 Base URL。Claude Code 走 Anthropic 协议时填:
https://taotoken.net/api注意这个地址后面不加 UTM 参数,直接作为 API Base 使用。如果你用的是 OpenAI 兼容协议的工具,端点路径可能不同,以接入文档为准:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite第三步,选 Model ID。Claude Code 场景下选 Anthropic 系列的模型 ID,具体可用列表在模型对话页能看到,也可以直接在对话里试:
https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite把这三样写进 Claude Code 的配置。Claude Code 读取的是用户级或项目级的settings.json,环境变量方式最省事,写进 shell 配置:
export ANTHROPIC_BASE_URL="https://taotoken.net/api" export ANTHROPIC_API_KEY="sk-你的密钥" export ANTHROPIC_MODEL="你的模型ID"写完后source ~/.zshrc或重开终端,然后claude启动,能正常对话就说明模型通道通了。这一步是整个调试的地基,MCP 和 Skill 的日志都建立在 Claude Code 能正常发起请求之上。如果你更想用图形化方式管理多个模型端点,也可以用 Coding Plan 做长期编码场景的配置:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite前置准备做完,接下来才是正题:MCP 和 Skill 各自怎么声明、怎么触发、日志里长什么样。
3. 可复制配置:settings.json 里 MCP 与 Skill 的声明骨架
这一节是全文最该抄的部分。Claude Code 的扩展配置分散在几个文件里,很多人搞混就是因为不知道哪个文件管哪件事。我按「项目根目录」为基准,给你一套完整骨架。
先看目录结构,心里有个图:
your-project/ ├── .claude/ │ ├── settings.json # 项目级设置,声明 MCP 与权限 │ └── skills/ │ └── deploy-check/ │ └── SKILL.md # 一个 Skill 就是一个 Markdown ├── .mcp.json # MCP Server 声明(项目级) └── scripts/ └── upload.py # Skill 里可能调用的脚本MCP 的声明放在.mcp.json,这是 Claude Code 识别 MCP Server 的标准位置。一个最小可用的 stdio 类型 Server 长这样:
{ "mcpServers": { "video-uploader": { "command": "python", "args": ["-m", "mcp_server_upload"], "env": { "UPLOAD_TOKEN": "${UPLOAD_TOKEN}" } } } }字段含义:command是启动进程的可执行文件,args是参数,env是注入给子进程的环境变量。Claude Code 启动时会拉起这个进程,通过 stdio 做 JSON-RPC 通信。注意${UPLOAD_TOKEN}这种写法是从宿主环境读取,不要把明文密钥写进.mcp.json。
Skill 的声明不需要在 settings.json 里注册,Claude Code 会自动扫描.claude/skills/下的子目录,每个子目录里放一个SKILL.md。文件名固定,内容就是给模型看的指令。一个部署检查 Skill 的例子:
--- name: deploy-check description: 部署前检查清单,当用户提到部署、上线、release 时触发 --- # 部署前检查 按顺序执行以下步骤,每步都要报告结果: 1. 运行 `git status`,确认没有未提交的改动 2. 运行 `pytest -q`,确认测试全绿 3. 检查 `.env` 中是否包含 `DEBUG=true`,如果有则中止并提醒 4. 全部通过后,输出「可以部署」并附上当前 commit hashdescription字段很关键,Claude 靠它判断什么时候该加载这个 Skill。写得太泛会误触发,写得太窄会不触发。
settings.json里主要管权限和 MCP 的启用开关,项目级配置示例:
{ "permissions": { "allow": [ "Bash(git status)", "Bash(pytest:*)", "mcp__video-uploader__upload" ], "deny": [ "Bash(rm -rf:*)" ] }, "enableAllProjectMcpServers": true }这里mcp__video-uploader__upload是 MCP 工具的权限标识,格式是mcp__<server名>__<工具名>。Skill 本身不需要在这里声明权限,但 Skill 里如果让 Claude 执行 Bash 命令,那些命令要落在allow列表里,否则会弹确认。
三件套对照记一下:Base URL + Key + Model ID管模型通道,.mcp.json管外部进程,.claude/skills/*/SKILL.md管流程指令。三者互不冲突,可以同时生效。
配置写完,重启 Claude Code,让它重新加载。接下来就是验证。
4. 验证请求:分别触发 MCP 工具与 Skill 指令看日志
配置对不对,不看文档看日志。这一节给你两个明确的触发动作,以及日志里该出现什么。
验证 MCP 调用路径。启动 Claude Code 时加调试参数,让它打印 MCP 连接过程:
claude --mcp-debug启动后你应该看到类似输出:
[mcp] connecting to server: video-uploader [mcp] server video-uploader started, pid=48213 [mcp] discovered tools: upload, list_videos, delete_video这三行说明 Server 进程起来了,工具列表也拿到了。然后在对话里直接说「用 video-uploader 上传 ./demo.mp4」,观察日志:
[mcp] call tool: video-uploader.upload [mcp] args: {"file_path": "./demo.mp4"} [mcp] result: {"ok": true, "url": "..."}看到call tool这一行,就证明走的是 MCP 通道,参数是结构化 JSON,没有「猜参数名」的环节。这就是 MCP 的核心价值:Schema 约束让调用确定性接近满分。
验证 Skill 加载路径。Skill 的触发靠语义匹配,你在对话里说「帮我做部署前检查」,Claude 会去匹配description。想看它到底加载了哪个 Skill,用:
claude --verbose触发后日志里会出现:
[skill] matched: deploy-check (score=0.87) [skill] loading .claude/skills/deploy-check/SKILL.md然后 Claude 会按 SKILL.md 里的步骤逐条执行,日志里跟着出现Bash(git status)、Bash(pytest:*)这些工具调用。注意区别:Skill 本身不执行任何东西,它只是把一段指令注入上下文,真正干活的是 Claude 随后调用的内置工具或 MCP 工具。
一个能同时看到两者协作的场景。假设你的 Skill 里写「上传前先跑 upload.py 检查文件」,而 upload.py 又通过 MCP 暴露成工具。触发 Skill 后,日志会呈现这样的链路:
[skill] matched: pre-upload-check [skill] loading SKILL.md [tool] Bash(python scripts/check.py) [mcp] call tool: video-uploader.upload [mcp] result: {"ok": true}这条链路把职责边界展示得很清楚:Skill 负责「先检查再上传」这个流程编排,MCP 负责「上传」这个具体动作的稳定执行。Skill 是导演,MCP 是演员。导演知道戏怎么走,但真正上台动手的是演员。
验证通过后,你对自己项目里每个扩展走哪条路就心里有数了。接下来处理踩坑。
5. 常见报错排查:401、local proxy failed 与 reading choices
配置阶段最容易撞的几类错误,我按真实日志对照给你排查路径。
401 Unauthorized。日志长这样:
API Error: 401 {"error":{"type":"authentication_error","message":"invalid x-api-key"}}原因通常是 Key 没生效或写错位置。检查顺序:先echo $ANTHROPIC_API_KEY确认环境变量真的导出了;再确认 Claude Code 读的是哪个 settings 文件,用户级和项目级可能互相覆盖;最后确认 Key 没有多余空格或换行。如果用的是 TaoToken 的 Key,去控制台确认这个 Key 没被删除或禁用。重新导出后必须重开终端,source有时对已启动的进程无效。
local proxy failed。日志:
Error: local proxy failed to start: listen tcp 127.0.0.1:xxxx: bind: address already in use这是本地端口被占用,常见于上一次 Claude Code 没退干净,或者别的工具占了同一个端口。处理办法:lsof -i :端口号找到进程 kill 掉,或者改配置换端口。如果你在 settings 里配了自定义代理端口,确认没有和系统里其他服务冲突。这类错误和网络通道无关,纯粹是本地资源争用。
reading choices 相关报错。日志:
Error: reading 'choices' - undefined (reading 'choices')这个报错通常出现在用 OpenAI 兼容协议的工具里,但实际请求打到了 Anthropic 协议的端点,返回结构对不上。根因是协议不匹配:Anthropic 返回的是content数组,OpenAI 返回的是choices数组。检查你的 Base URL 和工具要求的协议是否一致。Claude Code 走 Anthropic 协议,Base URL 用https://taotoken.net/api;如果你在 Cline 这类工具里选了 OpenAI 兼容模式,端点路径要按接入文档改。协议选错,返回体解析必然失败。
OAuth 相关报错。日志:
Error: OAuth token expired, please re-authenticate如果你用的是需要 OAuth 的 MCP Server(比如某些云服务官方 Server),token 过期就会这样。处理方式是重新走一遍该 Server 的授权流程,或者改用 API Key 鉴权的 Server。注意区分:模型通道的鉴权和 MCP Server 自己的鉴权是两套,401 可能来自任意一层,看报错里的 URL 判断是哪层。
MCP Server 起不来但没报错。日志里只有connecting没有started。多半是command路径不对,或者 Python 模块没装。手动跑一遍.mcp.json里的命令:
python -m mcp_server_upload看它报什么。手动能跑通,Claude Code 里跑不通,就是环境变量没传进去,检查env字段。
Skill 不触发。日志里没有[skill] matched。检查SKILL.md的description是否覆盖了你的说法,以及文件路径是否是.claude/skills/<名字>/SKILL.md。目录层级错一层就扫不到。
排查完这些,你的配置基本就稳了。最后说下不同场景该往哪条路走。
6. 按场景分流:什么时候用 Skill,什么时候上 MCP
回到最初那个问题。我实测下来的判断标准很简单,看四个维度。
分享范围。只有你自己用,Skill + 脚本够。要分享给团队甚至公开发布,上 MCP。因为 Skill 依赖 Claude 去「理解」你的脚本怎么调,每个人理解可能有偏差;MCP 的 Schema 是机器读的,一百个人调同一套接口,参数不会错。
调用频率。一天调几次,脚本启动开销无所谓。一天调几百次,MCP 的常驻进程优势就出来了。脚本方案每次都要冷启动、重新登录、重新初始化,20 次调用就是 20 次登录;MCP Server 启动一次,登录态留在内存,后续都是毫秒级函数调用。
跨工具复用。只在 Claude Code 里用,Skill 没问题。要在 Claude Desktop、Cursor、其他支持 MCP 的编辑器里共用同一套能力,必须 MCP。Skill 是 Claude Code 专属格式,别的工具不认。
状态保持。需要数据库连接池、常驻浏览器窗口、WebSocket 长连接,这些 Skill 做不到,因为 Skill 只是注入上下文,没有独立进程。MCP Server 是独立进程,想常驻什么就常驻什么。
把这四条套到你的场景上,答案基本就出来了。个人自用、低频、单工具、无状态,Skill + 脚本覆盖八成需求,别为了那 10% 到 20% 的稳定性提升去多写一层 Server 包装。但一旦命中「多人、高频、跨工具、要状态」任意一条,MCP 那层壳就不是多余,是临界点。
如果你打算把 MCP 能力长期跑在编码和 Agent 场景里,可以用 Coding Plan 统一管理模型端点和调用配额:
https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite需要新建或轮换 API Key 时走这里:
https://taotoken.net/console/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite配置细节和协议差异查接入文档:
https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite想先在对话里试模型 ID 和返回结构,用模型对话页:
https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite最后留一个我踩过的坑:别在 Skill 里写「如果脚本失败就重试三次」这种逻辑去替代 MCP 的稳定性。重试解决的是偶发失败,解决不了「参数猜错」这种系统性不确定。该上 Schema 的地方,重试一百次也还是猜。把流程编排交给 Skill,把确定性执行交给 MCP,各司其职,日志里那条调用链路会告诉你分工对不对。