npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@taikiy/mcp-server-test

v1.0.0

Published

A test server for Model Context Protocol (MCP) implementations

Readme

MCP Server Test Library

概要

MCPサーバーをコードベースでテストするためのライブラリです。MCP Inspectorのプロキシアーキテクチャを参考に、テスト環境でMCPサーバーの動作を検証できるようにします。

特徴

  • 完全なモック実装: 実際のプロセスを起動せずにMCPサーバーをテスト
  • 実サーバーサポート: stdioベースの実際のMCPサーバーもテスト可能
  • メッセージ履歴: すべての通信を記録し、後から検証可能
  • 豊富なアサーション: ツール、リソース、プロンプトの検証用ヘルパー
  • タイムアウト制御: レスポンス時間のテストに対応
  • エラーシミュレーション: エラーケースのテストが容易

クイックスタート

import { createTestClient, createTestServer, expectTool } from '@taiki-ssss/mcp-server-tester';

describe('My MCP Server', () => {
  let server: TestServer;
  let client: TestClient;

  beforeEach(async () => {
    server = await createTestServer({
      command: 'node',
      args: ['./dist/index.js'],
    });
    client = await createTestClient();
    await client.connect(server);
  });

  afterEach(async () => {
    await client.disconnect();
    await server.stop();
  });

  test('should list available tools', async () => {
    const response = await client.request('tools/list');
    
    expectTool(response).toContain({
      name: 'my-tool',
      description: 'My tool description',
      inputSchema: expect.any(Object),
    });
  });

  test('should execute tool successfully', async () => {
    const result = await client.request('tools/call', {
      name: 'my-tool',
      arguments: { input: 'test' },
    });

    expect(result.content).toEqual([{
      type: 'text',
      text: 'Expected output',
    }]);
  });
});

インストール

npm install @taiki-ssss/mcp-server-tester --save-dev

基本的な使い方

1. モックサーバーでのテスト

import { describe, test, expect } from 'vitest';
import { createTestClient, createMockServer } from '@taiki-ssss/mcp-server-tester';

describe('My MCP Server Tests', () => {
  test('should handle custom method', async () => {
    const client = createTestClient();
    const server = createMockServer();
    
    // カスタムハンドラーを登録
    server.registerHandler('myMethod', (params) => ({
      result: `Processed: ${params.input}`
    }));
    
    await server.start();
    await client.connect(server);
    
    const response = await client.request('myMethod', { input: 'test' });
    expect(response.result).toBe('Processed: test');
    
    await client.disconnect();
    await server.stop();
  });
});

2. 実際のMCPサーバーのテスト

import { createTestClient, createTestServer } from '@taiki-ssss/mcp-server-tester';

test('should connect to real server', async () => {
  const server = await createTestServer({
    command: 'node',
    args: ['./dist/my-server.js'],
  });
  
  const client = createTestClient();
  
  await server.start();
  await client.connect(server);
  
  // 実際のサーバーと通信
  const response = await client.request('tools/list');
  expect(response.tools).toBeDefined();
  
  await client.disconnect();
  await server.stop();
});

3. テストヘルパーの使用

import { 
  expectTool, 
  expectResource, 
  expectNoErrors,
  runTestScenario 
} from '@taiki-ssss/mcp-server-tester';

// ツールのテスト
test('should provide calculator tool', async () => {
  const response = await client.request('tools/list');
  
  expectTool(response).toContain({ 
    name: 'calculator',
    description: 'Performs calculations' 
  });
  expectTool(response).toHaveCount(3);
});

// シナリオテスト
test('complete workflow', async () => {
  await runTestScenario({
    name: 'User workflow',
    
    execute: async (client) => {
      // 1. ツールを取得
      const tools = await client.request('tools/list');
      
      // 2. ツールを実行
      const result = await client.request('tools/call', {
        name: tools.tools[0].name,
        arguments: { input: 'test' }
      });
      
      // 3. 完了通知
      await client.notify('workflow/complete', { id: '123' });
    },
    
    verify: (history) => {
      expectNoErrors(history);
      expect(history.requests).toHaveLength(3); // initialize + 2 requests
      expect(history.notifications).toHaveLength(1);
    }
  });
});

4. メッセージ履歴の検証

test('should track message history', async () => {
  // ... setup ...
  
  await client.request('method1');
  await client.notify('event1', { data: 'test' });
  await client.request('method2');
  
  const history = client.getHistory();
  
  // リクエストの検証
  expect(history.requests).toHaveLength(3); // initialize + 2
  expect(history.requests[1].method).toBe('method1');
  
  // 通知の検証
  expect(history.notifications).toHaveLength(1);
  expect(history.notifications[0].method).toBe('event1');
  
  // エラーがないことを確認
  expectNoErrors(history);
});

5. エラーハンドリングのテスト

test('should handle errors', async () => {
  server.registerHandler('failingMethod', () => {
    throw new Error('Something went wrong');
  });
  
  await expect(
    client.request('failingMethod')
  ).rejects.toThrow();
  
  const history = client.getHistory();
  expect(history.errors).toHaveLength(1);
  expect(history.errors[0].message).toContain('Something went wrong');
});

6. タイムアウトのテスト

test('should timeout slow requests', async () => {
  const client = createTestClient({ timeout: 100 });
  
  server.registerHandler('slowMethod', async () => {
    await new Promise(resolve => setTimeout(resolve, 200));
    return { result: 'too slow' };
  });
  
  await expect(
    client.request('slowMethod')
  ).rejects.toThrow('Request timeout');
});

API リファレンス

TestClient

  • connect(server?: TestServer): Promise<void> - サーバーに接続
  • disconnect(): Promise<void> - 接続を切断
  • request<T>(method: string, params?: any): Promise<T> - リクエストを送信
  • notify(method: string, params?: any): Promise<void> - 通知を送信
  • getHistory(): MessageHistory - メッセージ履歴を取得
  • getCapabilities(): ServerCapabilities | null - サーバー機能を取得

MockTestServer

  • start(): Promise<void> - サーバーを起動
  • stop(): Promise<void> - サーバーを停止
  • registerHandler(method: string, handler: Function): void - ハンドラーを登録
  • removeHandler(method: string): void - ハンドラーを削除
  • clearHandlers(): void - すべてのハンドラーをクリア

ヘルパー関数

  • expectTool(response) - ツール関連のアサーション
  • expectResource(response) - リソース関連のアサーション
  • expectPrompt(response) - プロンプト関連のアサーション
  • expectRequest(history, method) - リクエストの存在を確認
  • expectNotification(history, method) - 通知の存在を確認
  • expectNoErrors(history) - エラーがないことを確認
  • runTestScenario(scenario) - テストシナリオを実行
  • waitForMessage(client, predicate, timeout?) - 特定のメッセージを待機
  • createConfiguredMockServer(handlers) - 事前設定されたモックサーバーを作成

ベストプラクティス

  1. セットアップとクリーンアップ

    beforeEach(async () => {
      client = createTestClient();
      server = createMockServer();
    });
       
    afterEach(async () => {
      await client.disconnect();
      await server.stop();
    });
  2. タイムアウトの設定

    const client = createTestClient({ 
      timeout: 10000 // 10秒
    });
  3. エラーの適切な処理

    try {
      await client.request('method');
    } catch (error) {
      // エラーを検証
      expect(error.code).toBe(-32601);
    }
  4. メッセージ履歴のクリア

    client.clearHistory(); // テスト間で履歴をリセット