Laravel MCP Server

repository·main·Indexed 43 days ago

https://github.com/opgginc/laravel-mcp-server

A framework for building Model Context Protocol (MCP) servers within Laravel and Lumen applications. It features a route-first approach to register tools, resources, prompts, and notifications as web endpoints, including a fluent JsonSchema builder for tool inputs and the ability to generate MCP components from OpenAPI/Swagger specifications.

Tokens
21.3K
Snippets
69
Records
84
Agent score
54%

What's inside Laravel MCP Server

  1. Implement Dynamic Tool Filtering by Query String

    main

    To expose different tool sets based on URL query parameters, implement the DynamicToolResolverInterface.

    1. declaredTools(McpEndpointDefinition $endpoint): Returns the full catalog of tools available to this endpoint.
    2. resolve(McpEndpointDefinition $endpoint, ToolResolutionContext $context): Returns the specific subset of tools visible for the current request based on $context->queryParameters.
    3. consumedQueryParameters(): (Optional convention) List query keys that should be used for filtering but not forwarded as tool arguments. If omitted, these keys are forwarded as arguments.

    Register the resolver using ->dynamicTools(YourResolver::class) on the route.

    use OPGG\LaravelMcpServer\Data\ToolResolutionContext;
    use OPGG\LaravelMcpServer\Routing\McpEndpointDefinition;
    use OPGG\LaravelMcpServer\Services\ToolService\DynamicToolResolverInterface;
    
    final class LolPhaseToolResolver implements DynamicToolResolverInterface
    {
        public function declaredTools(McpEndpointDefinition $endpoint): array
        {
            return [
                \App\MCP\Tools\LolSearchChampionMetaTool::class,
                \App\MCP\Tools\LolGetChampionAnalysisTool::class,
                \App\MCP\Tools\LolGetLiveItemRecommendationsTool::class,
            ];
        }
    
        public function resolve(
            McpEndpointDefinition $endpoint,
            ToolResolutionContext $context,
        ): array {
            return match ($context->queryParameters['phase'] ?? null) {
                'lobby' => [
                    \App\MCP\Tools\LolSearchChampionMetaTool::class,
                    \App\MCP\Tools\LolGetChampionAnalysisTool::class,
                ],
                'inprogress' => [
                    \App\MCP\Tools\LolGetLiveItemRecommendationsTool::class,
                ],
                default => $this->declaredTools($endpoint),
            };
        }
    
        public function consumedQueryParameters(): array
        {
            return ['phase'];
        }
    }
    
    // Registration
    Route::mcp('/mcp/voice/lol/live')
        ->setServerInfo(
            name: 'OP.GG MCP Server - Voice lol Live',
            version: '1.0.0',
        )
        ->dynamicTools(LolPhaseToolResolver::class);
  2. Register MCP components on a Laravel route

    main

    To expose MCP (Model Context Protocol) capabilities, use the Route::mcp() method in your Laravel routes file. This method allows you to define a dedicated endpoint and attach specific tools, resources, and prompts to it. You must provide server metadata using setServerInfo().

    Available methods for registration:

    • setServerInfo(name: string, version: string): Sets the identity of the MCP server.
    • tools([class_name::class, ...]): Registers tool classes.
    • resources([class_name::class, ...]): Registers resource classes.
    • prompts([class_name::class, ...]): Registers prompt classes.
    use App\MCP\Prompts\WelcomePrompt;
    use App\MCP\Resources\BuildInfoResource;
    use App\MCP\Tools\GreetingTool;
    use Illuminate\Support\Facades\Route;
    
    Route::mcp('/mcp')
        ->setServerInfo(
            name: 'Example MCP Server',
            version: '2.0.0',
        )
        ->tools([GreetingTool::class])
        ->resources([BuildInfoResource::class])
        ->prompts([WelcomePrompt::class]);
  3. Secure MCP endpoints in production

    main

    It is recommended to protect your MCP endpoints using Laravel middleware (e.g., auth:sanctum or throttle) to ensure only authorized clients can access your tools.

    use Illuminate\Support\Facades\Route;
    
    Route::middleware([
        'auth:sanctum',
        'throttle:100,1',
    ])->group(function (): void {
        Route::mcp('/mcp')
            ->setServerInfo(
                name: 'Secure MCP',
                version: '2.0.0',
            )
            ->tools([
                \App\MCP\Tools\MyCustomTool::class,
            ]);
    });
  4. Migrate from v1.0.0 to v2.0.0

    main

    Version 2.0.0 introduces a route-first architecture, replacing the previous config-driven bootstrapping. Key changes include:

    • Removal of Config-driven Bootstrapping: config/mcp-server.php is no longer used. MCP routes must be explicitly registered in your routing files.
    • Transport Change: Legacy SSE endpoints (/sse, /message) are removed. Only Streamable HTTP is supported. POST /path handles JSON-RPC requests, while GET /path returns a 405 error.
    • Metadata Consolidation: Individual metadata mutators (like setName(), setVersion()) are replaced by a single setServerInfo() method.
    • Explicit Registration: Use Route::mcp('/path') in Laravel or McpRoute::register('/path') in Lumen.

    Quick Checklist:

    1. Remove old MCP config logic and SSE endpoint assumptions.
    2. Register MCP endpoints directly in route files.
    3. Replace setName(), setVersion(), etc., with setServerInfo().
    4. Move tool/resource/prompt registrations to the route builder chain.
    5. Run php artisan mcp:migrate-tools to automate tool interface updates.
    6. Update MCP clients to point to the new explicit route path.
  5. Verify your MCP endpoint

    main

    After registering your route, you can verify it using Artisan commands or a direct JSON-RPC request via curl.

    Artisan commands:

    • php artisan route:list | grep mcp to check if the route exists.
    • php artisan mcp:test-tool --list --endpoint=/mcp to list available tools.

    Manual JSON-RPC check:

    curl -X POST http://localhost:8000/mcp \
      -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
  6. Translate the README documentation

    main

    You can translate the README using a Python script. First, install the necessary Python dependencies, then export your Anthropic API key, and finally run the translation script. You can also specify target languages as arguments.

    pip install -r scripts/requirements.txt
    export ANTHROPIC_API_KEY='your-api-key'
    python scripts/translate_readme.py
    
    # To translate specific languages (e.g., Spanish and Korean):
    python scripts/translate_readme.py es ko
  7. Migrate Tool implementations to v1.1.0+

    main

    Version 1.1.0 of opgginc/laravel-mcp-server introduced breaking changes to the OPGG\LaravelMcpServer\Services\ToolService\ToolInterface. If you are upgrading from v1.0.x, you must update your tool implementations to match the new method signatures.

    Automated Migration

    You can use the provided Artisan command to refactor your tool classes automatically. The command identifies old signatures, creates a .backup file for each modified tool, and updates the methods and imports.

    • Default usage: php artisan mcp:migrate-tools (assumes tools are in app/MCP/Tools/)
    • Custom path: php artisan mcp:migrate-tools path/to/your/tools
    php artisan mcp:migrate-tools
  8. Install Laravel MCP Server via Composer

    main

    Install the package using Composer to add MCP (Model Context Protocol) capabilities to your Laravel or Lumen application.

    Requirements:

    • PHP >= 8.2
    • Laravel (Illuminate) >= 9.x
    • Lumen >= 9.x (optional)
    composer require opgginc/laravel-mcp-server
  9. Secure your MCP endpoint in production

    main

    You can protect your MCP endpoints using standard Laravel middleware (e.g., auth:sanctum or throttle) by wrapping the Route::mcp() definition within a middleware group.

    use Illuminate\Support\Facades\Route;
    
    Route::middleware([
        'auth:sanctum',
        'throttle:100,1',
    ])->group(function (): void {
        Route::mcp('/mcp')
            ->setServerInfo(
                name: 'Secure MCP',
                version: '2.0.0',
            )
            ->tools([
                \App\MCP\Tools\MyCustomTool::class,
            ]);
    });
  10. Register an MCP endpoint in Lumen

    main

    For Lumen applications, first register the service provider in bootstrap/app.php, then use the McpRoute::register() method to define your endpoint.

    // bootstrap/app.php
    $app->withFacades();
    $app->withEloquent();
    $app->register(OPGG\LaravelMcpServer\LaravelMcpServerServiceProvider::class);
    
    // In your routes file
    use OPGG\LaravelMcpServer\Routing\McpRoute;
    use OPGG\LaravelMcpServer\Services\ToolService\Examples\HelloWorldTool;
    
    McpRoute::register('/mcp')
        ->setServerInfo(
            name: 'OP.GG MCP Server',
            version: '2.0.0',
        )
        ->tools([
            HelloWorldTool::class,
        ]);
  11. Register an MCP endpoint in Laravel

    main

    In Laravel, use the Route::mcp() method to define an MCP endpoint. You can set server metadata using setServerInfo() and register tools, resources, prompts, and more directly on the route builder.

    Example registration:

    use Illuminate\Support\
    Facades\Route;
    use OPGG\LaravelMcpServer\Services\ToolService\Examples\HelloWorldTool;
    
    Route::mcp('/mcp')
        ->setServerInfo(
            name: 'My MCP Server',
            version: '2.0.0',
        )
        ->tools([
            HelloWorldTool::class,
        ]);
    use Illuminate\Support\Facades\Route;
    use OPGG\LaravelMcpServer\Services\ToolService\Examples\HelloWorldTool;
    use OPGG\LaravelMcpServer\Services\ToolService\Examples\VersionCheckTool;
    
    Route::mcp('/mcp')
        ->setServerInfo(
            name: 'OP.GG MCP Server',
            version: '2.0.0',
        )
        ->tools([
            HelloWorldTool::class,
            VersionCheckTool::class,
        ]);