# Llm Agents Php Mcp Server

> Create production-ready MCP servers in PHP with modern architecture, and flexible transport options.

- **Type:** MCP server
- **Install:** `agentstack add mcp-llm-agents-php-mcp-server`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [llm-agents-php](https://agentstack.voostack.com/s/llm-agents-php)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [llm-agents-php](https://github.com/llm-agents-php)
- **Source:** https://github.com/llm-agents-php/mcp-server

## Install

```sh
agentstack add mcp-llm-agents-php-mcp-server
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# PHP MCP Server SDK

[](https://packagist.org/packages/llm/mcp-server)
[](https://packagist.org/packages/llm/mcp-server)
[](LICENSE)
[](https://packagist.org/packages/llm/mcp-server)

A comprehensive PHP SDK for building [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction)
servers. Create production-ready MCP servers in PHP with modern architecture, flexible transport options, and
comprehensive feature support.

## Table of Contents

- [Requirements](#requirements)
- [Installation](#installation)
    - [Framework Integration](#framework-integration)
- [Quick Start](#quick-start)
- [Core Concepts](#core-concepts)
- [Transport Options](#transport-options)
    - [STDIO Transport](#stdio-transport-recommended-for-cli)
    - [HTTP Transport with SSE](#http-transport-with-sse)
    - [Streamable HTTP Transport](#streamable-http-transport)
- [Working with Tools](#working-with-tools)
    - [Basic Tool Registration](#basic-tool-registration)
    - [Advanced Tool with Multiple Content Types](#advanced-tool-with-multiple-content-types)
    - [Error Handling in Tools](#error-handling-in-tools)
- [Working with Resources](#working-with-resources)
- [Working with Prompts](#working-with-prompts)
- [HTTP Middleware](#http-middleware)
    - [Built-in Middleware](#built-in-middleware)
        - [CORS Middleware](#cors-middleware)
        - [Authentication Middleware](#authentication-middleware)
    - [Custom Middleware](#custom-middleware)
- [Advanced Configuration](#advanced-configuration)
    - [Complete Server Setup](#complete-server-setup)
    - [Event Store for Resumability](#event-store-for-resumability)
- [Common Patterns](#common-patterns)
    - [Handler Factory Pattern](#handler-factory-pattern)
    - [Decorator Pattern for Handlers](#decorator-pattern-for-handlers)
    - [Class-Based Tool Handlers with Schema Mapping](#class-based-tool-handlers-with-schema-mapping)
- [Ecosystem & Extensions](#ecosystem--extensions)
- [Contributing](#contributing)
- [License](#license)
- [Acknowledgments](#acknowledgments)

> This SDK implements the **MCP 2025-03-26** specification with full backward compatibility support.

## Features

- **Complete MCP Implementation**: Full support for tools, resources, prompts, and logging
- **Multiple Transport Options**: STDIO, HTTP with SSE, and streamable HTTP transports
- **Session Management**: Built-in session handling with configurable storage backends
- **Event-Driven Architecture**: ReactPHP-powered asynchronous operations
- **Middleware Support**: PSR-15 compatible HTTP middleware system
- **Type Safety**: Full PHP 8.3+ type declarations and comprehensive error handling
- **Extensible Design**: Pluggable components with clear interfaces
- **Production Ready**: Comprehensive logging, error handling, and testing support

### What's NOT Included

This SDK focuses on core MCP functionality and intentionally **does not include**:

- **Resource Discovery**: Automatic scanning and registration of resources from filesystem or annotations
- **Schema Generation**: Automatic generation of JSON schemas from PHP code or docblocks
- **Request Validation**: Built-in validation of incoming requests against defined schemas
- **Framework Integration**: Direct integration with web frameworks (Laravel, Symfony, etc.)

**Why?** These features are better implemented as separate packages or framework-specific bridges that can:

- Provide opinionated conventions for specific use cases
- Integrate deeply with framework ecosystems
- Offer different approaches to schema management
- Maintain focused, single-responsibility packages

## Requirements

- **PHP** >= 8.3 (required for advanced type features and performance)
- **Extensions**: `json`, `mbstring`, `pcre` (typically bundled with PHP)

## Installation

```bash
composer require llm/mcp-server
```

### Framework Integration

For enhanced developer experience with automatic discovery and validation:

**Spiral Framework**: Use the [spiral/mcp-server](https://github.com/spiral-packages/mcp-server) bridge

```bash
composer require spiral/mcp-server
```

**Other Frameworks**: Framework-specific bridges are planned. Contributions welcome!

## Quick Start

Here's a minimal working example that demonstrates core functionality:

```php
 ['type' => 'string', 'description' => 'Name to greet']],
);

