mcp-builder について
MCP サーバーの設計、実装、テスト、強化を支援する開発スキルです。開発者がツール、リソース、プロンプトを公開し、トランスポートを選び、クライアント連携を準備する手順を案内します。
主な機能
- 01MCP の機能とトランスポートを計画
- 02検証付きツールスキーマを定義
- 03ツール、リソース、プロンプトを実装
- 04stdio と SSE のトランスポートを設定
- 05エラー処理とセキュリティチェックを追加
- 06インメモリクライアントでサーバーをテスト
活用シーン
- 01アプリ向けの MCP サーバーを設計
- 02AI クライアントにデータや操作を公開
- 03ローカルまたはリモート接続の方式を選択
- 04デプロイ前にサーバーをテストして確認
MCP 対応
AI クライアントにツール、リソース、プロンプトを公開する MCP サーバーの開発を支援します。トランスポート設定とクライアント連携も扱います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ pixel-process-ug/ superkit-agents --skill mcp-builderインストール後、Claude Code で/mcp-builderを入力して読み込まれたか確認します。
詳細
MCP ビルダー
概要
AI クライアントにツール、リソース、プロンプトを公開する、本番品質の MCP(Model Context Protocol)サーバーを構築します。このスキルでは、ツールの定義、リソース管理、プロンプトテンプレート、トランスポートの設定(stdio、SSE)、エラー処理、セキュリティ強化、テスト、クライアントとの統合という、開発ライフサイクル全体を扱います。
フェーズ 1:設計
- 公開する機能(ツール、リソース、プロンプト)を特定します
- Zod/JSON Schema でツールスキーマを定義します
- リソース URI のパターンを計画します
- エラー処理戦略を設計します
- トランスポート層を選択します(CLI には stdio、Web には SSE)
停止 — 機能一覧とトランスポートの選択肢を提示し、ユーザーの承認を得てください。
機能選択の判断表
| 保有するもの | MCP プリミティブ | 例 |
|---|---|---|
| 状態を変更するアクション | ツール | create-issue、send-email、deploy-app |
| 読み取り/検索を行うアクション | ツール | search-documents、get-status |
| AI が読み取るデータ | リソース | config://settings、docs://api/endpoints |
| 再利用可能なプロンプトパターン | プロンプト | code-review、summarize-document |
| リアルタイムのデータフィード | リソース(購読可能) | metrics://cpu/current |
トランスポート選択の判断表
| コンテキスト | トランスポート | 理由 |
|---|---|---|
| CLI ツール、ローカルクライアント(Claude Desktop) | Stdio | シンプルで、ネットワークのオーバーヘッドがありません |
| Web アプリケーション、リモートクライアント | SSE | ネットワーク経由でアクセス可能で、リアルタイムです |
| ローカルとリモートの両方 | Stdio + SSE | 両方のユースケースに対応します |
| 高スループット、双方向通信 | WebSocket(カスタム) | SSE よりレイテンシーが低くなります |
フェーズ 2:実装
- MCP サーバープロジェクトの構成をセットアップします
- 入力検証を行うツールハンドラーを実装します
- リソースプロバイダーを実装します
- プロンプトテンプレートを追加します
- トランスポートと認証を設定します
停止 — セキュリティ強化に進む前に、基本的なスモークテストを実行してください。
プロジェクト構成
src/
index.ts # Server entry point
tools/
search.ts # Tool implementations
create.ts
resources/
documents.ts # Resource providers
config.ts
prompts/
review.ts # Prompt templates
lib/
database.ts # Shared utilities
validation.ts
tests/
tools.test.ts
resources.test.ts
package.json
tsconfig.json
ツール定義のパターン
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
});
server.tool(
'search-documents',
'Search documents by query. Returns matching documents with relevance scores.',
{
query: z.string().describe('Search query string'),
limit: z.number().min(1).max(100).default(10).describe('Maximum results to return'),
filter: z.object({
type: z.enum(['article', 'page', 'note']).optional(),
dateAfter: z.string().datetime().optional(),
}).optional().describe('Optional filters'),
},
async ({ query, limit, filter }) => {
const results = await searchEngine.search(query, { limit, ...filter });
return {
content: [{
type: 'text',
text: JSON.stringify(results, null, 2),
}],
};
}
);
ツール設計の原則
| 原則 | ルール |
|---|---|
| 明確な命名 | 動詞-名詞の形式:search-documents、create-issue |
| 説明的な説明 | 何をするのか、いつ使うのか、戻り値を説明します |
| 検証済みの入力 | すべてのフィールドに .describe() を指定した Zod スキーマ |
| 構造化された出力 | 適切にフォーマットされたテキストまたは JSON |
| 可能な場合は冪等にする | 同じ入力から同じ結果を生成します |
| 対応可能なエラー | isError: true を含む具体的なエラーメッセージ |
ツール応答のパターン
// Text response
return { content: [{ type: 'text', text: 'Operation completed successfully' }] };
// Structured data response
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
// Multi-part response
return {
content: [
{ type: 'text', text: `Found ${results.length} results:` },
{ type: 'text', text: results.map(r => `- ${r.title}: ${r.summary}`).join('\n') },
],
};
// Image response
return { content: [{ type: 'image', data: base64Data, mimeType: 'image/png' }] };
// Error response
return {
content: [{ type: 'text', text: `Error: ${error.message}` }],
isError: true,
};
リソース管理
リソース定義
// Static resource
server.resource(
'config',
'config://app/settings',
{ mimeType: 'application/json' },
async () => ({
contents: [{
uri: 'config://app/settings',
mimeType: 'application/json',
text: JSON.stringify(appConfig),
}],
})
);
// Dynamic resource with URI template
server.resource(
'document',
new ResourceTemplate('docs://{category}/{id}', { list: undefined }),
{ mimeType: 'text/markdown' },
async (uri, { category, id }) => ({
contents: [{
uri: uri.href,
mimeType: 'text/markdown',
text: await getDocument(category, id),
}],
})
);
リソース URI の規約
file:///path/to/file — Local files
https://api.example.com/data — Remote HTTP resources
db://database/table/id — Database records
config://app/settings — Configuration
docs://category/slug — Documentation
プロンプトテンプレート
server.prompt(
'code-review',
'Generate a code review for the given file',
{
filePath: z.string().describe('Path to the file to review'),
severity: z.enum(['strict', 'normal', 'lenient']).default('normal'),
},
async ({ filePath, severity }) => {
const code = await readFile(filePath, 'utf-8');
return {
messages: [{
role: 'user',
content: {
type: 'text',
text: `Review this code with ${severity} standards:\n\n\`\`\`\n${code}\n\`\`\``,
},
}],
};
}
);
トランスポート層
Stdio トランスポート(CLI ツール、ローカル開発)
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const transport = new StdioServerTransport();
await server.connect(transport);
SSE トランスポート(Web アプリケーション、リモートサーバー)
import express from 'express';
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
const app = express();
app.get('/sse', async (req, res) => {
const transport = new SSEServerTransport('/messages', res);
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
// Handle incoming messages
});
app.listen(3001);
フェーズ 3:セキュリティ強化
- 包括的なエラー処理を追加します
- レート制限とタイムアウトを実装します
- セキュリティレビューを実施します(入力のサニタイズ、権限チェック)
- 統合テストを作成します
- クライアント向けにツールとリソースを文書化します
停止 — デプロイ前に、すべてのテストに合格し、セキュリティレビューを完了してください。
エラー処理
server.tool('risky-operation', 'Performs an operation that might fail', {
input: z.string(),
}, async ({ input }) => {
try {
const result = await performOperation(input);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
} catch (error) {
if (error instanceof ValidationError) {
return {
content: [{ type: 'text', text: `Invalid input: ${error.message}` }],
isError: true,
};
}
if (error instanceof NotFoundError) {
return {
content: [{ type: 'text', text: `Resource not found: ${error.message}` }],
isError: true,
};
}
console.error('Unexpected error:', error);
return {
content: [{ type: 'text', text: 'An unexpected error occurred. Please try again.' }],
isError: true,
};
}
});
エラー処理のルール
| ルール | 理由 |
|---|---|
| クライアントにスタックトレースを決して公開しない | セキュリティリスクとなります |
すべてのエラーで isError: true を返す | クライアントが成功と失敗を区別できます |
| 予期しないエラーをサーバー側で記録する | デバッグと監視に役立ちます |
| 対応可能なエラーメッセージを提供する | クライアントが自力で修正できます |
| 外部呼び出しにタイムアウトを設定する | リクエストの停止を防ぎます |
| 処理前にすべての入力を検証する | 不正なデータを早期に拒否します |
セキュリティに関する考慮事項
| カテゴリ | ルール |
|---|---|
| 入力検証 | Zod スキーマ、パストラバーサルの防止、長さ制限 |
| 権限モデル | 最小権限、ディレクトリのホワイトリスト化、読み取り/書き込みツールの分離 |
| シークレット | 環境変数のみを使用し、応答に含めず、ログではマスクし、定期的にローテーションする |
| レート制限 | クライアントごとのツール呼び出し回数を制限する |
| 監査 | すべてのツール呼び出しをタイムスタンプ付きで記録する |
MCP サーバーのテスト
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
describe('MCP Server', () => {
let server: McpServer;
let client: Client;
beforeEach(async () => {
server = createServer();
client = new Client({ name: 'test-client', version: '1.0.0' });
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await Promise.all([
server.connect(serverTransport),
client.connect(clientTransport),
]);
});
test('search-documents returns results', async () => {
const result = await client.callTool({
name: 'search-documents',
arguments: { query: 'test', limit: 5 },
});
expect(result.content[0].type).toBe('text');
const data = JSON.parse(result.content[0].text);
expect(data.length).toBeLessThanOrEqual(5);
});
test('handles invalid input gracefully', async () => {
const result = await client.callTool({
name: 'search-documents',
arguments: { query: '', limit: -1 },
});
expect(result.isError).toBe(true);
});
});
クライアント統合
Claude Desktop の設定
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/server/dist/index.js"],
"env": {
"API_KEY": "your-key-here"
}
}
}
}
アンチパターン/よくある間違い
| アンチパターン | 問題となる理由 | 代わりに行うこと |
|---|---|---|
| 多くのことを行うツール | 使いにくく、テストしにくい | 目的を絞った単機能のツールに分割します |
| 入力検証がない | クラッシュやセキュリティ上の穴につながります | 常に Zod スキーマを使用します |
| 生のスタックトレースを返す | セキュリティリスクがあり、AI を混乱させます | 明確なメッセージとともに isError: true を返します |
| 外部呼び出しにタイムアウトがない | 無期限に停止します | すべての I/O にタイムアウトを設定します |
| ソースコードに秘密情報をハードコードする | 認証情報が漏えいします | 環境変数を使用します |
| 説明のないツール | クライアントが目的を把握できません | 明確な説明を記述します |
| 同期処理でイベントループをブロックする | サーバーが応答しなくなります | すべての I/O で async/await を使用します |
| テストがない | リグレッションが検出されません | InMemoryTransport でテストします |
ドキュメントの参照(Context7)
最新のドキュメントを参照するには、mcp__context7__resolve-library-id の後に mcp__context7__query-docs を使用します。返されたドキュメントは、記憶している知識より優先されます。
@anthropic-ai/sdk— Claude API クライアント、ツール定義、ストリーミング向け
統合ポイント
| スキル | 統合内容 |
|---|---|
senior-devops | MCP サーバーをコンテナ化してデプロイします |
agent-development | MCP サーバーがエージェントにツールを提供します |
security-review | ツールの入力/出力をセキュリティ強化します |
test-driven-development | ツール実装に TDD を適用します |
deployment | MCP サーバーのリリース向け CI/CD パイプライン |
planning | MCP サーバーの設計は実装計画の一部です |
スキルの種類
柔軟 — ユースケースに合わせて、プロジェクト構成、トランスポートの選択、ツールを調整します。Zod によるツール検証と isError によるエラー処理を強く推奨します。本番環境へのデプロイ前に、セキュリティレビューを行うことを推奨します。