2026 年,Model Context Protocol(MCP)已成为 AI 工具集成的事实标准。它允许大模型通过标准化接口调用外部工具、读取文件、操作数据库——而 Claude Code 在这一生态中扮演着独特的角色:它既可以作为 MCP 客户端,也可以作为 MCP 服务器向其他工具暴露能力。

本文将从零开始,带你完整走通"用 Claude Code 构建 MCP 服务器"的全流程,包括环境搭建、服务端启动、客户端接入、自定义工具开发,以及常见坑点排查。无论你是想把 Claude Code 的能力暴露给 Cursor、Windsurf,还是想自己搭一套 AI Agent 编排框架,这篇教程都能给你扎实的基础。

一、MCP 核心概念与双重身份

MCP 系统架构图

在深入操作之前,先把 MCP 的核心模型搞清楚,能省掉很多走弯路的时间。

MCP 的三层架构

MCP 协议定义了三个角色:

  • MCP Host(宿主):发起连接的应用程序,如 Claude Desktop、Cursor、Windsurf。Host 里运行着 LLM,负责决定何时调用工具。
  • MCP Client(客户端):内嵌在 Host 里的协议实现层,负责与 Server 通信。
  • MCP Server(服务器):独立进程,暴露 Tools(工具)、Resources(资源)、Prompts(提示词)三类能力。
ℹ️
关键理解:MCP Server 是一个普通进程,Host 通过 stdio 管道或 HTTP/SSE 与它通信。Claude Code 内置了完整的 MCP Server 实现,运行 claude mcp serve 就能让它以服务端模式启动。

Claude Code 的双重身份

Claude Code 的独特之处在于它同时具备两种身份:

作为 MCP Client

  • 连接外部 MCP Server
  • 调用数据库、JIRA、GitHub 等工具
  • 通过 claude mcp add 添加服务

作为 MCP Server

  • 暴露 Bash 执行、文件读写等能力
  • 运行 claude mcp serve 启动
  • 供 Cursor、Windsurf 等工具接入

重要的是,这两种身份是完全隔离的。当 Claude Code 作为 MCP Server 运行时,它并不会把自己正在连接的其他 MCP Server 的能力透传给上游 Host——每一层的 MCP 连接都是独立的进程边界,保证安全隔离。

三种传输方式

传输方式 适用场景 特点
stdio 本地工具集成 最简单,无网络暴露,进程隔离
HTTP + SSE 远程服务 支持多客户端,需要网络配置
Streamable HTTP 云端部署 2025年新规范,推荐用于云服务

本文主要讲解最常用的 stdio 模式,这也是 claude mcp serve 默认使用的传输方式。

二、环境准备与依赖安装

环境准备流程图

正式开始之前,确认你的机器满足以下前提条件:

  • 操作系统:macOS 或 Linux(Claude Desktop 目前不支持 Linux,但 Claude Code MCP Server 本身支持)
  • Node.js 20+(推荐用 nvm 管理版本)
  • 有效的 Anthropic API Key,或已登录 Claude 账号
1
安装 Node.js 20+(使用 nvm)

如果你还没有安装 nvm,先安装它,然后用它管理 Node 版本:

bash
# 安装 nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash

# 重新加载 shell 配置
source ~/.bashrc   # 或 source ~/.zshrc

# 安装并使用最新 LTS Node
nvm install --lts
nvm use --lts

# 验证版本(需要 >= 20)
node --version
2
全局安装 Claude Code CLI

Claude Code 通过 npm 分发,全局安装后即可在任意目录使用:

bash
npm install -g @anthropic-ai/claude-code

# 验证安装
claude --version
⚠️
如果提示 command not found: claude,需要将 npm 全局 bin 目录加入 PATH。运行 npm config get prefix 查看路径,然后将 <prefix>/bin 加入 ~/.zshrc~/.bashrc
3
首次运行——完成认证和权限初始化

在作为 MCP Server 使用之前,必须至少运行一次带有 --dangerously-skip-permissions 标志的命令来完成认证和接受权限协议。这一步是无头(headless)MCP 服务端模式正常运行的前提:

bash
# 首次运行,完成登录和权限初始化
# 注意:这会打开浏览器进行 OAuth 认证
claude --dangerously-skip-permissions "echo hello"
macOS 用户:首次运行时系统会弹出文件夹访问权限对话框,务必点击"允许",否则后续 MCP Server 启动时可能卡住无响应。