$greetHandler = new CallableHandler(function($args) {
    return [TextContent::make("Hello, " . ($args['name'] ?? 'World') . "!")];
});

$registry->registerTool($greetTool, $greetHandler);

// Create and start server
$server = new Server($protocol, $sessionManager, $logger);
$transport = new StdioServerTransport();
$server->listen($transport);
```

**Expected Output**: The server will listen on STDIN/STDOUT and respond to MCP requests.

**To Test**: Save as `server.php` and run `php server.php`, then send MCP messages via STDIN.

## Core Concepts

### Architecture Overview

The SDK follows a layered architecture:

```
┌─────────────────┐
│    Transport    │  (STDIO, HTTP, Streamable HTTP)
├─────────────────┤
│    Protocol     │  (MCP message handling)
├─────────────────┤
│   Dispatcher    │  (Route requests to handlers)
├─────────────────┤
│    Registry     │  (Tools, Resources, Prompts)
├─────────────────┤
│   Handlers      │  (Your business logic)
└─────────────────┘
```

### Key Components

- **Server**: Main orchestrator that binds protocol to transport
- **Protocol**: Handles MCP message parsing and session management
- **Registry**: Manages tools, resources, and prompts registration
- **Transport**: Communication layer (STDIO, HTTP, etc.)
- **Session Manager**: Handles client sessions and state persistence

## Transport Options

### STDIO Transport (Recommended for CLI)

Perfect for command-line tools and process-based communication:

```php
use Mcp\Server\Transports\StdioServerTransport;

$transport = new StdioServerTransport();
$server->listen($transport);
```

**Use Cases**: CLI tools, subprocess communication, development/testing

### HTTP Transport with SSE

For web-based applications with real-time communication:

```php
use Mcp\Server\Transports\HttpServer;
use Mcp\Server\Transports\HttpServerTransport;
use React\EventLoop\Loop;

$loop = Loop::get();
$httpServer = new HttpServer($loop, '127.0.0.1', 8080, '/mcp');
$transport = new HttpServerTransport($httpServer);
$server->listen($transport);
```

**Use Cases**: Web applications, browser-based clients, dashboard integrations

### Streamable HTTP Transport

Advanced HTTP transport with JSON response and resumability support:

```php
use Mcp\Server\Transports\StreamableHttpServerTransport;
use Mcp\Server\Defaults\InMemoryEventStore;

$eventStore = new InMemoryEventStore();
$transport = new StreamableHttpServerTransport(
    httpServer: $httpServer,
    enableJsonResponse: true,
    stateless: false,
    eventStore: $eventStore
);
$server->listen($transport);
```

**Use Cases**: High-performance applications, stateless deployments, fault-tolerant systems

## Working with Tools

Tools are executable functions that AI assistants can call to perform actions.

### Basic Tool Registration

```php
use PhpMcp\Schema\Tool;
use Mcp\Server\Defaults\CallableHandler;
use PhpMcp\Schema\Content\TextContent;

// Define tool schema
$calculatorTool = Tool::make(
    name: 'calculator',
    description: 'Performs basic mathematical operations',
    inputSchema: [
        'operation' => [
            'type' => 'string',
            'enum' => ['add', 'subtract', 'multiply', 'divide'],
            'description' => 'The operation to perform'
        ],
        'a' => ['type' => 'number', 'description' => 'First number'],
        'b' => ['type' => 'number', 'description' => 'Second number']
    ]
);

