php-mcp/laravel

repository·main·Indexed 19 days ago

https://github.com/php-mcp/laravel

A Laravel-optimized SDK for building Model Context Protocol (MCP) servers. It enables developers to expose Laravel application logic as Tools, Resources, and Prompts to AI assistants using either manual registration via the Mcp facade or attribute-based discovery. The SDK supports multiple transport layers, including STDIO for IDEs like Cursor, integrated HTTP, and a dedicated ReactPHP-based HTTP server for production environments.

Tokens
11.7K
Snippets
42
Records
52
Agent score
63%

What's inside php-mcp-laravel

  1. Handle exceptions in MCP tools

    main

    When a tool handler throws an exception, the Laravel MCP SDK automatically converts it into a valid JSON-RPC error response. This allows you to use standard PHP exceptions (like InvalidArgumentException or RuntimeException) to communicate errors to the MCP client.

    #[McpTool(name: 'get_user')]
    public function getUser(int $userId): array
    {
        $user = User::find($userId);
        
        if (!$user) {
            throw new \InvalidArgumentException("User with ID {$userId} not found");
        }
        
        return $user->toArray();
    }
  2. Use Laravel Dependency Injection in MCP handlers

    main

    MCP handlers are resolved via Laravel's service container. You can use standard constructor injection to provide services, gateways, or loggers to your tool methods.

    class OrderService
    {
        public function __construct(
            private PaymentGateway $gateway,
            private NotificationService $notifications,
            private LoggerInterface $logger
        ) {}
    
        #[McpTool(name: 'process_order')]
        public function processOrder(array $orderData): array
        {
            $this->logger->info('Processing order', $orderData);
            // ...
        }
    }
  3. Choose between JSON Response and SSE Modes

    main

    The dedicated HTTP server supports two transport modes via the enable_json_response setting:

    • JSON Mode ('enable_json_response' => true): Returns immediate JSON responses. Best for fast-executing tools.
    • SSE Mode ('enable_json_response' => false): Uses SSE streaming (default). Ideal for long-running operations and provides enhanced resumability.
  4. Deploy Dedicated HTTP Server with Supervisor

    main

    Since the dedicated HTTP server is a long-running process, it should be managed by a process manager like Supervisor in production.

    [program:laravel-mcp]
    process_name=%(program_name)s_%(process_num)02d
    command=php /var/www/laravel/artisan mcp:serve --transport=http
    autostart=true
    autorestart=true
    stopasgroup=true
    killasgroup=true
    user=www-data
    numprocs=1
    redirect_stderr=true
    stdout_logfile=/var/log/laravel-mcp.log
  5. Run the MCP Server via Integrated HTTP Transport

    main

    Integrated HTTP transport serves MCP through your existing Laravel application routes. This is best for development or applications with existing web servers.

    Default Routes:

    • GET /mcp - Streamable connection endpoint
    • POST /mcp - Message sending endpoint
    • DELETE /mcp - Session termination endpoint

    Legacy Mode Routes (if enabled):

    • GET /mcp/sse - Server-Sent Events endpoint
    • POST /mcp/message - Message sending endpoint
  6. Run the MCP Server via Dedicated HTTP Server

    main

    For production environments and high-traffic applications, use a dedicated ReactPHP-based HTTP server. This is the recommended approach for production.

    # Start dedicated server
    php artisan mcp:serve --transport=http
    
    # With custom configuration
    php artisan mcp:serve --transport=http \
        --host=0.0.0.0 \
        --port=8091 \
        --path-prefix=mcp_api
  7. Migrate from v2.x to v3.x

    main

    The migration from v2.x to v3.x contains breaking changes:

    1. Configuration Structure Changes Capabilities are now boolean flags instead of nested arrays:

    // v2.x
    'capabilities' => [
        'tools' => ['enabled' => true, 'listChanged' => true],
        'resources' => ['enabled' => true, 'subscribe' => true],
    ],
    
    // v3.x
    'capabilities' => [
        'tools' => true,
        'toolsListChanged' => true,
        'resources' => true,
        'resourcesSubscribe' => true,
    ],

    2. Session Configuration Session configuration now supports store and lottery keys:

    'session' => [
        'driver' => 'cache',
        'ttl' => 3600,
        'store' => config('cache.default'),
        'lottery' => [2, 100],
    ],

    3. Transport and CSRF

    • Default transport changed from sse to streamable.
    • CSRF exclusion pattern changed from mcp/* to mcp.

    4. API Changes

    • Deprecated methods were removed in favor of the new registry API.
    • Element registration now uses a new schema format.
  8. Install the Laravel MCP Server SDK

    main

    Install the package via Composer using the -W flag to ensure dependency compatibility. After installation, publish the configuration file and, if you plan to use database-backed session storage, publish and run the migrations.

    # Install the package
    composer require php-mcp/laravel:^3.0 -W
    
    # Publish configuration
    php artisan vendor:publish --provider="PhpMcp\Laravel\McpServiceProvider" --tag="mcp-config"
    
    # Setup database sessions (optional)
    php artisan vendor:publish --provider="PhpMcp\Laravel\McpServiceProvider" --tag="mcp-migrations"
    php artisan migrate
  9. Configure CSRF Exclusions for Integrated HTTP Transport

    main

    Because MCP clients send requests to your Laravel application, you must exclude the MCP routes from CSRF protection.

    // Laravel 11+
    // bootstrap/app.php
    ->withMiddleware(function (Middleware $middleware) {
        $middleware->validateCsrfTokens(except: [
            'mcp',           // For streamable transport (default)
            'mcp/*',         // For legacy transport (if enabled)
        ]);
    })
    
    // Laravel 10 and below
    // app/Http/Middleware/VerifyCsrfToken.php
    protected $except = [
        'mcp',           // For streamable transport (default)
        'mcp/*',         // For legacy transport (if enabled)
    ];
  10. Migrate from v3.0 to v3.1

    main

    Version 3.1 introduces several additive features with no breaking changes to existing v3.0 code:

    • Closure Handlers: You can now use anonymous functions for tools and resources.
    • Custom Input Schemas: Use the ->inputSchema(array $schema) method on blueprints to define complex JSON schemas for tool parameters.

    Example of new v3.1 features:

    // Closure-based tool
    Mcp::tool(function(float $x, float $y): float {
        return $x * $y;
    })->name('multiply');
    
    // Custom input schema
    Mcp::tool([CalculatorService::class, 'calculate'])
        ->inputSchema([
            'type' => 'object',
            'properties' => [
                'operation' => ['type' => 'string', 'enum' => ['add', 'subtract']]
            ],
            'required' => ['operation']
        ]);
  11. Run the MCP Server via STDIO Transport

    main

    Use STDIO transport for direct client execution, such as with the Cursor IDE or command-line tools.

    Warning: When using STDIO, never write to STDOUT in your handlers. STDOUT is reserved for JSON-RPC communication. Use Laravel's logger or STDERR for debugging.

    php artisan mcp:serve --transport=stdio
  12. Configure Integrated HTTP Transport Options

    main

    You can customize the integrated HTTP transport via the http_integrated configuration key.

    'http_integrated' => [
        'enabled' => true,
        'route_prefix' => 'mcp',           // URL prefix
        'middleware' => ['api'],           // Applied middleware
        'domain' => 'api.example.com',     // Optional domain
        'legacy' => false,                 // Use legacy SSE transport
    ],