Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Mcp Server Bundle Laravel Package

ecourty/mcp-server-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require ecourty/mcp-server-bundle
    

    Add to config/bundles.php:

    return [
        // ...
        EdouardCourty\McpServerBundle\McpServerBundle::class => ['all' => true],
    ];
    
  2. Basic Configuration Define a minimal config/packages/mcp_server.yaml:

    mcp_server:
        protocol_version: '2025-06-18'
        host: '0.0.0.0'
        port: 8080
    
  3. First Tool Implementation Create a tool class (e.g., src/Tool/MyTool.php):

    namespace App\Tool;
    
    use EdouardCourty\McpServerBundle\Tool\ToolInterface;
    
    class MyTool implements ToolInterface {
        public function execute(array $input): array {
            return ['result' => 'Processed: ' . $input['data']];
        }
    }
    
  4. Register Tool in Services

    # config/services.yaml
    services:
        App\Tool\MyTool:
            tags: ['mcp.tool']
    
  5. Run the Server

    php bin/console mcp:server:start
    

First Use Case: Simple Query Tool

Create a tool to fetch data from a database and expose it to the MCP client:

// src/Tool/DatabaseQueryTool.php
namespace App\Tool;

use Doctrine\ORM\EntityManagerInterface;
use EdouardCourty\McpServerBundle\Tool\ToolInterface;

class DatabaseQueryTool implements ToolInterface {
    public function __construct(private EntityManagerInterface $em) {}

    public function execute(array $input): array {
        $query = $this->em->createQuery($input['query']);
        return ['results' => $query->getResult()];
    }
}

Register it with:

services:
    App\Tool\DatabaseQueryTool:
        arguments: ['@doctrine.orm.entity_manager']
        tags: ['mcp.tool']

Implementation Patterns

Tool Development Workflow

  1. Interface Adherence All tools must implement ToolInterface with:

    public function execute(array $input): array;
    
    • Return structured JSON-serializable data.
    • Validate $input (e.g., using Symfony Validator).
  2. Dependency Injection Use Symfony’s DI to inject services (e.g., Doctrine, HTTP clients):

    use Symfony\Contracts\HttpClient\HttpClientInterface;
    
    class HttpTool implements ToolInterface {
        public function __construct(private HttpClientInterface $client) {}
        // ...
    }
    
  3. Tool Metadata Annotate tools with metadata (e.g., description, parameters) via YAML:

    # config/packages/mcp_tools.yaml
    mcp_tools:
        database_query:
            description: "Execute a Doctrine query."
            parameters:
                query: { type: string, required: true }
    
  4. Tool Groups Organize tools into logical groups (e.g., admin, user) for ACL:

    mcp_tools:
        groups:
            admin:
                - database_query
                - system_tools
    

Integration with Symfony Components

  1. Security Use Symfony’s security system to restrict tools:

    # config/packages/security.yaml
    access_control:
        - { path: ^/mcp/tools/database_query, roles: ROLE_ADMIN }
    
  2. Messenger for Async Tools Offload long-running tasks to Messenger:

    use Symfony\Component\Messenger\MessageBusInterface;
    
    class AsyncTool implements ToolInterface {
        public function __construct(private MessageBusInterface $bus) {}
    
        public function execute(array $input): array {
            $this->bus->dispatch(new ProcessInputMessage($input));
            return ['status' => 'queued'];
        }
    }
    
  3. Event Listeners Hook into MCP events (e.g., McpServerEvent::TOOL_EXECUTED):

    use EdouardCourty\McpServerBundle\Event\McpServerEvents;
    
    class ToolLogger implements EventSubscriberInterface {
        public static function getSubscribedEvents(): array {
            return [
                MCPServerEvents::TOOL_EXECUTED => 'onToolExecuted',
            ];
        }
    
        public function onToolExecuted(ToolExecutedEvent $event) {
            // Log tool usage
        }
    }
    