// Create handler
$calculatorHandler = new CallableHandler(function($args) {
    $a = $args['a'];
    $b = $args['b'];
    $operation = $args['operation'];
    
    $result = match($operation) {
        'add' => $a + $b,
        'subtract' => $a - $b,
        'multiply' => $a * $b,
        'divide' => $b !== 0 ? $a / $b : throw new InvalidArgumentException('Division by zero'),
        default => throw new InvalidArgumentException('Unknown operation')
    };
    
    return [TextContent::make("Result: $result")];
});

$registry->registerTool($calculatorTool, $calculatorHandler);
```

### Advanced Tool with Multiple Content Types

```php
use PhpMcp\Schema\Content\ImageContent;
use PhpMcp\Schema\Content\BlobResourceContents;

$imageProcessorHandler = new CallableHandler(function($args) {
    $imagePath = $args['image_path'];
    
    // Process image (example)
    $imageData = file_get_contents($imagePath);
    $base64Image = base64_encode($imageData);
    
    return [
        TextContent::make("Processed image: $imagePath"),
        ImageContent::make($base64Image, 'image/jpeg'),
    ];
});
```

### Error Handling in Tools

```php
use Mcp\Server\Exception\ValidationException;

$validatedToolHandler = new CallableHandler(function($args) {
    if (!isset($args['required_param'])) {
        throw new ValidationException([
            [
                'pointer' => '/required_param',
                'keyword' => 'required',
                'message' => 'This parameter is required'
            ]
        ]);
    }
    
    // Tool logic here
    return [TextContent::make('Success!')];
});
```

## Working with Resources

Resources provide read-only access to data that AI assistants can reference.

### Static Resources

```php
use PhpMcp\Schema\Resource;
use PhpMcp\Schema\Content\TextResourceContents;

$docResource = Resource::make(
    uri: 'file:///docs/readme.txt',
    name: 'README Documentation',
    description: 'Application documentation',
    mimeType: 'text/plain'
);

$docHandler = new CallableHandler(function($args) {
    $content = file_get_contents(__DIR__ . '/README.txt');
    return [TextResourceContents::make($args['uri'], 'text/plain', $content)];
});

$registry->registerResource($docResource, $docHandler);
```

### Dynamic Resource Templates

Resource templates use URI patterns to handle multiple similar resources:

```php
use PhpMcp\Schema\ResourceTemplate;

$userTemplate = ResourceTemplate::make(
    uriTemplate: 'user://{user_id}/profile',
    name: 'User Profile Template',
    description: 'Access user profile data',
    mimeType: 'application/json'
);

$userHandler = new CallableHandler(function($args) {
    $userId = $args['user_id'];
    
    // Fetch user data from database/API
    $userData = getUserData($userId);
    
    return [TextResourceContents::make(
        $args['uri'],
        'application/json',
        json_encode($userData)
    )];
});

$registry->registerResourceTemplate($userTemplate, $userHandler);
```

### Resource with Completion Providers

```php
use Mcp\Server\Defaults\ListCompletionProvider;

$completionProvider = new ListCompletionProvider(['admin', 'user', 'guest']);

$registry->registerResourceTemplate(
    $userTemplate,
    $userHandler,
    completionProviders: ['user_id' => $completionProvider]
);
```

## Working with Prompts

Prompts provide templated text generation for AI assistants.

### Basic Prompt

```php
use PhpMcp\Schema\Prompt;
use PhpMcp\Schema\Content\PromptMessage;
use PhpMcp\Schema\Enum\Role;

$codeReviewPrompt = Prompt::make(
    name: 'code_review',
    description: 'Generate code review prompt',
    arguments: [
        'code' => ['type' => 'string', 'required' => true, 'description' => 'Code to review'],
        'language' => ['type' => 'string', 'description' => 'Programming language']
    ]
);

$codeReviewHandler = new CallableHandler(function($args) {
    $code = $args['code'];
    $language = $args['language'] ?? 'unknown';
    
    $systemPrompt = "You are a senior software engineer reviewing {$language} code.";
    $userPrompt = "Please review this code:\n\n```{$language}\n{$code}\n```";
    
    return [
        PromptMessage::make(Role::User, TextContent::make($systemPrompt)),
        PromptMessage::make(Role::User, TextContent::make($userPrompt))
    ];
});

