#MCP #AI Agent #Node.js #开发实战
MCP(Model Context Protocol)是 AI 客户端与外部工具之间的开放协议:Claude 系列、Hermes、Cursor 等 客户端通过它调用你写的工具,获得实时数据与执行能力。上一篇《MCP 协议入门》讲清了协议概念, 这篇直接动手:用 TypeScript 从零写一个可运行的 MCP Server,暴露「查 GitHub 仓库信息」工具, 并接入客户端调试运行。全部代码不超过 60 行,照着敲一遍就能跑。
需要 Node.js 18+(自带全局 fetch,无需安装 axios)。初始化项目并安装官方 SDK:
mkdir mcp-github-info && cd mcp-github-info
npm init -y
npm install @modelcontextprotocol/sdk zod
SDK 当前主版本为 1.x,下面的写法均基于 1.x。如果你装到的是 0.x 旧版,
先 npm install @modelcontextprotocol/sdk@latest 升级。
新建 server.js,完整代码如下:
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: "github-info",
version: "1.0.0",
});
server.tool(
"get_repo_info",
"查询 GitHub 仓库的基本信息(stars、语言、描述)",
{ owner: z.string().describe("仓库所属用户或组织"), repo: z.string().describe("仓库名") },
async ({ owner, repo }) => {
const r = await fetch(`https://api.github.com/repos/${owner}/${repo}`, {
headers: { "User-Agent": "mcp-github-info" },
});
if (!r.ok) {
return { content: [{ type: "text", text: `请求失败:HTTP ${r.status}` }] };
}
const d = await r.json();
return {
content: [{
type: "text",
text: `${d.full_name}:${d.description ?? "无描述"},stars ${d.stargazers_count},语言 ${d.language ?? "未知"},最近更新 ${d.updated_at}`,
}],
};
},
);
const transport = new StdioServerTransport();
await server.connect(transport);
三个关键点:
不接客户端也能自测:向 stdin 发一条初始化消息,看 stdout 是否回包:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"0.0.1"}}}' | node server.js | head -c 300
能收到带 serverInfo 的 JSON-RPC 响应,说明服务器本身没问题。
官方调试器 @modelcontextprotocol/inspector 提供网页界面,能看到工具列表、手动调用、参数校验错误:
npx @modelcontextprotocol/inspector node server.js
启动后浏览器打开提示的地址,左侧选工具 get_repo_info,填 owner=octocat、repo=Hello-World 调用,右侧会显示返回文本和耗时。参数缺省或类型错误时,Inspector 会直接展示 zod 的校验报错——这是排查「客户端说参数不对」的最快路径。
本地 stdio 型服务器通过客户端的 MCP 配置文件注册。以 Claude Code 为例,编辑 .mcp.json:
{
"mcpServers": {
"github-info": {
"command": "node",
"args": ["/绝对路径/server.js"]
}
}
}
Hermes 在设置页的 MCP 服务器面板添加同一条「本地命令」配置即可。配好后在对话里直接问「查一下 octocat/Hello-World 有多少 star」,客户端会自动调用工具并返回实时数据。注意:修改配置后要重启客户端会话,工具列表在连接时一次性加载。
上面的示例已经包含 zod 校验。再补两个实战惯例:
z.enum(["stars", "issues"]) 让客户端只能选合法参数,减少无效调用AbortSignal.timeout(10000) 给 fetch 加 10 秒超时,避免工具卡死整个会话isError: true 的 content,客户端会把它当工具失败而非正常结果本地 stdio 适合个人使用;要给团队或线上服务用,需要换成 HTTP 传输:
StreamableHTTPServerTransport 或社区框架(如 FastMCP)发布为 SSE/HTTP 端点60 行代码,一个可用的 GitHub 查询工具服务器就完成了:本地自测通过、Inspector 验证参数校验、 接入客户端后对话即用。下一步可以给服务器加第二个工具(比如查询仓库 Issues), 或者换成 HTTP 传输部署到服务器上,把个人工具变成团队服务。