Prompt and Resource Management

  1. Dynamic Prompts Use Twig to render prompts dynamically:

    {# templates/mcp/prompts/welcome.twig #}
    Hello {{ user.name }}! Here are your tools:
    {% for tool in tools %}
        - {{ tool.description }}
    {% endfor %}
    

    Load in config:

    mcp_server:
        prompts:
            welcome: '@mcp/prompts/welcome.twig'
    
  2. Resource Caching Cache resources (e.g., FAQs) to reduce payload size:

    use Symfony\Contracts\Cache\CacheInterface;
    
    class FaqResourceTool implements ToolInterface {
        public function __construct(private CacheInterface $cache) {}
    
        public function execute(array $input): array {
            return $this->cache->get('faq', function() {
                return $this->fetchFaqFromDatabase();
            });
        }
    }
    

Gotchas and Tips

Common Pitfalls

  1. Protocol Version Mismatch

    • Issue: Clients may fail if the server’s protocol_version doesn’t match.
    • Fix: Always check the MCP spec for breaking changes.
    • Tip: Use a feature flag to support multiple versions temporarily:
      mcp_server:
          protocol_version: '2025-06-18'
          fallback_version: '2024-12-01'
      
  2. Tool Input Validation

    • Issue: Malformed input can crash tools.
    • Fix: Use Symfony’s Validator:
      use Symfony\Component\Validator\Validator\ValidatorInterface;
      
      class ValidatedTool implements ToolInterface {
          public function __construct(private ValidatorInterface $validator) {}
      
          public function execute(array $input): array {
              $errors = $this->validator->validate($input);
              if (count($errors)) {
                  throw new \RuntimeException((string) $errors);
              }
              // ...
          }
      }
      
  3. CORS and Authentication

    • Issue: Unauthorized access to tools.
    • Fix: Combine with Symfony’s security and CORS bundle:
      # config/packages/security.yaml
      firewalls:
          mcp:
              pattern: ^/mcp
              stateless: true
              json_login:
                  check_path: /mcp/auth
      
  4. Performance with Heavy Tools

    • Issue: Tools blocking the event loop.
    • Fix: Use ReactPHP for async tools:
      use React\Promise\PromiseInterface;
      
      class AsyncHttpTool implements ToolInterface {
          public function execute(array $input): array {
              return $this->client->request($input['url'])
                  ->then(fn(ResponseInterface $res) => $res->getBody()->getContents());
          }
      }
      

Debugging Tips

  1. Enable Verbose Logging

    mcp_server:
        debug: true
    

    Logs will appear in var/log/dev.log with tool execution details.

  2. Tool Execution Tracing Use the McpServerEvents::TOOL_EXECUTED event to trace inputs/outputs:

    public function onToolExecuted(ToolExecutedEvent $event) {
        \Log::debug('Tool executed', [
            'tool' => $event->getToolName(),
            'input' => $event->getInput(),
            'output' => $event->getOutput(),
            'duration_ms' => $event->getDuration(),
        ]);
    }
    
  3. Test Tools Locally Use the mcp:tool:test command to simulate tool execution:

    php bin/console mcp:tool:test database_query '{"query": "SELECT * FROM users"}'
    

Extension Points

  1. Custom Tool Factories Override tool instantiation for complex logic:

    use EdouardCourty\McpServerBundle\DependencyInjection\Compiler\ToolPass;
    
    class CustomToolFactoryPass extends ToolPass {
        public function process(\Symfony\Component\DependencyInjection\ContainerBuilder $container) {
            $definition = $container->findDefinition('mcp.tool_factory');
            $definition->addMethodCall('addFactory', [
                'database_query',
                [$container->getDefinition('App\Tool\DatabaseQueryToolFactory')],
            ]);
        }
    }
    
  2. Middleware for Tools Add preprocessing/postprocessing to tools:

    use EdouardCourty\McpServerBundle\Tool
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky