如何给 Claude Code 或 Cursor 装上“手脚”?三步搞定 Node.js MCP 服务端开发与本地联调

如何给 Claude Code 或 Cursor 装上“手脚”?三步搞定 Node.js MCP 服务端开发与本地联调
如何给 Claude Code 或 Cursor 装上“手脚”?三步搞定 Node.js MCP 服务端开发与本地联调

如何给 Claude Code 或 Cursor 装上“手脚”?三步搞定 Node.js MCP 服务端开发与本地联调

在 AI 编程席卷开发者的今天,你是否也有过这样的困惑:虽然 Claude 3.5 Sonnet 和 GPT-4o 足够聪明,但它们依然被困在沙箱里,只能“纸上谈兵”。如果你想让 AI 自动读取你本地的某张图片并提取信息、或者直接查询你本地的 SQL 数据库,你只能手动复制粘贴,效率极低。

有没有办法给 AI 装上“手脚”,让它能够直接安全地调用你本地的工具、读取你的本地文件系统?

答案就是 MCP(Model Context Protocol,模型上下文协议)。这是 Anthropic 官方推出的一套开放协议,旨在标准化 AI Client 与本地/远程数据源及工具之间的通信。有了 MCP,你的 AI 助手(如 Claude Desktop、Claude Code、Cursor、Trae 等)就可以真正接入现实世界。

今天,我们就来手把手带大家使用 Node.js + TypeScript 从零开发、调试并发布一个专属的 MCP 服务,帮助你彻底释放 AI Agent 的本地生产力!


1. 什么是 MCP?为什么它是 AI 时代的“连接器”?

传统的 AI 交互范式中,客户端只负责把用户的 Prompts 发送给大模型,然后接收文本。即使大模型支持 Function Calling,开发者也必须针对每个客户端、每个工具编写私有的连接胶水代码,碎片化极其严重。

MCP 协议改变了这一切。它引入了客户端-服务器架构,将 AI 引擎与数据/工具解耦:

  • MCP Host (客户端):如 Claude Desktop、Cursor、Claude Code,它们是协议的发起方,负责将用户的自然语言转化为具体的工具调用。
  • MCP Server (服务端):暴露特定的 Tools、Resources 或 Prompts,为客户端提供实际的业务处理能力。
  • 通信通道:支持标准的本地标准输入输出(Stdio)或远程的服务器发送事件(SSE)。

MCP 核心协议架构

通过这种星型拓扑架构,你只需编写一次 MCP 服务,就可以无缝接入支持 MCP 的任意 AI 客户端中。

在接下来的部分中,我们将针对硬核开发者,介绍如何从零搭建一个属于自己的 MCP Server。


2. 第一步:环境与脚手架准备

在开始开发前,请确保你本地已安装 Node.js 环境(推荐 Node.js v18 或以上版本,建议使用 NVM 进行多版本管理)。

你可以通过以下命令检查环境:

node --version
npm --version

初始化项目的核心方法

初始化 MCP 项目主要有三种途径:

  • 方法一(官方脚手架):使用 Anthropic 官方提供的 create-server 工具一键生成 TypeScript 模板:bashnpx @modelcontextprotocol/create-server my-mcp-server --name "My MCP Server" --description "A custom MCP server"
  • 方法二(手动配置):如果你希望完全掌控依赖与项目结构,可以手动搭建项目。这也是我们本文重点演示的方案,能够让你彻底搞懂依赖关系。
  • 方法三(Fork 官方生态):直接在官方的 Server 汇总仓库 中挑选一个现成的 Server(如 filesystem、git、postgres 等),在其基础上进行二次开发。

3. 第二步:手动搭建 Node.js TypeScript MCP 项目

为了深入理解 MCP 协议的工作原理,我们采用方法二(手动配置)来构建一个用于本地读取图片的 MCP 服务。

3.1 项目初始化与依赖安装

在控制台中执行以下命令,创建项目文件夹并初始化 package.json

mkdir image-processor
cd image-processor
npm init -y
mkdir src
touch src/index.ts

接下来,我们需要编辑 package.json。MCP 服务的运行依赖官方的 @modelcontextprotocol/sdk,同时我们使用 zod 进行工具入参的强类型校验,使用 zod-to-json-schema 将 Zod 格式自动转换为大模型所需的 JSON Schema。

请将 package.json 替换为以下内容:

{
"name": "mcp-image-processor",
"version": "1.0.0",
"description": "A custom MCP server for image reading and processing",
"type": "module",
"bin": {
"mcp-image-processor": "./build/index.js"
},
"scripts": {
"build": "tsc && chmod +x build/index.js",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.0.4",
"zod": "^3.24.1",
"zod-to-json-schema": "^3.24.1"
},
"devDependencies": {
"@types/node": "^22.10.2",
"typescript": "^5.7.2"
}
}

运行安装命令:

npm install

3.2 配置 TypeScript 编译环境

在项目根目录下创建 tsconfig.json 文件,并填入以下现代 Node.js 编译选项:

{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}

3.3 编写 MCP 核心逻辑

打开 src/index.ts,写入如下完整的核心代码。这段代码主要做了三件事:

1. 实例化 Server 对象,定义服务名与版本。

2. 注册 ListToolsRequestSchema 处理器,向 AI 客户端声明支持的 Tool 列表(包含入参 JSON Schema)。

3. 注册 CallToolRequestSchema 处理器,实现具体的工具执行逻辑,即读取本地图片并转化为 Base64 返回。

#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { zodToJsonSchema } from "zod-to-json-schema";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ToolSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { z } from "zod";
import path from "path";
import fs from "fs/promises";

const ToolInputSchema = ToolSchema.shape.inputSchema;
type ToolInput = z.infer<typeof ToolInputSchema>;

