spiral / mcp-server
Spiral bridge for MCP server
Fund package maintenance!
roadrunner-server
Requires
- php: ^8.3
- cuyz/valinor: ^1.7
- php-mcp/server: dev-main
- spiral/attributes: ^3.0
- spiral/boot: ^3.15
- spiral/json-schema-generator: ^2.0
- spiral/tokenizer: ^3.15
Requires (Dev)
- phpunit/phpunit: ^10.1
- rector/rector: ^2.0
- spiral/code-style: ^2.2
- spiral/testing: ^2.3
- vimeo/psalm: ^6.10
This package is auto-updated.
Last update: 2025-08-21 07:14:47 UTC
README
A powerful and flexible Model Context Protocol (MCP) Server implementation for the Spiral Framework. This package provides a complete MCP server solution with automatic tool discovery, attribute-based configuration, and seamless integration with Spiral's dependency injection container.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- Configuration
- Creating Tools
- Tool Attributes
- Middleware
- Contributing
- License
Features
✨ Automatic Tool Discovery - Automatically discovers and registers MCP tools using PHP attributes
🔧 Multiple Transport Options - Supports HTTP, streaming HTTP, and STDIO transports
🎯 Attribute-Based Configuration - Define tool behavior with simple PHP attributes
🛡️ Schema Validation - Automatic JSON schema generation using spiral/json-schema-generator
⚡ Middleware Support - Extensible middleware system for request/response processing
🔌 Spiral Integration - First-class integration with Spiral Framework's IoC container
📊 Session Management - Built-in session handling with configurable TTL
🚀 Production Ready - Designed for high-performance production environments
Requirements
- PHP 8.3 or higher
- Spiral Framework 3.15+
- Composer
Installation
Install the package via Composer:
composer require spiral/mcp-server
Add the bootloader to your Spiral application:
// app/src/Application/Kernel.php use Spiral\McpServer\Bootloader\McpServerBootloader; protected const LOAD = [ // ... other bootloaders McpServerBootloader::class, ];
Quick Start
1. Create Your First Tool
Create a simple calculator tool:
<?php namespace App\Tool; use Spiral\McpServer\Attribute\Tool; use Spiral\McpServer\Attribute\IsReadonly; #[Tool( name: 'calculator_add', description: 'Adds two numbers together' )] #[IsReadonly] class CalculatorTool { public function __invoke(CalculatorRequest $request): array { return [ 'result' => $request->a + $request->b, 'operation' => 'addition' ]; } }
2. Define the Request Schema
<?php namespace App\Tool; use Spiral\JsonSchemaGenerator\Attribute\Field; final readonly class CalculatorRequest { public function __construct( #[Field( title: 'First Number', description: 'The first number to add' )] public float $a, #[Field( title: 'Second Number', description: 'The second number to add' )] public float $b, ) {} }
Note: For more information about DTO schema definition visit spiral/json-schema-generator.
3. Set Environment Variables
# .env MCP_TRANSPORT=http MCP_HOST=127.0.0.1 MCP_PORT=8090 MCP_SERVER_NAME="My MCP Server" MCP_SERVER_VERSION="1.0.0"
4. Start the Server
You can start the server in two ways:
Option 1: Using the MCP Dispatcher (Recommended for production)
SAPI=mcp php app.php
Option 2: Using the Console Command
php app.php mcp
Your MCP server is now running and ready to accept requests!
Configuration
Environment Variables
Variable | Default | Description |
---|---|---|
MCP_TRANSPORT |
http |
Transport type: http , stream , or stdio |
MCP_HOST |
127.0.0.1 |
Server host address |
MCP_PORT |
8090 |
Server port number |
MCP_SERVER_NAME |
MCP Server |
Server identification name |
MCP_SERVER_VERSION |
1.0.0 |
Server version |
MCP_SESSION_TTL |
3600 |
Session TTL in seconds |
SAPI |
cli |
Set to mcp to enable MCP dispatcher |
Custom Configuration
You can override the default configuration by binding your own Configuration
instance:
use PhpMcp\Server\Configuration; use PhpMcp\Schema\Implementation; use PhpMcp\Schema\ServerCapabilities; // In your bootloader $this->container->bindSingleton(Configuration::class, function() { return new Configuration( serverInfo: Implementation::make('Custom Server', '2.0.0'), capabilities: ServerCapabilities::make(), // ... other options ); });
Creating Tools
Basic Tool Structure
Tools are simple PHP classes that implement the __invoke()
method. They support Dependency Injection (DI) and can be
injected with any dependencies, like in the following example:
<?php namespace App\Tool; use Spiral\Files\FilesInterface;use Spiral\McpServer\Attribute\Tool; use Spiral\McpServer\Attribute\IsReadonly; use Spiral\JsonSchemaGenerator\Attribute\Field; #[Tool( name: 'file_reader', description: 'Reads content from a file with validation' )] #[IsReadonly] final readonly class FileReaderTool { public function __construct( private FilesInterface $files, ) {} public function __invoke(FileRequest $request): array { if (!$this->files->exists($request->path)) { throw new \InvalidArgumentException('File not found'); } return [ 'content' => $this->files->read($request->path), 'size' => $this->files->size($request->path), ]; } } final readonly class FileRequest { public function __construct( /** * @param not-empty-string $path */ #[Field( title: 'File Path', description: 'Absolute path to the file to read' )] public string $path, #[Field( title: 'Encoding', description: 'Expected file encoding', default: 'utf-8' )] public string $encoding = 'utf-8', /** * @param positive-int $maxSize */ #[Field( title: 'Maximum Size', description: 'Maximum file size in bytes', default: 1048576 )] public int $maxSize = 1048576, // 1MB ) {} }
Note: For more information about DTO schema definition visit spiral/json-schema-generator.
Tools Without Parameters
For tools that don't require input parameters:
#[Tool( name: 'system_status', description: 'Gets current system status' )] class SystemStatusTool { public function __invoke(): array { return [ 'memory_usage' => memory_get_usage(true), 'peak_memory' => memory_get_peak_usage(true), 'uptime' => $this->getUptime(), ]; } private function getUptime(): int { // Implementation details... return 0; } }
Tool Attributes
Core Tool Attribute
The #[Tool]
attribute is required for all MCP tools:
#[Tool( name: 'unique_tool_name', description: 'Clear description of what this tool does' )]
Behavioral Attributes
Read-Only Tools
#[IsReadonly(readOnlyHint: true)] // Tool doesn't modify environment
Destructive Operations
#[IsDestructive(destructive: true)] // Tool may perform destructive updates
Idempotent Operations
#[IsIdempotent(idempotent: true)] // Repeated calls have no additional effect
Open World Tools
#[IsOpenWorld(openWorld: true)] // Tool interacts with external entities
Complete Example with All Attributes
#[Tool( name: 'file_manager', description: 'Manages file operations with external storage' )] #[IsDestructive(destructive: true)] #[IsIdempotent(idempotent: false)] #[IsOpenWorld(openWorld: true)] class FileManagerTool { public function __invoke(FileOperation $operation): array { // Implementation... return ['status' => 'success']; } }
Middleware
Creating Custom Middleware
<?php use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; class LoggingMiddleware { public function __invoke( ServerRequestInterface $request, callable $next ): ResponseInterface { $start = microtime(true); $response = $next($request); $duration = microtime(true) - $start; error_log("MCP Request processed in {$duration}s"); return $response; } }
Registering Middleware
// In your bootloader or service use Spiral\McpServer\MiddlewareRegistryInterface; public function boot(MiddlewareRegistryInterface $registry): void { $registry->register(new LoggingMiddleware()); $registry->register(new AuthenticationMiddleware()); $registry->register(new RateLimitingMiddleware()); }
Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
- Clone the repository
- Install dependencies:
composer install
- Run tests:
composer test
- Run static analysis:
composer psalm
Code Style
This project follows PSR-12 coding standards. Run the code fixer:
composer cs-fix
License
The MIT License (MIT). Please see License File for more information.
Built with ❤️ by the Spiral Team
For more information about the Spiral Framework, visit spiral.dev