php-sdk/README.md
Edouard Courty 158e64627f
feat(server): add server lifecycle events (#175)
Signed-off-by: Edouard Courty <edouard.courty2@gmail.com>
2026-02-23 22:40:43 +01:00

287 lines
8.5 KiB
Markdown

# MCP PHP SDK
The official PHP SDK for Model Context Protocol (MCP). It provides a framework-agnostic API for implementing MCP servers
and clients in PHP.
> [!IMPORTANT]
> This SDK is currently in active development with ongoing refinement of its architecture and features. While
> functional, the API may experience changes as we work toward stabilization.
>
> If you want to help us stabilize the SDK, please see the [issue tracker](https://github.com/modelcontextprotocol/php-sdk/issues).
This project represents a collaboration between [the PHP Foundation](https://thephp.foundation/) and the [Symfony project](https://symfony.com/). It adopts
development practices and standards from the Symfony project, including [Coding Standards](https://symfony.com/doc/current/contributing/code/standards.html) and the
[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html).
Until the first major release, this SDK is considered [experimental](https://symfony.com/doc/current/contributing/code/experimental.html).
## Roadmap
**Features**
- [ ] Stabilize server component with all needed handlers and functional tests
- [ ] Extend documentation, including integration guides for popular frameworks
- [ ] Implement Client component
- [ ] Support multiple schema versions
## Installation
```bash
composer require mcp/sdk
```
## Quick Start
This example demonstrates the most common usage pattern - a STDIO server using attribute discovery.
### 1. Define Your MCP Elements
Create a class with MCP capabilities using attributes:
```php
<?php
namespace App;
use Mcp\Capability\Attribute\McpTool;
use Mcp\Capability\Attribute\McpResource;
class CalculatorElements
{
/**
* Adds two numbers together.
*
* @param int $a The first number
* @param int $b The second number
* @return int The sum of the two numbers
*/
#[McpTool]
public function add(int $a, int $b): int
{
return $a + $b;
}
/**
* Performs basic arithmetic operations.
*/
#[McpTool(name: 'calculate')]
public function calculate(float $a, float $b, string $operation): float|string
{
return match($operation) {
'add' => $a + $b,
'subtract' => $a - $b,
'multiply' => $a * $b,
'divide' => $b != 0 ? $a / $b : 'Error: Division by zero',
default => 'Error: Unknown operation'
};
}
#[McpResource(
uri: 'config://calculator/settings',
name: 'calculator_config',
mimeType: 'application/json'
)]
public function getSettings(): array
{
return ['precision' => 2, 'allow_negative' => true];
}
}
```
### 2. Create the Server Script
Create your MCP server:
```php
#!/usr/bin/env php
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use Mcp\Server;
use Mcp\Server\Transport\StdioTransport;
$server = Server::builder()
->setServerInfo('Calculator Server', '1.0.0')
->setDiscovery(__DIR__, ['.'])
->build();
$transport = new StdioTransport();
$server->run($transport);
```
### 3. Configure Your MCP Client
Add to your client configuration (e.g., Claude Desktop's `mcp.json`):
```json
{
"mcpServers": {
"php-calculator": {
"command": "php",
"args": ["/absolute/path/to/your/server.php"]
}
}
}
```
### 4. Test Your Server
```bash
# Test with MCP Inspector
npx @modelcontextprotocol/inspector php /path/to/server.php
# Your AI assistant can now call:
# - add: Add two integers
# - calculate: Perform arithmetic operations
# - Read config://calculator/settings resource
```
## Key Features
### Attribute-Based Discovery
Define MCP elements using PHP attributes with automatic discovery:
```php
// Tool with automatic name and description from method
#[McpTool]
public function generateReport(): string { /* ... */ }
// Tool with custom name
#[McpTool(name: 'custom_name')]
public function myMethod(): string { /* ... */ }
// Resource with URI and metadata
#[McpResource(uri: 'config://app/settings', mimeType: 'application/json')]
public function getConfig(): array { /* ... */ }
```
### Manual Registration
Register capabilities programmatically:
```php
$server = Server::builder()
->addTool([MyClass::class, 'myMethod'], 'tool_name')
->addResource([MyClass::class, 'getData'], 'data://config')
->build();
```
### Multiple Transport Options
**STDIO Transport** (Command-line integration):
```php
$transport = new StdioTransport();
$server->run($transport);
```
**HTTP Transport** (Web-based communication):
```php
$transport = new StreamableHttpTransport($request, $responseFactory, $streamFactory);
$response = $server->run($transport);
// Handle $response in your web application
```
### Session Management
By default, the SDK uses in-memory sessions. You can configure different session stores:
```php
use Mcp\Server\Session\FileSessionStore;
use Mcp\Server\Session\InMemorySessionStore;
use Mcp\Server\Session\Psr16SessionStore;
use Symfony\Component\Cache\Psr16Cache;
use Symfony\Component\Cache\Adapter\RedisAdapter;
// Use default in-memory sessions with custom TTL
$server = Server::builder()
->setSession(ttl: 7200) // 2 hours
->build();
// Override with file-based storage
$server = Server::builder()
->setSession(new FileSessionStore(__DIR__ . '/sessions'))
->build();
// Override with in-memory storage and custom TTL
$server = Server::builder()
->setSession(new InMemorySessionStore(3600))
->build();
// Override with PSR-16 cache-based storage
// Requires psr/simple-cache and symfony/cache (or any other PSR-16 implementation)
// composer require psr/simple-cache symfony/cache
$redisAdapter = new RedisAdapter(
RedisAdapter::createConnection('redis://localhost:6379'),
'mcp_sessions'
);
$server = Server::builder()
->setSession(new Psr16SessionStore(
cache: new Psr16Cache($redisAdapter),
prefix: 'mcp-',
ttl: 3600
))
->build();
```
### Discovery Caching
Use any PSR-16 cache implementation to cache discovery results and avoid running discovery on every server start:
```php
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Psr16Cache;
$cache = new Psr16Cache(new FilesystemAdapter('mcp-discovery'));
$server = Server::builder()
->setDiscovery(
basePath: __DIR__,
scanDirs: ['.', 'src'], // Default: ['.', 'src']
excludeDirs: ['vendor'], // Default: ['vendor', 'node_modules']
cache: $cache
)
->build();
```
## Documentation
**Core Concepts:**
- [Server Builder](docs/server-builder.md) - Complete ServerBuilder reference and configuration
- [Transports](docs/transports.md) - STDIO and HTTP transport setup and usage
- [MCP Elements](docs/mcp-elements.md) - Creating tools, resources, and prompts
- [Client Communication](docs/client-communication.md) - Communicating back to the client from server-side
- [Events](docs/events.md) - Hooking into server lifecycle with events
**Learning:**
- [Examples](docs/examples.md) - Comprehensive example walkthroughs
**External Resources:**
- [Model Context Protocol documentation](https://modelcontextprotocol.io)
- [Model Context Protocol specification](https://spec.modelcontextprotocol.io)
- [Officially supported servers](https://github.com/modelcontextprotocol/servers)
## PHP Libraries Using the MCP SDK
* [pronskiy/mcp](https://github.com/pronskiy/mcp) - Additional DX layer
* [symfony/mcp-bundle](https://github.com/symfony/mcp-bundle) - Symfony integration bundle
* [josbeir/cakephp-synapse](https://github.com/josbeir/cakephp-synapse) - CakePHP integration plugin
## Contributing
We are passionate about supporting contributors of all levels of experience and would love to see you get involved in
the project. See the [contributing guide](CONTRIBUTING.md) to get started before you [report issues](https://github.com/modelcontextprotocol/php-sdk/issues) and [send pull requests](https://github.com/modelcontextprotocol/php-sdk/pulls).
## Credits
The starting point for this SDK was the [PHP-MCP](https://github.com/php-mcp/server) project, initiated by
[Kyrian Obikwelu](https://github.com/CodeWithKyrian), and the [Symfony AI initiative](https://github.com/symfony/ai). We are grateful for the work
done by both projects and their contributors, which created a solid foundation for this SDK.
## License
This project is licensed under the Apache License, Version 2.0 for new contributions, with existing code under the MIT License - see the [LICENSE](LICENSE) file for details.