Token导航 LogoToken导航

MCP Server · 开发工具

MCP Dev Kit

为Model Context Protocol (MCP)服务器提供全面的测试、调试和日志记录工具,包括智能快照测试、自定义匹配器和安全的调试日志记录。

stdio官方级别未说明来源级核验工具 0vitest
开发工具TypeScriptJavaScript

快速开始

作者 / 组织
gnana997
提供方
gnana997
运行时
Node.js

工具数量

0

来源目录标注

资源数量

0

来源目录标注

提示词数量

0

来源目录标注

GitHub Star

1

仓库热度

收录来源

1 个

MCP World

选型结论

MCP Dev Kit 属于开发工具类 MCP Server,公开资料标注 0 个工具,通过stdio 本地进程接入,客户端适配情况以官方文档为准,有可以直接复制的安装命令;接入前要先准备 访问 Token。

分类

开发工具

传输方式

stdio

认证方式

访问 Token

部署方式

公开资料未说明

安装与配置

安装命令

npx vitest

客户端配置示例

{
  "mcpServers": {
    "mcp-dev-kit": {
      "command": "npx",
      "args": [
        "vitest"
      ]
    }
  }
}

按公开安装命令拼出来的示例,字段名和参数以仓库 README 为准;带 YOUR_API_KEY 这类占位符的位置记得换成自己的值。

上手步骤

  1. 1

    准备运行环境

    stdio 服务在本地起进程,需要先装好 Node.js,再按安装命令拉取依赖。

  2. 2

    安装服务

    复制下面的安装命令执行;命令里带占位符的位置换成自己的密钥或路径。

  3. 3

    写入客户端配置

    在客户端的 MCP 配置里填启动命令和参数,保存后完全退出客户端再打开,让新配置生效。

  4. 4

    验证是否可用

    连接成功后客户端会列出 0 个工具,随便调一个只读工具确认能返回结果。

接入前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

详细介绍

mcp开发工具包

模型上下文协议(MCP)服务器的完整测试和调试工具包

使用全面的测试工具、智能快照测试和stdio安全调试日志构建可靠的MCP服务器。

为什么选择mcp开发工具包?

开发MCP服务器面临着独特的挑战:

  • ❌ 测试很难 -MCP服务器没有内置测试实用程序
  • ❌ 快照中断 -每次运行时,时间戳和ID都会发生变化
  • ❌ 日志记录中断stdio - console.log() 破坏JSON-RPC通信
  • ❌ 手动断言 -用于常见检查的重复样板

mcp-dev-kit解决了所有这些问题:

  • ✅ MCPTestClient -MCP服务器的全功能测试客户端
  • ✅ 智能快照 -自动排除动态字段(时间戳、ID)
  • ✅ 定制火柴 -工具、资源、提示的可读断言
  • ✅ 安全记录 -调试时不破坏JSON-RPC协议

快速开始

安装

npm install --save-dev mcp-dev-kit vitest

基本测试设置

1.创建 vitest.setup.ts:

import { installMCPMatchers } from 'mcp-dev-kit/matchers';

installMCPMatchers();

2.配置 vitest.config.ts:

import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'node',
    setupFiles: ['./vitest.setup.ts'],
  },
});

3.编写测试(server.test.ts):

import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { MCPTestClient } from 'mcp-dev-kit/client';

describe('My MCP Server', () => {
  let client: MCPTestClient;

  beforeAll(async () => {
    client = new MCPTestClient({
      command: 'node',
      args: ['./my-server.js'],
    });
    await client.connect();
  });

  afterAll(async () => {
    await client.disconnect();
  });

  it('should list available tools', async () => {
    const tools = await client.listTools();
    expect(tools).toHaveLength(2);
    expect(tools[0]).toHaveToolProperty('name', 'echo');
  });

  it('should execute tools successfully', async () => {
    const result = await client.callTool('echo', { message: 'hello' });
    await expect(result).toReturnToolResult('hello');
  });

  it('should have stable response structure', async () => {
    const result = await client.callTool('list_files', { path: '/' });
    expect(result).toMatchToolResponseSnapshot();
  });
});

4.将调试日志添加到服务器:

// At the top of your MCP server file
import 'mcp-dev-kit/logger';

