Alejandro Rioja.
AI Agents

はじめてのMCPサーバーの作り方:実践ガイド

Alejandro Rioja
Alejandro Rioja
2 分で読める
TL;DR

MCP(Model Context Protocol)は、コンテキストウィンドウを圧迫せずに、データベース、ファイル、APIなどの外部ツールやデータへの構造化されたアクセスをClaudeに与える方法です。サーバーは見た目より簡単です:SDKをインストールし、ツールをJSONスキーマとして定義し、ハンドラーを実装し、stdioで接続します。30分以内にClaudeがカスタムツールを呼び出せるようになります。

無料ニュースレター

毎週水曜。28,400人以上の読者。無駄なし。

目次

2026年6月更新。

TL;DR: MCP(Model Context Protocol)は、コンテキストウィンドウを圧迫せずに、データベース、ファイル、APIなどの外部ツールやデータへの構造化されたアクセスをClaudeに与える方法です。サーバーは見た目より簡単です:SDKをインストールし、ツールをJSONスキーマとして定義し、ハンドラーを実装し、stdioで接続します。30分以内にClaudeがカスタムツールを呼び出せるようになります。

[オペレーターの視点] 私は定期的にエージェントに新しいツールを組み込んでいます。MCPは今やそれをクリーンに行うための標準的な方法です。サーバーを一度構築すれば、MCP対応のすべてのクライアント——Claude Desktop、Claude Code、Anthropic SDKを使用するすべてのアプリ——が呼び出し側のコードを変更せずに使用できます。これが価値です:一度作って、どこでも再利用する。

MCPとは何か

Model Context Protocolは、AIモデルが外部コンテキストとツールに接続する方法を標準化するオープンプロトコルです。AIインテグレーションのUSB-C規格と考えてください:以前は、Claudeにデータベースを読ませたりAPIを呼び出させたりしたいアプリは、それぞれ独自の仕組みを考える必要がありました。MCPを使えば、MCPサーバーを一つ作るだけで、準拠するすべてのホストが使用できます。

MCPはサーバーが提供できる3つのものを定義します:

ほとんどのオペレーターユースケースでは、ツールサーバーを構築します。リソースとプロンプトは基本が動いてから後で対応します。

アーキテクチャはクライアント-サーバーで、クライアント(Claude Desktop、Claude Code、カスタムアプリ)がすべてを制御します。サーバーは受動的——ツール呼び出しリクエストを待ち受けて結果を返すだけです。

すべてのMCPサーバーの3つの部品

構築するMCPサーバーはすべて同じ構造を持ちます:

  1. サーバーオブジェクト——サーバーの名前、バージョン、提供する機能(ツール、リソース、プロンプト)を宣言
  2. ツール定義——名前、説明、入力のJSONスキーマを持つツールのリスト
  3. リクエストハンドラー——Claudeがツールを呼び出したときに実行される関数

それだけです。開始時にデータベース、HTTPスタック、auth層は不要です。最小サーバーは30行未満のTypeScriptです。

前提条件(2分)

MCPサーバーを実行するためにAnthropic APIキーは不要です。APIキーはクライアント(Claude Desktop)にあり、サーバーにはありません。

ステップ1:プロジェクトのセットアップ(3分)

bash
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript tsx @types/node

package.jsonに追加:

json
{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "dev": "tsx src/index.ts"
  }
}

tsconfig.jsonを作成:

json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "strict": true
  },
  "include": ["src/**/*"]
}

ステップ2:最小サーバーを書く(5分)

src/index.tsを作成:

typescript
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
  { name: "my-mcp-server", version: "1.0.0" },
  { capabilities: { tools: {} } }
);

// このサーバーが提供するツールを宣言
server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: [
    {
      name: "get_word_count",
      description: "テキストブロックの単語数を数えます。",
      inputSchema: {
        type: "object",
        properties: {
          text: {
            type: "string",
            description: "単語を数えるテキスト",
          },
        },
        required: ["text"],
      },
    },
  ],
}));

// クライアントからのツール呼び出しを処理
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  if (name === "get_word_count") {
    const { text } = args as { text: string };
    const count = text.trim().split(/\s+/).filter(Boolean).length;
    return {
      content: [{ type: "text", text: `単語数:${count}` }],
    };
  }

  throw new Error(`不明なツール:${name}`);
});

// stdioで接続——Claude DesktopがサーバーとやりとりするEways
const transport = new StdioServerTransport();
await server.connect(transport);

これが完全なサーバーです。1つのツール(get_word_count)を登録して実装します。構造が重要です。

