Laravel MCP (laravel/mcp) дозволяє застосунку стати MCP-сервером: AI-клієнти (Claude, ChatGPT, Cursor) отримують доступ до інструментів, ресурсів і промптів вашого продукту.
php artisan make:mcp-server ShopServer
php artisan make:mcp-tool SearchProductsTool
#[Name('Shop')]
#[Version('1.0.0')]
#[Instructions('Пошук товарів і перегляд замовлень магазину.')]
class ShopServer extends Server
{
protected array $tools = [SearchProductsTool::class, OrderStatusTool::class];
protected array $resources = [ReturnPolicyResource::class];
protected array $prompts = [];
}
#[IsReadOnly]
class OrderStatusTool extends Tool
{
protected string $description = 'Статус замовлення поточного користувача за номером.';
public function schema(JsonSchema $schema): array
{
return ['number' => $schema->integer()->required()];
}
public function handle(Request $request): Response
{
$data = $request->validate(['number' => 'required|integer']);
$order = $request->user()->orders()->where('number', $data['number'])->first();
return $order ? Response::text($order->status->label()) : Response::error('Замовлення не знайдено.');
}
}
Реєстрація у routes/ai.php:
Mcp::web('/mcp/shop', ShopServer::class)->middleware(['auth:sanctum', 'throttle:mcp']);
Mcp::local('shop', ShopServer::class); // для локальних агентів через artisan
Захист - вебсервер MCP це публічний API:
- автентифікація:
auth:sanctumз токеном у заголовкуAuthorizationабо OAuth 2.1 через Passport (Mcp::oauthRoutes()+auth:api) - другий варіант потрібен клієнтам на кшталт Claude.ai, що підключаються від імені користувача; - авторизація в кожному інструменті:
$request->user()і політики. Модель передасть будь-який номер замовлення - перевірка «чи належить воно користувачу» обов'язкова; shouldRegister()- приховати інструмент від користувачів без прав чи підписки: він не з'явиться в списку й не викликається;- анотації (
#[IsReadOnly],#[IsDestructive],#[IsIdempotent]) - підказки клієнту, які дії потребують підтвердження. Це не захист - клієнт може їх ігнорувати; - обмеження частоти - агенти викликають інструменти в циклі значно частіше за людей;
- мінімальні дані у відповіді: результат інструмента потрапляє в контекст моделі й далі може опинитися будь-де. Не повертати зайвих полів.
Prompt injection з вашого боку: дані, які сервер повертає (відгуки, описи товарів від продавців), можуть містити інструкції для моделі. Позначайте їх як дані, а деструктивні інструменти не робіть доступними разом з інструментами, що читають сторонній контент.
Тестування:
ShopServer::actingAs($user)
->tool(OrderStatusTool::class, ['number' => 1042])
->assertOk()
->assertSee('Доставлено');
Для ручної перевірки - php artisan mcp:inspector.