// Now console.log works without breaking JSON-RPC!
console.log('Server started');
console.error('Connection error', error);

5.运行测试:

npx vitest

特性

MCP测试客户端

通过stdio生成和测试MCP服务器的综合测试客户端。

import { MCPTestClient } from 'mcp-dev-kit/client';

const client = new MCPTestClient({
  command: 'node',
  args: ['./my-server.js'],
  env: { DEBUG: 'true' },
  timeout: 30000,
});

await client.connect();

// Test server capabilities
const serverInfo = client.getServerInfo();
const capabilities = client.getServerCapabilities();

// List and call tools
const tools = await client.listTools();
const result = await client.callTool('my-tool', { param: 'value' });

// List and read resources
const resources = await client.listResources();
const content = await client.readResource('file://config.json');

// List and get prompts
const prompts = await client.listPrompts();
const prompt = await client.getPrompt('greeting', { name: 'Alice' });

// Helper methods for common patterns
const toolResult = await client.expectToolCallSuccess('my-tool', { input: 'test' });
const error = await client.expectToolCallError('bad-tool', {});

await client.disconnect();

主要特点:

  • 自动流程生命周期管理
  • 请求/响应与超时匹配
  • 服务器通知处理
  • 全面的错误处理
  • TypeScript优先,具有完全类型安全性

定制Vitest配对器

用于MCP特定测试的可读、富有表现力的断言。

import { installMCPMatchers } from 'mcp-dev-kit/matchers';

installMCPMatchers();

可用匹配器:

// Tool assertions
await expect(client).toHaveTool('echo');
const tools = await client.listTools();
expect(tools[0]).toHaveToolProperty('description', 'Echoes back the message');
expect(tools[0]).toMatchToolSchema({
  type: 'object',
  required: ['message']
});

// Resource assertions
await expect(client).toHaveResource('config://app.json');
const resources = await client.listResources();
expect(resources[0]).toHaveProperty('uri', 'config://app.json');

// Prompt assertions
await expect(client).toHavePrompt('greeting');
const prompts = await client.listPrompts();
expect(prompts[0]).toHaveProperty('name', 'greeting');

// Tool result assertions
const result = await client.callTool('echo', { message: 'test' });
await expect(result).toReturnToolResult('test');
await expect(client.callTool('unknown', {})).toThrowToolError();

优点:

  • 清晰、自文档化的测试代码
  • 测试失败时更好的错误消息
  • 减少测试文件中的样板
  • 使用TypeScript进行类型安全

快照测试

MCP感知快照测试,具有智能现场排除功能。

为什么要对MCP进行快照测试?

MCP服务器响应通常包含每次运行时都会发生变化的动态数据:

  • 时间戳(2024-11-03T10:30:00.000Z)
  • 请求ID(abc123)
  • 执行时间(42.5ms)
  • 自动递增ID、文件索引节点、git SHA

每次运行时,常规快照测试都会失败。 mcp-devkit会自动排除这些字段 同时捕获稳定的响应结构。

快速示例
import { installMCPMatchers } from 'mcp-dev-kit/matchers';

installMCPMatchers();

describe('File System Server', () => {
  it('should return consistent file listing structure', async () => {
    const result = await client.callTool('list_files', { path: '/project' });

    // Timestamps, IDs, and dynamic fields automatically excluded!
    expect(result).toMatchToolResponseSnapshot();
  });

  it('should have stable tool definitions', async () => {
    const tools = await client.listTools();

    // Captures tool schemas for regression detection
    expect(tools).toMatchToolListSnapshot();
  });

  it('should snapshot custom data structures', async () => {
    const data = {
      users: [...],
      timestamp: new Date().toISOString(), // Auto-excluded
      requestId: 'abc123',                   // Auto-excluded
    };

    expect(data).toMatchMCPSnapshot();
  });
});
可用的快照匹配器

toMatchMCPSnapshot(options?) -任何MCP数据的通用快照匹配器

expect(serverResponse).toMatchMCPSnapshot();
expect(data).toMatchMCPSnapshot({ exclude: ['user.id', 'files.*.size'] });

toMatchToolResponseSnapshot(options?) -工具调用结果

