Apidog

オールインワン協働API開発プラットフォーム

API設計

APIドキュメント

APIデバッグ

APIモック

API自動テスト

MCPサーバーをTypeScriptでClaude Desktopに接続する方法

中村 拓也

中村 拓也

Updated on 4月 9, 2025

モデルコンテキストプロトコル(MCP)は、AIアシスタントが外部ツールやデータソースと相互作用する方法における重要な進歩を表しています。Anthropicによって開発されたMCPは、Claudeがカスタムサーバーとシームレスに通信できるようにし、会話の文脈を離れることなくリアルタイム情報にアクセスし、複雑なワークフローを実行し、APIと相互作用することを可能にします。この機能は、ClaudeをスタンドアロンのLLMから、外部の機能を活用しながら会話の一貫性を保つことができる多目的アシスタントに変えます。

この包括的なガイドでは、TypeScriptでMCPサーバーをゼロから構築し、Claude Desktopに接続するプロセスを説明します。この統合を実装することで、Claudeはリアルタイムデータの取得、計算の実行、または会話の中で直接カスタムビジネスロジックと相互作用するタスクを実行できるようになります。

MCPサーバーの実装に入る前に、API開発ツールの選択がワークフローの効率に大きく影響することを言及する価値があります。

  • Postmanが長らく業界標準である一方で、Apidogは私たちが構築しているような現代の開発ワークフローを完璧に補完する優れた代替手段として登場しました。
  • Postmanが開発中のAPIにおいて制約を持つのに対し、ApidogはAPI仕様とリクエストのリアルタイム同期を提供し、APIの進化に伴い文書とテストが自動的に最新の状態に保たれることを保証します。
  • 視覚的なAPI仕様の作成、無制限のコレクション実行(Postmanの月25回の制限に対して)、自動生成されたリクエストやモックレスポンスなどの強力な機能を持つApidogは、APIライフサイクル全体を効率化します。視覚的なテスト作成や自己ホスト型のランナーを含む包括的なテスト機能は、私たちのMCPサーバーのような複雑な統合を実装するチームに理想的です。

TypeScriptのMCPサーバーを構築する際には、Apidogのコラボラティブな機能や開発に重点を置いたアプローチが、チームの生産性を向上させ、プロセス全体でAPIが一貫してよくテストされ、十分に文書化されることを保証できることを考慮してください。

ボタン

モデルコンテキストプロトコルの理解

モデルコンテキストプロトコルは、Claudeが外部サービスと通信するための標準化された方法を定義します。Claudeが外部ソースから情報が必要であると認識した場合、特別にフォーマットされたJSONリクエストを介してMCPサーバーを呼び出すことができます。サーバーはこのリクエストを処理し、要求されたデータを返し、Claudeはそれを応答に組み込むことができます。

MCPは、従来のAI統合アプローチに対していくつかの利点を提供します:

  • 文脈認識: Claudeはリクエストを行う際に全会話履歴を保持します。
  • 双方向コミュニケーション: プロトコルはClaudeとあなたのサーバー間の複雑な対話をサポートします。
  • セキュリティと制御: あなたが公開する機能とリクエストの処理方法を決定します。
  • シームレスな体験: ユーザーは基盤となる統合を知らずに自然にClaudeと相互作用します。

前提条件

MCPサーバーの構築を始める前に、次のものが必要です:

  • Node.js(v18以上)がインストールされていること
  • Visual Studio Codeなどのコードエディタ
  • TypeScriptの基本的な知識
  • Claude Desktopアプリケーションがインストールされていること
  • Express.jsに精通していること(サーバーエンドポイントを構築するため)

TypeScriptプロジェクトの設定

MCPサーバー用の新しいTypeScriptプロジェクトを作成し始めましょう:

mkdir claude-mcp-server
cd claude-mcp-server
npm init -y
npm install typescript @types/node ts-node express @types/express cors @types/cors
npx tsc --init

次に、tsconfig.jsonを以下の設定を含むように更新します:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

MCPサーバーの実装

プロジェクトのルートディレクトリにserver.tsという新しいファイルを作成します。これが我々のMCPサーバーのエントリーポイントになります:

import express from 'express';
import cors from 'cors';
import { Request, Response } from 'express';

// MCPプロトコルの型を定義
interface MCPRequest {
  query: string;
  conversation_id: string;
  request_id: string;
  parameters?: Record<string, any>;
}

interface MCPResponse {
  response: string;
  status: 'success' | 'error';
  error?: string;
}

const app = express();
app.use(cors());
app.use(express.json());

// ヘルスチェックエンドポイント
app.get('/health', (req: Request, res: Response) => {
  res.status(200).json({ status: 'healthy' });
});

// MCPエンドポイント
app.post('/mcp', (req: Request, res: Response) => {
  try {
    const mcpRequest = req.body as MCPRequest;
    console.log('受信したMCPリクエスト:', JSON.stringify(mcpRequest, null, 2));

    // クエリに基づいてリクエストを処理
    const response = processQuery(mcpRequest);
    
    res.status(200).json({
      status: 'success',
      response
    } as MCPResponse);
  } catch (error) {
    console.error('MCPリクエストの処理中にエラーが発生:', error);
    res.status(500).json({
      status: 'error',
      error: error instanceof Error ? error.message : '不明なエラー',
      response: '申し訳ありませんが、リクエストの処理中にエラーが発生しました。'
    } as MCPResponse);
  }
});

