1. 为什么我要把 MCP 和 Skills+CLI 放在一起用
MCP 是一种基于 JSON-RPC 的开放协议,让模型通过标准消息格式调用外部工具、读取上下文;Skills+CLI 则是把本地命令行工具封装成模型可选择的“技能”,让模型直接生成curl、jq、grep这类命令。前者适合对接远程 API、数据库、专有服务,后者适合本地自动化、文件操作、快速组合。两者不是替代关系,而是互补关系。
我最近在本地 AI 工具链里同时用了这两种范式:远程服务走 MCP,本地动作走 Skills+CLI,然后用 TaoToken 的统一 Key 和 API 通道把模型调用收口到一处。这样做的直接好处是,配置文件里不再散落多个厂商的 Key,模型切换、额度查看、错误排查都集中在一个入口。这篇就按“可复制配置 + 跑通验证”的节奏,把config.toml和settings.json骨架、TaoToken 接入步骤、一次 CLI 调用验证动作完整走一遍。
适合谁看:正在配本地 AI 工具链、想让模型既能调远程 MCP 工具又能执行本地命令、并且希望用统一 Key 管理模型通道的人。下面所有配置都可以直接复制改路径使用。
2. TaoToken 前置:统一 Key 与 API 通道
TaoToken 在这里的角色是“模型调用的统一入口”。你不需要在 MCP 配置、CLI 脚本、编辑器插件里分别填不同厂商的 Key,而是拿一个 TaoToken 的 API Key,把 base URL 指向https://taotoken.net/api,各个工具链组件都走这个通道。
先做三件事:
第一,注册并登录后进入控制台,找到 API Keys 页面创建一个 Key。建议按用途命名,比如local-mcp-cli,方便后面排查是哪个环节在用。
第二,确认你要用的模型名称。TaoToken 的模型对话页面可以直接试跑,确认模型能正常响应后再写进配置。
第三,如果你打算长期跑编码类 Agent,可以看一下 Coding Plan 的额度说明,避免跑到一半额度不够。
关键地址如下,配置时按需取用:
- 官网入口:https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=
- API 基址:https://taotoken.net/api
- 模型对话:https://taotoken.net/api/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=model_chat
- Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=coding_plan
- 控制台:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=console
- API Keys:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=api_keys
- 接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=doc
- ClaudeCodeAnthropic:https://taotoken.net/claude-code-anthropic?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=claude_code
注意:API 基址不要加 UTM 参数,否则部分客户端会把查询串当成路径的一部分,导致 404。只有页面类链接才带 UTM。
拿到 Key 之后,先别急着写进所有配置文件。建议先用一条最小请求验证 Key 和通道是否通,再往下配 MCP 和 CLI。验证命令在第四节给出。
3. 可复制配置:config.toml 与 settings.json 骨架
这一节是全文的核心。我把配置拆成两层:config.toml负责 MCP 服务端和模型通道,settings.json负责 CLI 侧和编辑器侧的技能声明。两层都指向 TaoToken 的同一个 Key。
3.1 config.toml:MCP 服务端与模型通道
# ~/.config/ai-toolchain/config.toml [model] # 统一走 TaoToken 的 API 通道 provider = "taotoken" base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" default_model = "claude-sonnet-4-20250514" timeout_seconds = 60 [mcp] # MCP 服务端监听本地,供 CLI 和编辑器通过 JSON-RPC 调用 transport = "stdio" server_name = "local-mcp-bridge" log_level = "info" [mcp.servers.filesystem] command = "npx" args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/workspace"] enabled = true [mcp.servers.fetch] command = "npx" args = ["-y", "@modelcontextprotocol/server-fetch"] enabled = true [skills] # Skills+CLI:把本地命令声明为技能,模型只看到名称和简短说明 enabled = true skill_dir = "~/.config/ai-toolchain/skills" max_inline_skills = 8 [skills.registry] curl = { cmd = "curl", desc = "HTTP 请求,支持 -s 静默、-X 方法、-H 头" } jq = { cmd = "jq", desc = "JSON 解析与过滤,支持 .path 和管道" } grep = { cmd = "grep", desc = "文本匹配,支持 -r 递归、-i 忽略大小写" } rg = { cmd = "rg", desc = "快速全文搜索,默认递归" }这里有几个设计点值得说明。api_key_env指向环境变量而不是把 Key 写死在文件里,避免配置文件被同步到 Git 时泄露。mcp.transport = "stdio"是最省事的本地传输方式,CLI 启动时把 MCP 服务端作为子进程拉起,通过标准输入输出跑 JSON-RPC。skills.max_inline_skills = 8是刻意限制的:只把当前任务最可能用到的技能描述注入上下文,其余技能按需检索,避免工具元数据把上下文窗口填满。
3.2 settings.json:CLI 侧与编辑器侧
{ "aiToolchain": { "provider": "taotoken", "baseUrl": "https://taotoken.net/api", "apiKeyEnv": "TAOTOKEN_API_KEY", "model": "claude-sonnet-4-20250514" }, "mcp": { "bridge": "local-mcp-bridge", "configPath": "~/.config/ai-toolchain/config.toml", "autoStart": true }, "skills": { "enabled": true, "skillDir": "~/.config/ai-toolchain/skills", "inline": ["curl", "jq", "grep", "rg"], "onDemand": true }, "cli": { "shell": "/bin/zsh", "timeoutMs": 30000, "allowPipe": true, "allowRedirect": true } }cli.allowPipe和allowRedirect是 Skills+CLI 范式的关键开关。打开之后,模型生成的命令可以用|组合,比如curl -s ... | jq '.data' | grep "pattern",由 Shell 负责数据流,模型不需要自己编排中间结果传递。这正是 Unix 哲学里“组合小工具”的做法,也是 MCP 需要额外链式调用才能实现的能力。
3.3 环境变量与目录准备
# 写入环境变量,建议放到 ~/.zshrc 或 ~/.bashrc export TAOTOKEN_API_KEY="sk-你的TaoTokenKey" # 创建配置目录和技能目录 mkdir -p ~/.config/ai-toolchain/skills # 确认配置文件就位 ls -la ~/.config/ai-toolchain/如果你用的是 Windows,把~/.config/ai-toolchain/换成%APPDATA%\ai-toolchain\,环境变量用setx TAOTOKEN_API_KEY "sk-..."设置,其余配置字段一致。
4. 验证请求:一次 CLI 调用跑通工具链
配置写完不代表通了。我习惯先用一条最小请求验证模型通道,再用一条 CLI 命令验证 Skills+CLI 组合,最后用一次 MCP 工具发现验证 JSON-RPC 链路。
4.1 验证模型通道
curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "只回复 ok"}], "max_tokens": 16 }' | jq -r '.choices[0].message.content'预期输出是ok。如果返回 401,说明 Key 没读到或写错了;如果返回 404,检查 base URL 是不是误加了 UTM 参数;如果超时,先确认网络能访问taotoken.net。
4.2 验证 Skills+CLI 组合
这一步模拟模型生成命令、Shell 执行、结果回传的完整链路:
# 模拟模型生成的组合命令:请求 API 并解析 JSON curl -s https://taotoken.net/api/models \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ | jq -r '.data[].id' \ | grep -i "claude" \ | head -5这条命令本身就是 Skills+CLI 范式的缩影:curl负责 HTTP,jq负责结构化解析,grep负责过滤,head负责截断。模型只需要生成这一行字符串,执行环境负责解析和执行,输出结果再返回给模型。上下文里只承载了任务描述和这一行命令,没有把每个工具的详细模式塞进去。
4.3 验证 MCP 的 JSON-RPC 链路
MCP 走的是 JSON-RPC 2.0 消息格式。你可以手动发一条tools/list请求,确认 MCP 服务端能正常响应:
# 启动 MCP 服务端并发送 tools/list 请求 echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \ | npx -y @modelcontextprotocol/server-filesystem /Users/me/workspace预期返回一个 JSON 对象,result.tools数组里列出该 MCP 服务端暴露的工具。如果返回-32601 Method not found,说明服务端版本不支持tools/list,换成initialize先握手再列工具。如果进程直接退出无输出,检查npx是否能正常拉包。
4.4 一次完整的 CLI 调用验证动作
把上面三步串起来,跑一次端到端验证:
# 1. 确认环境变量 echo $TAOTOKEN_API_KEY | head -c 8 # 2. 确认模型通道 curl -s https://taotoken.net/api/chat/completions \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"claude-sonnet-4-20250514","messages":[{"role":"user","content":"回复 ready"}],"max_tokens":16}' \ | jq -r '.choices[0].message.content' # 3. 确认 Skills+CLI 组合 curl -s https://taotoken.net/api/models \ -H "Authorization: Bearer $TAOTOKEN_API_KEY" \ | jq -r '.data[].id' | head -3 # 4. 确认 MCP JSON-RPC echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \ | npx -y @modelcontextprotocol/server-filesystem /Users/me/workspace \ | jq '.result.tools | length'四步都返回预期结果,说明模型通道、Skills+CLI、MCP JSON-RPC 三条链路都通了。任何一步失败,按下一节的排查表定位。
5. 本篇常见错排查
配置类问题大多集中在 Key、路径、协议版本三处。我按实际踩过的顺序列出来。
5.1 401 Unauthorized
最常见的原因是环境变量没生效。export只对当前 Shell 会话有效,新开终端就丢了。检查方法:
# 确认当前 Shell 能读到 echo $TAOTOKEN_API_KEY # 确认配置文件里引用的变量名一致 grep api_key_env ~/.config/ai-toolchain/config.toml如果echo输出为空,把export写进~/.zshrc或~/.bashrc,然后source一下。另一个原因是 Key 复制时带了空格或换行,用echo $TAOTOKEN_API_KEY | wc -c确认长度是否符合预期。
5.2 404 Not Found
九成是 base URL 写错了。TaoToken 的 API 基址是https://taotoken.net/api,不要加 UTM 参数,也不要在末尾多加/v1或/chat。有些客户端会自动拼接路径,如果你在 base URL 里已经写了/chat/completions,客户端再拼一次就变成/chat/completions/chat/completions。
# 正确 base_url = "https://taotoken.net/api" # 错误:多了路径 base_url = "https://taotoken.net/api/chat/completions" # 错误:带了 UTM base_url = "https://taotoken.net/api?utm_source=xxx"5.3 MCP 服务端启动失败
npx拉包失败、Node 版本过低、路径不存在都会导致 MCP 服务端起不来。逐个排查:
# 确认 Node 版本 node -v # 确认 npx 能拉包 npx -y @modelcontextprotocol/server-filesystem --help # 确认路径存在 ls -la /Users/me/workspace如果npx卡住,可能是 npm registry 访问慢,换一个镜像源再试。如果路径不存在,MCP 服务端会直接退出,日志里通常有ENOENT。
5.4 JSON-RPC 返回 -32700 Parse error
这是消息格式问题。JSON-RPC 2.0 要求消息体是合法 JSON,且必须包含jsonrpc、method、id三个字段。常见错误是单引号嵌套导致 Shell 把 JSON 拆坏了:
# 错误:内层用了单引号,Shell 提前截断 echo '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' # 正确:用双引号包裹,内层转义 echo "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"tools/list\",\"params\":{}}"或者把 JSON 写进文件再cat进去,避免 Shell 转义问题。
5.5 Skills 没被模型识别
如果模型生成的命令里没有用到你声明的技能,检查skills.inline列表是否包含该技能,以及max_inline_skills是否被其他技能占满。技能描述太长也会挤占上下文,建议每个技能的desc控制在 30 字以内,只写命令名和关键参数。
# 好的描述:简短、含关键参数 curl = { cmd = "curl", desc = "HTTP 请求,支持 -s 静默、-X 方法、-H 头" } # 差的描述:太长,挤占上下文 curl = { cmd = "curl", desc = "curl 是一个用于传输数据的命令行工具,支持 HTTP、HTTPS、FTP 等多种协议,可以通过 -X 指定方法,通过 -H 添加请求头,通过 -d 发送数据体,通过 -o 保存到文件..." }6. 把统一 Key 收口到工具链的下一步
走到这里,你应该已经能用一份config.toml和一份settings.json,把 MCP 的 JSON-RPC 链路和 Skills+CLI 的组合链路都指向 TaoToken 的同一个 Key。远程服务走 MCP,本地动作走 CLI,模型只看到技能名称和简短说明,上下文不被工具元数据填满。
接下来可以做的几件事:把常用 CLI 命令继续注册成技能,比如git、docker、ffmpeg,每个只写一行描述;对需要严格输入输出的远程服务,用 MCP 封装,但对外暴露成 CLI 风格的命令,保持接口一致;技能描述按需检索,不要一次性全量注入。
如果你还没创建 Key,从 API Keys 页面拿一个;配置过程中遇到报错,对照接入文档的字段说明;想先确认模型能不能正常响应,用模型对话页面试跑一条;打算长期跑编码类 Agent,提前看一下 Coding Plan 的额度规则。统一 Key 的价值不在于省事,而在于出问题时你只需要排查一个入口。