const result = await client.callTool('query_database', { query: 'SELECT * FROM orders' });
expect(result).toMatchToolResponseSnapshot();

toMatchToolListSnapshot(options?) -关于工具定义

const tools = await client.listTools();
expect(tools).toMatchToolListSnapshot();

toMatchResourceListSnapshot(options?) -关于资源列表

const resources = await client.listResources();
expect(resources).toMatchResourceListSnapshot();

toMatchPromptListSnapshot(options?) -用于快速定义

const prompts = await client.listPrompts();
expect(prompts).toMatchPromptListSnapshot();
智能默认值

这些字段是 自动排除 从所有快照中:

  • timestamp
  • requestId
  • executionTime
  • cacheKey
  • _meta.timestamp
  • serverInfo.startedAt
  • serverInfo.uptime

例子:

// Original response
{
  "users": [...],
  "timestamp": "2024-11-03T10:30:00.000Z",  // ❌ Excluded
  "requestId": "abc123",                     // ❌ Excluded
  "executionTime": 42.5                      // ❌ Excluded
}

// Snapshot (only stable data)
{
  "users": [...]  // ✅ Captured
}
自定义排除

使用glob模式排除其他字段:

// Exclude file system-specific fields
expect(result).toMatchToolResponseSnapshot({
  exclude: ['files.*.size', 'files.*.inode', 'files.*.modified']
});

// Exclude all auto-increment IDs
expect(data).toMatchMCPSnapshot({
  exclude: ['*.id', '*.userId', 'rows.*.orderId']
});

// Exclude nested timestamps with custom names
expect(response).toMatchMCPSnapshot({
  exclude: ['data.users.*.createdAt', 'metadata.generatedAt']
});

模式语法:

  • field -不包括顶级字段
  • nested.field -排除嵌套字段
  • array.*.field -从所有数组项中排除字段
  • data.users.*.createdAt -不包括 createdAt 来自所有用户 data.users
演出

带有属性排除的快照测试增加的开销可以忽略不计:

