1. 从三周踩坑说起:Skill、MCP、Hook、Plugin 到底谁管谁
刚上手 Claude Code 那阵子,我把它当成一个「更聪明的命令行助手」,直到团队里同时冒出四种扩展需求,才发现事情没那么简单。前端同学想让它记住组件库的用法,后端同学想让它查内部配置中心,DevOps 同学想让它每次改文件前先跑一遍检查,还有人问能不能把这堆东西打包给全组用。四个诉求,对应四个名词:Skill、MCP、Hook、Plugin。我当时的反应很朴素——那我这个需求到底该选哪个?
结果就是三周里反复横跳。同一个「数据库建表规范」,我在 CLAUDE.md 里写了一遍 Markdown,又在一个 Skill 的 SKILL.md 里抄了一遍,最后发现某个 MCP Server 的 Python 脚本里还硬编码了第三份。三份内容各自能跑,但谁也不知道谁的存在,改一处忘两处。这种混乱不是工具的问题,是我一开始就把它们当成了「四选一」的并列选项。
真实关系是分层的。Skill 解决「Claude 知不知道这类任务该怎么做」,本质是按需加载的知识包;MCP 解决「Claude 能不能跟外部系统实时对话」,本质是标准化的连接协议;Hook 解决「Claude 做事的前后要不要自动触发点什么」,本质是生命周期事件钩子;Plugin 解决「这些能力怎么分发给整个团队」,本质是打包与治理容器。它们分别对应知识管理、系统集成、流程自动化、能力分发四个层次,不是竞争关系,而是可以叠加的组合件。
我后来画了一张决策图,核心就一句话:先判断你的问题落在哪一层,再决定用哪个机制。80% 的日常场景,Skill 加 MCP 就够了;Hook 和 Plugin 是团队规模上来、治理需求暴露之后才需要补的。这篇就把这张图展开,并且给你一份可以直接抄进项目的 settings.json 配置片段,以及 MCP 接入后怎么验证真的通了。工具侧的 Key 和 API 通道,我会用 TaoToken 统一收口,省得每个扩展各配一套凭证。
2. 前置准备:用 TaoToken 统一 Key 与 API 通道
在动手配 Skill、MCP、Hook 之前,有个容易被忽略但很关键的前置动作:把模型访问的凭证和通道统一掉。原因很实际——Claude Code 本身、MCP Server 里如果调模型、以及各种脚本化的扩展,如果各自维护一套 Key,后面排查问题时你根本分不清是扩展逻辑错了还是凭证过期了。
我的做法是走 TaoToken 这一层。它提供统一的 API 通道,Claude Code 和工具侧都指向同一个 Base URL,Key 也只维护一份。官网入口是 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,API 地址是 https://taotoken.net/api ,注意 API 这个地址不带 UTM 参数,配置里直接写干净的就行。
具体要准备三样东西,我把它叫「三件套」,后面每个扩展机制只要涉及模型调用,都复用这三件套:
第一是Base URL,统一填https://taotoken.net/api。第二是API Key,去控制台生成,地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_content=console&utm_campaign=rewrite ,生成后复制保存,它只显示一次。第三是Model ID,这个取决于你实际要用的模型,在模型对话页能看到可用列表,地址是 https://taotoken.net/models?utm_source=taotoken_aicg_blog_end&utm_content=models&utm_campaign=rewrite 。
如果你只是想先验证通道通不通,最省事的办法是打开模型对话页直接发一句话,地址 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_content=chat&utm_campaign=rewrite ,能正常返回就说明 Key 和通道没问题,再去配 Claude Code 就少一层变量。
这里有个我踩过的坑要提醒:很多人配 Claude Code 时把 Key 写进项目里的.claude/settings.json然后提交到 Git,这是安全事故。凭证应该放在用户级配置或者环境变量里,项目级配置只放不敏感的行为开关。后面第三节我会把两种配置分开写清楚。
另外,如果你打算长期用 Claude Code 做编码和 Agent 类任务,可以了解下 Coding Plan,地址 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_content=coding-plan&utm_campaign=rewrite ,它更适合高频编码场景,比按次调用更划算。但这一步不是必须的,先把基础通道跑通再说。
3. 可复制配置:settings.json 与 MCP 接入片段
这一节是全文最实操的部分,我给的都是可以直接复制、改改路径就能用的片段。先明确一个原则:用户级配置放凭证和全局行为,项目级配置放项目相关的扩展声明。Claude Code 读取配置的优先级是项目级覆盖用户级,所以敏感信息放用户级最安全。
先看用户级的~/.claude/settings.json,这里放模型通道和全局 Hook:
{ "env": { "ANTHROPIC_BASE_URL": "https://taotoken.net/api", "ANTHROPIC_API_KEY": "sk-你的TaoToken密钥", "ANTHROPIC_MODEL": "你的ModelID" }, "hooks": { "PreToolUse": [ { "matcher": "Write|Edit", "hooks": [ { "type": "command", "command": "python3 ~/.claude/hooks/pre-write-guard.py", "timeout": 10000 } ] } ], "PostToolUse": [ { "matcher": "", "hooks": [ { "type": "command", "command": "python3 ~/.claude/hooks/log-tool-usage.py" } ] } ] } }注意ANTHROPIC_BASE_URL这里填的是不带 UTM 的干净地址,ANTHROPIC_API_KEY换成你在控制台生成的那串。ANTHROPIC_MODEL填你要用的 Model ID。这三个就是前面说的三件套,Claude Code 主进程靠它们走 TaoToken 通道。
再看项目级的.claude/settings.json,这里只放 MCP Server 声明和项目级权限,不放 Key:
{ "mcpServers": { "internal-config": { "command": "python3", "args": ["-m", "mcp_servers.config_server"], "env": { "CONFIG_API_BASE": "https://internal.example.com/api" } }, "db-schema": { "command": "npx", "args": ["-y", "@company/mcp-db-schema"], "env": { "DB_DSN": "postgresql://readonly@db.internal:5432/app" } } }, "permissions": { "allow": ["Read", "Glob", "Grep"], "deny": ["Bash(rm -rf *)"] } }这里mcpServers下每个键就是一个 MCP Server 的名字,command加args是启动方式,env是它自己需要的环境变量。注意 MCP Server 如果需要调模型,它的模型凭证也应该走 TaoToken,而不是另配一套。你可以在它的env里加ANTHROPIC_BASE_URL和ANTHROPIC_API_KEY,值跟用户级一致。
Skill 的配置不走 settings.json,它是文件系统约定。项目级 Skill 放在.claude/skills/下,每个 Skill 一个目录,目录里一个SKILL.md,头部用 YAML frontmatter 声明名称和触发描述:
--- name: frontend-tracking description: 前端埋点 SDK 接入规范。当需要添加用户行为追踪时使用。 --- # 前端埋点规范 ## 初始化 在 `app.tsx` 引入 `@company/tracker`,调用 `initTracker({ appId: process.env.TRACKER_APP_ID })`。 ## 事件命名 - 页面浏览:`page_view_{pageName}` - 按钮点击:`btn_click_{buttonName}` ## 禁止事项 - 禁止在 `useEffect` 中直接调用 `track()` - 禁止上报手机号、邮箱等 PII 数据description这一行很关键,Claude 就是靠它判断「当前任务要不要加载这个 Skill」。写得越具体,误触发越少。我见过有人把 description 写成「前端相关」,结果后端任务也被加载,纯属浪费 token。
Hook 脚本本身也要落地。比如~/.claude/hooks/pre-write-guard.py,作用是拦截写入敏感关键词的文件:
import json import sys SENSITIVE = ["password", "secret", "connectionString", "PRIVATE KEY"] def main(): payload = json.load(sys.stdin) tool_input = payload.get("tool_input", {}) content = str(tool_input.get("content", "")) + str(tool_input.get("new_string", "")) for kw in SENSITIVE: if kw.lower() in content.lower(): print(f"BLOCKED: 检测到敏感关键词 {kw}", file=sys.stderr) sys.exit(2) sys.exit(0) if __name__ == "__main__": main()Hook 脚本通过退出码控制行为:退出 0 放行,退出 2 阻止并回传 stderr 给 Claude。这个约定要记牢,写错了 Hook 会静默失效。
4. 验证请求:确认 MCP 与通道真的通了
配置写完不代表生效,必须验证。我按「先通道、再 MCP、后 Hook」的顺序来,逐层排除变量。
第一步验证 TaoToken 通道。在终端里直接 curl 一下:
curl -s https://taotoken.net/api/v1/messages \ -H "x-api-key: sk-你的TaoToken密钥" \ -H "anthropic-version: 2023-06-01" \ -H "content-type: application/json" \ -d '{ "model": "你的ModelID", "max_tokens": 64, "messages": [{"role": "user", "content": "回复 OK 两个字母"}] }'如果返回里能看到content字段且文本是 OK 相关,说明 Key、Base URL、Model ID 三件套都对。如果返回 401,看第五节排障。
第二步验证 Claude Code 是否读到配置。在项目目录下启动 Claude Code,输入/status或者直接问它「你当前用的模型是什么」。如果它报的模型跟你配的 Model ID 一致,说明用户级 settings.json 生效了。这一步能过,说明 Claude Code 主进程已经走 TaoToken 通道。
第三步验证 MCP Server 是否挂载成功。在 Claude Code 里输入/mcp命令,它会列出当前加载的所有 MCP Server 及其状态。正常应该看到internal-config和db-schema两个,状态是 connected。如果显示 failed 或者根本没列出来,说明启动命令有问题。
第四步做一次真实的 MCP 调用。直接对 Claude 说:「用 db-schema 这个 MCP 查一下 users 表有哪些字段」。如果它调用了 MCP 工具并返回了真实字段列表,说明整条链路通了。这一步的返回内容应该是你数据库里的真实结构,而不是它编的——如果它没调工具直接回答,说明 MCP 没被正确识别,回去检查mcpServers的键名和启动命令。
第五步验证 Hook。故意让 Claude 写一个包含password的文件,比如「帮我在 config.py 里写一行 password = 'test'」。如果 Hook 生效,它会阻止写入并提示检测到敏感关键词。如果直接写进去了,说明 Hook 脚本路径不对或者退出码写错了。
这五步走完,你的 Skill、MCP、Hook 三条线就都有验证依据了。Plugin 的验证更简单,装完之后/plugin能看到列表和版本号即可。
5. 常见报错排查:401、local proxy failed、reading choices、OAuth
这一节我按真实遇到过的报错来写,每个都给现象、原因、解法。
401 Unauthorized。现象是 curl 或 Claude Code 返回 401。原因通常是三种:Key 复制时带了空格或换行;Key 已经失效或被删;Base URL 写错,比如多加了/v1导致路径拼接错误。解法是先确认ANTHROPIC_BASE_URL就是https://taotoken.net/api,不要自己加后缀;然后重新去控制台生成一个 Key,地址 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_content=api-keys&utm_campaign=rewrite ,复制时注意别带首尾空白。如果还不行,用第四节的 curl 单独测通道,把 Claude Code 这个变量排除掉。
local proxy failed。现象是 Claude Code 启动时报本地代理失败。这个报错跟网络代理无关,通常是 Claude Code 尝试连的 Base URL 不可达,或者本地有残留的代理环境变量干扰。解法是检查 shell 里有没有HTTP_PROXY、HTTPS_PROXY这类变量,有就临时 unset 掉再启动;同时确认ANTHROPIC_BASE_URL拼写正确。如果公司网络有出口限制,确认taotoken.net在允许列表里。
reading choices 相关报错。现象是调用模型后返回结构解析失败,提示读取 choices 字段出错。这通常发生在你用 OpenAI 兼容格式去请求 Anthropic 格式的端点,或者反过来。TaoToken 的/api端点走的是 Anthropic 原生格式,请求体里应该是messages加max_tokens,响应里是content数组,不是choices。如果你在 MCP Server 里用了 OpenAI SDK 去调,就会撞这个错。解法是 MCP Server 里改用 Anthropic SDK,或者确认你调的是对应的兼容端点。
OAuth 相关报错。现象是 Claude Code 提示需要登录或 OAuth 失败。这通常是因为你同时配了ANTHROPIC_API_KEY和某种登录态,两者冲突。解法是明确用 Key 模式:确保ANTHROPIC_API_KEY有值,并且没有残留的登录 token 文件。如果之前登录过官方账号,清掉对应的凭证缓存再启动。
MCP Server 显示 failed 但没报错。现象是/mcp里状态是 failed,日志里没细节。解法是手动在终端跑一遍启动命令,比如python3 -m mcp_servers.config_server,看它自己报什么。常见原因是依赖没装、Python 路径不对、或者env里的变量缺失导致启动即退出。
Hook 不生效。现象是配了 Hook 但该拦的没拦。解法按顺序查:脚本路径是不是绝对路径(相对路径在 Claude Code 里不可靠);脚本有没有执行权限;退出码是不是用了 2 而不是 1;matcher 正则有没有写对,比如Write|Edit中间不能有空格。我踩过的坑是 matcher 写成了write|edit小写,结果永远不匹配。
排查的核心思路是分层隔离:通道问题用 curl 测,Claude Code 问题用/status测,MCP 问题用/mcp加手动启动测,Hook 问题用故意触发测。一次只动一个变量,别同时改三处然后猜是哪个生效了。
6. 按场景选型:一张决策图收口
回到最开始那张决策图,我把它压成一套可以照着走的判断流程。
先问第一个问题:你要解决的是「Claude 不知道怎么做」还是「Claude 拿不到实时数据」还是「某个时机要自动做点什么」还是「要分发给团队」。这四个问题分别指向 Skill、MCP、Hook、Plugin。
如果是「不知道怎么做」,再分:这条知识是所有任务都要遵守的底线,还是只有特定任务才需要。全局底线放 CLAUDE.md,特定任务放 Skill。判断标准很简单——如果后端任务根本不需要读前端埋点规范,那它就不该进 CLAUDE.md。
如果是「拿不到实时数据」,再分:你连的是静态文档还是实时系统。API 手册、字段说明这种三个月才变一次的,用 Skill 描述就够,上 MCP 是过度设计。数据库本体、K8s 集群状态、内部 API 这种随时在变的,才需要 MCP Server。
如果是「某个时机自动做」,再分:事前还是事后。事前检查用 PreToolUse,事后记录用 PostToolUse,会话开始或结束用 SessionStart 和 Stop。Hook 只做任务无关的自动化,别拿它注入任务相关的知识。
如果是「分发给团队」,直接上 Plugin。但前提是真的有三人以上协作,一个人的项目维护 Plugin 纯属给自己加负担。
组合方式上,最常见的生产配置是:CLAUDE.md 放全局规范,若干 Skill 放专项 SOP,一两个 MCP Server 接实时系统,一个 PreToolUse Hook 做安全拦截。Plugin 等到团队规模上来再封装。这套组合覆盖了绝大多数场景,也不会过度设计。
工具侧的 Key 和通道,全程用 TaoToken 统一收口,Claude Code 主进程、MCP Server 里的模型调用、以及任何脚本化的扩展,都指向同一个 Base URL 和同一份 Key。这样出问题时你只需要排查一个通道,而不是四个。
最后给个实用建议:每次加新扩展之前,先问自己「不加会怎样」。如果答案是「也能跑,只是稍微麻烦点」,那就先别加。扩展机制的价值在于解决真实瓶颈,不在于堆砌。我三周踩坑最大的收获不是学会了四个名词,而是学会了什么时候不该用它们。