mcpField
M
mcp-development

mcp-development

github.com/rohitg00開発2.8k181 回インストール24 週間前に更新
リポジトリ

mcp-development について

MCP 開発者向けの実践ガイドです。ツール、リソース、プロンプトテンプレートを備えたサーバーの構築、トランスポート設定、入力検証、エラー処理を扱い、クライアント設定とチェック項目も含みます。

主な機能

  1. 01ツールを備えた MCP サーバーの構築
  2. 02リソースとプロンプトテンプレートの定義
  3. 03Stdio と SSE のトランスポート設定
  4. 04Zod による入力検証
  5. 05エラー処理と安全な終了
  6. 06クライアント設定の記述

活用シーン

  1. 01クライアントが呼び出すツールの実装
  2. 02クライアントへの読み取り専用リソースの提供
  3. 03一般的なタスク向けプロンプトテンプレートの設計
  4. 04MCP サーバーの実装と設定の確認

MCP 対応

MCP サーバー開発を中心に、クライアント設定も扱います。Stdio または SSE を通じて、ツール、リソース、プロンプトを MCP クライアントに公開する方法を説明します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/rohitg00/awesome-claude-code-toolkit --skill mcp-development

インストール後、Claude Code で/mcp-developmentを入力して読み込まれたか確認します。

詳細

MCP の開発

ツールを備えた MCP サーバー

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "project-tools",
  version: "1.0.0",
});

server.tool(
  "search_files",
  "Search for files matching a glob pattern in the project directory",
  {
    pattern: z.string().describe("Glob pattern (e.g., '**/*.ts')"),
    directory: z.string().optional().describe("Base directory to search from"),
  },
  async ({ pattern, directory }) => {
    const files = await glob(pattern, { cwd: directory ?? process.cwd() });
    return {
      content: [
        {
          type: "text",
          text: files.length > 0
            ? files.join("\n")
            : `No files found matching ${pattern}`,
        },
      ],
    };
  }
);

server.tool(
  "run_query",
  "Execute a read-only SQL query against the application database",
  {
    query: z.string().describe("SQL SELECT query to execute"),
    limit: z.number().default(100).describe("Maximum rows to return"),
  },
  async ({ query, limit }) => {
    if (!query.trim().toUpperCase().startsWith("SELECT")) {
      return {
        content: [{ type: "text", text: "Only SELECT queries are allowed" }],
        isError: true,
      };
    }
    const rows = await db.query(`${query} LIMIT ${limit}`);
    return {
      content: [{ type: "text", text: JSON.stringify(rows, null, 2) }],
    };
  }
);

リソース

server.resource(
  "schema",
  "db://schema",
  "Current database schema with all tables, columns, and relationships",
  async () => {
    const schema = await db.query(`
      SELECT table_name, column_name, data_type, is_nullable
      FROM information_schema.columns
      WHERE table_schema = 'public'
      ORDER BY table_name, ordinal_position
    `);
    return {
      contents: [
        {
          uri: "db://schema",
          mimeType: "application/json",
          text: JSON.stringify(schema, null, 2),
        },
      ],
    };
  }
);

server.resource(
  "config",
  "config://app",
  "Application configuration (secrets redacted)",
  async () => {
    const config = await loadConfig();
    const safe = redactSecrets(config);
    return {
      contents: [
        {
          uri: "config://app",
          mimeType: "application/json",
          text: JSON.stringify(safe, null, 2),
        },
      ],
    };
  }
);

プロンプトテンプレート

server.prompt(
  "review-code",
  "Review code changes for bugs, security issues, and style",
  {
    diff: z.string().describe("Git diff or code to review"),
    focus: z.enum(["security", "performance", "style", "all"]).default("all"),
  },
  async ({ diff, focus }) => ({
    messages: [
      {
        role: "user",
        content: {
          type: "text",
          text: `Review this code diff. Focus: ${focus}\n\n${diff}`,
        },
      },
    ],
  })
);

クライアントの設定

{
  "mcpServers": {
    "project-tools": {
      "command": "node",
      "args": ["./mcp-server/dist/index.js"],
      "env": {
        "DATABASE_URL": "postgres://localhost:5432/app"
      }
    },
    "remote-server": {
      "url": "https://mcp.example.com/sse",
      "headers": {
        "Authorization": "Bearer ${MCP_TOKEN}"
      }
    }
  }
}

トランスポートの設定

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const transport = new StdioServerTransport();
await server.connect(transport);

HTTP ベースのサーバーでは、クライアントにストリーミングレスポンスを送信するために SSE トランスポートを使用します。

アンチパターン

  • 使用するタイミングを説明していない、曖昧な説明のツールを作成する
  • 処理前に Zod スキーマで入力を検証しない
  • エラーの生のスタックトレースをクライアントに返す
  • エラーレスポンスに isError: true フラグがない
  • 組み合わせて使えるツールではなく、細かすぎるツールを作りすぎる
  • リソースのレスポンスでシークレットをマスキングしない

チェックリスト

  • 各ツールに、使用するタイミングと理由を説明する明確な説明がある
  • 入力パラメーターが Zod スキーマとわかりやすいメッセージで検証されている
  • エラーレスポンスに isError: true とユーザーにわかりやすいメッセージが含まれている
  • リソースがシークレットをマスキングした読み取り専用データを公開している
  • プロンプトテンプレートが一般的なタスク向けに、構造化された出発点を提供している
  • サーバーが SIGINT/SIGTERM で正常にシャットダウンする
  • ツールがモノリシックではなく、組み合わせて使える(1つの機能を適切に実行する)
  • 必要な環境変数を含めて、クライアントの設定が文書化されている

コメント