ステップ3:ビルドしてClaude Desktopに登録(5分)

TypeScriptをビルド:

bash
npm run build

Claude Desktopの設定ファイルに登録します。

macOS~/Library/Application Support/Claude/claude_desktop_config.json Windows%APPDATA%\Claude\claude_desktop_config.json

ファイルが存在しない場合は作成:

json
{
  "mcpServers": {
    "my-mcp-server": {
      "command": "node",
      "args": ["/absolute/path/to/my-mcp-server/build/index.js"]
    }
  }
}

絶対パスを使用します。保存後にClaude Desktopを再起動します。メッセージ入力にハンマーアイコン(🔨)が表示されれば、Claudeがあなたのツールをdiscoverしたサインです。

ステップ4:便利なツールを作る

単語カウントは説明用です。より便利なツールを紹介します:プロジェクトディレクトリからファイルを読む——コードベース、changelog、設定ファイルを要約するコンテキスト注入エージェントに使用しているものです。

typescript
import { readFileSync, readdirSync } from "fs";
import { join, extname } from "path";

const ALLOWED_EXTENSIONS = [".md", ".txt", ".ts", ".json", ".yaml"];
const PROJECT_DIR = process.env.PROJECT_DIR ?? process.cwd();

ロジックは同じです:正確なJSONスキーマでツールを定義し、ハンドラーを実装し、パストラバーサルを防ぐために入力を検証し、クライアントにテキストを返します。

私がはまった落とし穴(あなたがはまらないように)

パスは絶対パスでなければなりません。 Claude Desktop設定の相対パスは期待通りに解決されません。常に完全パス /home/user/... を使用してください。

stdioはサーバーでconsole.logを使えないことを意味します。 Claude Desktopはstdin/stdoutを通じてサーバーと通信します。デバッグのconsole.logはJSON-RPCストリームを破壊します。代わりにstderrにログ:

typescript
process.stderr.write(`デバッグ:${message}\n`);

設定変更のたびにClaude Desktopを再起動してください。 MCPサーバーは起動時に読み込まれます。編集した設定ファイルはアプリを閉じて再度開くまで何もしません。

ツールの説明がプロダクトです。 Claudeはdescriptionフィールドに基づいてツールを呼び出すかどうか決めます。曖昧な説明はClaudeがいつ使うべきか分からないことを意味します。正確な説明はClaudeが適切なタイミングでそれを使うことを意味します。実装よりも説明に時間をかけてください。

本番環境でのMCPサーバーの使い方

stdioパターンはClaude DesktopとClaude Code(ローカル)に最適です。本番エージェント——Cloudflare Workersで実行している30以上——では、ステップごとにHaikuとSonnetにルーティングする柔軟性が必要なため、Anthropic SDKのtool-use APIを直接使用します。

実際に使っているパターン:

  1. ローカル開発ツール——プロジェクト固有のツールを公開するClaude Code用MCPサーバー
  2. コンテキスト注入——手動コピーなしに関連ドキュメントをプリロードするMCPサーバー
  3. プロトタイプからAPIへのブリッジ——MCP を先に構築し(イテレーションが速い)、その後ロジックをSDK tool-useに移植

次に作るもの

サーバー構造が理解できたら、有用なツールはClaudeの外部コンテキストにアクセスするものです:

よくある質問

MCPサーバーを構築するにはAnthropic APIキーが必要ですか?

いいえ。MCPサーバーはAnthropic APIを呼び出しません。クライアントからのツール呼び出しリクエストに応答するだけです。APIキーはクライアントにあり、サーバーにはありません。

MCPサーバーは外部APIを呼び出せますか?

はい——ハンドラーは単なる非同期TypeScriptコードです。天気APIをフェッチし、データベースをクエリし、ファイルに書き込む。サーバーはハンドラーが内部で何をするかを気にしません。

stdioとHTTPトランスポートの違いは何ですか?

stdioはローカルサーバー用——Claude DesktopやClaude Codeと同じマシン。HTTP with SSEはWebサービスとしてデプロイできるリモートサーバー用。stdioから始めてください;デバッグが簡単です。

Claudeはいつ自分のツールを呼び出すべきか知っていますか?

Claudeはツールのdescriptionフィールドと会話のコンテキストに基づいて決定します。Claudeがツールを無視し続ける場合は、説明を絞り込んでください。

続きを読む

AIプレイブックをメールでお届け

毎週水曜。28,400人以上の読者。無駄なし。

↵ すべての結果を見る esc esc で閉じる