Skip to content

自定义工具 ​

MCP、Skill、Slash Command,三条路径分别在什么场景下用。

三条扩展路径 ​

想让 Claude Code 干一件官方没内置的事,有三条路径能选。它们不是替代关系,而是各占不同抽象层。

MCP server:暴露一个新的原语。数据库、API、外部服务、专门的浏览器控制,这些都是原语。它们的共同特征是"提供了 Claude 之前完全够不到的能力"。写 MCP 意味着你在给 Claude 装一只新手。

Skill:打包一段有指导意义的工作流。工具已经有了,但怎么组合怎么用需要经验。skill 就是把这些经验写成 markdown,让 Claude 在遇到类似任务时按你的方法走。skill 不加新工具,只加"怎么用工具"的知识。

Slash command:给一段 prompt 或者一段 bash 起个快捷方式。它是最轻的一层,本质上是宏。适合那种"我经常要跟 Claude 说一模一样的话"或者"我经常要跑一模一样的命令"的场景。

怎么选 ​

问自己三个问题:

  1. 我要接的这个能力,Claude 目前能不能做到?做不到就写 MCP,能做到就往下看。
  2. 我要让 Claude 学的是一套"怎么做"的方法论吗?是就写 skill。
  3. 我只是想少打字?那就写 slash command。

一个具体例子。假设你想让 Claude Code 帮你自动发飞书消息通知同事 PR 已 ready:

  • 如果 Claude 现在没法调飞书 API,写 MCP server,让它有 send_lark_message 工具。
  • 如果 Claude 已经能调(通过 MCP 或者 bash curl),但你希望它每次通知都按公司模板走,写 skill。
  • 如果只是想每次自己手动触发一句"@某人 PR ready 请评审",写 slash command。

三层可以叠着用:slash command 调 skill,skill 里用 MCP tool。

一个最小 MCP tool(Python FastMCP) ​

FastMCP 是 Python 生态里最简单的 MCP server 框架,装完写十几行就能跑。

bash
pip install fastmcp

假设你要写一个工具,让 Claude 能把一段文本翻成盲文点字(举个不太常见的例子避免和现成 server 撞车):

python
# braille_server.py
from fastmcp import FastMCP

BRAILLE_MAP = {
    "a": "⠁", "b": "⠃", "c": "⠉",
    "d": "⠙", "e": "⠑", " ": " ",
}

mcp = FastMCP("braille")

@mcp.tool()
def to_braille(text: str) -> str:
    """把英文文本转成 Unicode 盲文点字。"""
    return "".join(BRAILLE_MAP.get(c.lower(), "?") for c in text)

if __name__ == "__main__":
    mcp.run(transport="stdio")

在 Claude Code 里注册:

json
{
  "mcpServers": {
    "braille": {
      "type": "stdio",
      "command": "python",
      "args": ["/absolute/path/to/braille_server.py"]
    }
  }
}

重启 Claude Code,工具会以 mcp__braille__to_braille 出现。

一个最小 MCP tool(TypeScript SDK) ​

如果项目本身是 Node 栈,用官方 TypeScript SDK 更顺手:

bash
npm install @modelcontextprotocol/sdk zod
typescript
// index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({ name: "hash", version: "0.1.0" });

server.tool(
  "sha256",
  { text: z.string() },
  async ({ text }) => {
    const crypto = await import("node:crypto");
    const hex = crypto.createHash("sha256").update(text).digest("hex");
    return { content: [{ type: "text", text: hex }] };
  },
);

await server.connect(new StdioServerTransport());

注册方式跟 Python 那版一样,只是 command 换成 node dist/index.js。

Debug tips ​

自定义工具写完最容易踩的坑是 Claude Code 根本没起 server、或者起了但 tool 没暴露出来。几个必查点:

开 debug 模式:

bash
claude --debug

会把每一次 MCP 握手、每一次 tool 调用的 request 和 response 打到终端。看握手阶段如果 server 没回响应,多半是 command 路径写错或 Python 环境不对。

看日志文件:Claude Code 会把每次会话的完整日志落到本地。macOS 和 Linux 在 ~/.claude/logs/,Windows 在 %APPDATA%\claude\logs\。MCP server 的 stderr 也会汇总到这里。

手动跑一遍 server:MCP server 本质上是一个可执行程序,你可以脱离 Claude Code 直接跑它,往 stdin 发 {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}} 看它有没有回响应。回不了说明代码里有问题,跟 Claude Code 没关系。

权限没放行:新工具第一次调用时 Claude Code 会弹权限提示。如果你在 --dangerously-skip-permissions 模式跑,就不会弹但也不一定放行。稳妥做法是在 settings 的 permissions.allow 里手动加。

不要把 MCP server 当轻量脚本写

每次 Claude Code 启动都会拉起所有配置的 MCP server。如果你的 server 启动要 10 秒(拉大模型、连远程数据库),整个 CLI 打开都会慢。慢启动的服务改成 lazy connect,或者干脆挪到 skill 里用 bash 触发。

什么时候把工具升级成 skill ​

一个 MCP tool 单独用没问题,但 Claude 每次都得自己想清楚怎么串。串对了还好,串错了就掉坑。这种时候在 .claude/skills/ 下加一个 markdown,把这个工具的正确姿势写死,Claude 遇到相关任务时会自动加载这份指导。工具管能力,skill 管方法,两层结合才是完整的扩展。

三条路径对比表 ​

三条路径的典型区别整理一下方便查:

维度MCP serverSkillSlash Command
提供什么新工具、新原语工作流、方法论快捷入口
触发方式主 agent 自主调用关键词 / 描述自动加载用户手动输入 /xxx
上下文占用只在调用时占加载后常驻展开时替换成 prompt
需要写代码是否,只写 markdown否
分发难度高(要打包发布)中(复制目录)低(复制文件)
团队共享通过 marketplace.claude/skills/ 入 git.claude/commands/ 入 git

三条路径的组合玩法 ​

三层可以互相调用,日常项目里很常见的一种组合是:

  • 一个 MCP server 提供最底层能力,比如"查我们公司的用户信息服务"。
  • 一个 skill 教 Claude 什么时候该查、查完之后按什么模板生成脱敏摘要。
  • 一个 slash command /user <id> 作为快捷入口,展开成一段调用 skill 的自然语言 prompt。

这种分层的好处是:MCP 只关心底层协议、skill 只关心业务方法、command 只关心用户体验,三层各自独立演化。团队里加个新同事,他只要会用 /user 就行,底下的复杂度都被封装掉了。

版本管理 ​

自定义工具一旦被团队用起来就是准生产系统。MCP server 建议正经打包发布(PyPI、npm 或者内网仓库),版本号跟 semver,配置里锁定具体版本别写 latest。skill 和 command 是 markdown,直接跟项目 git 走,改动通过 PR 评审。这几条做好之后,Claude Code 的扩展体系才能长期维护,不会一年之后没人敢动。

一条实用建议:写完先手动跑通 ​

自定义工具最容易出的问题是"以为 Claude 会用其实不会"。写完不要直接扔给主 agent 让它自由发挥,先自己在会话里明确说一句"用工具 X 处理 Y",看它是不是走了预期路径。走通了再放到 skill 里写方法论,让 Claude 在无提示的情况下也能想起来用。这一步能省掉后面大量的调试时间。

本教程为社区中文学习整理,非官方发布。Claude Code 属于 Anthropic。