三、启动 Claude Code 作为 MCP 服务端

启动 MCP 服务端流程图

环境就绪后,用一条命令就能把 Claude Code 变成 MCP 服务器:

bash
claude mcp serve

服务器启动后会监听 stdin,等待来自 MCP 客户端的 JSON-RPC 2.0 消息。它暴露的核心工具包括:

工具名 功能描述 典型用途
Bash 执行 shell 命令 运行测试、构建、部署
Read 读取文件内容 查看源码、配置文件
Write 写入文件 创建、覆盖文件
Edit 精确字符串替换 修改代码片段
Glob 文件模式匹配 查找特定后缀文件
Grep 内容搜索(ripgrep) 全局代码搜索
Agent 启动子 Agent 复杂任务分解编排
ℹ️
工作目录:MCP Server 的工具默认在启动时的当前目录下操作。你可以为不同项目启动不同的 Server 实例,每个实例有独立的工作目录上下文,互不干扰。

手动测试 MCP 通信

可以用 @modelcontextprotocol/inspector 工具可视化测试 Server:

bash
# 安装 MCP Inspector
npx @modelcontextprotocol/inspector claude mcp serve

浏览器会打开 Inspector UI,你可以在里面直接调用各个工具、查看返回的 JSON 响应,非常直观。

四、配置 MCP 客户端接入

MCP 客户端配置对比图

服务端准备好了,下一步是让 MCP 客户端(Claude Desktop、Cursor 等)接入它。不同客户端的配置文件路径略有不同,但格式都是统一的 JSON。

Claude Desktop 接入配置

配置文件路径:

  • macOS:~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows:%APPDATA%\Claude\claude_desktop_config.json
JSON — claude_desktop_config.json
{
  "mcpServers": {
    "claude-code": {
      "command": "claude",
      "args": ["mcp", "serve"],
      "env": {}
    }
  }
}
⚠️
配置完成后,必须完全退出并重新启动 Claude Desktop(不是最小化,要从系统托盘完全退出),新的 MCP Server 才会被检测到。

Cursor 接入配置

在 Cursor 的设置里找到 MCP 配置,或直接编辑项目根目录下的 .cursor/mcp.json

JSON — .cursor/mcp.json
{
  "mcpServers": {
    "claude-code": {
      "command": "claude",
      "args": ["mcp", "serve"],
      "env": {
        "ANTHROPIC_API_KEY": "sk-ant-..."
      }
    }
  }
}

多项目隔离配置

如果你有多个项目,可以为每个项目配置不同工作目录的 Server 实例:

JSON — 多项目 MCP 配置
{
  "mcpServers": {
    "project-frontend": {
      "command": "claude",
      "args": ["mcp", "serve"],
      "cwd": "/Users/me/projects/my-frontend"
    },
    "project-backend": {
      "command": "claude",
      "args": ["mcp", "serve"],
      "cwd": "/Users/me/projects/my-backend"
    }
  }
}
配置成功后,在 Claude Desktop 左下角的工具栏里会出现锤子图标,点击可以查看所有可用的 MCP 工具列表。如果没有出现,检查 JSON 语法(不能有尾逗号)或查看 Claude Desktop 的日志。

五、构建自定义 MCP 工具服务器

自定义 MCP 工具开发流程

前面的步骤让你能使用 Claude Code 内置的工具集。但 MCP 的真正威力在于:你可以用 TypeScript 或 Python 快速编写自己的工具服务器,给 Claude 扩展任何领域的能力——无论是查数据库、调内部 API,还是执行业务逻辑。

下面我们用官方的 TypeScript SDK 实现一个真实的工具服务器。以一个"代码质量检查工具"为例,它能调用 ESLint 并返回格式化后的结果。

1
初始化项目并安装依赖
bash
mkdir my-mcp-server && cd my-mcp-server
npm init -y

# 安装 MCP SDK 和必要的依赖
npm install @modelcontextprotocol/sdk zod

# TypeScript 支持
npm install -D typescript @types/node tsx
2
配置 TypeScript
JSON — tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}
3
编写 MCP Server 核心代码

创建 src/index.ts

