Laravel MCP について
Laravel MCP は、Laravel アプリケーションに Model Context Protocol を実装するための Composer パッケージです。PHP と Laravel の開発者を対象とし、AI モデルと Laravel アプリをつなぐ標準化されたインターフェースを提供します。
主な機能
- 01HTTP、WebSocket、Stdio のトランスポート
- 02ツールの登録と実行
- 03URI ベースのリソース管理
- 04プロンプトテンプレートと進捗追跡
- 05複数レベルのログ機能
活用シーン
- 01Laravel アプリの機能を MCP ツールとして公開
- 02URI ベースのリソースでファイルやデータを提供
- 03プロンプトテンプレートを使ったコードレビューアシスタントの構築
MCP 対応
本プロジェクトは Laravel 向けの MCP サーバーフレームワークであり、ツール、リソース、プロンプトを MCP クライアントに公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Laravel MCP
Laravel アプリケーションに Model Context Protocol(MCP)を実装するための Laravel パッケージです。このプロトコルにより、標準化されたインターフェースを介して AI モデルと Laravel アプリケーション間の通信が可能になります。
:star: mcphub で注目のプロジェクトとして掲載されています
要件
システム要件
- PHP 8.1 以降
- Laravel 10.x
- Composer 2.x
- OpenSSL PHP Extension
- PDO PHP Extension
- Mbstring PHP Extension
- XML PHP Extension
- Ctype PHP Extension
- JSON PHP Extension
- ReactPHP(HTTP/WebSocket トランスポート用)
- ext-json(JSON の処理用)
オプションの要件
- Redis(WebSocket のスケーリング用)
- Supervisor(プロセス管理用)
- ext-pcntl(シグナル処理用)
- ext-posix(プロセス管理用)
機能
-
複数のトランスポートオプション
- HTTP トランスポート(RESTful API)
- WebSocket トランスポート(リアルタイム)
- Stdio トランスポート(コマンドライン)
- ホストとポートの設定
-
サーバー機能
- ツールの登録と実行
- リソース管理
- プロンプトの処理
- 進捗状況の追跡
- ロギングシステム
- モデルの優先設定
-
ツールシステム
- パラメーター付きのカスタムツールを登録
- 引数を使ったツール呼び出しを処理
- 構造化された応答を返す
- エラー処理と検証
-
リソース管理
- URI ベースのリソースアクセス
- リソーステンプレート
- 動的なリソース処理
- コンテンツタイプのサポート
-
プロンプトシステム
- テンプレートベースのプロンプト
- 動的な引数処理
- コンテキスト管理
- メッセージ履歴のサポート
-
進捗状況の追跡
- リアルタイムの進捗状況更新
- トークンベースの追跡
- 進捗全体のサポート
- クライアント通知システム
-
ロギングシステム
- 複数のログレベル
- ロガーの識別
- 構造化ロギング
- トランスポートに依存しないロギング
ドキュメント
このプロジェクトでは、すべてのクラスとメソッドに包括的な PHPDoc ドキュメントを用意しています。ドキュメントはソースコード内で直接参照でき、以下の内容を網羅しています。
コアコンポーネント
-
サーバー機能(
src/Capabilities/ServerCapabilities.php)- サーバー機能の管理
- 実験的機能の設定
- ロギング設定
- コンポーネント機能(プロンプト、リソース、ツール)
-
クライアント機能(
src/Capabilities/ClientCapabilities.php)- 機能フラグの管理
- ルートディレクトリの設定
- 状態のシリアライズ/デシリアライズ
コンポーネント機能
-
ツール機能(
src/Capabilities/ToolsCapability.php)- ツールリストの変更追跡
- 状態管理
- 変更通知のサポート
-
リソース機能(
src/Capabilities/ResourcesCapability.php)- リソース購読の管理
- 変更追跡
- 状態のシリアライズ
-
プロンプト機能(
src/Capabilities/PromptsCapability.php)- プロンプトリストの変更追跡
- 状態管理
- 変更通知
-
ルート機能(
src/Capabilities/RootsCapability.php)- ルートディレクトリの管理
- ディレクトリ設定
- アクセス制御の設定
サーバー管理
- MCP サーバーコマンド(
src/Commands/MCPServerCommand.php)- サーバー起動時の設定
- トランスポートの選択
- シグナル処理
- グレースフルシャットダウン
各コンポーネントには以下が含まれます。
- クラスの詳細な説明
- 機能と機能一覧
- 設定例
- 使用例
- メソッドのドキュメント
- パラメーターの説明
- 戻り値のドキュメント
ドキュメントを参照するには:
src/ディレクトリ内のソースファイルを確認します- IDE の PHPDoc 連携機能を使用します
- phpDocumentor を使用して HTML ドキュメントを生成します(任意)
HTML ドキュメントを生成するには:
composer require --dev phpdocumentor/phpdocumentor
vendor/bin/phpdoc -d src/ -t docs/
インストール
Composer を使用してインストールします。
composer require laravelmcp/mcp
パッケージのサービスプロバイダーとファサードは自動的に登録されます。
設定
- 設定を公開します:
php artisan vendor:publish --provider="LaravelMCP\MCP\MCPServiceProvider" --tag="config"
- 環境変数を設定します:
MCP_SERVER_HOST=127.0.0.1
MCP_SERVER_PORT=8080
MCP_SERVER_TRANSPORT=http
基本的な使い方
サーバーの起動
# Start the server with default HTTP transport
php artisan mcp:serve
# Start with specific transport and options
php artisan mcp:serve --transport=websocket --host=0.0.0.0 --port=8081
# Start with stdio transport (useful for CLI applications)
php artisan mcp:serve --transport=stdio
サーバーのセットアップ
use LaravelMCP\MCP\Server\MCPServer;
use LaravelMCP\MCP\Transport\HttpTransport;
// Create and configure server
$server = new MCPServer();
// Configure transport
$transport = new HttpTransport($server, [
'host' => '127.0.0.1',
'port' => 8080
]);
$server->setTransport($transport);
$server->initialize();
// Start the server
$server->start();
異なるトランスポートの使用
use LaravelMCP\MCP\Transport\WebSocketTransport;
use LaravelMCP\MCP\Transport\StdioTransport;
use LaravelMCP\MCP\Transport\TransportFactory;
// Using WebSocket transport
$wsTransport = new WebSocketTransport($server, [
'host' => '0.0.0.0',
'port' => 8081
]);
// Using Stdio transport (for CLI applications)
$stdioTransport = new StdioTransport($server);
// Using transport factory
$factory = new TransportFactory();
$transport = $factory->create('http', $server, [
'host' => '127.0.0.1',
'port' => 8080
]);
ツールの登録
use LaravelMCP\MCP\Server\FastMCP;
use LaravelMCP\MCP\Facades\MCP;
// Using FastMCP (recommended)
$mcp = new FastMCP();
// Register a simple calculation tool
$mcp->tool('calculate', [
'num1' => ['type' => 'number', 'required' => true],
'num2' => ['type' => 'number', 'required' => true],
'operation' => ['type' => 'string', 'required' => true]
])(function ($args) {
$num1 = $args['num1'];
$num2 = $args['num2'];
$operation = $args['operation'];
return match ($operation) {
'+' => ['result' => $num1 + $num2],
'-' => ['result' => $num1 - $num2],
'*' => ['result' => $num1 * $num2],
'/' => $num2 != 0 ? ['result' => $num1 / $num2] : ['error' => 'Division by zero'],
default => ['error' => 'Invalid operation']
};
});
// Register a tool with error handling
$mcp->tool('process-data', [
'items' => ['type' => 'array', 'required' => true],
'token' => ['type' => 'string', 'required' => false]
])(function ($args) use ($mcp) {
try {
$items = $args['items'];
$token = $args['token'] ?? uniqid();
foreach ($items as $index => $item) {
// Process item
$progress = ($index + 1) / count($items);
MCP::sendProgress($progress, $token, count($items));
MCP::sendLog("Processing item {$index + 1}", 'info', 'processor');
}
return ['processed' => count($items)];
} catch (\Exception $e) {
MCP::sendLog($e->getMessage(), 'error', 'processor');
return ['error' => $e->getMessage()];
}
});
リソースの管理
// Register a file resource
$mcp->resource('file://{path}')(function ($matches) {
$path = $matches['path'] ?? null;
if (!$path || !file_exists($path)) {
return ['error' => 'File not found'];
}
return [
'content' => file_get_contents($path),
'metadata' => [
'size' => filesize($path),
'modified' => filemtime($path),
'mime' => mime_content_type($path)
]
];
});
// Register a database resource
$mcp->resource('db://{table}/{id}')(function ($matches) {
$table = $matches['table'] ?? null;
$id = $matches['id'] ?? null;
if (!$table || !$id) {
return ['error' => 'Invalid parameters'];
}
try {
$record = DB::table($table)->find($id);
return $record ? ['data' => $record] : ['error' => 'Record not found'];
} catch (\Exception $e) {
return ['error' => $e->getMessage()];
}
});
// Register a health check resource
$mcp->resource('/health')(function () {
return ['status' => 'ok'];
});
プロンプトの処理
// Basic prompt template
$mcp->prompt('code-review', [
'language' => ['type' => 'string', 'required' => true],
'code' => ['type' => 'string', 'required' => true]
])(function ($args) {
return [
['role' => 'system', 'content' => 'You are a code review assistant.'],
['role' => 'user', 'content' => "Please review this {$args['language']} code:\n\n{$args['code']}"]
];
});
// Prompt with context
$mcp->prompt('chat', [
'message' => ['type' => 'string', 'required' => true],
'context' => ['type' => 'array', 'required' => false]
])(function ($args) {
$messages = $args['context'] ?? [];
$messages[] = [
'role' => 'user',
'content' => $args['message']
];
return $messages;
});
進捗とログ
use LaravelMCP\MCP\Facades\MCP;
// Send progress updates
MCP::sendProgress(0.5, 'task_123', 1.0);
// Send logs with different levels
MCP::sendLog('Processing started', 'info', 'processor');
MCP::sendLog('Warning: Rate limit approaching', 'warning', 'rate-limiter');
MCP::sendLog('Error occurred: Invalid input', 'error', 'validator');
MCP::sendLog('Debug: Request payload', 'debug', 'http');
モデルの設定
use LaravelMCP\MCP\Sampling\ModelPreferences;
// Basic model preferences
$preferences = new ModelPreferences(
costPriority: 0.5,
intelligencePriority: 0.8,
speedPriority: 0.3
);
MCP::setModelPreferences($preferences);
// Model preferences with hints
$preferences = new ModelPreferences(
costPriority: 0.7,
intelligencePriority: 0.9,
speedPriority: 0.4,
hints: ['creative', 'concise']
);
MCP::setModelPreferences($preferences);
// Create from array
$preferences = ModelPreferences::create([
'costPriority' => 0.6,
'intelligencePriority' => 0.8,
'speedPriority' => 0.5,
'hints' => ['detailed', 'technical']
]);
MCP::setModelPreferences($preferences);
エラー処理
use LaravelMCP\MCP\Facades\MCP;
try {
// Initialize server
$server = new MCPServer();
if (!$server->getTransport()) {
throw new RuntimeException('Transport not initialized');
}
// Handle tool call
$result = $server->handleToolCall('test_tool', [
'param1' => 'value1',
'param2' => 'value2'
]);
// Handle resource request
$resource = $server->handleResourceRequest('test://resource');
// Handle prompt request
$prompt = $server->handlePromptRequest('test_prompt', [
'arg1' => 'value1'
]);
} catch (RuntimeException $e) {
MCP::sendLog("Runtime error: {$e->getMessage()}", 'error', 'server');
} catch (\Exception $e) {
MCP::sendLog("Unexpected error: {$e->getMessage()}", 'error', 'server');
}
LLM を楽しむ:コードレビューアシスタントの構築
コードを分析し、改善を提案し、さらにはバグを修正できるコードレビューアシスタントを構築する、完全な例を紹介します。
use LaravelMCP\MCP\Server\FastMCP;
use LaravelMCP\MCP\Facades\MCP;
use Illuminate\Support\Facades\Storage;
$mcp = new FastMCP();
// Register a tool for analyzing code complexity
$mcp->tool('analyze-complexity', [
'code' => ['type' => 'string', 'required' => true],
'language' => ['type' => 'string', 'required' => true]
])(function ($args) {
// Simulate complexity analysis
$metrics = [
'cyclomatic' => random_int(1, 10),
'cognitive' => random_int(1, 15),
'lines' => count(explode("\n", $args['code']))
];
return [
'metrics' => $metrics,
'suggestion' => $metrics['cyclomatic'] > 5 ? 'Consider breaking down this function' : 'Complexity is acceptable'
];
});
// Register a code improvement prompt
$mcp->prompt('suggest-improvements', [
'code' => ['type' => 'string', 'required' => true],
'language' => ['type' => 'string', 'required' => true],
'context' => ['type' => 'string', 'required' => false]
])(function ($args) {
$messages = [
[
'role' => 'system',
'content' => "You are an expert {$args['language']} developer. Analyze the code and suggest improvements for:
1. Performance
2. Readability
3. Best practices
4. Potential bugs
Be specific and provide examples."
],
[
'role' => 'user',
'content' => "Here's the code to review:\n\n```{$args['language']}\n{$args['code']}\n```"
]
];
if (isset($args['context'])) {
$messages[] = [
'role' => 'user',
'content' => "Additional context: {$args['context']}"
];
}
return $messages;
});
// Register a resource for storing review history
$mcp->resource('reviews://{file_hash}')(function ($matches) {
$hash = $matches['file_hash'] ?? null;
if (!$hash) return ['error' => 'Invalid file hash'];
$reviewPath = "reviews/{$hash}.json";
if (!Storage::exists($reviewPath)) {
return ['error' => 'No review history found'];
}
return ['history' => json_decode(Storage::get($reviewPath), true)];
});
// Create a fun code review workflow
$mcp->tool('review-code', [
'code' => ['type' => 'string', 'required' => true],
'language' => ['type' => 'string', 'required' => true],
'style' => ['type' => 'string', 'enum' => ['serious', 'fun', 'sarcastic'], 'default' => 'serious']
])(function ($args) use ($mcp) {
$fileHash = md5($args['code']);
$reviewToken = uniqid('review_');
try {
// Step 1: Analyze complexity
MCP::sendProgress(0.2, $reviewToken, "Analyzing code complexity...");
$complexity = $mcp->call('analyze-complexity', [
'code' => $args['code'],
'language' => $args['language']
]);
// Step 2: Get improvement suggestions
MCP::sendProgress(0.5, $reviewToken, "Getting expert suggestions...");
$personality = match($args['style']) {
'fun' => "Be playful and use coding puns, but maintain professionalism.",
'sarcastic' => "Use witty, sarcastic humor (but stay constructive and kind).",
default => "Be direct and professional."
};
$suggestions = $mcp->prompt('suggest-improvements', [
'code' => $args['code'],
'language' => $args['language'],
'context' => "Please {$personality}\nComplexity metrics: " . json_encode($complexity['metrics'])
]);
// Step 3: Store review history
MCP::sendProgress(0.8, $reviewToken, "Saving review history...");
Storage::put("reviews/{$fileHash}.json", json_encode([
'timestamp' => now(),
'complexity' => $complexity,
'suggestions' => $suggestions,
'style' => $args['style']
]));
// Step 4: Format response
MCP::sendProgress(1.0, $reviewToken, "Done!");
$funnyComments = [
'fun' => [
"🎮 Game Over! Your code review is ready!",
"🎯 Hit the target! Here's your review!",
"🎪 Step right up to see your code review!"
],
'sarcastic' => [
"🎭 Oh look, another masterpiece to review...",
"🎪 Ladies and gentlemen, behold this code!",
"🎯 Well, well, well... what do we have here?"
],
'serious' => [
"✅ Code review completed",
"📋 Analysis complete",
"🔍 Review finished"
]
];
return [
'message' => $funnyComments[$args['style']][array_rand($funnyComments[$args['style']])],
'complexity' => $complexity,
'suggestions' => $suggestions,
'history_uri' => "reviews://{$fileHash}"
];
} catch (\Exception $e) {
MCP::sendLog("Review error: {$e->getMessage()}", 'error', 'reviewer');
return ['error' => "Oops! The code reviewer needs coffee! ({$e->getMessage()})"];
}
});
// Example usage:
$result = $mcp->call('review-code', [
'code' => '
function fibonacci($n) {
if ($n <= 1) return $n;
return fibonacci($n - 1) + fibonacci($n - 2);
}
',
'language' => 'php',
'style' => 'fun'
]);
// Output might include fun messages like:
// "🎮 Game Over! Your code review is ready!"
// With suggestions about using memoization for better performance
// and adding parameter validation!
この例では、次の内容を示します:
- 複雑さの分析を伴うツールの登録
- 個性を持たせたカスタムプロンプトテンプレート
- レビュー履歴のリソース管理
- 楽しいメッセージによる進捗追跡
- ユーモアを交えたエラー処理
- 複数の MCP 機能の統合
- 実際のコード改善ワークフロー
テスト
テストスイートを実行します:
composer test
コントリビューション
詳細については、CONTRIBUTING.mdをご覧ください。
セキュリティ
セキュリティ関連の問題を発見した場合は、イシュートラッカーではなく、[email protected] までメールでご連絡ください。
ライセンス
MIT ライセンス(MIT)です。詳細については、ライセンスファイルをご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。