数据大小标准化开销备注
10-100个项目\ {

const result = await client.callTool('list_users', {}); const parsed = JSON.parse(result.content[0]?.text || '{}');

// Explicit assertions for critical properties expect(parsed.users).toHaveLength(50); expect(parsed.users[0]).toHaveProperty('name'); expect(parsed.users[0]).toHaveProperty('email');

// Snapshot for structure regression detection expect(result).toMatchToolResponseSnapshot(); });


看 [示例/快照示例/](./examples/snapshot-example/) 查看带有基准的完整工作示例。

### 调试日志记录

不会中断JSON-RPC stdio通信的安全调试日志记录。

#### 问题

MCP服务器通过stdio上的JSON-RPC进行通信。每条消息必须是stdout上的一行JSON:

{"jsonrpc":"2.0","method":"tools/list","params":{...}}\n


如果你在stdout中写任何其他东西(比如 `console.log()`),它腐蚀了溪流:

Server starting... ← Breaks protocol! {"jsonrpc":"2.0","method":"tools/list","params":{...}}\n


结果: `SyntaxError: Unexpected token 'S'`

#### 解决方案

**mcp-devkit将所有控制台输出重定向到stderr**,保持stdout干净:

- **标准输出** =纯JSON-RPC(协议)
- **标准错误** =所有日志(调试)

#### 自动修补程序(推荐)

// At the top of your MCP server file import 'mcp-dev-kit/logger';

// Now console.log works without breaking JSON-RPC! console.log('Server started', { port: 3000 }); console.info('Configuration loaded'); console.warn('Deprecated feature used'); console.error('Connection failed', error);


**选择退出:**

MCP_DEV_KIT_NO_AUTO_PATCH=true node server.js


#### 手动记录仪

为了获得更多控制,请创建一个自定义记录器实例:

import { createLogger } from 'mcp-dev-kit';

const logger = createLogger({ timestamps: true, colors: true, level: 'info', // Only show info and above logFile: './server.log', // Optional file output });

logger.info('Server starting...'); logger.warn('Configuration may need updating'); logger.error('Connection failed', { reason: 'timeout' });

// Cleanup when done await logger.close();


#### 记录器功能

- **自动修补** -只需导入并整合.log即可
- **彩色输出** -颜色编码日志级别(自动检测TTY)
- **时间戳** -所有日志上的ISO8601时间戳
- **对象格式化** -漂亮的打印对象 `util.inspect()`
- **文件日志记录** -可选异步文件输出
- **清理** -对原始控制台的优雅修复
- **零开销** -轻量级,使用微微色(7 KB)

#### 配置

**日志级别:**

const logger = createLogger({ level: 'warn' });

logger.debug('Not shown'); logger.info('Not shown'); logger.warn('Shown'); // ✓ logger.error('Shown'); // ✓


**颜色:**

createLogger({ colors: false }); // Force disable createLogger({ colors: true }); // Force enable // Auto-detected by default based on process.stderr.isTTY


**时间戳:**

createLogger({ timestamps: false }); // Disable // ISO8601 format: 2024-11-03T12:34:56.789Z


**文件日志记录:**

const logger = createLogger({ logFile: './server.log', });

logger.info('This goes to both stderr and server.log');

// Flush pending writes await logger.close();


## 测试指南

### 测试结构

按MCP功能组织测试:

describe('My MCP Server', () => { let client: MCPTestClient;

beforeAll(async () => { client = new MCPTestClient({ command: 'node', args: ['./server.js'] }); await client.connect(); });

afterAll(async () => { await client.disconnect(); });

describe('Server Initialization', () => { it('should expose correct server info', () => { const info = client.getServerInfo(); expect(info.name).toBe('my-server'); expect(info.version).toBe('1.0.0'); });

it('should declare required capabilities', () => { const caps = client.getServerCapabilities(); expect(caps.tools).toBeDefined(); }); });

describe('Tools', () => { it('should list all available tools', async () => { const tools = await client.listTools(); expect(tools).toHaveLength(3); expect(tools.map(t => t.name)).toEqual(['echo', 'calculate', 'search']); });

it('should execute tools successfully', async () => { const result = await client.callTool('echo', { message: 'test' }); expect(result.content[0]?.text).toBe('test'); });

it('should handle tool errors gracefully', async () => { const error = await client.expectToolCallError('calculate', { invalid: 'params' }); expect(error.message).toContain('Invalid parameters'); });

it('should have stable tool schemas', async () => { const tools = await client.listTools(); expect(tools).toMatchToolListSnapshot(); }); });

describe('Resources', () => { it('should list available resources', async () => { await expect(client).toHaveResource('config://app.json'); });

it('should read resource content', async () => { const content = await client.readResource('config://app.json'); expect(content.contents[0]?.text).toContain('version'); }); });

describe('Prompts', () => { it('should provide defined prompts', async () => { await expect(client).toHavePrompt('greeting'); });

it('should render prompts with arguments', async () => { const prompt = await client.getPrompt('greeting', { name: 'Alice' }); expect(prompt.messages[0]?.content.text).toContain('Alice'); }); }); });


### 测试最佳实践

**✅ 做:**

1. **测试所有MCP功能** -工具、资源、提示
1. **使用描述性测试名称** -明确说明正在测试的内容
1. **结合匹配和快照** -显式断言+结构验证
1. **测试错误案例** -不要只测试快乐的道路
1. **清理资源** -始终断开客户端连接 `afterAll`
1. **适当使用超时** -为慢速操作设置合理的超时
1. **测试服务器生命周期** -测试初始化和关闭

**❌ 不要:**

1. **不共享客户端状态** -每个测试套件都应该有自己的客户端
1. **不要跳过错误测试** -错误处理至关重要
1. **不测试实现细节** -仅测试公共API
1. **不要创建不稳定的测试** -避免依赖时间的断言
1. **不要忽略快照** -仔细查看快照更改
1. **不要硬编码系统特定的路径** -使用相对路径或环境变量

### 错误测试

始终测试错误条件:

it('should validate tool parameters', async () => { const error = await client.expectToolCallError('calculate', { // Missing required parameter }); expect(error.code).toBe(-32602); // Invalid params expect(error.message).toContain('Required parameter'); });

it('should handle resource not found', async () => { await expect( client.readResource('nonexistent://resource') ).rejects.toThrow('Resource not found'); });

it('should reject unknown tools', async () => { await expect( client.callTool('unknown-tool', {}) ).rejects.toThrow(); });


### 性能测试

关键操作的测试响应时间:

it('should respond quickly to tool calls', async () => { const start = Date.now(); await client.callTool('quick-operation', {}); const duration = Date.now() - start;

expect(duration).toBeLessThan(1000); // { // 1. List available tools const tools = await client.listTools(); expect(tools.length).toBeGreaterThan(0);

// 2. Get resource for context const config = await client.readResource('config://app.json'); const settings = JSON.parse(config.contents[0]?.text || '{}');

// 3. Execute tool with context const result = await client.callTool('process', { mode: settings.defaultMode, }); expect(result.content[0]?.text).toBeTruthy();

// 4. Verify result structure expect(result).toMatchToolResponseSnapshot(); });


## 例子

看 [示例/](./examples/) 完整示例目录:

- **[快照示例/](./examples/snapshot-example/)** -使用基准完成快照测试
- **[记录器/基本用法.ts](./examples/logger/basic-usage.ts)** -自动补丁控制台
- **[记录器/手动设置.ts](./examples/logger/manual-setup.ts)** -自定义记录器实例
- **[logger/file-loging.ts](./examples/logger/file-logging.ts)** -记录到文件
- **[logger/mcp-server-example.ts](./examples/logger/mcp-server-example.ts)** -真正的MCP服务器

运行示例:

npm install -g tsx tsx examples/logger/basic-usage.ts


## API 参考

### MCPTestClient

class MCPTestClient { constructor(options: { command: string; args?: string[]; env?: Record; timeout?: number; });

// Connection management connect(): Promise; disconnect(): Promise;

// Server info getServerInfo(): ServerInfo; getServerCapabilities(): ServerCapabilities;

// Tools listTools(): Promise; callTool(name: string, args: unknown): Promise; expectToolCallSuccess(name: string, args: unknown): Promise; expectToolCallError(name: string, args: unknown): Promise;

// Resources listResources(): Promise; readResource(uri: string): Promise;

// Prompts listPrompts(): Promise ; getPrompt(name: string, args?: unknown): Promise; }


### 日志记录器

interface LoggerOptions { enabled?: boolean; // Enable/disable logger (default: true) timestamps?: boolean; // Show timestamps (default: true) colors?: boolean; // Force colors on/off (default: auto-detect) level?: 'debug'|'info'|'warn'|'error'; // Min level (default: 'debug') stream?: WritableStream; // Custom output (default: process.stderr) logFile?: string; // Optional file output }

function createLogger(options?: LoggerOptions): DebugLogger; function patchConsole(options?: LoggerOptions): void; function unpatchConsole(): void;


### 匹配器

// Installation function installMCPMatchers(): void;

// Tool matchers expect(client).toHaveTool(name: string); expect(tool).toHaveToolProperty(property: string, value?: any); expect(tool).toMatchToolSchema(schema: object); expect(result).toReturnToolResult(expected: any); expect(promise).toThrowToolError();

// Resource matchers expect(client).toHaveResource(uri: string);

// Prompt matchers expect(client).toHavePrompt(name: string);

// Snapshot matchers expect(data).toMatchMCPSnapshot(options?: { exclude?: string[] }); expect(result).toMatchToolResponseSnapshot(options?: { exclude?: string[] }); expect(tools).toMatchToolListSnapshot(options?: { exclude?: string[] }); expect(resources).toMatchResourceListSnapshot(options?: { exclude?: string[] }); expect(prompts).toMatchPromptListSnapshot(options?: { exclude?: string[] });


## 故障排除

### 测试挂起还是超时?

增加超时时间:

const client = new MCPTestClient({ command: 'node', args: ['./server.js'], timeout: 60000, // 60 seconds });


### 快照意外失败?

检查是否排除了足够的动态字段:

expect(result).toMatchToolResponseSnapshot({ exclude: [ 'timestamp', 'requestId', 'files.*.modified', 'data.*.generatedAt', ] });


### 日志未显示?

检查您的日志级别:

createLogger({ level: 'debug' }); // Show everything


### 颜色不起作用?

颜色仅在stderr为TTY时有效。强制启用/禁用:

createLogger({ colors: true }); // Always color createLogger({ colors: false }); // Never color


### 客户端未连接?

验证您的服务器是否正在使用stdio传输并响应初始化:

// Server must respond to initialize request server.setRequestHandler(InitializeRequestSchema, async (request) => { return { protocolVersion: '2024-11-05', capabilities: { tools: {} }, serverInfo: { name: 'my-server', version: '1.0.0' }, }; });


## 需求

- Node.js>=18.0.0
- TypeScript>=5.0.0(如果使用TypeScript)
- Vitest>=1.0.0(用于测试功能)

## 贡献

看 [贡献.md](./CONTRIBUTING.md) 用于开发设置和指南。

## 许可证

MIT© [格纳997](https://github.com/gnana997)

## 相关项目

- [@模型上下文协议/sdk](https://modelcontextprotocol.io) -官方MCP SDK
- [模型上下文协议](https://modelcontextprotocol.io) -协议规范
- [Nochen jsonrpc](https://www.npmjs.com/package/node-stdio-jsonrpc) -基于stdio的JSON-RPC 2.0

______________________________________________________________________

**内置❤️ 对于MCP社区**

觉得这个有用吗?  ⭐

工具与能力

工具数量

0

资源数量

0

提示词数量

0

能力标签

MCP测试TypeScript本地部署服务器调试快照测试JSON-RPC开发工具

数量来自来源目录的标注,具体工具清单以官方文档为准。

典型使用场景

让助手直接读代码

把仓库、提交记录和 issue 交给模型检索,补全和重构时不用来回复制文件。

在对话里跑命令

触发构建、测试和脚本,执行结果直接回到上下文,省去切终端。

接进开发流程

把 PR、CI 状态和代码审查接进助手,减少在几个工具之间跳。

选择建议

值得选的地方

  • 只提供 0 个工具,职责集中,接入后不容易误操作。
  • 有现成的安装命令,不用自己找入口,照着跑就能起服务。
  • 公开说明写得比较完整,接入前能看清能力边界。

先想清楚的地方

  • stdio 方式要求本地装好 Node.js,换机器要重新装一遍。
  • 需要自备访问 Token,没有凭据没法直接试。
  • 第三方目录整理,版本更新和行为细节以官方仓库为准。

更适合

  • 需要在开发工具场景里让模型直接调用外部能力的人。
  • 想先快速试一下、能接受在本地跑服务的人。

不太适合

  • 完全不想在本地装环境的人。
  • 暂时拿不到访问 Token的人。
  • 需要厂商级 SLA 和技术支持的生产环境。

同类对比

5 个同类
MCP Server工具数传输方式安装命令收录来源最后核验
MCP Dev Kit

MCP World · 本页

0stdio有1 个2026-05-17
Git 838e2ec1

MCP World

12stdio有2 个2026-05-17
Markitdown MCP 2c653a5f

MCP World

1stdio有1 个2026-05-17
Context7 831acf40

MCP World

0stdio有1 个2026-05-17
Context7 MCP C671e75a

MCP World

0stdio有1 个2026-05-17

按同分类和工具数量挑出最接近的几条,字段以各自详情页为准。

常见问题

5 条

MCP Dev Kit 怎么安装?

公开资料给出的安装命令是 npx vitest,运行环境为 Node.js。装完后按客户端要求写进 MCP 配置,重启客户端生效。

MCP Dev Kit 怎么在 Claude Desktop、Cursor 里配置?

它是stdio 本地进程,客户端配置里要写启动命令和参数,运行环境是 Node.js;保存后完全退出客户端再打开,配置才会生效。

MCP Dev Kit 收费吗?

本站只整理公开资料,不代收费用,也没有标注具体价格。是否收费取决于服务本身和背后的接口额度,正式使用前按官方说明确认。

MCP Dev Kit 需要 API Key 吗?

公开资料标注的认证方式是访问 Token,也就是要先拿到凭据才能连上;凭据只填在自己本地的配置里,不要写进公开仓库。

MCP Dev Kit 支持哪些客户端?

公开资料没有标注具体客户端;能配置本地 MCP 命令的客户端都能接,配置方式参照官方文档。

来源信息

继续浏览同类 MCP