MCP Inspector:最重要的调试工具
MCP Inspector 是官方提供的可视化调试工具,是开发 MCP Server 的必备利器。它提供了一个 Web 界面,无需配置 Claude Desktop 就能直接连接并测试 Server 的所有能力。
MCP Inspector ┌─────────────────────────────────────────────────────────┐ │ 浏览器 Web 界面(http://localhost:5173) │ │ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │ │ Tools │ │ Resources │ │ Prompts │ │ │ │ 列举工具 │ │ 列举资源 │ │ 列举模板 │ │ │ │ 调用测试 │ │ 读取内容 │ │ 获取填充 │ │ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────┐ │ │ │ JSON-RPC 消息日志(实时) │ │ │ │ → {"method":"tools/call","params":{...}} │ │ │ │ ← {"result":{"content":[...]}} │ │ │ └─────────────────────────────────────────────────┘ │ └──────────────────────────┬──────────────────────────────┘ │ stdio / HTTP MCP Server (你的 Server 进程)
启动 Inspector
# 基本用法:连接 stdio Server npx @modelcontextprotocol/inspector node dist/index.js # 使用 tsx 直接运行 TypeScript npx @modelcontextprotocol/inspector tsx src/index.ts # 传递环境变量 GITHUB_TOKEN=xxx npx @modelcontextprotocol/inspector node dist/index.js # 连接 HTTP Server(Streamable HTTP 传输) npx @modelcontextprotocol/inspector --transport http --url http://localhost:3000/mcp # 指定不同端口(默认 5173) npx @modelcontextprotocol/inspector --port 5174 node dist/index.js
Inspector 主要功能
Tools 测试
列举所有工具,填写参数并直接调用,查看返回结果和错误信息
Resources 浏览
列举并读取所有资源,查看内容类型和内容本身
Prompts 预览
列举并获取填充后的 Prompt,预览生成的消息序列
消息日志
实时查看所有 JSON-RPC 请求和响应,方便排查协议层面的问题
单元测试策略
MCP Server 的单元测试重点在于测试工具处理函数的业务逻辑,而不是 MCP 协议本身。
提取可测试的处理函数
// handlers/file-tools.ts — 将处理逻辑独立出来,便于测试 import * as fs from "fs/promises"; import * as path from "path"; export interface ReadFileOptions { allowedBase: string; } export async function readFileHandler( filePath: string, options: ReadFileOptions ): Promise<{ content: string; error?: string }> { const resolved = path.resolve(filePath); const base = path.resolve(options.allowedBase); if (!resolved.startsWith(base)) { return { content: "", error: `访问被拒绝:${resolved}` }; } try { const content = await fs.readFile(resolved, "utf-8"); return { content }; } catch (err) { return { content: "", error: (err as Error).message }; } }
使用 Vitest 编写测试
// handlers/file-tools.test.ts import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { readFileHandler } from "./file-tools.js"; import * as fs from "fs/promises"; import * as os from "os"; import * as path from "path"; describe("readFileHandler", () => { let tmpDir: string; beforeAll(async () => { tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "mcp-test-")); await fs.writeFile(path.join(tmpDir, "test.txt"), "Hello MCP!"); }); afterAll(async () => { await fs.rm(tmpDir, { recursive: true }); }); it("应该能读取允许目录内的文件", async () => { const result = await readFileHandler( path.join(tmpDir, "test.txt"), { allowedBase: tmpDir } ); expect(result.error).toBeUndefined(); expect(result.content).toBe("Hello MCP!"); }); it("应该拒绝路径遍历攻击", async () => { const result = await readFileHandler( path.join(tmpDir, "../..", "etc/passwd"), { allowedBase: tmpDir } ); expect(result.error).toContain("访问被拒绝"); }); it("应该在文件不存在时返回错误", async () => { const result = await readFileHandler( path.join(tmpDir, "nonexistent.txt"), { allowedBase: tmpDir } ); expect(result.error).toBeDefined(); }); });
集成测试
集成测试验证 MCP 协议层的完整交互,使用 SDK 的 Client 直接连接 Server 进行测试:
// integration.test.ts import { describe, it, expect, beforeAll, afterAll } from "vitest"; import { Client } from "@modelcontextprotocol/sdk/client/index.js"; import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js"; describe("MCP Server 集成测试", () => { let client: Client; beforeAll(async () => { // 启动 Server 进程并建立 MCP 连接 const transport = new StdioClientTransport({ command: "node", args: ["dist/index.js"], env: { ...process.env, NODE_ENV: "test" }, }); client = new Client( { name: "test-client", version: "1.0.0" }, { capabilities: {} } ); await client.connect(transport); }); afterAll(async () => { await client.close(); }); it("应该返回工具列表", async () => { const { tools } = await client.listTools(); expect(tools.length).toBeGreaterThan(0); // 检查特定工具是否存在 const addTool = tools.find(t => t.name === "add"); expect(addTool).toBeDefined(); }); it("add 工具应该返回正确结果", async () => { const result = await client.callTool({ name: "add", arguments: { a: 3, b: 4 }, }); expect(result.isError).toBeFalsy(); expect(result.content[0].type).toBe("text"); const textContent = result.content[0] as { type: "text"; text: string }; expect(textContent.text).toContain("7"); }); });
发布到 npm / PyPI
npm 发布准备
{
"name": "@yourname/mcp-server-mytools",
"version": "1.0.0",
"description": "MCP Server for ...",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"bin": {
"mcp-server-mytools": "dist/index.js"
},
"files": ["dist", "README.md"],
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build"
},
"keywords": ["mcp", "model-context-protocol", "claude"],
"peerDependencies": {
"@modelcontextprotocol/sdk": "^1.0.0"
}
}
# 构建并发布到 npm npm run build npm login npm publish --access public # 发布后,用户可以这样使用: npx @yourname/mcp-server-mytools
README 最佳实践
MCP Server 的 README 应包含:
- Server 功能的简明描述和使用场景
- 提供哪些 Tools / Resources / Prompts 及其说明
- Claude Desktop 配置示例(JSON 片段)
- 必需的环境变量列表及获取方式
- 权限要求说明(访问哪些系统资源)
向 MCP Registry 提交
MCP Registry(registry.modelcontextprotocol.io)是官方的 Server 目录,提交后可以大幅提升发现率。
- 确保 npm 包已发布,README 完整清晰
- 访问
github.com/modelcontextprotocol/servers - Fork 仓库,在
README.md中的社区 Server 列表添加你的 Server 条目 - 提交 Pull Request,等待 Maintainer 审核
- 审核通过后,Server 会出现在 Claude Desktop 和其他 MCP 工具的推荐列表中
发布前检查清单
发布前务必完成:1) 所有功能有单元测试且通过;2) 在真实 Claude Desktop 中完成 end-to-end 测试;3) README 包含安装和配置说明;4) 版本号遵循语义化版本控制(semver);5) 安全审查已完成(无硬编码密钥、无路径遍历漏洞);6) 在 package.json 中包含 "mcp" 关键词便于发现。