### Bash Commands for Supervisor and Nginx Setup Source: https://github.com/php-mcp/server/blob/main/README.md Shell commands to install Supervisor, create its configuration file, and manage the MCP server process. It also includes commands to enable and restart Nginx, and check the status of Supervisor-managed processes. ```bash # 1. Install your application on VPS git clone https://github.com/yourorg/your-mcp-server.git /var/www/mcp-server cd /var/www/mcp-server composer install --no-dev --optimize-autoloader # 2. Install Supervisor sudo apt-get install supervisor # 3. Create Supervisor configuration sudo nano /etc/supervisor/conf.d/mcp-server.conf ``` ```bash # Enable and start supervisor sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start mcp-server:* # Enable and start nginx sudo systemctl enable nginx sudo systemctl restart nginx # Check status sudo supervisorctl status ``` -------------------------------- ### Run PHP MCP Server Example Source: https://github.com/php-mcp/server/blob/main/README.md This bash snippet details how to navigate to an example directory, make the PHP server executable, and then run it. This is useful for testing and understanding the server's functionality. ```bash # Navigate to an example directory cd examples/01-discovery-stdio-calculator/ # Make the server executable chmod +x server.php # Run the server (or configure it in your MCP client) ./server.php ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/php-mcp/server/blob/main/README.md This command installs the necessary dependencies for development, including testing frameworks and tools, using Composer for the PHP project. ```bash # Install development dependencies composer install --dev ``` -------------------------------- ### Dockerfile for MCP Server Production Deployment Source: https://github.com/php-mcp/server/blob/main/README.md A Dockerfile to build a production-ready image for the MCP server. It installs PHP, Nginx, Supervisor, necessary extensions, copies application code, installs Composer dependencies, and configures the entry point to start Supervisord. ```dockerfile FROM php:8.3-fpm-alpine # Install system dependencies RUN apk --no-cache add \ nginx \ supervisor \ && docker-php-ext-enable opcache # Install PHP extensions for MCP RUN docker-php-ext-install pdo_mysql pdo_sqlite opcache # Create application directory WORKDIR /var/www/mcp # Copy application code COPY . /var/www/mcp COPY docker/nginx.conf /etc/nginx/nginx.conf COPY docker/supervisord.conf /etc/supervisord.conf COPY docker/php.ini /usr/local/etc/php/conf.d/production.ini # Install Composer dependencies RUN composer install --no-dev --optimize-autoloader --no-interaction # Set permissions RUN chown -R www-data:www-data /var/www/mcp # Expose port EXPOSE 80 # Start supervisor CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"] ``` -------------------------------- ### Install Dependencies Source: https://github.com/php-mcp/server/blob/main/CONTRIBUTING.md Installs runtime and development dependencies for the php-mcp/server project using Composer. ```Bash composer install ``` -------------------------------- ### Install PHP MCP Server SDK Source: https://github.com/php-mcp/server/blob/main/README.md This snippet shows the Composer command to install the PHP MCP Server SDK. It is the primary method for adding the SDK to a PHP project. ```Bash composer require php-mcp/server ``` -------------------------------- ### Client Configuration for PHP MCP Servers Source: https://github.com/php-mcp/server/blob/main/README.md Provides example client configurations in JSON format for connecting to different PHP MCP server transports, including Stdio and HTTP. ```JSON { "mcpServers": { "my-php-server": { "command": "php", "args": ["/absolute/path/to/server.php"] } } } ``` ```JSON { "mcpServers": { "my-http-server": { "url": "http://localhost:8080/mcp/sse" } } } ``` -------------------------------- ### Run Tests with Code Coverage Source: https://github.com/php-mcp/server/blob/main/README.md This command runs the test suite and generates a code coverage report, which requires Xdebug to be installed and configured. ```bash # Run tests with coverage (requires Xdebug) composer test:coverage ``` -------------------------------- ### Set Up SSL/TLS with Let's Encrypt Source: https://github.com/php-mcp/server/blob/main/README.md This bash snippet shows the steps to install Certbot and generate an SSL certificate for a domain using Let's Encrypt, securing the MCP server with HTTPS. It assumes Nginx is the web server. ```bash # Install Certbot for Let's Encrypt sudo apt install certbot python3-certbot-nginx # Generate SSL certificate sudo certbot --nginx -d mcp.yourdomain.com ``` -------------------------------- ### PHP Advanced Content Types (TextContent, ImageContent, AudioContent) Source: https://github.com/php-mcp/server/blob/main/README.md Provides examples of using advanced content types like `TextContent` for formatted code or markdown, `ImageContent` for images, and `AudioContent` for audio files. These classes allow for more specific return value handling. ```php use PhpMcp\Schema\Content\{TextContent, ImageContent, AudioContent, ResourceContent}; public function getFormattedCode(): TextContent { return TextContent::code('withServerInfo('PHP Calculator Server', '1.0.0') ->build(); // Discover MCP elements via attributes $server->discover( basePath: __DIR__, scanDirs: ['src'] ); // Start listening via stdio transport $transport = new StdioServerTransport(); $server->listen($transport); } catch (\Throwable $e) { fwrite(STDERR, "[CRITICAL ERROR] " . $e->getMessage() . "\n"); exit(1); } ``` -------------------------------- ### PHP Middleware for HTTP Server Transport Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how to use PSR-7 compatible middleware with HttpServerTransport and StreamableHttpServerTransport. Includes an example of an authentication middleware and a logging/CORS middleware, showing how to handle both synchronous and asynchronous responses. ```PHP use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use React\Promise\PromiseInterface; class AuthMiddleware { public function __invoke(ServerRequestInterface $request, callable $next) { $apiKey = $request->getHeaderLine('Authorization'); if (empty($apiKey)) { return new Response(401, [], 'Authorization required'); } $request = $request->withAttribute('user_id', $this->validateApiKey($apiKey)); $result = $next($request); return match (true) { $result instanceof PromiseInterface => $result->then(fn($response) => $this->handle($response)), $result instanceof ResponseInterface => $this->handle($result), default => $result }; } private function handle($response) { return $response instanceof ResponseInterface ? $response->withHeader('X-Auth-Provider', 'mcp-server') : $response; } } $middlewares = [ new AuthMiddleware(), new LoggingMiddleware(), function(ServerRequestInterface $request, callable $next) { $result = $next($request); return match (true) { $result instanceof PromiseInterface => $result->then(function($response) { return $response instanceof ResponseInterface ? $response->withHeader('Access-Control-Allow-Origin', '*') : $response; }), $result instanceof ResponseInterface => $result->withHeader('Access-Control-Allow-Origin', '*'), default => $result }; } ]; $transport = new StreamableHttpServerTransport( host: '127.0.0.1', port: 8080, middlewares: $middlewares ); ``` -------------------------------- ### PHP Exception Handling for JSON-RPC Errors Source: https://github.com/php-mcp/server/blob/main/README.md Illustrates how tool handlers in the MCP server can throw PHP exceptions, which are automatically converted into JSON-RPC error responses for MCP clients. Includes examples of InvalidArgumentException and OverflowException. ```PHP #[McpTool(name: 'divide_numbers')] public function divideNumbers(float $dividend, float $divisor): float { if ($divisor === 0.0) { // Any exception with descriptive message will be sent to client throw new \InvalidArgumentException('Division by zero is not allowed'); } return $dividend / $divisor; } #[McpTool(name: 'calculate_factorial')] public function calculateFactorial(int $number): int { if ($number < 0) { throw new \InvalidArgumentException('Factorial is not defined for negative numbers'); } if ($number > 20) { throw new \OverflowException('Number too large, factorial would cause overflow'); } // Implementation continues... return $this->factorial($number); } ``` -------------------------------- ### PHP CompletionProvider: Pre-configured Instances Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates providing pre-configured instances of completion providers, either directly or from class properties, for methods like `generatePrompt` in `DocumentService`. ```PHP class DocumentService { #[McpPrompt(name: 'document_prompt')] public function generatePrompt( #[CompletionProvider(provider: new UserIdCompletionProvider($database))] // Pre-configured instance string $userId, #[CompletionProvider(provider: $this->categoryProvider)] // Instance from property string $category ): array { return [['role' => 'user', 'content' => "Generate document for user {$userId} in {$category}"]]; } } ``` -------------------------------- ### Basic PHP MCP Server Configuration Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates basic server configuration using the `ServerBuilder` fluent interface. It sets server information, capabilities, and pagination limits. ```PHP use PhpMcp\Server\Server; use PhpMcp\Schema\ServerCapabilities; $server = Server::make() ->withServerInfo('My App Server', '2.1.0') ->withCapabilities(ServerCapabilities::make( resources: true, resourcesSubscribe: true, prompts: true, tools: true )) ->withPaginationLimit(100) ->build(); ``` -------------------------------- ### Register Prompts with Completion Providers (PHP) Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how to manually register prompts with completion providers using class strings or closures. Completion providers can be defined via method attributes or inline. ```php $server = Server::make() ->withServerInfo('Completion Demo', '1.0.0') // Using provider class (resolved from container) ->withPrompt( [DocumentHandler::class, 'generateReport'], name: 'document_report' // Completion providers are auto-discovered from method attributes ) // Using closure with inline completion providers ->withPrompt( function( #[CompletionProvider(values: ['json', 'xml', 'csv', 'yaml'])] string $format, #[CompletionProvider(enum: Priority::class)] string $priority ): array { return [['role' => 'user', 'content' => "Export data in {$format} format with {$priority} priority"]]; }, name: 'export_data' ) ->build(); ``` -------------------------------- ### Run PHP Unit Tests Source: https://github.com/php-mcp/server/blob/main/README.md This command executes the project's test suite using Composer, ensuring code quality and functionality. ```bash # Run the test suite composer test ``` -------------------------------- ### PHP CompletionProvider: Custom Class Implementation Source: https://github.com/php-mcp/server/blob/main/README.md Shows how to create custom completion providers by implementing the `CompletionProviderInterface` for dynamic suggestions, demonstrated with a `UserIdCompletionProvider` and its usage in a `UserService`. ```PHP use PhpMcp\Server\Contracts\CompletionProviderInterface; use PhpMcp\Server\Contracts\SessionInterface; use PhpMcp\Server\Attributes\{McpResourceTemplate, CompletionProvider}; class UserIdCompletionProvider implements CompletionProviderInterface { public function __construct(private DatabaseService $db) {} public function getCompletions(string $currentValue, SessionInterface $session): array { // Dynamic completion from database return $this->db->searchUsers($currentValue); } } class UserService { #[McpResourceTemplate(uriTemplate: 'user://{userId}/profile')] public function getUserProfile( #[CompletionProvider(provider: UserIdCompletionProvider::class)] // Class string - resolved from container string $userId ): array { return ['id' => $userId, 'name' => 'John Doe']; } } ``` -------------------------------- ### Run Tests Source: https://github.com/php-mcp/server/blob/main/CONTRIBUTING.md Executes the project's tests using Composer or directly via the Pest testing framework. ```Bash composer test ``` ```Bash ./vendor/bin/pest ``` -------------------------------- ### PHP MCP Server Manual Registration Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates programmatic registration of tools, resources, and prompts using ServerBuilder. Supports various handler formats including class methods, invokable classes, and closures. Manual registrations take precedence over discovered elements and are not cached. ```php use App\Handlers\{EmailHandler, ConfigHandler, UserHandler, PromptHandler}; use PhpMcp\Schema\{ToolAnnotations, Annotations}; $server = Server::make() ->withServerInfo('Manual Registration Server', '1.0.0') // Register a tool with handler method ->withTool( [EmailHandler::class, 'sendEmail'], // Handler: [class, method] name: 'send_email', // Tool name (optional) description: 'Send email to user', // Description (optional) annotations: ToolAnnotations::make( // Annotations (optional) title: 'Send Email Tool' ) ) // Register invokable class as tool ->withTool(UserHandler::class) // Handler: Invokable class // Register a closure as tool ->withTool( function(int $a, int $b): int { // Handler: Closure return $a + $b; }, name: 'add_numbers', description: 'Add two numbers together' ) // Register a resource with closure ->withResource( function(): array { // Handler: Closure return ['timestamp' => time(), 'server' => 'php-mcp']; }, uri: 'config://runtime/status', // URI (required) mimeType: 'application/json' // MIME type (optional) ) // Register a resource template ->withResourceTemplate( [UserHandler::class, 'getUserProfile'], uriTemplate: 'user://{userId}/profile' // URI template (required) ) // Register a prompt with closure ->withPrompt( function(string $topic, string $tone = 'professional'): array { return [ ['role' => 'user', 'content' => "Write about {$topic} in a {$tone} tone"] ]; }, name: 'writing_prompt' // Prompt name (optional) ) ->build(); ``` -------------------------------- ### Enable Resource Subscriptions (PHP) Source: https://github.com/php-mcp/server/blob/main/README.md Illustrates how to enable resource subscriptions for the MCP server and notify clients of changes in resource handlers. This allows for real-time updates to subscribed clients. ```php use PhpMcp\Schema\ServerCapabilities; $server = Server::make() ->withCapabilities(ServerCapabilities::make( resourcesSubscribe: true, // Enable resource subscriptions prompts: true, tools: true )) ->build(); // In your resource handler, you can notify clients of changes: #[McpResource(uri: 'file://config.json')] public function getConfig(): array { // When config changes, notify subscribers $this->notifyResourceChange('file://config.json'); return ['setting' => 'value']; } ``` -------------------------------- ### Supervisor Configuration for MCP Server Source: https://github.com/php-mcp/server/blob/main/README.md Configuration file for Supervisor to manage the MCP server process. It specifies process name, command to run, auto-start/restart behavior, user, logging, and other process control parameters. ```ini [program:mcp-server] process_name=%(program_name)s_%(process_num)02d command=php /var/www/mcp-server/server.php --transport=http --host=127.0.0.1 --port=8080 autostart=true autorestart=true stopasgroup=true killasgroup=true user=www-data numprocs=1 redirect_stderr=true stdout_logfile=/var/log/mcp-server.log stdout_logfile_maxbytes=10MB stdout_logfile_backups=3 ``` -------------------------------- ### MCP Client Configuration for PHP Server Source: https://github.com/php-mcp/server/blob/main/README.md This JSON configuration file specifies how an MCP client should connect to the PHP server. It defines the command to execute and the arguments to pass, including the path to the server script. ```JSON { "mcpServers": { "php-calculator": { "command": "php", "args": ["/absolute/path/to/your/mcp-server.php"] } } } ``` -------------------------------- ### PHP CompletionProvider: Simple List Values Source: https://github.com/php-mcp/server/blob/main/README.md Explains how to use the `values` parameter within the `CompletionProvider` attribute for static completion lists, as shown for `contentType` and `difficulty` in `ContentService`. ```PHP use PhpMcp\Server\Attributes\{McpPrompt, CompletionProvider}; class ContentService { #[McpPrompt(name: 'content_generator')] public function generateContent( #[CompletionProvider(values: ['blog', 'article', 'tutorial', 'guide', 'documentation'])] string $contentType, #[CompletionProvider(values: ['beginner', 'intermediate', 'advanced', 'expert'])] string $difficulty ): array { return [['role' => 'user', 'content' => "Create a {$difficulty} level {$contentType}"]]; } } ``` -------------------------------- ### PHP CompletionProvider: Enum-Based Completions Source: https://github.com/php-mcp/server/blob/main/README.md Illustrates using the `enum` parameter in `CompletionProvider` for both string-backed enums (`Priority`) and unit enums (`Status`), as applied in the `createTask` method of `TaskService`. ```PHP enum Priority: string { case LOW = 'low'; case MEDIUM = 'medium'; case HIGH = 'high'; case CRITICAL = 'critical'; } enum Status // Unit enum (no backing values) { case DRAFT; case PUBLISHED; case ARCHIVED; } class TaskService { #[McpTool(name: 'create_task')] public function createTask( string $title, #[CompletionProvider(enum: Priority::class)] // String-backed enum uses values string $priority, #[CompletionProvider(enum: Status::class)] // Unit enum uses case names string $status ): array { return ['id' => 123, 'title' => $title, 'priority' => $priority, 'status' => $status]; } } ``` -------------------------------- ### PHP File and Stream Handling Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how the PHP MCP server automatically handles file and stream operations, including reading file content, returning stream resources, and structuring responses with MIME types. ```PHP public function getFileContent(): \SplFileInfo { return new \SplFileInfo('/path/to/file.txt'); // Auto-detects MIME type } ``` ```PHP public function getStreamContent() { $stream = fopen('/path/to/data.json', 'r'); return $stream; // Will be read and closed automatically } ``` ```PHP public function getStructuredResource(): array { return [ 'text' => 'File content here', 'mimeType' => 'text/plain' ]; // Or for binary data: // return [ // 'blob' => base64_encode($binaryData), // 'mimeType' => 'application/octet-stream' // ]; } ``` -------------------------------- ### PHP Parameter-Level Schema Attributes Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how to use the `#[Schema]` attribute at the parameter level to define schema properties like format, pattern, description, minimum, and maximum values for method arguments. PHP type hints are used alongside these attributes. ```php use PhpMcp\Server\Attributes\{McpTool, Schema}; #[McpTool(name: 'validate_user')] public function validateUser( #[Schema(format: 'email')] // PHP already knows it's string string $email, #[Schema( pattern: '^[A-Z][a-z]+$', description: 'Capitalized name' )] string $name, #[Schema(minimum: 18, maximum: 120)] // PHP already knows it's integer int $age ): bool { return filter_var($email, FILTER_VALIDATE_EMAIL) !== false; } ``` -------------------------------- ### Discover MCP Elements in PHP Project Source: https://github.com/php-mcp/server/blob/main/README.md Initiates the MCP element discovery process within a PHP project. After building the server, this code scans specified directories for attribute-marked elements, optionally caching the results for performance. ```PHP // Build server first $server = Server::make() ->withServerInfo('My App Server', '1.0.0') ->build(); // Then discover elements $server->discover( basePath: __DIR__, scanDirs: ['src/Handlers', 'src/Services'], // Directories to scan excludeDirs: ['src/Tests'], // Directories to skip saveToCache: true // Cache results (default: true) ); ``` -------------------------------- ### PHP SSL Context Configuration for HTTPS Source: https://github.com/php-mcp/server/blob/main/README.md Configures SSL context options for the StreamableHttpServerTransport to enable HTTPS deployments. Shows how to specify certificate and private key paths, and disable peer verification for self-signed certificates. ```PHP $sslContext = [ 'ssl' => [ 'local_cert' => '/path/to/certificate.pem', 'local_pk' => '/path/to/private-key.pem', 'verify_peer' => false, 'allow_self_signed' => true, ] ]; $transport = new StreamableHttpServerTransport( host: '0.0.0.0', port: 8443, sslContext: $sslContext ); ``` -------------------------------- ### PHP Streamable HTTP Server Transport Source: https://github.com/php-mcp/server/blob/main/README.md Sets up a server using the Streamable HTTP transport, recommended for production and remote servers. It supports resumable connections, event sourcing, and offers JSON response mode and stateless operation. ```PHP use PhpMcp\Server\Transports\StreamableHttpServerTransport; $server = Server::make() ->withServerInfo('Streamable Server', '1.0.0') ->withLogger($logger) ->withCache($cache) // Required for resumability ->build(); $server->discover(__DIR__, ['src']); // Create streamable transport with resumability $transport = new StreamableHttpServerTransport( host: '127.0.0.1', // MCP protocol prohibits 0.0.0.0 port: 8080, mcpPathPrefix: 'mcp', enableJsonResponse: false, // Use SSE streaming (default) stateless: false // Enable stateless mode for session-less clients ); $server->listen($transport); ``` ```PHP // For fast-executing tools, enable JSON mode $transport = new StreamableHttpServerTransport( host: '127.0.0.1', port: 8080, enableJsonResponse: true // Immediate JSON responses ); ``` ```PHP $transport = new StreamableHttpServerTransport( host: '127.0.0.1', port: 8080, stateless: true // Each request is independent ); ``` -------------------------------- ### Configure PHP MCP Server with Dependencies Source: https://github.com/php-mcp/server/blob/main/README.md Configures the PHP MCP server by chaining methods to set server information, integrate PSR-3 Logger, PSR-16 Cache, and PSR-11 Container, and manage session settings. It also sets a pagination limit for list responses. ```PHP use Psr\Log\Logger; use Psr\SimpleCache\CacheInterface; use Psr\Container\ContainerInterface; $server = Server::make() ->withServerInfo('Production Server', '1.0.0') ->withLogger($myPsrLogger) // PSR-3 Logger ->withCache($myPsrCache) // PSR-16 Cache ->withContainer($myPsrContainer) // PSR-11 Container ->withSession('cache', 7200) // Cache-backed sessions, 2hr TTL ->withPaginationLimit(50) // Limit list responses ->build(); ``` -------------------------------- ### PHP MCP Server Session Management Options Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates different session management strategies for the PHP MCP server. Options include in-memory sessions, cache-backed persistent sessions, and custom session handlers implementing SessionHandlerInterface, each with configurable Time-To-Live (TTL). ```PHP // In-memory sessions (default, not persistent) ->withSession('array', 3600) // Cache-backed sessions (persistent across restarts) ->withSession('cache', 7200) // Custom session handler (implement SessionHandlerInterface) ->withSessionHandler(new MyCustomSessionHandler(), 1800) ``` -------------------------------- ### Define MCP Elements using PHP 8 Attributes Source: https://github.com/php-mcp/server/blob/main/README.md Defines MCP elements (Tools, Resources, Resource Templates, Prompts) using PHP 8 attributes. This method leverages attribute-based discovery for automatic registration of methods marked with specific MCP attributes. ```PHP use PhpMcp\Server\Attributes\{McpTool, McpResource, McpResourceTemplate, McpPrompt}; class UserManager { /** * Creates a new user account. */ #[McpTool(name: 'create_user')] public function createUser(string $email, string $password, string $role = 'user'): array { // Create user logic return ['id' => 123, 'email' => $email, 'role' => $role]; } /** * Get user configuration. */ #[McpResource( uri: 'config://user/settings', mimeType: 'application/json' )] public function getUserConfig(): array { return ['theme' => 'dark', 'notifications' => true]; } /** * Get user profile by ID. */ #[McpResourceTemplate( uriTemplate: 'user://{userId}/profile', mimeType: 'application/json' )] public function getUserProfile(string $userId): array { return ['id' => $userId, 'name' => 'John Doe']; } /** * Generate welcome message prompt. */ #[McpPrompt(name: 'welcome_user')] public function welcomeUserPrompt(string $username, string $role): array { return [ ['role' => 'user', 'content' => "Create a welcome message for {$username} with role {$role}"] ]; } } ``` -------------------------------- ### Custom Dependency Injection with PSR-11 Container (PHP) Source: https://github.com/php-mcp/server/blob/main/README.md Shows how to configure custom dependency injection for MCP element handlers using PSR-11 compatible containers. This includes using the basic container with manual additions or integrating with external containers like PHP-DI. ```php use Psr\Container\ContainerInterface; class DatabaseService { public function __construct(private \PDO $pdo) {} #[McpTool(name: 'query_users')] public function queryUsers(): array { $stmt = $this->pdo->query('SELECT * FROM users'); return $stmt->fetchAll(); } } // Option 1: Use the basic container and manually add dependencies $basicContainer = new \PhpMcp\Server\Defaults\BasicContainer(); $basicContainer->set(\PDO::class, new \PDO('sqlite::memory:')); // Option 2: Use any PSR-11 compatible container (PHP-DI, Laravel, etc.) $container = new \DI\Container(); $container->set(\PDO::class, new \PDO('mysql:host=localhost;dbname=app', $user, $pass)); $server = Server::make() ->withContainer($basicContainer) // Handlers get dependencies auto-injected ->build(); ``` -------------------------------- ### Client Configuration for MCP Server Source: https://github.com/php-mcp/server/blob/main/README.md A JSON configuration object specifying the URL for an MCP server instance named 'my-server'. This is used by clients to connect to the deployed MCP server. ```json { "mcpServers": { "my-server": { "url": "https://mcp.yourdomain.com/mcp" } } } ``` -------------------------------- ### Implement Resumability with Custom Event Store in PHP Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how to create a custom `DatabaseEventStore` implementing `EventStoreInterface` to enable resumability with `StreamableHttpServerTransport`. This involves storing events and replaying them after a specific event ID. ```php use PhpMcp\Server\Contracts\EventStoreInterface; use PhpMcp\Server\Defaults\InMemoryEventStore; use PhpMcp\Server\Transports\StreamableHttpServerTransport; // Use the built-in in-memory event store (for development/testing) $eventStore = new InMemoryEventStore(); // Or implement your own persistent event store class DatabaseEventStore implements EventStoreInterface { public function storeEvent(string $streamId, string $message): string { // Store event in database and return unique event ID return $this->database->insert('events', [ 'stream_id' => $streamId, 'message' => $message, 'created_at' => now() ]); } public function replayEventsAfter(string $lastEventId, callable $sendCallback): void { // Replay events for resumability $events = $this->database->getEventsAfter($lastEventId); foreach ($events as $event) { $sendCallback($event['id'], $event['message']); } } } // Configure transport with event store $transport = new StreamableHttpServerTransport( host: '127.0.0.1', port: 8080, eventStore: new DatabaseEventStore() // Enable resumability ); ``` -------------------------------- ### PHP Automatic Return Value Formatting (Simple Types) Source: https://github.com/php-mcp/server/blob/main/README.md Demonstrates how the PHP MCP server automatically formats simple return values from handlers into `TextContent`. This includes strings, integers, booleans, arrays, null values, and void return types. ```php // Simple values are auto-wrapped in TextContent public function getString(): string { return "Hello World"; } // → TextContent public function getNumber(): int { return 42; } // → TextContent public function getBool(): bool { return true; } // → TextContent public function getArray(): array { return ['key' => 'value']; } // → TextContent (JSON) // Null handling public function getNull(): ?string { return null; } // → TextContent("(null)") public function returnVoid(): void { /* no return */ } // → Empty content ``` -------------------------------- ### Docker Compose Configuration for MCP Server Source: https://github.com/php-mcp/server/blob/main/README.md A docker-compose.yml file to define and run the MCP server application in a containerized environment. It includes service definitions for the MCP server, optional database, port mapping, environment variables, volumes, health checks, and restart policies. ```yaml services: mcp-server: build: . ports: - "8080:80" environment: - MCP_ENV=production - MCP_LOG_LEVEL=info volumes: - ./storage:/var/www/mcp/storage restart: unless-stopped healthcheck: test: ["CMD", "curl", "-f", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 # Optional: Add database if needed database: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: secure_password MYSQL_DATABASE: mcp_server volumes: - mysql_data:/var/lib/mysql restart: unless-stopped volumes: mysql_data: ``` -------------------------------- ### PHP Stdio Server Transport Source: https://github.com/php-mcp/server/blob/main/README.md Sets up a server using the Stdio transport, which is ideal for direct client execution and command-line tools. It uses STDIN/STDOUT for communication. Ensure handlers do not write to STDOUT. ```PHP use PhpMcp\Server\Transports\StdioServerTransport; $server = Server::make() ->withServerInfo('Stdio Server', '1.0.0') ->build(); $server->discover(__DIR__, ['src']); // Create stdio transport (uses STDIN/STDOUT by default) $transport = new StdioServerTransport(); // Start listening (blocking call) $server->listen($transport); ``` -------------------------------- ### Run Code Style Checks Source: https://github.com/php-mcp/server/blob/main/README.md This command performs code style checks on the project, ensuring adherence to coding standards. ```bash # Run code style checks composer lint ``` -------------------------------- ### PHP MCP Server Element Discovery Source: https://github.com/php-mcp/server/blob/main/README.md Configures the server's discovery process, specifying directories to scan and exclude, and controlling whether to force a re-scan and save results to cache. Discovered elements are cached, while manual registrations are not. ```php $server->discover( basePath: __DIR__, scanDirs: ['src/Handlers', 'src/Services'], // Scan these directories excludeDirs: ['tests', 'vendor'], // Skip these directories force: false, // Force re-scan (default: false) saveToCache: true // Save to cache (default: true) ); ``` -------------------------------- ### Run Code Style Fixer Source: https://github.com/php-mcp/server/blob/main/CONTRIBUTING.md Applies code style fixes using Composer or directly via the PHP CS Fixer executable to ensure adherence to coding standards. ```Bash composer lint ``` ```Bash ./vendor/bin/php-cs-fixer fix ``` -------------------------------- ### Implement Custom Session Handler in PHP Source: https://github.com/php-mcp/server/blob/main/README.md Shows how to create a `DatabaseSessionHandler` that implements `SessionHandlerInterface` for custom session storage using a PDO connection. It includes methods for reading, writing, destroying, and garbage collecting sessions. ```php use PhpMcp\Server\Contracts\SessionHandlerInterface; class DatabaseSessionHandler implements SessionHandlerInterface { public function __construct(private \PDO $db) {} public function read(string $id): string|false { $stmt = $this->db->prepare('SELECT data FROM sessions WHERE id = ?'); $stmt->execute([$id]); $session = $stmt->fetch(\PDO::FETCH_ASSOC); return $session ? $session['data'] : false; } public function write(string $id, string $data): bool { $stmt = $this->db->prepare( 'INSERT OR REPLACE INTO sessions (id, data, updated_at) VALUES (?, ?, ?)' ); return $stmt->execute([$id, $data, time()]); } public function destroy(string $id): bool { $stmt = $this->db->prepare('DELETE FROM sessions WHERE id = ?'); return $stmt->execute([$id]); } public function gc(int $maxLifetime): array { $cutoff = time() - $maxLifetime; $stmt = $this->db->prepare('DELETE FROM sessions WHERE updated_at < ?'); $stmt->execute([$cutoff]); return []; // Return array of cleaned session IDs if needed } } // Use custom session handler $server = Server::make() ->withSessionHandler(new DatabaseSessionHandler(), 3600) ->build(); ``` -------------------------------- ### Configure Firewall for MCP Server Source: https://github.com/php-mcp/server/blob/main/README.md This snippet demonstrates how to configure a firewall using UFW to allow necessary ports (SSH, HTTP, HTTPS) and deny potentially insecure ports for the MCP server. It ensures only essential traffic is permitted. ```bash # Only allow necessary ports sudo ufw allow ssh sudo ufw allow 80 sudo ufw allow 443 sudo ufw deny 8080 # MCP port should not be publicly accessible sudo ufw enable ``` -------------------------------- ### PHP Method-Level Schema Configuration Source: https://github.com/php-mcp/server/blob/main/README.md Illustrates the use of the `#[Schema]` attribute at the method level to configure schema properties for the entire method, including nested object structures and required fields. This enhances validation for complex data structures passed as arguments. ```php /** * Process user data with nested validation. */ #[McpTool(name: 'create_user')] #[Schema( properties: [ 'profile' => [ 'type' => 'object', 'properties' => [ 'name' => ['type' => 'string', 'minLength' => 2], 'age' => ['type' => 'integer', 'minimum' => 18], 'email' => ['type' => 'string', 'format' => 'email'] ], 'required' => ['name', 'email'] ] ], required: ['profile'] )] public function createUser(array $userData): array { // PHP type hint provides base 'array' type // Method-level Schema adds object structure validation return ['id' => 123, 'status' => 'created']; } ``` -------------------------------- ### Define Calculator MCP Elements in PHP Source: https://github.com/php-mcp/server/blob/main/README.md Defines PHP classes with attributes to expose methods as MCP tools. The `add` method adds two numbers, and the `power` method calculates powers with schema validation for inputs. ```PHP withServerInfo('HTTP Server', '1.0.0') ->withLogger($logger) // Recommended for HTTP ->build(); $server->discover(__DIR__, ['src']); // Create HTTP transport $transport = new HttpServerTransport( host: '127.0.0.1', // MCP protocol prohibits 0.0.0.0 port: 8080, // Port number mcpPathPrefix: 'mcp' // URL prefix (/mcp/sse, /mcp/message) ); $server->listen($transport); ``` -------------------------------- ### PHP Complete Schema Override Source: https://github.com/php-mcp/server/blob/main/README.md Shows how to completely override schema generation using the `definition` property within the `#[Schema]` attribute at the method level. This bypasses all automatic inference and requires manual definition of the entire JSON schema. ```php #[McpTool(name: 'process_api_request')] #[Schema(definition: [ 'type' => 'object', 'properties' => [ 'endpoint' => ['type' => 'string', 'format' => 'uri'], 'method' => ['type' => 'string', 'enum' => ['GET', 'POST', 'PUT', 'DELETE']], 'headers' => [ 'type' => 'object', 'patternProperties' => [ '^[A-Za-z0-9-]+$' => ['type' => 'string'] ] ] ], 'required' => ['endpoint', 'method'] ])] public function processApiRequest(string $endpoint, string $method, array $headers): array { // PHP type hints are completely ignored when definition is provided // The schema definition above takes full precedence return ['status' => 'processed', 'endpoint' => $endpoint]; } ``` -------------------------------- ### Enable Strict Types Source: https://github.com/php-mcp/server/blob/main/CONTRIBUTING.md Enforces strict type checking at the beginning of PHP files. ```PHP declare(strict_types=1); ```