TypeScript — src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { execSync } from "child_process";
import { readFileSync, existsSync } from "fs";
import { resolve } from "path";

// 创建 MCP Server 实例
const server = new McpServer({
  name: "code-quality-server",
  version: "1.0.0",
});

// ── 工具 1:ESLint 检查 ──
server.tool(
  "lint_file",
  "对指定文件运行 ESLint 检查,返回格式化后的 lint 结果",
  {
    file_path: z.string().describe("要检查的文件路径(相对或绝对路径)"),
    fix: z.boolean().optional().describe("是否自动修复可修复的问题,默认 false"),
  },
  async ({ file_path, fix = false }) => {
    const absPath = resolve(file_path);
    if (!existsSync(absPath)) {
      return {
        content: [{ type: "text", text: `错误:文件不存在 ${absPath}` }],
        isError: true,
      };
    }

    try {
      const fixFlag = fix ? "--fix" : "";
      const result = execSync(
        `npx eslint ${fixFlag} --format=compact "${absPath}"`,
        { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
      );
      return {
        content: [{ type: "text", text: result || "✓ 没有发现 lint 错误" }],
      };
    } catch (err: any) {
      // ESLint 发现问题时会以非零退出码退出,stdout 里有结果
      return {
        content: [{ type: "text", text: err.stdout || err.message }],
      };
    }
  }
);

// ── 工具 2:读取 package.json 依赖信息 ──
server.tool(
  "get_dependencies",
  "读取当前项目的 package.json,返回依赖列表和版本信息",
  {
    project_path: z.string().optional().describe("项目路径,默认当前目录"),
    type: z
      .enum(["all", "dependencies", "devDependencies"])
      .optional()
      .describe("依赖类型,默认 all"),
  },
  async ({ project_path = ".", type = "all" }) => {
    const pkgPath = resolve(project_path, "package.json");
    if (!existsSync(pkgPath)) {
      return {
        content: [{ type: "text", text: `未找到 package.json: ${pkgPath}` }],
        isError: true,
      };
    }

    const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
    const result: Record = { name: pkg.name, version: pkg.version };

    if (type === "all" || type === "dependencies") {
      result.dependencies = pkg.dependencies || {};
    }
    if (type === "all" || type === "devDependencies") {
      result.devDependencies = pkg.devDependencies || {};
    }

    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
    };
  }
);

// ── 启动服务 ──
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Code Quality MCP Server running on stdio");
}

main().catch((err) => {
  console.error("Fatal error:", err);
  process.exit(1);
});
4
配置构建命令并编译

package.jsonscripts 中添加:

JSON — package.json(scripts 部分)
{
  "scripts": {
    "build": "tsc",
    "dev": "tsx src/index.ts"
  },
  "type": "module"
}
bash
# 编译 TypeScript
npm run build

# 验证构建产物
ls build/
⚠️
使用 TypeScript 时,必须先 npm run build,否则 MCP 客户端启动时会找不到入口文件。这是最常见的新手坑。
5
注册到 MCP 客户端

将你的自定义 Server 添加到 Claude Desktop 配置:

JSON — claude_desktop_config.json
{
  "mcpServers": {
    "code-quality": {
      "command": "node",
      "args": ["/absolute/path/to/my-mcp-server/build/index.js"]
    }
  }
}

重启 Claude Desktop,然后在对话框里试用:"帮我检查 src/utils.ts 的 lint 问题"

用 Python 也可以:官方提供了 FastMCP 库(pip install mcp),用装饰器声明工具,代码量更少。TypeScript SDK 适合需要类型安全的团队项目,Python 适合快速原型。

六、常见问题排查指南

常见问题排查流程图

在实际接入过程中,有几类问题出现频率极高。下面按症状分类给出排查步骤:

