Alejandro Rioja.
AI Agents

如何构建你的第一个MCP服务器:实践指南

Alejandro Rioja
Alejandro Rioja
2 分钟阅读
TL;DR

MCP(模型上下文协议)是给Claude提供对外部工具和数据(数据库、文件、API)结构化访问的方式,而无需塞满上下文窗口。服务器比看起来简单:安装SDK,将工具定义为JSON schema,实现处理器,通过stdio连接。30分钟内就能让Claude调用你的自定义工具。

免费新闻通讯

每周三。28,400+ 读者。纯干货。

目录

2026年6月更新。

TL;DR: MCP(模型上下文协议)是给Claude提供对外部工具和数据(数据库、文件、API)结构化访问的方式,而无需塞满上下文窗口。服务器比看起来简单:安装SDK,将工具定义为JSON schema,实现处理器,通过stdio连接。30分钟内就能让Claude调用你的自定义工具。

[运营者视角] 我定期将新工具接入我的智能体,MCP现在是干净实现这一点的标准路径。服务器一旦构建完成,每个支持MCP的客户端——Claude Desktop、Claude Code、任何使用Anthropic SDK的应用——都可以在不修改调用代码的情况下使用它。这就是价值所在:构建一次,随处复用。

MCP究竟是什么

模型上下文协议是一个开放协议,标准化了AI模型连接外部上下文和工具的方式。把它想象成AI集成的USB-C标准:在此之前,每个想让Claude读取数据库或调用API的应用都必须自己发明一套解决方案。有了它,你构建一个MCP服务器,任何兼容的主机都可以使用它。

MCP定义了服务器可以提供的三类内容:

对于大多数运营者用例,你在构建工具服务器。资源和提示词在基础工作运行后再处理。

架构是客户端-服务器模式,由客户端(Claude Desktop、Claude Code、你的自定义应用)控制一切。服务器是被动的——只是监听工具调用请求并返回结果。

每个MCP服务器的三个组成部分

你构建的每个MCP服务器都有相同的结构:

  1. 服务器对象 — 声明服务器的名称、版本和能力(工具、资源、提示词)
  2. 工具定义 — 包含名称、描述和输入JSON schema的工具列表
  3. 请求处理器 — Claude调用工具时运行的函数

就这些。开始时不需要数据库、HTTP栈或认证层。最小服务器不到30行TypeScript。

前置条件(2分钟)

运行MCP服务器本身不需要Anthropic API密钥。API密钥在客户端(Claude Desktop)中,不在你的服务器中。

第一步:设置项目(3分钟)

bash
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript tsx @types/node

添加到package.json

json
{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "dev": "tsx src/index.ts"
  }
}

创建tsconfig.json

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "strict": true
  },
  "include": ["src/**/*"]
}

第二步:编写最小服务器(5分钟)

创建src/index.ts

typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "my-mcp-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

// 声明此服务器提供的工具
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "get_word_count",
      description: "统计文本块中的单词数。",
      inputSchema: {
        type: "object",
        properties: {
          text: {
            type: "string",
            description: "要统计单词的文本",
          },
        },
        required: ["text"],
      },
    },
  ],
}));

// 处理客户端的工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "get_word_count") {
    const { text } = args as { text: string };
    const count = text.trim().split(/\s+/).filter(Boolean).length;
    return {
      content: [{ type: "text", text: `单词数:${count}` }],
    };
  }

  throw new Error(`未知工具:${name}`);
});

// 通过stdio连接——这是Claude Desktop与服务器通信的方式
const transport = new StdioServerTransport();
await server.connect(transport);

这就是完整的服务器。它注册一个工具(get_word_count)并实现它。结构才是关键。

第三步:构建并在Claude Desktop中注册(5分钟)

构建TypeScript:

bash
npm run build

在Claude Desktop的配置文件中注册它。

macOS~/Library/Application Support/Claude/claude_desktop_config.json Windows%APPDATA%\Claude\claude_desktop_config.json

如果文件不存在,创建它:

json
{
  "mcpServers": {
    "my-mcp-server": {
      "command": "node",
      "args": ["/my-mcp-server的绝对路径/build/index.js"]
    }
  }
}

使用绝对路径。保存后重启Claude Desktop。你会在消息输入栏看到锤子图标(🔨)——这意味着Claude已发现你的工具。

第四步:构建一个有用的工具

词数统计是用于说明的。这里有个更有用的工具:从项目目录读取文件,这是我用于汇总代码库、changelog或配置文件的上下文注入智能体的方案。

typescript
import { readFileSync, readdirSync } from "fs";
import { join, extname } from "path";

const ALLOWED_EXTENSIONS = [".md", ".txt", ".ts", ".json", ".yaml"];
const PROJECT_DIR = process.env.PROJECT_DIR ?? process.cwd();

逻辑是相同的:用精确的JSON schema定义工具,实现处理器,验证输入以防止路径遍历,并向客户端返回文本。

我踩过的坑(让你不要再踩)

路径必须是绝对路径。 Claude Desktop配置中的相对路径不会按预期解析。始终使用完整路径/home/user/...

stdio意味着服务器中不能使用console.log Claude Desktop通过stdin/stdout与服务器通信。调试用的console.log会损坏JSON-RPC流。改用stderr记录日志:

typescript
process.stderr.write(`调试:${message}\n`);

每次配置更改后重启Claude Desktop。 MCP服务器在启动时加载。编辑的配置文件在关闭并重新打开应用之前不会生效。

工具描述就是产品。 Claude根据description字段决定是否调用你的工具。描述模糊意味着Claude不知道何时使用它。描述精确意味着Claude在正确时机使用它。在描述上花费比实现更多的时间。

我如何在生产中使用MCP服务器

stdio模式非常适合Claude Desktop和Claude Code(本地)。对于生产智能体——在Cloudflare Workers上运行的30个以上——我直接使用Anthropic SDK的tool-use API,因为我需要按步骤灵活路由到Haiku还是Sonnet

我实际使用的模式:

  1. 本地开发工具 — 为Claude Code提供项目特定工具的MCP服务器
  2. 上下文注入 — 无需手动复制即可预加载相关文档的MCP服务器
  3. 原型到API的桥梁 — 先构建MCP(迭代更快),然后将逻辑移植到SDK tool-use用于生产

接下来构建什么

一旦服务器结构清晰,有用的工具就是那些访问Claude外部上下文的工具:

常见问题

构建MCP服务器需要Anthropic API密钥吗?

不需要。你的MCP服务器不调用Anthropic API。它只是响应客户端的工具调用请求。API密钥在客户端,不在服务器中。

我的MCP服务器可以调用外部API吗?

可以——处理器只是异步TypeScript代码。获取天气API、查询数据库、写入文件。服务器不关心处理器内部做什么。

stdio和HTTP传输有什么区别?

stdio用于本地服务器——与Claude Desktop或Claude Code在同一台机器上。HTTP with SSE用于可以部署为Web服务的远程服务器。从stdio开始;调试更简单。

Claude如何知道何时调用我的工具?

Claude根据工具的description字段和对话上下文做出决定。如果Claude持续忽略你的工具,请精炼描述。

继续阅读

将AI实战手册发送到您的邮箱

每周三。28,400+ 读者。纯干货。

↵ 查看全部结果 esc esc 关闭