// 1. 初始化 MCP Server
const server = new Server(
{
name: "image-processor",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);

// 定义参数 Schema,限制输入路径为字符串
const ReadImageArgsSchema = z.object({
path: z.string().describe("本地图片的绝对路径"),
});

// 2. 声明暴露的工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "read-image",
description: "读取本地指定路径的图片,并返回 Base64 编码与 MIME 类型",
inputSchema: zodToJsonSchema(ReadImageArgsSchema) as ToolInput,
},
],
};
});

// 3. 处理工具具体调用的分发逻辑
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;

try {
if (name === "read-image") {
const parsed = ReadImageArgsSchema.safeParse(args);
if (!parsed.success) {
throw new Error(`参数校验失败: ${parsed.error.message}`);
}

const imagePath = path.resolve(parsed.data.path);

// 读取文件 Buffer
const imageBuffer = await fs.readFile(imagePath);
const base64String = imageBuffer.toString("base64");

// 提取后缀并识别对应的 MIME 类型
const ext = path.extname(imagePath).toLowerCase();
const mimeType =
{
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".gif": "image/gif",
".webp": "image/webp",
}[ext] || "application/octet-stream";

return {
content: [
{
type: "image",
data: base64String,
mimeType: mimeType,
},
],
};
} else {
throw new Error(`未知的工具: ${name}`);
}
} catch (error: any) {
console.error("执行时捕获异常:", error);
return {
isError: true,
content: [
{
type: "text",
text: `处理图片失败: ${error.message}`,
},
],
};
}
});

// 4. 建立基于 Stdio (标准输入输出) 的进程通信通道
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Image Processor Server running on stdio");
}

main().catch((error) => {
console.error("启动失败:", error);
process.exit(1);
});

⚠️ 核心排坑点:为什么 Server 日志必须输出到 console.error 因为本服务是通过命令行标准输入输出(Stdio)进行通信的,stdout 是协议数据传输的专用通道。如果你在代码中误用了 console.log() 来输出普通调试日志,该信息会被客户端错误地当做 MCP 协议报文解析,导致协议直接崩溃!所有的调试与生命周期日志必须输出至 stderr(即使用 console.error)。

在开发完成后,执行以下命令进行本地 TypeScript 编译:

npm run build

编译成功后,你会在根目录下看到生成的 build/index.js 产物。


4. 第三步:本地联调与验证

由于 MCP 协议是无状态的、由客户端驱动的,我们通常需要借助外部工具或客户端来验证它是否正常工作。

4.1 方式一:接入 Cursor 进行真实场景测试

如果你使用的是 Cursor 编辑器,你可以通过图形界面直接接入:

1. 打开 Cursor,进入 Settings -> Models -> MCP

2. 点击 + Add New MCP Server

3. 配置如下参数:- Name: image-processor- Type: command- Command: node c:/你的路径/image-processor/build/index.js (请替换为实际绝对路径)

如何给 Claude Code 或 Cursor 装上“手脚”?三步搞定 Node.js MCP 服务端开发与本地联调

4. 点击保存后,看到状态显示为绿色的 Connected 即表示接入成功。

现在你就可以在 Cursor Chat 或 Composer 模式下直接对 AI 说:“帮我分析一下 d:/mock/test_image.png 这张架构图画了什么”,AI 就会自动调用 read-image 抓取该图片并完成分析!

4.2 方式二:使用官方 MCP Inspector 独立调试

如果你不想频繁重启 AI 客户端,或者需要检查协议的收发包报文,推荐使用官方的 MCP Inspector。这是一款功能极其强大、带 Web UI 的进程级联调工具。

1. 全局安装调试器:bashnpm install -g @modelcontextprotocol/inspector

2. 启动 Inspector(需要传入你的 server 入口绝对路径):bashnpx @modelcontextprotocol/inspector node c:/你的路径/image-processor/build/index.js

3. 启动成功后,控制台会输出一个本地 Web UI 地址(通常是 http://localhost:5173/)。

4. 在浏览器中打开该地址,点击左上角的 Connect 按钮建立会话,你就可以直观地在 UI 界面中看到注册的 read-image 工具。填入参数,点击 Run Tool 即可立即发起调用测试,还能实时查看到底层的 JSON-RPC 通信数据报文。


5. 第四步:打包发布到 npm

当你的 MCP 服务开发稳定,希望分享给团队或全球开发者使用时,最佳方式是将其发布为独立的 npm 包。

1. 配置 binary 入口:在 package.json 中配置 "bin" 字段指向构建出来的 index.js(已在 package.json 模板中配置完成)。

2. 构建打包bashnpm run build

3. 发布 npm(请确保已登录 npm 账号):bashnpm publish

4. 共享接入:发布成功后,其他开发者无需将你的源码拉到本地,直接在 Cursor 或 Claude Desktop 的配置文件中将启动命令改为:json"image-processor": {"command": "npx","args": ["-y", "你的npm包名"]}即可一键完成拉取与启动!


总结:AI 工具革命的新起点

MCP 将大模型从“单兵作战”推进到了“万物互联”的新时代。从前端工程师的角度来看: - Claude Desktop / Cursor 扮演着类似浏览器的底座角色。 - MCP Server 则是各种提供专业数据的网站与微型 API 站点。 - 本地文件与远程接口就是底层的后端支撑。

通过极简的协议契约,我们用几十行 TypeScript 就可以将复杂的本地能力完美桥接到大模型中。赶紧动手编写一个属于你自己的 MCP Server 吧,给你的 AI 装上划时代的“手脚”!


公众号二维码

长按二维码关注 “边学边练”

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

相关阅读

最新文章

热门文章

本栏目文章