// 様々なクエリタイプを処理する関数
function processQuery(request: MCPRequest): string {
  const { query, parameters } = request;

  // クエリ処理の例 - 使い方に応じてカスタマイズしてください
  switch (query) {
    case 'getCurrentTime':
      return `現在の時刻は ${new Date().toLocaleTimeString()} です`;
    
    case 'getWeather':
      const location = parameters?.location || '不明';
      // 実際のアプリではここで天気APIを呼び出す
      return `${location} の天気は現在晴れで 72°F です`;
    
    case 'calculateSum':
      if (parameters?.numbers && Array.isArray(parameters.numbers)) {
        const sum = parameters.numbers.reduce((a: number, b: number) => a + b, 0);
        return `数値の合計は ${sum} です`;
      }
      return '合計計算のための無効なパラメータです';

    default:
      return `未認識のクエリ: ${query}`;
  }
}

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`MCPサーバーがポート ${PORT} で実行中`);
});

MCPサーバーの実行

サーバーを実行するには、次のコマンドを実行します:

npx ts-node server.ts

MCPサーバーはポート3000(または指定したポート)で実行されているはずです。

Claude Desktopへの接続

MCPサーバーが実行中になったら、Claude Desktopを構成して接続する必要があります。手順は次のとおりです:

  1. Claude Desktopアプリケーションを開く
  2. 設定に移動する(通常は右上隅にあります)
  3. 「実験的機能」セクションに移動する
  4. 「モデルコンテキストプロトコル」トグルを有効にする
  5. URL http://localhost:3000/mcp で新しいMCPエンドポイントを追加する
  6. 設定を保存する

これでClaude DesktopはカスタムMCPサーバーと通信できるようになります。

統合のテスト

ClaudeのMCPサーバーをテストするには、実装した特定のクエリをトリガーする質問をClaudeにしてみてください。例えば:

  • 「今の時刻は?」(getCurrentTime クエリをトリガーするはずです)
  • 「サンフランシスコの天気は?」(「サンフランシスコ」をロケーションパラメータとして含むgetWeather クエリをトリガーするはずです)
  • 「5、10、15、20の合計を計算できますか?」(calculateSum クエリをトリガーするはずです)

Claudeがこれらの質問に答えるために外部情報が必要であると認識すると、自動的にMCPリクエストをサーバーに送信し、返答をその回答に組み込みます。

MCPサーバーの拡張

私たちが構築した基本的なサーバーは出発点にすぎません。機能を拡張するためのいくつかのアイデアを以下に示します:

認証の追加

MCPサーバーを保護するために、認証を追加します:

// 基本authのためのミドルウェア
const authenticateMCP = (req: Request, res: Response, next: Function) => {
  const apiKey = req.headers['x-api-key'];
  if (!apiKey || apiKey !== process.env.MCP_API_KEY) {
    return res.status(401).json({
      status: 'error',
      error: 'Unauthorized',
      response: '認証に失敗しました'
    });
  }
  next();
};

// MCPエンドポイントにミドルウェアを適用
app.post('/mcp', authenticateMCP, (req: Request, res: Response) => {
  // 既存の処理コード
});

データベース統合の実装

MCPサーバーをデータベースに接続して情報を取得または保存します:

import { MongoClient } from 'mongodb';

// データベース接続の初期化
const dbClient = new MongoClient('mongodb://localhost:27017');
let db: any;

async function connectToDb() {
  await dbClient.connect();
  db = dbClient.db('mcpDatabase');
  console.log('データベースに接続されました');
}

connectToDb().catch(console.error);

// データベースとの対話のためのクエリハンドラーを追加
case 'getUserData':
  if (parameters?.userId) {
    const user = await db.collection('users').findOne({ id: parameters.userId });
    return user ? JSON.stringify(user) : 'ユーザーが見つかりません';
  }
  return '無効なユーザーIDです';

Webhookサポートの追加

外部サービスに通知するためのWebhook機能を実装します:

case 'sendNotification':
  if (parameters?.message && parameters?.destination) {
    // 外部通知サービスを呼び出す
    await fetch('https://your-webhook-url.com', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ message: parameters.message })
    });
    return `通知が ${parameters.destination} に送信されました`;
  }
  return '無効な通知パラメータです';

MCPサーバー開発のベストプラクティス

  1. エラーを適切に処理する: 例外を常にキャッチし、情報豊かなエラーメッセージを返します
  2. ロギングを実装する: デバッグと監査のためにすべてのリクエストとレスポンスをログに記録します
  3. TypeScriptインターフェースを使用する: すべてのデータ構造の明確なインターフェースを定義します
  4. タイムアウトを設定する: ハングアップする操作を防ぐためにリクエストのタイムアウトを実装します
  5. 入力を検証する: 処理する前にすべての入力パラメータを慎重に検証します
  6. ユニットテストを追加する: 信頼性を確保するためにクエリハンドラーを徹底的にテストします

結論

TypeScriptのMCPサーバーを構築することで、Claudeの機能を拡張するエキサイティングな可能性が開かれます。このガイドに従うことで、Claudeを自身のサービスやデータに統合するための基盤を作りました。モデルコンテキストプロトコルにより、ユーザーは会話の流れを壊すことなく外部情報にアクセスするシームレスな体験を得ることができます。

MCPが進化し続けるにつれて、大規模言語モデルと外部システム間のさらに洗練された統合が期待されます。生産性ツール、ナレッジマネジメントシステム、またはカスタムビジネスアプリケーションを構築する場合でも、MCPはClaudeの知性をあなたの専門的な機能と結びつける強力な方法を提供します。

特定のユースケースに固有の追加のクエリハンドラーでサーバーを拡張し始めて、MCP開発者のコミュニティとあなたの経験を共有してください。