$registry->registerPrompt($codeReviewPrompt, $codeReviewHandler);
```

### Advanced Prompt with Multiple Message Types

```php
$conversationPrompt = new CallableHandler(function($args) {
    $context = $args['context'];
    $question = $args['question'];
    
    return [
        [
            'role' => 'user',
            'content' => [
                'type' => 'text',
                'text' => "Context: $context"
            ]
        ],
        [
            'role' => 'user', 
            'content' => [
                'type' => 'text',
                'text' => "Question: $question"
            ]
        ]
    ];
});
```

## Session Management

### Custom Session Handlers

Implement the `SessionHandlerInterface` for custom storage:

```php
use Mcp\Server\Contracts\SessionHandlerInterface;

class DatabaseSessionHandler implements SessionHandlerInterface
{
    public function __construct(private PDO $pdo) {}
    
    public function read(string $id): string|false
    {
        $stmt = $this->pdo->prepare('SELECT data FROM sessions WHERE id = ?');
        $stmt->execute([$id]);
        return $stmt->fetchColumn() ?: false;
    }
    
    public function write(string $id, string $data): bool
    {
        $stmt = $this->pdo->prepare(
            'INSERT INTO sessions (id, data, updated_at) VALUES (?, ?, NOW()) 
             ON DUPLICATE KEY UPDATE data = VALUES(data), updated_at = NOW()'
        );
        return $stmt->execute([$id, $data]);
    }
    
    public function destroy(string $id): bool
    {
        $stmt = $this->pdo->prepare('DELETE FROM sessions WHERE id = ?');
        return $stmt->execute([$id]);
    }
    
    public function gc(int $maxLifetime): array
    {
        $stmt = $this->pdo->prepare(
            'DELETE FROM sessions WHERE updated_at execute([$maxLifetime]);
        return []; // Return deleted session IDs if needed
    }
}
```

### Cache-Based Session Storage

```php
use Mcp\Server\Session\CacheSessionHandler;
use Mcp\Server\Defaults\FileCache;

$cache = new FileCache('/tmp/mcp_sessions.cache');
$sessionHandler = new CacheSessionHandler($cache, ttl: 7200);
$sessionManager = new SessionManager($sessionHandler, $logger, $loop);
```

## HTTP Middleware

### Built-in Middleware

#### CORS Middleware

```php
use Mcp\Server\Transports\Middleware\CorsMiddleware;

$corsMiddleware = new CorsMiddleware(
    allowedOrigins: ['https://myapp.com', 'https://localhost:3000'],
    allowedMethods: ['GET', 'POST', 'DELETE', 'OPTIONS'],
    allowedHeaders: ['Content-Type', 'Authorization', 'Mcp-Session-Id'],
    maxAge: 86400,
);

$httpServer = new HttpServer(
    $loop,
    '127.0.0.1',
    8080,
    '/mcp',
    middleware: [$corsMiddleware],
);
```

#### Authentication Middleware

```php
use Mcp\Server\Transports\Middleware\AuthenticationMiddleware;

$authMiddleware = new AuthenticationMiddleware(
    authenticator: function($request, $authHeader) {
        // Bearer token validation
        if (!str_starts_with($authHeader, 'Bearer ')) {
            return false;
        }
        
        $token = substr($authHeader, 7);
        return validateToken($token); // Your validation logic
    },
    protectedPaths: ['/mcp']
);
```

### Custom Middleware

```php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class LoggingMiddleware implements MiddlewareInterface
{
    public function __construct(private LoggerInterface $logger) {}
    
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        $start = microtime(true);
        
        $this->logger->info('Request started', [
            'method' => $request->getMethod(),
            'path' => $request->getUri()->getPath()
        ]);
        
        $response = $handler->handle($request);
        
        $duration = microtim

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [llm-agents-php](https://github.com/llm-agents-php)
- **Source:** [llm-agents-php/mcp-server](https://github.com/llm-agents-php/mcp-server)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-llm-agents-php-mcp-server
- Seller: https://agentstack.voostack.com/s/llm-agents-php
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