claude 命令找不到(command not found)
运行 npm config get prefix 获取全局安装路径,然后把 <prefix>/bin 加入 PATH:
echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> ~/.zshrc && source ~/.zshrc
MCP Server 启动后卡住,客户端无法连接
macOS 上最常见原因是首次运行时没有授予文件夹访问权限。进入"系统设置 → 隐私与安全性 → 文件和文件夹",确认 Terminal 或 Claude Desktop 有访问权限,然后重新运行 claude --dangerously-skip-permissions "echo test"
JSON 配置报解析错误
JSON 不允许尾逗号(,},])。推荐用 jsonlint 校验:cat claude_desktop_config.json | npx jsonlint
工具调用返回 500 错误
500 是 Server 内部错误,说明你的 Server 代码抛出了未捕获的异常。在工具处理函数里加 try/catch,把 err.messageisError: true 的形式返回,方便调试。
Claude Desktop 工具列表里看不到我的服务器
检查三点:① JSON 语法是否正确;② command 指定的可执行文件是否存在(用绝对路径更稳定);③ 是否完全退出并重启了 Claude Desktop(不是刷新,要彻底关闭重开)。
在 Windows 上 stdout 被意外捕获导致通信失败
MCP stdio 传输使用 stdout 作为通信通道,Server 代码里绝对不能向 stdout 打印任何内容(包括调试日志)。所有日志必须写到 stderr:console.error("debug info"),而不是 console.log

查看 Claude Desktop 日志

当问题不明显时,查看 MCP 运行日志是最有效的手段:

bash — macOS
# 查看 Claude Desktop 的 MCP 日志
tail -f ~/Library/Logs/Claude/mcp*.log

七、进阶:多实例编排与工作流集成

多实例编排架构图

掌握基础配置后,下面介绍几种在生产环境中真正发挥 MCP 威力的进阶模式。

模式一:Plan → Execute → Verify 工作流

这是 Claude Code 官方推荐的高效协作模式:

  1. Plan:用 /plan 命令让 Claude 先分解任务,生成可审阅的步骤列表
  2. Execute:审核 Plan 后批准执行,Claude 通过 MCP 工具完成各步骤
  3. Verify:用 Bash 工具跑测试,把失败信息直接 pipe 给 Claude 定位修复
ℹ️
.claude/settings.json 里设置权限白名单,可以精确控制 MCP Server 能执行哪些命令,避免高危操作的副作用。例如只允许读取、禁止删除文件。

模式二:CLAUDE.md 项目上下文注入

在项目根目录创建 CLAUDE.md,每次启动会话时 Claude Code 会自动加载它,所有 MCP 工具调用都会带上这些上下文:

Markdown — CLAUDE.md
# Project: My SaaS Backend

## 技术栈
- Node.js + Fastify + TypeScript
- PostgreSQL(连接串在 .env 里)
- 测试框架:Vitest

## 编码规范
- 使用 Result 类型而非 throw 传递错误
- 所有数据库操作走 repository 层
- 新功能必须有对应的 .test.ts 文件

## 常用命令
- 跑测试:`npm test`
- 本地启动:`npm run dev`
- 数据库迁移:`npm run db:migrate`

模式三:多 Agent 编排

Claude Code 的 MCP Server 暴露了 Agent 工具,允许在任务执行中动态派生子 Agent。这使得复杂任务的并行处理成为可能:

Prompt — 通过 MCP 触发多 Agent
# 在 Claude Desktop 里发送的 Prompt
请帮我同时做三件事:
1. 检查 src/ 目录下所有 TypeScript 文件的 lint 错误
2. 在 README.md 里更新 API 文档
3. 运行测试并报告覆盖率

请并行处理,不要等每步完成再开始下一步。

Token 消耗监控

长时间的 MCP 会话会积累大量上下文,影响速度和成本。养成这些习惯:

  • 定期用 /cost 命令查看当前会话的 Token 消耗
  • /compact 压缩历史对话,保留核心摘要
  • /clear 在切换任务时重置上下文
  • @path/file 语法精确引用文件,而不是让 Claude 自己搜索

核心要点总结

  • MCP 采用 Host / Client / Server 三层架构,通过 JSON-RPC 2.0 通信
  • Claude Code 同时具备 MCP Client 和 MCP Server 两种身份,每层隔离
  • 首次使用必须运行 --dangerously-skip-permissions 完成权限初始化
  • claude mcp serve 以 stdio 模式暴露 Bash、Read、Write 等核心工具
  • TypeScript SDK 或 FastMCP 可快速构建自定义工具服务器
  • Server 代码绝对不能向 stdout 输出,日志必须写 stderr
  • 多项目用不同 cwd 的 Server 实例隔离,CLAUDE.md 注入项目上下文
Claude Code MCP Server JSON-RPC 2.0 stdio 传输 TypeScript SDK AI 工具集成