๐ค Laravel Vibes
A Laravel package for implementing the Machine Control Protocol (MCP) server
projectsaturnstudios
README
๐ค Laravel Vibes
A powerful Laravel package for implementing the Machine Control Protocol (MCP) server, enabling seamless integration with AI agents in your applications. Build intelligent, interactive features with structured tool definitions and real-time communication.
<details> <summary>๐ Table of Contents</summary>
- ๐ค Laravel Vibes
- โจ Key Features
- ๐ฆ Implementation Status
- ๐ Documentation
- ๐ง Installation
- โ๏ธ Configuration
- ๐ Usage
- ๐ Tool Discovery & Registration
- ๐งช Comprehensive Testing Guide
- ๐งฐ API Reference
- ๐ก๏ธ Middleware Components
- ๐ค MCP Protocol Integration
- ๐ Advanced Usage Examples
- ๐ Laravel 12 Compatibility
- ๐ Deployment Considerations
- ๐ Architecture
- ๐ Roadmap
- ๐ฅ Credits
- ๐ Security
- ๐ License
- ๐ค Contributing
- ๐ Flow Diagrams
- ๐ Real-World Examples
</details>
โจ Key Features
- ๐ง Tool Registration System - Define, register, and expose tools for AI agents to use
- ๐ Server-Sent Events (SSE) - Real-time communication with AI agents via event streams
- ๐ฃ๏ธ API Endpoints - Ready-to-use endpoints for MCP protocol implementation
- ๐งฉ Primitive Handlers - Extensible system for various MCP primitives
- ๐ Auto-Discovery - Automatic discovery of tool implementations in your codebase
- ๐ฆบ Type Safety - Full PHP 8.2+ type hinting and return type declarations
- ๐ฎ Future-Ready - Foundation for upcoming MCP features (resources, prompts, samples, and roots) with framework in place
๐ฆ Implementation Status
This section provides a clear overview of which MCP primitives are currently implemented and which are planned for future releases.
Primitive Implementation Status
Primitive | Status | Version Introduced | Notes |
---|---|---|---|
Tools | โ Full | 0.1.0 | Complete implementation with repositories, data objects, and discovery |
Resources | ๐ง Partial | 0.4.0 | Framework in place, API not finalized |
Prompts | ๐ง Partial | 0.4.0 | Framework in place, API not finalized |
Samples | ๐ง Partial | 0.4.0 | Framework in place, API not finalized |
Roots | ๐ง Partial | 0.4.0 | Framework in place, API not finalized |
Feature Availability Matrix
Feature | v0.1.0 | v0.2.0 | v0.3.0 | v0.4.0 | Planned |
---|---|---|---|---|---|
Tool Registration | โ | โ | โ | โ | โ |
Server-Sent Events | โ | โ | โ | โ | โ |
Auto-Discovery | โ | โ | โ | โ | โ |
Primitive Caching | โ | โ | โ | โ | โ |
Resource Primitives | โ | โ | โ | ๐ง | โ |
Prompt Primitives | โ | โ | โ | ๐ง | โ |
Sample Primitives | โ | โ | โ | ๐ง | โ |
Root Primitives | โ | โ | โ | ๐ง | โ |
Legend:
- โ Full implementation
- ๐ง Partial implementation
- โ Not implemented
๐ Documentation
Comprehensive documentation for Laravel Vibes is available in the docs/
directory:
Documentation File | Description |
---|---|
TheAgency.md | Detailed documentation for TheAgency class, the central orchestrator for MCP primitives |
ClassDiagram.md | Structural diagram showing relationships between classes |
UsageExamples.md | Practical examples for using Laravel Vibes in your applications |
CONTRIBUTING.md | Guidelines for contributing to Laravel Vibes |
Flow-Diagrams.md | Visual diagrams of Laravel Vibes architecture and workflows |
Examples.md | Real-world examples of Laravel Vibes implementation |
index.md | Overview and core concepts documentation |
Class Diagram
Below is a simplified class diagram showing the main components of Laravel Vibes:
classDiagram
class TheAgency {
+addPrimitiveHandler(mixed primitiveHandlerClass)
+removePrimitiveHandler(string primitiveHandlerClass)
+addTool(mixed tool)
+getTool(string name)
}
class VibeTool {
#string name
+static getMetadata() array
+getName() string
}
class PrimitiveHandler {
<<interface>>
+getName() string
}
TheAgency o-- VibeTool : manages
VibeTool ..|> PrimitiveHandler : implements
๐ง Installation
You can install the package via composer:
composer require projectsaturnstudios/laravel-vibes
The package will automatically register its service provider with Laravel.
โ๏ธ Configuration
Publish the configuration files with:
php artisan vendor:publish --tag="vibes"
This will publish the configuration file to config/vibes.php
and config/cors.vibes.php
.
Key configuration options:
return [
'service_info' => [
'server_name' => env('VIBE_SVC_NAME', 'laravel-vibes-server'),
'server_version' => env('VIBE_SVC_VERSION', '1.0.0'),
'heartbeat_interval' => 20, // seconds
'catch_exceptions' => false, // Catch exceptions in MCP event loop
],
'features' => [
'tools' => true, // Tool registration and execution (fully implemented)
'resources' => false, // Resource discovery and access (partial implementation)
'prompts' => false, // Prompt templates and execution (partial implementation)
'samples' => false, // Model behavior configuration (partial implementation)
'roots' => false, // Custom workflow entry points (partial implementation)
],
'auto_discover_all_primitives' => [app()->path()],
'auto_discover_base_path' => base_path(),
// Tool repository and route configurations...
];
๐ Learn more: For advanced configuration options, see the Configuration section in TheAgency.md.
๐ Usage
Registering Tools
Register AI tools in your service provider:
use App\Tools\TextAnalysisTool;
use App\Tools\DataFetchTool;
// In a service provider's boot method
public function boot()
{
$agency = app('the-agency');
$agency->addTools([
TextAnalysisTool::class,
DataFetchTool::class,
]);
}
Or register via the config file:
'tools' => [
'text-analysis' => \App\Tools\TextAnalysisTool::class,
'data-fetch' => \App\Tools\DataFetchTool::class,
],
Defining a Custom Tool
Create a tool that AI agents can use:
<?php
namespace App\Tools;
use ProjectSaturnStudios\Vibes\Primitives\Tools\Data\VibeTool;
class WeatherTool extends VibeTool
{
protected string $name = 'weather';
public static function getMetadata(): array
{
return [
'name' => 'weather',
'description' => 'Get current weather for a location',
'parameters' => [
'type' => 'object',
'properties' => [
'location' => [
'type' => 'string',
'description' => 'City name or location'
]
],
'required' => ['location']
]
];
}
public function handle(string $location)
{
// Implement weather lookup logic
return [
'location' => $location,
'temperature' => 72,
'conditions' => 'sunny'
];
}
}
Using Server-Sent Events
Connect AI agents to your application using SSE:
// Frontend JavaScript
const eventSource = new EventSource('/mcp/sse');
const sessionId = generateUniqueId();
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('Received update:', data);
};
Handling AI Agent Messages
Process incoming MCP messages from agents:
// POST to /mcp/sse/messages
{
"jsonrpc": "2.0",
"method": "run_tool",
"session_id": "session-12345",
"id": "req-1",
"params": {
"name": "weather",
"input": {
"location": "San Francisco"
}
}
}
๐ Learn more: Detailed usage examples are available in the UsageExamples.md documentation.
๐ Tool Discovery & Registration
Laravel Vibes follows a similar approach to Laravel Event Sourcing for loading primitives, using automatic discovery and registration patterns. For more detailed examples, see the UsageExamples.md documentation.
Auto-Discovery
The package automatically discovers and registers tools and other MCP primitives in the configured directories:
// config/vibes.php
'auto_discover_all_primitives' => [app()->path()], // Directories to scan for primitives
'auto_discover_base_path' => base_path(), // Base path for relative directories
During application bootstrapping, Laravel Vibes scans these directories for classes that implement the PrimitiveHandler
interface and automatically registers them with TheAgency:
protected function discoverPrimitiveHandlers() : void
{
$agency = app(TheAgency::class);
$cachedPrimitiveHandlers = $this->getCachedPrimitiveHandlers();
if (! is_null($cachedPrimitiveHandlers)) {
$agency->addPrimitiveHandlers($cachedPrimitiveHandlers);
return;
}
(new PrimitiveHandlerDiscoveryService)
->within(config('vibes.auto_discover_all_primitives'))
->useBasePath(config('vibes.auto_discover_base_path', base_path()))
->ignoringFiles(Composer::getAutoloadedFiles(base_path('composer.json')))
->addToTheAgency($agency);
}
Manual Registration
For manual registration, modify your AppServiceProvider
or create a dedicated service provider:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use ProjectSaturnStudios\Vibes\TheAgency;
use App\MCP\Tools\WeatherTool;
use App\MCP\Tools\TranslationTool;
use App\MCP\Resources\UserResource;
use App\MCP\Prompts\GreetingPrompt;
class MCPServiceProvider extends ServiceProvider
{
public function boot()
{
// Get the agency singleton
$agency = app(TheAgency::class);
// Register tools
$agency->addTools([
WeatherTool::class,
TranslationTool::class,
]);
// Register other primitives when implemented
// $agency->addResources([
// UserResource::class,
// ]);
// $agency->addPrompts([
// GreetingPrompt::class,
// ]);
}
}
Then add your provider to config/app.php
:
'providers' => [
// Other service providers...
App\Providers\MCPServiceProvider::class,
],
Caching Primitives
For production environments, Laravel Vibes provides caching mechanisms to improve performance. The discovered primitives are cached at bootstrap/cache/vibes.php
.
To clear the cache during development:
php artisan cache:clear
You can also implement a dedicated command to manage the primitive cache (similar to Laravel Event Sourcing's event-sourcing:cache-event-handlers
):
// Register the command in your service provider
$this->app->booted(function () {
$this->app['events']->listen('cache:clearing', function () {
// Clear cached primitives
@unlink($this->app['config']['vibes.service_info.cache_path'].'/vibes.php');
});
});
๐งช Comprehensive Testing Guide
This section provides guidance and examples for testing Laravel Vibes components, focusing on custom tools and AI agent interactions.
Unit Testing Custom Tools
Test your custom tools to ensure they properly handle inputs and produce expected outputs:
<?php
namespace Tests\Unit\Tools;
use Tests\TestCase;
use App\Tools\WeatherTool;
use ProjectSaturnStudios\Vibes\TheAgency;
use ProjectSaturnStudios\Vibes\Exceptions\InvalidToolParameters;
class WeatherToolTest extends TestCase
{
protected TheAgency $agency;
protected WeatherTool $weatherTool;
protected function setUp(): void
{
parent::setUp();
$this->agency = app(TheAgency::class);
$this->weatherTool = new WeatherTool();
// Register the tool with TheAgency
$this->agency->addTool($this->weatherTool);
}
/** @test */
public function it_has_correct_metadata()
{
$metadata = WeatherTool::getMetadata();
$this->assertEquals('weather', $metadata['name']);
$this->assertArrayHasKey('description', $metadata);
$this->assertArrayHasKey('parameters', $metadata);
$this->assertArrayHasKey('properties', $metadata['parameters']);
$this->assertArrayHasKey('location', $metadata['parameters']['properties']);
}
/** @test */
public function it_handles_valid_location()
{
$result = $this->weatherTool->handle('San Francisco');
$this->assertIsArray($result);
$this->assertArrayHasKey('location', $result);
$this->assertArrayHasKey('temperature', $result);
$this->assertArrayHasKey('conditions', $result);
$this->assertEquals('San Francisco', $result['location']);
}
/** @test */
public function it_throws_exception_for_invalid_location()
{
$this->expectException(InvalidToolParameters::class);
$this->weatherTool->handle('NonExistentLocation123456789');
}
/** @test */
public function it_is_registered_with_the_agency()
{
$tool = $this->agency->getTool('weather');
$this->assertNotNull($tool);
$this->assertInstanceOf(WeatherTool::class, $tool);
}
}
Mocking External Services
Test tools that interact with external services by mocking the HTTP responses:
<?php
namespace Tests\Unit\Tools;
use Tests\TestCase;
use App\Tools\ExternalApiTool;
use Illuminate\Support\Facades\Http;
use ProjectSaturnStudios\Vibes\Exceptions\ToolExecutionError;
class ExternalApiToolTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
// Mock external API responses
Http::fake([
'api.example.com/data*' => Http::response([
'success' => true,
'data' => [
'id' => 123,
'name' => 'Test Item',
'value' => 99.95
]
], 200),
'api.example.com/error*' => Http::response([
'success' => false,
'error' => 'Resource not found'
], 404),
]);
}
/** @test */
public function it_fetches_and_formats_external_data()
{
$tool = new ExternalApiTool();
$result = $tool->handle('data', ['id' => 123]);
$this->assertIsArray($result);
$this->assertTrue($result['success']);
$this->assertEquals('Test Item', $result['data']['name']);
$this->assertEquals(99.95, $result['data']['value']);
}
/** @test */
public function it_handles_api_errors_appropriately()
{
$this->expectException(ToolExecutionError::class);
$tool = new ExternalApiTool();
$tool->handle('error', ['id' => 999]);
}
/** @test */
public function it_retries_on_temporary_failures()
{
Http::fake([
// First call fails, second succeeds
'api.example.com/flaky*' => Http::sequence()
->push(['error' => 'Server busy'], 503)
->push(['success' => true, 'data' => ['name' => 'Flaky Test']], 200),
]);
$tool = new ExternalApiTool();
$result = $tool->handle('flaky', ['id' => 456]);
$this->assertTrue($result['success']);
$this->assertEquals('Flaky Test', $result['data']['name']);
}
}
Integration Testing with TheAgency
Test the integration of tools with TheAgency:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use App\Tools\CalculatorTool;
use ProjectSaturnStudios\Vibes\TheAgency;
use ProjectSaturnStudios\Vibes\VibeSesh;
class AgencyToolIntegrationTest extends TestCase
{
protected TheAgency $agency;
protected function setUp(): void
{
parent::setUp();
$this->agency = app(TheAgency::class);
// Register test tools
$this->agency->addTool(CalculatorTool::class);
}
/** @test */
public function it_executes_calculator_tool_through_agency()
{
// Create a test session
$session = new VibeSesh('test-session-123');
// Prepare a tool execution request
$request = [
'jsonrpc' => '2.0',
'method' => 'run_tool',
'id' => 'req-'.time(),
'session_id' => $session->getId(),
'params' => [
'name' => 'calculator',
'input' => [
'operation' => 'add',
'a' => 5,
'b' => 7
]
]
];
// Process through TheAgency
$response = $this->agency->processRequest($request, $session);
// Verify response
$this->assertEquals('2.0', $response['jsonrpc']);
$this->assertEquals($request['id'], $response['id']);
$this->assertEquals(12, $response['result']['sum']);
}
/** @test */
public function it_returns_proper_error_for_invalid_tool_name()
{
$session = new VibeSesh('test-session-123');
$request = [
'jsonrpc' => '2.0',
'method' => 'run_tool',
'id' => 'req-'.time(),
'session_id' => $session->getId(),
'params' => [
'name' => 'non-existent-tool',
'input' => []
]
];
$response = $this->agency->processRequest($request, $session);
$this->assertArrayHasKey('error', $response);
$this->assertEquals(-32601, $response['error']['code']);
}
}
Testing SSE Connections
Test Server-Sent Events (SSE) connections using the following approach:
<?php
namespace Tests\Feature;
use Tests\TestCase;
use Illuminate\Testing\TestResponse;
use Illuminate\Support\Facades\Event;
use App\Events\AgentConnected;
class SSEConnectionTest extends TestCase
{
/** @test */
public function it_establishes_sse_connection_successfully()
{
// Listen for connection events
Event::fake([AgentConnected::class]);
// Make request to SSE endpoint
$response = $this->get('/mcp/sse', [
'Accept' => 'text/event-stream',
'Cache-Control' => 'no-cache',
'X-Requested-With' => 'XMLHttpRequest',
]);
// Check connection setup
$response->assertStatus(200);
$response->assertHeader('Content-Type', 'text/event-stream');
$response->assertHeader('Cache-Control', 'no-cache, private');
$response->assertHeader('Connection', 'keep-alive');
// Confirm response has SSE format
$this->assertStringContainsString('data:', $response->getContent());
$this->assertStringContainsString('id:', $response->getContent());
$this->assertStringContainsString('event: endpoint-info', $response->getContent());
// Verify event was dispatched
Event::assertDispatched(AgentConnected::class);
}
/** @test */
public function it_includes_endpoint_information_in_sse_init()
{
$response = $this->get('/mcp/sse');
// Extract the JSON data from the SSE response
$matches = [];
preg_match('/data: (.+)/', $response->getContent(), $matches);
if (count($matches) > 1) {
$data = json_decode($matches[1], true);
$this->assertIsArray($data);
$this->assertArrayHasKey('endpoints', $data);
$this->assertArrayHasKey('message', $data['endpoints']);
$this->assertEquals(route('vibes.messages'), $data['endpoints']['message']);
} else {
$this->fail('Could not extract SSE data from response');
}
}
}
Mocking AI Agent Interactions
Test components that interact with AI agents:
<?php
namespace Tests\Unit\Services;
use Tests\TestCase;
use App\Services\ClaudeService;
use Illuminate\Support\Facades\Http;
use ProjectSaturnStudios\Vibes\TheAgency;
use App\Tools\CalculatorTool;
class ClaudeServiceTest extends TestCase
{
protected ClaudeService $service;
protected function setUp(): void
{
parent::setUp();
// Get TheAgency and register tools
$agency = app(TheAgency::class);
$agency->addTool(CalculatorTool::class);
// Create service with mocked dependencies
$this->service = app(ClaudeService::class);
// Mock Claude API responses
Http::fake([
'https://api.anthropic.com/v1/messages' => Http::response([
'id' => 'msg_01234567',
'model' => 'claude-3-opus-20240229',
'content' => [
['type' => 'text', 'text' => 'This is a test response from Claude']
],
'tool_calls' => [
[
'id' => 'call_01234567',
'name' => 'calculator',
'parameters' => [
'operation' => 'multiply',
'a' => 4,
'b' => 5
]
]
]
], 200),
]);
}
/** @test */
public function it_sends_request_to_claude_api()
{
$response = $this->service->createMessage('Test prompt');
$this->assertIsArray($response);
$this->assertArrayHasKey('content', $response);
$this->assertArrayHasKey('tool_calls', $response);
$this->assertEquals('This is a test response from Claude', $response['content'][0]['text']);
}
/** @test */
public function it_handles_tool_calls()
{
// Get a sample tool call from the API response
$response = $this->service->createMessage('Test prompt');
$toolCall = $response['tool_calls'][0];
// Process the tool call
$result = $this->service->handleToolCall($toolCall, 'test-convo-123');
$this->assertIsArray($result);
$this->assertEquals('success', $result['status']);
$this->assertEquals(20, $result['result']['product']); // 4 * 5 = 20
}
}
PHPUnit Configuration Recommendations
Here's a sample PHPUnit configuration for optimal testing of Laravel Vibes components:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php"
colors="true">
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
<testsuite name="Feature">
<directory suffix="Test.php">./tests/Feature</directory>
</testsuite>
<testsuite name="Tools">
<directory suffix="Test.php">./tests/Unit/Tools</directory>
</testsuite>
<testsuite name="Agent">
<directory suffix="Test.php">./tests/Feature/Agent</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">./app</directory>
<directory suffix=".php">./src</directory>
</include>
</coverage>
<php>
<env name="APP_ENV" value="testing"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="ANTHROPIC_API_KEY" value="test_api_key"/>
<env name="VIBES_TOOLS_CACHE" value="false"/>
</php>
</phpunit>
Testing Best Practices
When testing Laravel Vibes components, follow these best practices:
- Isolate your tests: Ensure each test is independent and can run in any order.
- Use test doubles: Mock external dependencies like HTTP APIs, databases, and services.
- Test edge cases: Verify behavior with invalid inputs, error conditions, and boundary values.
- Emulate real-world scenarios: Create tests that mirror actual usage patterns.
- Test asynchronous behavior: Verify SSE connections and event listeners work correctly.
- Use data providers: Test tools with multiple input/output combinations.
- Check exception handling: Verify tools throw appropriate exceptions for invalid inputs.
- Test middleware independently: Isolate middleware functionality from controller logic.
For detailed example tests, check out the tests directory in the Laravel Vibes repository.
๐ Learn more: For more detailed testing examples and strategies, see the Testing section in UsageExamples.md.
๐ Laravel 12 Compatibility
Laravel Vibes is designed to be fully compatible with Laravel 12.x, leveraging many of its new features and improvements to provide optimal performance and developer experience.
Version Compatibility Matrix
The following table shows Laravel Vibes package version compatibility with Laravel framework versions:
Laravel Vibes Version | Laravel Version | PHP Version | Status |
---|---|---|---|
1.0.x | 12.x | โฅ 8.2 | Full Support |
0.9.x | 11.x | โฅ 8.1 | Maintained |
0.8.x | 10.x | โฅ 8.1 | Legacy Support |
0.7.x | 9.x | โฅ 8.0 | End of Support |
Laravel 12 Features Utilized
Laravel Vibes takes advantage of several new features introduced in Laravel 12:
Improved Rate Limiting
Laravel Vibes uses the enhanced rate limiting capabilities in Laravel 12 to manage AI agent connections and prevent resource abuse:
// In LaravelVibesServiceProvider.php
RateLimiter::for('mcp-agent', function (Request $request) {
return [
Limit::perMinute(60)->by($request->session()->getId()),
Limit::perDay(1000)->by($request->session()->getId()),
];
});
Route Grouping Improvements
The package uses Laravel 12's improved route group definitions for cleaner organization:
// Before Laravel 12
Route::middleware(['mcp-agent', 'throttle:mcp'])->prefix('mcp')->group(function () {
Route::get('/sse', [MCPAgentEntryController::class, 'open_a_channel']);
Route::post('/sse/messages', [MCPAgentEntryController::class, 'asController']);
});
// With Laravel 12
Route::middleware(['mcp-agent', 'throttle:mcp'])->group(function () {
Route::prefix('mcp')->group(function () {
Route::get('/sse', [MCPAgentEntryController::class, 'open_a_channel']);
Route::post('/sse/messages', [MCPAgentEntryController::class, 'asController']);
});
});
PHP 8.2 Readonly Classes
Laravel Vibes models use PHP 8.2 readonly classes for improved type safety and performance:
readonly class ToolMetadata
{
public function __construct(
public string $name,
public string $description,
public array $parameters,
public array $returns
) {}
}
First-class Enum Support
Laravel 12's improved support for PHP enums is used throughout the package:
enum ToolStatus: string
{
case ACTIVE = 'active';
case DEPRECATED = 'deprecated';
case EXPERIMENTAL = 'experimental';
}
Upgrading from Previous Laravel Versions
If you're upgrading from a previous Laravel version, follow these steps to ensure compatibility with Laravel Vibes:
From Laravel 11.x
-
Update your dependencies in
composer.json
:"require": { "php": "^8.2", "projectsaturnstudios/laravel-vibes": "^1.0", "laravel/framework": "^12.0" }
-
Run Composer update:
composer update
-
Update configuration if needed:
php artisan vendor:publish --tag=vibes-config --force
-
Update any custom tool implementations to use the new tool signature format:
// Laravel 11.x public function handle($parameter1, $parameter2) // Laravel 12.x public function handle(string $parameter1, ?array $parameter2 = null)
From Laravel 10.x or Earlier
- First upgrade to Laravel 11.x following the official upgrade guide.
- Update to Laravel Vibes 0.9.x.
- Test thoroughly that all tools and functionality work correctly.
- Then follow the steps above to upgrade to Laravel 12 and Laravel Vibes 1.0.x.
Known Issues & Limitations
Session Handling in Laravel 12
Laravel 12 implements stricter session handling. When using SSE connections with Laravel Vibes, you must use the provided ScaffoldSSEConnection
middleware to avoid session conflicts:
Route::get('/mcp/sse', [MCPAgentEntryController::class, 'open_a_channel'])
->middleware([ScaffoldSSEConnection::class]);
Service Container Changes
Laravel 12's service container features improved dependency resolution. If you've extended Laravel Vibes core classes, ensure your bindings are properly registered:
// Update service bindings in your ServiceProvider
$this->app->bind(TheAgency::class, CustomAgency::class);
$this->app->bind(ToolRepository::class, CustomToolRepository::class);
Queue System Changes
If you're using Laravel Vibes with background jobs, note that Laravel 12 introduces changes to the queue system:
// Laravel 12 now uses the dispatchSync method instead of dispatchNow
ProcessAgentMessageJob::dispatchSync($message);
Composer Requirements
To use Laravel Vibes with Laravel 12, ensure your composer.json
includes the following requirements:
{
"require": {
"php": "^8.2",
"projectsaturnstudios/laravel-vibes": "^1.0",
"laravel/framework": "^12.0",
"illuminate/contracts": "^12.0"
}
}
Specific extension requirements:
ext-json
: Required for JSON processingext-curl
: Required for HTTP client functionalityext-mbstring
: Required for string manipulation
For development environments, we recommend:
{
"require-dev": {
"phpunit/phpunit": "^10.0",
"mockery/mockery": "^1.6",
"laravel/pint": "^1.13"
}
}
๐ Learn more: Check the compatibility documentation for detailed information about supported features and versions.
๐ Deployment Considerations
This section provides guidance for deploying Laravel Vibes in production environments, focusing on performance, scaling, and security considerations.
Production Environment Configuration
When preparing your Laravel Vibes application for production, ensure these environment-specific settings:
# .env for production
APP_ENV=production
APP_DEBUG=false
CACHE_DRIVER=redis
SESSION_DRIVER=redis
QUEUE_CONNECTION=redis
# Laravel Vibes specific settings
VIBE_SVC_NAME=your-production-service-name
VIBE_SVC_VERSION=1.0.0
VIBES_TOOLS_CACHE=true
VIBES_HEARTBEAT_INTERVAL=30
Enable production-optimized caching:
# Generate optimized class loading
php artisan optimize
# Cache routes, config, and views
php artisan route:cache
php artisan config:cache
php artisan view:cache
# Cache MCP primitives
php artisan vibes:cache-primitives
Performance Optimization
Optimize your Laravel Vibes application for high traffic and AI agent interactions:
Tool Execution Optimization
// config/vibes.php
'tool_execution' => [
'timeout' => 5, // Maximum time (seconds) for tool execution
'max_memory' => '256M', // Memory limit for tool execution
'cache_ttl' => 60, // Cache tool results for similar inputs (seconds)
'batch_size' => 10, // Batch size for processing multiple tool calls
],
Queue Configuration for Tool Processing
Move long-running operations to background queues:
<?php
namespace App\Tools;
use ProjectSaturnStudios\Vibes\Primitives\Tools\Data\VibeTool;
use Illuminate\Contracts\Queue\ShouldQueue;
class LongRunningProcessTool extends VibeTool implements ShouldQueue
{
public $timeout = 300; // 5 minutes
public $tries = 3;
public $backoff = 30;
// Tool implementation...
}
Compression and Response Optimization
// In app/Http/Kernel.php
protected $middleware = [
// Other middleware...
\Illuminate\Http\Middleware\AddLinkHeadersForPreloadedAssets::class,
\ProjectSaturnStudios\Vibes\Http\Middleware\CompressResponse::class,
];
Scaling Strategies
Laravel Vibes can be scaled horizontally or vertically depending on your needs:
Horizontal Scaling with Load Balancing
For handling many concurrent AI agent connections:
โโโโโโโโโโโโโโโโโโโ
โ Load Balancer โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ โ โ
โโโโโโโโโโผโโโโโโโโโ โโโโโโโโโผโโโโโโโโโโ โโโโโโโโผโโโโโโโโโโโ
โ Laravel Vibes โ โ Laravel Vibes โ โ Laravel Vibes โ
โ Instance 1 โ โ Instance 2 โ โ Instance 3 โ
โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโฌโโโโโโโโโโ โโโโโโโโฌโโโโโโโโโโโ
โ โ โ
โโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโผโโโโโโโโโ
โ Redis/Memcached โ
โ (Session/Cache) โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โโโโโโโโโโผโโโโโโโโโ
โ Database โ
โโโโโโโโโโโโโโโโโโโ
If implementing horizontal scaling, ensure:
- Session persistence via Redis/Memcached
- Sticky sessions for SSE connections
- Shared storage for file uploads/resources
Queue Workers for Tool Processing
# Run multiple queue workers for tool execution
php artisan queue:work redis --queue=high,tool-execution,default --tries=3 --backoff=30 --max-time=3600
Monitoring and Logging
Implement robust monitoring for AI agent interactions:
Log Configuration
// config/logging.php
'channels' => [
'vibes' => [
'driver' => 'daily',
'path' => storage_path('logs/vibes.log'),
'level' => env('VIBES_LOG_LEVEL', 'warning'),
'days' => 14,
],
],
Telemetry Integration
// In a service provider
$this->app->singleton('vibes.telemetry', function () {
return new \App\Services\VibeTelemetryService(
endpoint: config('vibes.telemetry.endpoint'),
projectId: config('vibes.telemetry.project_id')
);
});
// In your custom tool
public function handle(string $input)
{
app('vibes.telemetry')->recordToolExecution($this->getName(), start_time: microtime(true));
// Tool implementation...
app('vibes.telemetry')->recordToolCompletion($this->getName(), microtime(true) - $startTime);
}
Key Metrics to Monitor
- Tool execution time and success rate: Track performance of individual tools
- SSE connection count and duration: Monitor active AI agent connections
- Queue processing rate: Ensure background tasks aren't backing up
- Memory usage: Watch for memory leaks during long-running SSE connections
- Redis/database connection saturation: Ensure sufficient pool for connections
Resource Management
AI interactions can be resource-intensive. Configure proper limits:
// config/vibes.php
'resources' => [
'max_sse_connections' => 1000, // Maximum concurrent SSE connections
'sse_timeout' => 3600, // Maximum SSE connection lifetime (seconds)
'max_concurrent_tools' => 100, // Maximum concurrent tool executions
'rate_limits' => [
'tool_execution' => 60, // Maximum tool calls per minute per session
'message_size' => 1024 * 1024, // Maximum message size in bytes
],
],
PHP-FPM configuration for SSE connections:
; php-fpm.conf optimized for SSE connections
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 30
pm.max_requests = 500
request_terminate_timeout = 0
Security in Production
Implement additional security measures for production:
CORS Configuration
// config/cors.vibes.php
return [
'paths' => ['mcp/*'],
'allowed_methods' => ['GET', 'POST'],
'allowed_origins' => ['https://your-trusted-domain.com'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['X-Requested-With', 'Content-Type', 'Origin', 'Authorization'],
'exposed_headers' => [],
'max_age' => 86400, // 24 hours
'supports_credentials' => true,
];
Input Validation
All tool parameters should be thoroughly validated:
public function handle(string $input)
{
$validated = Validator::make(['input' => $input], [
'input' => 'required|string|max:1000',
])->validate();
// Proceed with validated input
}
Rate Limiting
Configure tiered rate limiting for different operations:
RateLimiter::for('mcp-agent', function (Request $request) {
return [
Limit::perMinute(60)->by($request->session()->getId()), // Regular operations
Limit::perMinute(10)->by($request->session()->getId())->for(function ($request) {
return $request->input('method') === 'run_tool'; // Tool executions
}),
Limit::perDay(1000)->by($request->ip()), // Daily limit
];
});
Hosting Platform-Specific Guidelines
Laravel Forge
# Laravel Forge - Recommended PHP-FPM config
php_value[session.cache_limiter] = nocache
php_value[output_buffering] = 0
php_value[zlib.output_compression] = Off
php_value[implicit_flush] = On
php_value[max_execution_time] = 0
Docker Deployment
# Dockerfile optimized for Laravel Vibes
FROM php:8.2-fpm
# Install dependencies
RUN apt-get update && apt-get install -y \
libzip-dev \
zip \
unzip \
&& docker-php-ext-install zip pdo_mysql pcntl
# Install Redis extension
RUN pecl install redis && docker-php-ext-enable redis
# Configure PHP for SSE
RUN echo "output_buffering = Off" >> /usr/local/etc/php/conf.d/docker-php-sse.ini \
&& echo "zlib.output_compression = Off" >> /usr/local/etc/php/conf.d/docker-php-sse.ini \
&& echo "implicit_flush = On" >> /usr/local/etc/php/conf.d/docker-php-sse.ini
# Copy application
COPY . /var/www
WORKDIR /var/www
# Install Composer dependencies
RUN composer install --optimize-autoloader --no-dev
# Optimize Laravel
RUN php artisan optimize \
&& php artisan route:cache \
&& php artisan config:cache \
&& php artisan view:cache
# Expose port
EXPOSE 9000
CMD ["php-fpm"]
AWS Elastic Beanstalk
For .ebextensions/01-laravel-vibes.config
:
option_settings:
aws:elasticbeanstalk:container:php:phpini:
document_root: /public
memory_limit: 256M
zlib.output_compression: "Off"
output_buffering: "0"
max_execution_time: 300
container_commands:
01_optimize:
command: "php artisan optimize"
02_route_cache:
command: "php artisan route:cache"
03_config_cache:
command: "php artisan config:cache"
04_view_cache:
command: "php artisan view:cache"
05_vibes_cache:
command: "php artisan vibes:cache-primitives"
These deployment considerations will help ensure your Laravel Vibes application is robust, performant, and secure in production environments. Always test thoroughly in a staging environment that mirrors your production configuration before deploying updates.
๐ Learn more: For detailed performance benchmarks and advanced scaling strategies, see the Deployment section in UsageExamples.md.
๐ Architecture
Laravel Vibes is built with a modular architecture focusing on these components:
- TheAgency: Central manager for all MCP primitives
- VibeTool: Base class for implementing tools
- Primitive Handlers: Extensible system for different primitive types
- MCPAgentEntryController: Handles SSE and agent message endpoints
- ServiceProvider: Auto-registration and configuration
The package uses these Laravel packages:
spatie/laravel-package-tools
for package configurationspatie/laravel-data
for data objectslorisleiva/laravel-actions
for single-responsibility actions
For a detailed overview of component implementation status, refer to the Implementation Status section above. For more comprehensive documentation on the architecture, see the ClassDiagram.md and TheAgency.md documentation files.
๐ Learn more: View the complete class diagram and architectural details in ClassDiagram.md.
๐ Roadmap
Future development plans aligned with our implementation status:
Version | Focus Area | Planned Features |
---|---|---|
0.5.0 | Resources | - Complete Resources primitive implementation<br>- Resource discovery and access<br>- Resource validation and transformation |
0.6.0 | Prompts | - Full Prompts primitive support<br>- Template system for AI interactions<br>- Prompt chaining and composition |
0.7.0 | Samples | - Samples primitive for model configuration<br>- Temperature and top-p controls<br>- Example response generation |
0.8.0 | Roots | - Custom workflow entry points<br>- Advanced routing for AI interactions<br>- Contextual session management |
1.0.0 | Stability | - Complete test coverage for all components<br>- Improved logging and monitoring<br>- Performance optimizations<br>- Comprehensive documentation |
The current focus is on completing the Resources primitive implementation for the upcoming 0.5.0 release. Contributions are welcome for any of the planned features.
๐ฅ Credits
- Project Saturn Studios - Package development and maintenance
๐ Security
If you discover any security-related issues, please email security@projectsaturnstudios.com instead of using the issue tracker.
๐ License
This package is licensed under the MIT License. See the LICENSE.md file for more information.
๐ค Contributing
We welcome contributions to Laravel Vibes! Please see our Contributing Guidelines for details on how to get started, coding standards, and our pull request process.
๐ Flow Diagrams
Visual diagrams of Laravel Vibes architecture and interaction flows are available in the Flow Diagrams documentation. These diagrams help developers understand how the components work together and implement the package effectively.
๐ Real-World Examples
For comprehensive real-world implementation examples, check out our Examples documentation. These examples demonstrate practical use cases and implementation patterns to help you get started quickly.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
MCP Package Docs Server
Facilitates LLMs to efficiently access and fetch structured documentation for packages in Go, Python, and NPM, enhancing software development with multi-language support and performance optimization.
Claude Code MCP
An implementation of Claude Code as a Model Context Protocol server that enables using Claude's software engineering capabilities (code generation, editing, reviewing, and file operations) through the standardized MCP interface.
@kazuph/mcp-taskmanager
Model Context Protocol server for Task Management. This allows Claude Desktop (or any MCP client) to manage and execute tasks in a queue-based system.
Linear MCP Server
Enables interaction with Linear's API for managing issues, teams, and projects programmatically through the Model Context Protocol.
mermaid-mcp-server
A Model Context Protocol (MCP) server that converts Mermaid diagrams to PNG images.
Jira-Context-MCP
MCP server to provide Jira Tickets information to AI coding agents like Cursor

Linear MCP Server
A Model Context Protocol server that integrates with Linear's issue tracking system, allowing LLMs to create, update, search, and comment on Linear issues through natural language interactions.

Sequential Thinking MCP Server
This server facilitates structured problem-solving by breaking down complex issues into sequential steps, supporting revisions, and enabling multiple solution paths through full MCP integration.