php-sdk/docs/examples.md
Johannes Wachter 02e86377e4
Add elicitation support for server-to-client user input requests (#228)
- Add ElicitAction enum (accept/decline/cancel)
- Add schema definitions for elicitation fields (string, number, boolean, enum)
- Add ElicitationSchema wrapper for requestedSchema
- Add ElicitRequest and ElicitResult for elicitation/create method
- Update ClientCapabilities to support elicitation capability
- Add elicit() method to ClientGateway
- Store client capabilities in session during initialization
- Add comprehensive unit tests
- Add elicitation example server with book_restaurant, confirm_action, and collect_feedback tools
2026-02-15 23:34:19 +01:00

355 lines
9.7 KiB
Markdown

# Examples
The MCP PHP SDK includes comprehensive examples demonstrating different patterns and use cases. Each example showcases
specific features and can be run independently to understand how the SDK works.
## Table of Contents
- [Getting Started](#getting-started)
- [Running Examples](#running-examples)
- [Examples](#examples)
## Getting Started
All examples are located in the `examples/` directory and use the SDK dependencies from the root project. Most examples
can be run directly without additional setup.
### Prerequisites
```bash
# Install dependencies (in project root)
composer install
```
## Running Examples
The bootstrapping of the example will choose the used transport based on the SAPI you use.
### STDIO Transport
The STDIO transport will use standard input/output for communication:
```bash
# Interactive testing with MCP Inspector
npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php
# Run with debugging enabled
npx @modelcontextprotocol/inspector -e DEBUG=1 -e FILE_LOG=1 php examples/discovery-calculator/server.php
# Or configure the script path in your MCP client
# Path: php examples/discovery-calculator/server.php
```
### HTTP Transport
The Streamable HTTP transport will be chosen if running examples with a web servers:
```bash
# Start the server
php -S localhost:8000 examples/discovery-userprofile/server.php
# Test with MCP Inspector
npx @modelcontextprotocol/inspector http://localhost:8000
# Test with curl
curl -X POST http://localhost:8000 \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"},"capabilities":{}}}'
```
## Examples
### Discovery Calculator
**File**: `examples/discovery-calculator/`
**What it demonstrates:**
- Attribute-based discovery using `#[McpTool]` and `#[McpResource]`
- Basic arithmetic operations
- Configuration management through resources
- State management between tool calls
**Key Features:**
```php
#[McpTool(name: 'calculate')]
public function calculate(float $a, float $b, string $operation): float|string
#[McpResource(
uri: 'config://calculator/settings',
name: 'calculator_config',
mimeType: 'application/json'
)]
public function getConfiguration(): array
```
**Usage:**
```bash
# Interactive testing
npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php
# Or configure in MCP client: php examples/discovery-calculator/server.php
```
### Explicit Registration
**File**: `examples/explicit-registration/`
**What it demonstrates:**
- Manual registration of tools, resources, and prompts
- Alternative to attribute-based discovery
- Simple handler functions
**Key Features:**
```php
$server = Server::builder()
->addTool([SimpleHandlers::class, 'echoText'], 'echo_text')
->addResource([SimpleHandlers::class, 'getAppVersion'], 'app://version')
->addPrompt([SimpleHandlers::class, 'greetingPrompt'], 'personalized_greeting')
```
### Environment Variables
**File**: `examples/env-variables/`
**What it demonstrates:**
- Environment variable integration
- Server configuration from environment
- Environment-based tool behavior
**Key Features:**
- Reading environment variables within tools
- Conditional behavior based on environment
- Environment validation and defaults
### Custom Dependencies
**File**: `examples/custom-dependencies/`
**What it demonstrates:**
- Dependency injection with PSR-11 containers
- Service layer architecture
- Repository pattern implementation
- Complex business logic integration
**Key Features:**
```php
$container->set(TaskRepositoryInterface::class, $taskRepo);
$container->set(StatsServiceInterface::class, $statsService);
$server = Server::builder()
->setContainer($container)
->setDiscovery(__DIR__, ['.'])
```
### Cached Discovery
**File**: `examples/cached-discovery/`
**What it demonstrates:**
- Discovery caching for improved performance
- PSR-16 cache integration
- Cache invalidation strategies
**Key Features:**
```php
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Component\Cache\Psr16Cache;
$cache = new Psr16Cache(new FilesystemAdapter('mcp-discovery'));
$server = Server::builder()
->setDiscovery(__DIR__, ['.'], [], $cache)
```
### Client Communication
**File**: `examples/client-communication/`
**What it demonstrates:**
- Server initiated communication back to the client
- Logging, sampling, progress and notifications
- Using `ClientGateway` in tool method via method argument injection of `RequestContext`
### Discovery User Profile
**File**: `examples/discovery-userprofile/`
**What it demonstrates:**
- HTTP transport with StreamableHttpTransport
- Resource templates with URI parameters
- Completion providers for parameter hints
- User profile management system
- Session persistence with FileSessionStore
**Key Features:**
```php
#[McpResourceTemplate(
uriTemplate: 'user://{userId}/profile',
name: 'user_profile',
mimeType: 'application/json'
)]
public function getUserProfile(
#[CompletionProvider(values: ['101', '102', '103'])]
string $userId
): array
#[McpPrompt(name: 'generate_bio_prompt')]
public function generateBio(string $userId, string $tone = 'professional'): array
```
**Usage:**
```bash
# Start the HTTP server
php -S localhost:8000 examples/discovery-userprofile/server.php
# Test with MCP Inspector
npx @modelcontextprotocol/inspector http://localhost:8000
# Or configure in MCP client: http://localhost:8000
```
### Combined Registration
**File**: `examples/combined-registration/`
**What it demonstrates:**
- Mixing attribute discovery with manual registration
- HTTP server with both discovered and manual capabilities
- Flexible registration patterns
**Key Features:**
```php
$server = Server::builder()
->setDiscovery(__DIR__, ['.']) // Automatic discovery
->addTool([ManualHandlers::class, 'manualGreeter']) // Manual registration
->addResource([ManualHandlers::class, 'getPriorityConfig'], 'config://priority')
```
### Complex Tool Schema
**File**: `examples/complex-tool-schema/`
**What it demonstrates:**
- Advanced JSON schema definitions
- Complex data structures and validation
- Event scheduling and management
- Enum types and nested objects
**Key Features:**
```php
#[Schema(definition: [
'type' => 'object',
'properties' => [
'title' => ['type' => 'string', 'minLength' => 1, 'maxLength' => 100],
'eventType' => ['type' => 'string', 'enum' => ['meeting', 'deadline', 'reminder']],
'priority' => ['type' => 'string', 'enum' => ['low', 'medium', 'high', 'urgent']]
]
])]
public function scheduleEvent(array $eventData): array
```
### Schema Showcase
**File**: `examples/schema-showcase/`
**What it demonstrates:**
- Comprehensive JSON schema features
- Parameter-level schema validation
- String constraints (minLength, maxLength, pattern)
- Numeric constraints (minimum, maximum, multipleOf)
- Array and object validation
**Key Features:**
```php
#[McpTool]
public function formatText(
#[Schema(
type: 'string',
minLength: 5,
maxLength: 100,
pattern: '^[a-zA-Z0-9\s\.,!?\-]+$'
)]
string $text,
#[Schema(enum: ['uppercase', 'lowercase', 'title', 'sentence'])]
string $format = 'sentence'
): array
```
### Elicitation
**File**: `examples/server/elicitation/`
**What it demonstrates:**
- Server-to-client elicitation requests
- Interactive user input during tool execution
- Multi-field form schemas with validation
- Boolean confirmation dialogs
- Enum fields with human-readable labels
- Handling accept/decline/cancel responses
- Session persistence requirement for server-initiated requests
**Key Features:**
```php
// Check client support before eliciting
if (!$context->getClientGateway()->supportsElicitation()) {
return ['status' => 'error', 'message' => 'Client does not support elicitation'];
}
// Build schema with multiple field types
$schema = new ElicitationSchema(
properties: [
'party_size' => new NumberSchemaDefinition(
title: 'Party Size',
integerOnly: true,
minimum: 1,
maximum: 20
),
'date' => new StringSchemaDefinition(
title: 'Reservation Date',
format: 'date'
),
'dietary' => new EnumSchemaDefinition(
title: 'Dietary Restrictions',
enum: ['none', 'vegetarian', 'vegan'],
enumNames: ['None', 'Vegetarian', 'Vegan']
),
],
required: ['party_size', 'date']
);
// Send elicitation request
$result = $client->elicit(
message: 'Please provide your reservation details',
requestedSchema: $schema
);
// Handle response
if ($result->isAccepted()) {
$data = $result->content; // User-provided data
} elseif ($result->isDeclined() || $result->isCancelled()) {
// User declined or cancelled
}
```
**Important Notes:**
- Elicitation requires a session store (e.g., `FileSessionStore`)
- Check client capabilities with `supportsElicitation()` before sending requests
- Schema supports primitive types: string, number/integer, boolean, enum
- String fields support format validation: date, date-time, email, uri
- Users can accept (providing data), decline, or cancel requests
**Usage:**
```bash
# Interactive testing with MCP client that supports elicitation
npx @modelcontextprotocol/inspector php examples/server/elicitation/server.php
# Test with Goose (confirmed working by reviewer)
# Or configure in Claude Desktop or other MCP clients
```
**Example Tools:**
1. **book_restaurant** - Multi-field reservation form with number, date, and enum fields
2. **confirm_action** - Simple boolean confirmation dialog
3. **collect_feedback** - Rating and comments form with optional fields