AI エージェント開発実践ガイド:Claude Code サブエージェント・MCP・カスタムコマンド完全実装【2025年版】¶
はじめに¶
Claude Code の最新機能を活用して、実践的な AI エージェントシステムを構築するための実装ガイドです。サブエージェント設計パターン、MCP サーバー開発、カスタムスラッシュコマンド実装を、実際のコード例とともに詳解します。
この記事のポイント¶
専門特化エージェント体制
ドメイン固有のサブエージェントによる効率的な分業システム
MCP サーバー開発
外部ツール連携のためのカスタム MCP サーバー実装
カスタムコマンド開発
ワークフロー固有のスラッシュコマンド作成
マルチモデル戦略
タスク特性に応じた最適モデル選択システム
1. サブエージェント設計パターン実装¶
基本構造の設計¶
サブエージェントの設定ファイルを体系的に管理するディレクトリ構造を構築します。
.claude/
├── agents/
│ ├── database-specialist.md
│ ├── frontend-specialist.md
│ ├── security-specialist.md
│ └── devops-specialist.md
└── shared/
├── common-tools.md
└── coding-standards.md
データベース専門エージェントの実装¶
<!-- .claude/agents/database-specialist.md -->
# データベース設計・最適化専門エージェント
## 役割定義
- データベーススキーマ設計と最適化
- クエリパフォーマンスチューニング
- インデックス戦略の立案・実装
## 使用モデル
claude-3.5-sonnet
## 専門知識領域
- RDBMS: PostgreSQL, MySQL, SQLite
- NoSQL: MongoDB, Redis, DynamoDB
- ORM: TypeORM, Prisma, Sequelize
## 標準実装パターン
### ERD設計テンプレート
```sql
-- テーブル設計の基本パターン
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- インデックス設計
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_created_at ON users(created_at);
パフォーマンス分析クエリ¶
-- 実行計画の分析
EXPLAIN (ANALYZE, BUFFERS)
SELECT u.*, p.title
FROM users u
JOIN posts p ON u.id = p.user_id
WHERE u.created_at > NOW() - INTERVAL '30 days';
タスク実行プロセス¶
- 要件分析とエンティティ抽出
- 正規化レベルの決定
- インデックス戦略の策定
- パフォーマンステストの実装
- 本番環境での検証
### フロントエンド専門エージェントの実装 ```markdown <!-- .claude/agents/frontend-specialist.md --> # フロントエンド開発専門エージェント ## 役割定義 - React/Vue/Angular コンポーネント設計 - 状態管理アーキテクチャの実装 - UI/UX 最適化とアクセシビリティ対応 ## 使用モデル gpt-4o ## 技術スタック - Framework: React 18+, Next.js 14+ - State: Zustand, Redux Toolkit, SWR - Styling: Tailwind CSS, Styled Components - Testing: Jest, React Testing Library, Playwright ## コンポーネント設計パターン ### Compound Component Pattern ```typescript // Button コンポーネントの実装例 interface ButtonProps { variant?: 'primary' | 'secondary' | 'danger'; size?: 'sm' | 'md' | 'lg'; children: React.ReactNode; onClick?: () => void; } export const Button: React.FC<ButtonProps> = ({ variant = 'primary', size = 'md', children, onClick }) => { const baseClasses = 'font-medium rounded focus:outline-none focus:ring-2'; const variantClasses = { primary: 'bg-blue-600 text-white hover:bg-blue-700', secondary: 'bg-gray-200 text-gray-900 hover:bg-gray-300', danger: 'bg-red-600 text-white hover:bg-red-700' }; const sizeClasses = { sm: 'px-3 py-1.5 text-sm', md: 'px-4 py-2 text-base', lg: 'px-6 py-3 text-lg' }; return ( <button className={`${baseClasses} ${variantClasses[variant]} ${sizeClasses[size]}`} onClick={onClick} > {children} </button> ); };
カスタムフック実装¶
// API データ取得フック
import { useState, useEffect } from 'react';
interface UseApiState<T> {
data: T | null;
loading: boolean;
error: string | null;
}
export function useApi<T>(url: string): UseApiState<T> {
const [state, setState] = useState<UseApiState<T>>({
data: null,
loading: true,
error: null
});
useEffect(() => {
const fetchData = async () => {
try {
setState(prev => ({ ...prev, loading: true }));
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
setState({ data, loading: false, error: null });
} catch (error) {
setState({
data: null,
loading: false,
error: error instanceof Error ? error.message : 'Unknown error'
});
}
};
fetchData();
}, [url]);
return state;
}
ベストプラクティス¶
- コンポーネントの単一責任原則
- Props drilling の回避
- パフォーマンス最適化(React.memo, useMemo, useCallback)
- アクセシビリティ対応(ARIA属性、キーボードナビゲーション)
## 2. MCP サーバー開発実践 ### GitHub 連携 MCP サーバーの実装 ```typescript // github-mcp-server.ts import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { Octokit } from '@octokit/rest'; interface GitHubConfig { token: string; owner: string; repo: string; } class GitHubMCPServer { private server: Server; private octokit: Octokit; private config: GitHubConfig; constructor(config: GitHubConfig) { this.config = config; this.octokit = new Octokit({ auth: config.token }); this.server = new Server( { name: 'github-integration', version: '1.0.0' }, { capabilities: { tools: {} } } ); this.setupTools(); } private setupTools() { // Issue 作成ツール this.server.setRequestHandler('tools/list', async () => ({ tools: [ { name: 'create_issue', description: 'GitHub Issue を作成', inputSchema: { type: 'object', properties: { title: { type: 'string' }, body: { type: 'string' }, labels: { type: 'array', items: { type: 'string' } } }, required: ['title', 'body'] } }, { name: 'list_pull_requests', description: 'Pull Request 一覧を取得', inputSchema: { type: 'object', properties: { state: { type: 'string', enum: ['open', 'closed', 'all'] } } } } ] })); // Issue 作成の実装 this.server.setRequestHandler('tools/call', async (request) => { if (request.params.name === 'create_issue') { const { title, body, labels } = request.params.arguments as { title: string; body: string; labels?: string[]; }; try { const response = await this.octokit.rest.issues.create({ owner: this.config.owner, repo: this.config.repo, title, body, labels }); return { content: [ { type: 'text', text: `Issue created successfully: #${response.data.number}\nURL: ${response.data.html_url}` } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error creating issue: ${error instanceof Error ? error.message : 'Unknown error'}` } ] }; } } // PR 一覧取得の実装 if (request.params.name === 'list_pull_requests') { const { state = 'open' } = request.params.arguments as { state?: string }; try { const response = await this.octokit.rest.pulls.list({ owner: this.config.owner, repo: this.config.repo, state: state as 'open' | 'closed' | 'all' }); const prList = response.data.map(pr => ({ number: pr.number, title: pr.title, author: pr.user?.login, state: pr.state, url: pr.html_url })); return { content: [ { type: 'text', text: JSON.stringify(prList, null, 2) } ] }; } catch (error) { return { content: [ { type: 'text', text: `Error listing PRs: ${error instanceof Error ? error.message : 'Unknown error'}` } ] }; } } throw new Error('Unknown tool'); }); } async start() { const transport = new StdioServerTransport(); await this.server.connect(transport); } } // サーバー起動 const config: GitHubConfig = { token: process.env.GITHUB_TOKEN || '', owner: process.env.GITHUB_OWNER || '', repo: process.env.GITHUB_REPO || '' }; const server = new GitHubMCPServer(config); server.start().catch(console.error);
MCP サーバー設定ファイル¶
{
"mcpServers": {
"github": {
"command": "node",
"args": ["./github-mcp-server.js"],
"env": {
"GITHUB_TOKEN": "${{ secrets.GITHUB_TOKEN }}",
"GITHUB_OWNER": "your-username",
"GITHUB_REPO": "your-repo"
}
},
"database": {
"command": "node",
"args": ["./database-mcp-server.js"],
"env": {
"DATABASE_URL": "${{ secrets.DATABASE_URL }}"
}
}
}
}
3. カスタムスラッシュコマンド実装¶
プロジェクト初期化コマンド¶
<!-- .claude/commands/init-project.md -->
# プロジェクト初期化
新しいプロジェクトの基本構造を自動生成します。
## 実行内容
1. TypeScript + React プロジェクトの作成
2. ESLint、Prettier の設定
3. GitHub Actions ワークフローの配置
4. ディレクトリ構造の標準化
## セットアップコマンド
```bash
# Next.js プロジェクトの作成
npx create-next-app@latest PROJECT_NAME --typescript --tailwind --eslint --app
# 開発依存関係の追加
npm install -D @types/node @typescript-eslint/eslint-plugin @typescript-eslint/parser prettier eslint-config-prettier
# Husky とlint-staged の設定
npm install -D husky lint-staged
npx husky install
標準ディレクトリ構造¶
src/
├── app/
│ ├── globals.css
│ ├── layout.tsx
│ └── page.tsx
├── components/
│ ├── ui/
│ │ ├── Button.tsx
│ │ └── Input.tsx
│ └── common/
│ ├── Header.tsx
│ └── Footer.tsx
├── hooks/
│ └── useApi.ts
├── lib/
│ └── utils.ts
└── types/
└── index.ts
設定ファイルテンプレート¶
.eslintrc.json¶
{
"extends": [
"next/core-web-vitals",
"@typescript-eslint/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"rules": {
"@typescript-eslint/no-unused-vars": "error",
"@typescript-eslint/no-explicit-any": "warn"
}
}
.prettierrc¶
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 100,
"tabWidth": 2
}
### コードレビューコマンド
```markdown
<!-- .claude/commands/code-review.md -->
# コードレビュー実行
変更されたファイルに対して包括的なコードレビューを実行します。
## チェック項目
- [ ] TypeScript型安全性
- [ ] パフォーマンス最適化
- [ ] セキュリティ脆弱性
- [ ] コード品質(複雑度、可読性)
- [ ] テストカバレッジ
## 実行プロセス
### 1. 変更ファイルの特定
```bash
git diff --name-only HEAD~1
2. 静的解析実行¶
# ESLint チェック
npx eslint . --ext .ts,.tsx --fix
# TypeScript 型チェック
npx tsc --noEmit
# セキュリティスキャン
npm audit
3. テスト実行¶
# ユニットテスト
npm test -- --coverage
# E2Eテスト
npm run test:e2e
レビュー観点¶
パフォーマンス¶
- 不要な再レンダリングの回避
- メモ化の適切な使用
- バンドルサイズの最適化
セキュリティ¶
- XSS対策の実装
- 入力値の適切な検証
- 認証・認可の実装
可読性¶
- 命名規則の遵守
- コメントの適切性
- 関数の単一責任原則
## 4. マルチモデル選択戦略 ### タスク特性別モデル選択ロジック ```typescript // model-selector.ts interface TaskContext { type: 'database' | 'frontend' | 'backend' | 'devops' | 'security'; complexity: 'low' | 'medium' | 'high'; codebase_size: 'small' | 'medium' | 'large'; performance_priority: boolean; } interface ModelConfig { name: string; strengths: string[]; ideal_use_cases: string[]; cost_tier: 'low' | 'medium' | 'high'; } class ModelSelector { private models: Map<string, ModelConfig> = new Map([ ['claude-3.5-sonnet', { name: 'claude-3.5-sonnet', strengths: ['code analysis', 'complex reasoning', 'large context'], ideal_use_cases: ['database design', 'architecture review'], cost_tier: 'medium' }], ['gpt-4o', { name: 'gpt-4o', strengths: ['rapid prototyping', 'frontend development', 'creative solutions'], ideal_use_cases: ['UI/UX development', 'quick iterations'], cost_tier: 'high' }], ['claude-sonnet-4', { name: 'claude-sonnet-4', strengths: ['software engineering', 'debugging', 'optimization'], ideal_use_cases: ['complex debugging', 'performance optimization'], cost_tier: 'high' }] ]); selectOptimalModel(context: TaskContext): string { // データベース関連タスク if (context.type === 'database') { return context.complexity === 'high' ? 'claude-sonnet-4' : 'claude-3.5-sonnet'; } // フロントエンド開発 if (context.type === 'frontend') { return context.performance_priority ? 'claude-sonnet-4' : 'gpt-4o'; } // セキュリティ関連 if (context.type === 'security') { return 'claude-sonnet-4'; // 最高精度を要求 } // デフォルト選択 return 'claude-3.5-sonnet'; } generateAgentConfig(context: TaskContext): string { const selectedModel = this.selectOptimalModel(context); return ` # ${context.type.toUpperCase()} 専門エージェント ## 使用モデル ${selectedModel} ## 選択理由 - タスクタイプ: ${context.type} - 複雑度: ${context.complexity} - パフォーマンス優先: ${context.performance_priority} ## 最適化設定 model: ${selectedModel} temperature: ${context.type === 'security' ? '0.1' : '0.3'} max_tokens: ${context.codebase_size === 'large' ? '8192' : '4096'} `; } } // 使用例 const selector = new ModelSelector(); const context: TaskContext = { type: 'database', complexity: 'high', codebase_size: 'large', performance_priority: true }; console.log(selector.generateAgentConfig(context));
動的エージェント配置システム¶
// agent-orchestrator.ts
interface AgentDefinition {
name: string;
model: string;
specialization: string;
context_window: number;
cost_per_request: number;
}
class AgentOrchestrator {
private agents: AgentDefinition[] = [];
private activeAgents: Map<string, AgentDefinition> = new Map();
async deploySpecializedAgent(taskType: string, requirements: TaskContext): Promise<string> {
const modelSelector = new ModelSelector();
const optimalModel = modelSelector.selectOptimalModel(requirements);
const agentId = `${taskType}-${Date.now()}`;
const agentConfig: AgentDefinition = {
name: agentId,
model: optimalModel,
specialization: taskType,
context_window: this.getContextWindow(optimalModel),
cost_per_request: this.getCostPerRequest(optimalModel)
};
// エージェント設定ファイルの生成
const configPath = `.claude/agents/${agentId}.md`;
const configContent = this.generateAgentConfig(agentConfig, requirements);
// ファイルシステムに保存(実際の実装では fs を使用)
await this.writeAgentConfig(configPath, configContent);
this.activeAgents.set(agentId, agentConfig);
return agentId;
}
private generateAgentConfig(agent: AgentDefinition, requirements: TaskContext): string {
return `# ${agent.specialization.toUpperCase()} 専門エージェント
## 基本設定
- エージェントID: ${agent.name}
- 使用モデル: ${agent.model}
- 専門分野: ${agent.specialization}
## パフォーマンス設定
- コンテキストウィンドウ: ${agent.context_window}
- 推定コスト: $${agent.cost_per_request}/リクエスト
## タスク固有設定
- 複雑度対応: ${requirements.complexity}
- コードベース規模: ${requirements.codebase_size}
- パフォーマンス重視: ${requirements.performance_priority}
## 実行可能タスク
${this.getTaskList(agent.specialization)}
## 連携エージェント
${this.getCollaborationAgents(agent.specialization)}
`;
}
private getTaskList(specialization: string): string {
const taskMappings = {
database: `
- ERD設計と最適化
- インデックス戦略策定
- クエリパフォーマンスチューニング
- データマイグレーション計画`,
frontend: `
- コンポーネント設計と実装
- 状態管理アーキテクチャ
- パフォーマンス最適化
- アクセシビリティ対応`,
security: `
- 脆弱性スキャンと対策
- セキュアコーディング
- 認証・認可実装
- セキュリティポリシー策定`
};
return taskMappings[specialization as keyof typeof taskMappings] || '- 汎用的な開発タスク';
}
private getCollaborationAgents(specialization: string): string {
const collaborations = {
database: '- backend-specialist: API設計連携\n- devops-specialist: 運用最適化',
frontend: '- backend-specialist: API仕様調整\n- security-specialist: XSS/CSRF対策',
security: '- 全エージェント: セキュリティレビュー'
};
return collaborations[specialization as keyof typeof collaborations] || '- 必要に応じて他エージェントと連携';
}
private getContextWindow(model: string): number {
const contextMappings = {
'claude-3.5-sonnet': 200000,
'gpt-4o': 128000,
'claude-sonnet-4': 200000
};
return contextMappings[model as keyof typeof contextMappings] || 100000;
}
private getCostPerRequest(model: string): number {
const costMappings = {
'claude-3.5-sonnet': 0.015,
'gpt-4o': 0.03,
'claude-sonnet-4': 0.06
};
return costMappings[model as keyof typeof costMappings] || 0.01;
}
private async writeAgentConfig(path: string, content: string): Promise<void> {
// 実際の実装では fs.writeFile を使用
console.log(`Writing agent config to ${path}`);
console.log(content);
}
}
5. 実践的ワークフロー統合¶
開発プロセスの自動化¶
#!/bin/bash
# development-workflow.sh
# 1. 要件分析フェーズ
echo "🔍 要件分析を開始..."
claude /agents/business-analyst "要件を分析し、技術仕様に落とし込んでください"
# 2. アーキテクチャ設計
echo "🏗️ アーキテクチャ設計を実行..."
claude /agents/architect "システムアーキテクチャを設計してください"
# 3. 並行開発実行
echo "⚡ 並行開発を開始..."
claude /agents/database-specialist "データベース設計を実装してください" &
claude /agents/backend-specialist "API実装を開始してください" &
claude /agents/frontend-specialist "UIコンポーネントを開発してください" &
# 4. 統合テスト
wait # 全ての並行処理完了を待機
echo "🧪 統合テストを実行..."
claude /agents/qa-specialist "統合テストを実行し、品質を検証してください"
# 5. デプロイメント
echo "🚀 デプロイメントを実行..."
claude /agents/devops-specialist "本番環境にデプロイしてください"
継続的改善ループ¶
# .github/workflows/ai-agent-improvement.yml
name: AI Agent Performance Analysis
on:
schedule:
- cron: '0 6 * * *' # 毎日6時に実行
workflow_dispatch:
jobs:
analyze-agent-performance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Analyze Agent Effectiveness
run: |
# エージェントの実行ログを分析
python scripts/analyze-agent-performance.py
- name: Update Agent Configurations
run: |
# パフォーマンスデータに基づいてエージェント設定を最適化
claude /commands/optimize-agents
- name: Commit Optimizations
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add .claude/agents/
git commit -m "🤖 自動最適化: エージェント設定更新" || exit 0
git push
まとめ¶
本ガイドでは、Claude Code の最新機能を活用した実践的な AI エージェントシステムの構築方法を詳解しました。
- サブエージェント設計: 専門特化による効率的な分業体制
- MCP サーバー開発: 外部ツール連携の自動化
- カスタムコマンド: ワークフロー固有の自動化
- マルチモデル戦略: タスク特性に応じた最適選択
これらの実装により、従来の手動開発プロセスから AI エージェント主導の自動化された開発環境への移行が可能になります。