refactor: transport agnostic examples (#131)
This commit is contained in:
parent
fb3c1e65a6
commit
ff26b4ff61
46 changed files with 157 additions and 289 deletions
|
|
@ -52,17 +52,17 @@
|
||||||
},
|
},
|
||||||
"autoload-dev": {
|
"autoload-dev": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Mcp\\Example\\HttpCombinedRegistration\\": "examples/http-combined-registration/",
|
"Mcp\\Example\\CachedDiscovery\\": "examples/cached-discovery/",
|
||||||
"Mcp\\Example\\HttpComplexToolSchema\\": "examples/http-complex-tool-schema/",
|
"Mcp\\Example\\ClientCommunication\\": "examples/client-communication/",
|
||||||
"Mcp\\Example\\HttpDiscoveryUserProfile\\": "examples/http-discovery-userprofile/",
|
"Mcp\\Example\\CombinedRegistration\\": "examples/combined-registration/",
|
||||||
"Mcp\\Example\\HttpSchemaShowcase\\": "examples/http-schema-showcase/",
|
"Mcp\\Example\\ComplexToolSchema\\": "examples/complex-tool-schema/",
|
||||||
"Mcp\\Example\\StdioCachedDiscovery\\": "examples/stdio-cached-discovery/",
|
"Mcp\\Example\\CustomDependencies\\": "examples/custom-dependencies/",
|
||||||
"Mcp\\Example\\StdioClientCommunication\\": "examples/stdio-client-communication/",
|
|
||||||
"Mcp\\Example\\StdioCustomDependencies\\": "examples/stdio-custom-dependencies/",
|
|
||||||
"Mcp\\Example\\StdioDiscoveryCalculator\\": "examples/stdio-discovery-calculator/",
|
|
||||||
"Mcp\\Example\\StdioEnvVariables\\": "examples/stdio-env-variables/",
|
|
||||||
"Mcp\\Example\\StdioExplicitRegistration\\": "examples/stdio-explicit-registration/",
|
|
||||||
"Mcp\\Example\\CustomMethodHandlers\\": "examples/custom-method-handlers/",
|
"Mcp\\Example\\CustomMethodHandlers\\": "examples/custom-method-handlers/",
|
||||||
|
"Mcp\\Example\\DiscoveryCalculator\\": "examples/discovery-calculator/",
|
||||||
|
"Mcp\\Example\\DiscoveryUserProfile\\": "examples/discovery-userprofile/",
|
||||||
|
"Mcp\\Example\\EnvVariables\\": "examples/env-variables/",
|
||||||
|
"Mcp\\Example\\ExplicitRegistration\\": "examples/explicit-registration/",
|
||||||
|
"Mcp\\Example\\SchemaShowcase\\": "examples/schema-showcase/",
|
||||||
"Mcp\\Tests\\": "tests/"
|
"Mcp\\Tests\\": "tests/"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,7 @@ specific features and can be run independently to understand how the SDK works.
|
||||||
|
|
||||||
- [Getting Started](#getting-started)
|
- [Getting Started](#getting-started)
|
||||||
- [Running Examples](#running-examples)
|
- [Running Examples](#running-examples)
|
||||||
- [STDIO Examples](#stdio-examples)
|
- [Examples](#examples)
|
||||||
- [HTTP Examples](#http-examples)
|
|
||||||
- [Advanced Patterns](#advanced-patterns)
|
|
||||||
- [Testing and Debugging](#testing-and-debugging)
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
|
@ -26,28 +23,30 @@ composer install
|
||||||
|
|
||||||
## Running Examples
|
## Running Examples
|
||||||
|
|
||||||
### STDIO Examples
|
The bootstrapping of the example will choose the used transport based on the SAPI you use.
|
||||||
|
|
||||||
STDIO examples use standard input/output for communication:
|
### STDIO Transport
|
||||||
|
|
||||||
|
The STDIO transport will use standard input/output for communication:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Interactive testing with MCP Inspector
|
# Interactive testing with MCP Inspector
|
||||||
npx @modelcontextprotocol/inspector php examples/stdio-discovery-calculator/server.php
|
npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php
|
||||||
|
|
||||||
# Run with debugging enabled
|
# Run with debugging enabled
|
||||||
npx @modelcontextprotocol/inspector -e DEBUG=1 -e FILE_LOG=1 php examples/stdio-discovery-calculator/server.php
|
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
|
# Or configure the script path in your MCP client
|
||||||
# Path: php examples/stdio-discovery-calculator/server.php
|
# Path: php examples/discovery-calculator/server.php
|
||||||
```
|
```
|
||||||
|
|
||||||
### HTTP Examples
|
### HTTP Transport
|
||||||
|
|
||||||
HTTP examples run as web servers:
|
The Streamable HTTP transport will be chosen if running examples with a web servers:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Start the server
|
# Start the server
|
||||||
php -S localhost:8000 examples/http-discovery-userprofile/server.php
|
php -S localhost:8000 examples/discovery-userprofile/server.php
|
||||||
|
|
||||||
# Test with MCP Inspector
|
# Test with MCP Inspector
|
||||||
npx @modelcontextprotocol/inspector http://localhost:8000
|
npx @modelcontextprotocol/inspector http://localhost:8000
|
||||||
|
|
@ -59,11 +58,11 @@ curl -X POST http://localhost:8000 \
|
||||||
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"},"capabilities":{}}}'
|
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0.0"},"capabilities":{}}}'
|
||||||
```
|
```
|
||||||
|
|
||||||
## STDIO Examples
|
## Examples
|
||||||
|
|
||||||
### Discovery Calculator
|
### Discovery Calculator
|
||||||
|
|
||||||
**File**: `examples/stdio-discovery-calculator/`
|
**File**: `examples/discovery-calculator/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Attribute-based discovery using `#[McpTool]` and `#[McpResource]`
|
- Attribute-based discovery using `#[McpTool]` and `#[McpResource]`
|
||||||
|
|
@ -87,14 +86,14 @@ public function getConfiguration(): array
|
||||||
**Usage:**
|
**Usage:**
|
||||||
```bash
|
```bash
|
||||||
# Interactive testing
|
# Interactive testing
|
||||||
npx @modelcontextprotocol/inspector php examples/stdio-discovery-calculator/server.php
|
npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php
|
||||||
|
|
||||||
# Or configure in MCP client: php examples/stdio-discovery-calculator/server.php
|
# Or configure in MCP client: php examples/discovery-calculator/server.php
|
||||||
```
|
```
|
||||||
|
|
||||||
### Explicit Registration
|
### Explicit Registration
|
||||||
|
|
||||||
**File**: `examples/stdio-explicit-registration/`
|
**File**: `examples/explicit-registration/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Manual registration of tools, resources, and prompts
|
- Manual registration of tools, resources, and prompts
|
||||||
|
|
@ -111,7 +110,7 @@ $server = Server::builder()
|
||||||
|
|
||||||
### Environment Variables
|
### Environment Variables
|
||||||
|
|
||||||
**File**: `examples/stdio-env-variables/`
|
**File**: `examples/env-variables/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Environment variable integration
|
- Environment variable integration
|
||||||
|
|
@ -125,7 +124,7 @@ $server = Server::builder()
|
||||||
|
|
||||||
### Custom Dependencies
|
### Custom Dependencies
|
||||||
|
|
||||||
**File**: `examples/stdio-custom-dependencies/`
|
**File**: `examples/custom-dependencies/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Dependency injection with PSR-11 containers
|
- Dependency injection with PSR-11 containers
|
||||||
|
|
@ -145,7 +144,7 @@ $server = Server::builder()
|
||||||
|
|
||||||
### Cached Discovery
|
### Cached Discovery
|
||||||
|
|
||||||
**File**: `examples/stdio-cached-discovery/`
|
**File**: `examples/cached-discovery/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Discovery caching for improved performance
|
- Discovery caching for improved performance
|
||||||
|
|
@ -165,7 +164,7 @@ $server = Server::builder()
|
||||||
|
|
||||||
### Client Communication
|
### Client Communication
|
||||||
|
|
||||||
**File**: `examples/stdio-client-communication/`
|
**File**: `examples/client-communication/`
|
||||||
|
|
||||||
**What it demostrates:**
|
**What it demostrates:**
|
||||||
- Server initiated communcation back to the client
|
- Server initiated communcation back to the client
|
||||||
|
|
@ -173,11 +172,9 @@ $server = Server::builder()
|
||||||
- Using `ClientGateway` in service class via `ClientAwareInterface` and corresponding trait
|
- Using `ClientGateway` in service class via `ClientAwareInterface` and corresponding trait
|
||||||
- Using `ClientGateway` in tool method via method argument injection
|
- Using `ClientGateway` in tool method via method argument injection
|
||||||
|
|
||||||
## HTTP Examples
|
|
||||||
|
|
||||||
### Discovery User Profile
|
### Discovery User Profile
|
||||||
|
|
||||||
**File**: `examples/http-discovery-userprofile/`
|
**File**: `examples/discovery-userprofile/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- HTTP transport with StreamableHttpTransport
|
- HTTP transport with StreamableHttpTransport
|
||||||
|
|
@ -205,7 +202,7 @@ public function generateBio(string $userId, string $tone = 'professional'): arra
|
||||||
**Usage:**
|
**Usage:**
|
||||||
```bash
|
```bash
|
||||||
# Start the HTTP server
|
# Start the HTTP server
|
||||||
php -S localhost:8000 examples/http-discovery-userprofile/server.php
|
php -S localhost:8000 examples/discovery-userprofile/server.php
|
||||||
|
|
||||||
# Test with MCP Inspector
|
# Test with MCP Inspector
|
||||||
npx @modelcontextprotocol/inspector http://localhost:8000
|
npx @modelcontextprotocol/inspector http://localhost:8000
|
||||||
|
|
@ -215,7 +212,7 @@ npx @modelcontextprotocol/inspector http://localhost:8000
|
||||||
|
|
||||||
### Combined Registration
|
### Combined Registration
|
||||||
|
|
||||||
**File**: `examples/http-combined-registration/`
|
**File**: `examples/combined-registration/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Mixing attribute discovery with manual registration
|
- Mixing attribute discovery with manual registration
|
||||||
|
|
@ -232,7 +229,7 @@ $server = Server::builder()
|
||||||
|
|
||||||
### Complex Tool Schema
|
### Complex Tool Schema
|
||||||
|
|
||||||
**File**: `examples/http-complex-tool-schema/`
|
**File**: `examples/complex-tool-schema/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Advanced JSON schema definitions
|
- Advanced JSON schema definitions
|
||||||
|
|
@ -255,7 +252,7 @@ public function scheduleEvent(array $eventData): array
|
||||||
|
|
||||||
### Schema Showcase
|
### Schema Showcase
|
||||||
|
|
||||||
**File**: `examples/http-schema-showcase/`
|
**File**: `examples/schema-showcase/`
|
||||||
|
|
||||||
**What it demonstrates:**
|
**What it demonstrates:**
|
||||||
- Comprehensive JSON schema features
|
- Comprehensive JSON schema features
|
||||||
|
|
|
||||||
|
|
@ -3,14 +3,15 @@
|
||||||
This directory contains various examples of how to use the PHP MCP SDK.
|
This directory contains various examples of how to use the PHP MCP SDK.
|
||||||
|
|
||||||
You can run the examples with the dependencies already installed in the root directory of the SDK.
|
You can run the examples with the dependencies already installed in the root directory of the SDK.
|
||||||
|
The bootstrapping of the example will choose the used transport based on the SAPI you use.
|
||||||
|
|
||||||
For running an example, you execute the `server.php` like this:
|
For running an example, you execute the `server.php` like this:
|
||||||
```bash
|
```bash
|
||||||
# For examples using STDIO transport
|
# For using the STDIO transport:
|
||||||
php examples/stdio-discovery-calculator/server.php
|
php examples/discovery-calculator/server.php
|
||||||
|
|
||||||
# For examples using Streamable HTTP transport
|
# For using the Streamable HTTP transport:
|
||||||
php -S localhost:8000 examples/http-discovery-userprofile/server.php
|
php -S localhost:8000 examples/discovery-userprofile/server.php
|
||||||
```
|
```
|
||||||
|
|
||||||
You will see debug outputs to help you understand what is happening.
|
You will see debug outputs to help you understand what is happening.
|
||||||
|
|
@ -18,7 +19,7 @@ You will see debug outputs to help you understand what is happening.
|
||||||
Run with Inspector:
|
Run with Inspector:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npx @modelcontextprotocol/inspector php examples/stdio-discovery-calculator/server.php
|
npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php
|
||||||
```
|
```
|
||||||
|
|
||||||
## Debugging
|
## Debugging
|
||||||
|
|
@ -29,5 +30,5 @@ directory.
|
||||||
|
|
||||||
With the Inspector you can set the environment variables like this:
|
With the Inspector you can set the environment variables like this:
|
||||||
```bash
|
```bash
|
||||||
npx @modelcontextprotocol/inspector -e DEBUG=1 -e FILE_LOG=1 php examples/stdio-discovery-calculator/server.php
|
npx @modelcontextprotocol/inspector -e DEBUG=1 -e FILE_LOG=1 php examples/discovery-calculator/server.php
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,13 @@
|
||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use Http\Discovery\Psr17Factory;
|
||||||
|
use Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
|
||||||
use Mcp\Capability\Registry\Container;
|
use Mcp\Capability\Registry\Container;
|
||||||
|
use Mcp\Server\Transport\StdioTransport;
|
||||||
|
use Mcp\Server\Transport\StreamableHttpTransport;
|
||||||
|
use Mcp\Server\Transport\TransportInterface;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
use Psr\Log\AbstractLogger;
|
use Psr\Log\AbstractLogger;
|
||||||
use Psr\Log\LoggerInterface;
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
|
@ -21,6 +27,31 @@ set_exception_handler(function (Throwable $t): never {
|
||||||
exit(1);
|
exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TransportInterface<int>|TransportInterface<ResponseInterface>
|
||||||
|
*/
|
||||||
|
function transport(): TransportInterface
|
||||||
|
{
|
||||||
|
if ('cli' === \PHP_SAPI) {
|
||||||
|
return new StdioTransport(logger: logger());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new StreamableHttpTransport(
|
||||||
|
(new Psr17Factory())->createServerRequestFromGlobals(),
|
||||||
|
logger: logger(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function shutdown(ResponseInterface|int $result): never
|
||||||
|
{
|
||||||
|
if ('cli' === \PHP_SAPI) {
|
||||||
|
exit($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
(new SapiEmitter())->emit($result);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
function logger(): LoggerInterface
|
function logger(): LoggerInterface
|
||||||
{
|
{
|
||||||
return new class extends AbstractLogger {
|
return new class extends AbstractLogger {
|
||||||
|
|
|
||||||
54
examples/cached-discovery/CachedCalculatorElements.php
Normal file
54
examples/cached-discovery/CachedCalculatorElements.php
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CachedDiscovery;
|
||||||
|
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
use Mcp\Exception\ToolCallException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example MCP elements for demonstrating cached discovery.
|
||||||
|
*
|
||||||
|
* This class contains simple calculator tools that will be discovered
|
||||||
|
* and cached for improved performance on subsequent server starts.
|
||||||
|
*/
|
||||||
|
class CachedCalculatorElements
|
||||||
|
{
|
||||||
|
#[McpTool(name: 'add_numbers')]
|
||||||
|
public function add(int $a, int $b): int
|
||||||
|
{
|
||||||
|
return $a + $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[McpTool(name: 'multiply_numbers')]
|
||||||
|
public function multiply(int $a, int $b): int
|
||||||
|
{
|
||||||
|
return $a * $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[McpTool(name: 'divide_numbers')]
|
||||||
|
public function divide(int $a, int $b): float
|
||||||
|
{
|
||||||
|
if (0 === $b) {
|
||||||
|
throw new ToolCallException('Division by zero is not allowed');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $a / $b;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[McpTool(name: 'power')]
|
||||||
|
public function power(int $base, int $exponent): int
|
||||||
|
{
|
||||||
|
return (int) $base ** $exponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
37
examples/cached-discovery/server.php
Normal file
37
examples/cached-discovery/server.php
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/bootstrap.php';
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
use Mcp\Server;
|
||||||
|
use Mcp\Server\Session\FileSessionStore;
|
||||||
|
use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
|
||||||
|
use Symfony\Component\Cache\Psr16Cache;
|
||||||
|
|
||||||
|
logger()->info('Starting MCP Cached Discovery Calculator Server...');
|
||||||
|
|
||||||
|
$server = Server::builder()
|
||||||
|
->setServerInfo('Cached Discovery Calculator', '1.0.0', 'Calculator with cached discovery for better performance.')
|
||||||
|
->setContainer(container())
|
||||||
|
->setSession(new FileSessionStore(__DIR__.'/sessions'))
|
||||||
|
->setLogger(logger())
|
||||||
|
->setDiscovery(__DIR__, cache: new Psr16Cache(new PhpFilesAdapter(directory: __DIR__.'/cache')))
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$result = $server->run(transport());
|
||||||
|
|
||||||
|
logger()->info('Server listener stopped gracefully.', ['result' => $result]);
|
||||||
|
|
||||||
|
shutdown($result);
|
||||||
71
examples/client-communication/ClientAwareService.php
Normal file
71
examples/client-communication/ClientAwareService.php
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\ClientCommunication;
|
||||||
|
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
use Mcp\Schema\Content\TextContent;
|
||||||
|
use Mcp\Schema\Enum\LoggingLevel;
|
||||||
|
use Mcp\Server\ClientAwareInterface;
|
||||||
|
use Mcp\Server\ClientAwareTrait;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
final class ClientAwareService implements ClientAwareInterface
|
||||||
|
{
|
||||||
|
use ClientAwareTrait;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
$this->logger->info('SamplingTool instantiated for sampling example.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array{incident: string, recommended_actions: string, model: string}
|
||||||
|
*/
|
||||||
|
#[McpTool('coordinate_incident_response', 'Coordinate an incident response with logging, progress, and sampling.')]
|
||||||
|
public function coordinateIncident(string $incidentTitle): array
|
||||||
|
{
|
||||||
|
$this->log(LoggingLevel::Warning, \sprintf('Incident triage started: %s', $incidentTitle));
|
||||||
|
|
||||||
|
$steps = [
|
||||||
|
'Collecting telemetry',
|
||||||
|
'Assessing scope',
|
||||||
|
'Coordinating responders',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($steps as $index => $step) {
|
||||||
|
$progress = ($index + 1) / \count($steps);
|
||||||
|
|
||||||
|
$this->progress($progress, 1, $step);
|
||||||
|
|
||||||
|
usleep(180_000); // Simulate work being done
|
||||||
|
}
|
||||||
|
|
||||||
|
$prompt = \sprintf(
|
||||||
|
'Provide a concise response strategy for incident "%s" based on the steps completed: %s.',
|
||||||
|
$incidentTitle,
|
||||||
|
implode(', ', $steps)
|
||||||
|
);
|
||||||
|
|
||||||
|
$result = $this->sample($prompt, 350, 90, ['temperature' => 0.5]);
|
||||||
|
|
||||||
|
$recommendation = $result->content instanceof TextContent ? trim((string) $result->content->text) : '';
|
||||||
|
|
||||||
|
$this->log(LoggingLevel::Info, \sprintf('Incident triage completed for %s', $incidentTitle));
|
||||||
|
|
||||||
|
return [
|
||||||
|
'incident' => $incidentTitle,
|
||||||
|
'recommended_actions' => $recommendation,
|
||||||
|
'model' => $result->model,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
62
examples/client-communication/server.php
Normal file
62
examples/client-communication/server.php
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/bootstrap.php';
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
use Mcp\Schema\Enum\LoggingLevel;
|
||||||
|
use Mcp\Schema\ServerCapabilities;
|
||||||
|
use Mcp\Server;
|
||||||
|
use Mcp\Server\ClientGateway;
|
||||||
|
use Mcp\Server\Session\FileSessionStore;
|
||||||
|
|
||||||
|
$server = Server::builder()
|
||||||
|
->setServerInfo('Client Communication Demo', '1.0.0')
|
||||||
|
->setLogger(logger())
|
||||||
|
->setContainer(container())
|
||||||
|
->setSession(new FileSessionStore(__DIR__.'/sessions'))
|
||||||
|
->setCapabilities(new ServerCapabilities(logging: true, tools: true))
|
||||||
|
->setDiscovery(__DIR__)
|
||||||
|
->addTool(
|
||||||
|
function (string $dataset, ClientGateway $client): array {
|
||||||
|
$client->log(LoggingLevel::Info, sprintf('Running quality checks on dataset "%s"', $dataset));
|
||||||
|
|
||||||
|
$tasks = [
|
||||||
|
'Validating schema',
|
||||||
|
'Scanning for anomalies',
|
||||||
|
'Reviewing statistical summary',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($tasks as $index => $task) {
|
||||||
|
$progress = ($index + 1) / count($tasks);
|
||||||
|
|
||||||
|
$client->progress(progress: $progress, total: 1, message: $task);
|
||||||
|
|
||||||
|
usleep(140_000); // Simulate work being done
|
||||||
|
}
|
||||||
|
|
||||||
|
$client->log(LoggingLevel::Info, sprintf('Dataset "%s" passed automated checks.', $dataset));
|
||||||
|
|
||||||
|
return [
|
||||||
|
'dataset' => $dataset,
|
||||||
|
'status' => 'passed',
|
||||||
|
'notes' => 'No significant integrity issues detected during automated checks.',
|
||||||
|
];
|
||||||
|
},
|
||||||
|
name: 'run_dataset_quality_checks',
|
||||||
|
description: 'Perform dataset quality checks with progress updates and logging.'
|
||||||
|
)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$result = $server->run(transport());
|
||||||
|
|
||||||
|
shutdown($result);
|
||||||
41
examples/combined-registration/DiscoveredElements.php
Normal file
41
examples/combined-registration/DiscoveredElements.php
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CombinedRegistration;
|
||||||
|
|
||||||
|
use Mcp\Capability\Attribute\McpResource;
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
|
||||||
|
final class DiscoveredElements
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* A tool discovered via attributes.
|
||||||
|
*
|
||||||
|
* @return string a status message
|
||||||
|
*/
|
||||||
|
#[McpTool(name: 'discovered_status_check')]
|
||||||
|
public function checkSystemStatus(): string
|
||||||
|
{
|
||||||
|
return 'System status: OK (discovered)';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A resource discovered via attributes.
|
||||||
|
* This will be overridden by a manual registration with the same URI.
|
||||||
|
*
|
||||||
|
* @return string content
|
||||||
|
*/
|
||||||
|
#[McpResource(uri: 'config://priority', name: 'priority_config_discovered')]
|
||||||
|
public function getPriorityConfigDiscovered(): string
|
||||||
|
{
|
||||||
|
return 'Discovered Priority Config: Low';
|
||||||
|
}
|
||||||
|
}
|
||||||
48
examples/combined-registration/ManualHandlers.php
Normal file
48
examples/combined-registration/ManualHandlers.php
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CombinedRegistration;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
final class ManualHandlers
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A manually registered tool.
|
||||||
|
*
|
||||||
|
* @param string $user the user to greet
|
||||||
|
*
|
||||||
|
* @return string greeting
|
||||||
|
*/
|
||||||
|
public function manualGreeter(string $user): string
|
||||||
|
{
|
||||||
|
$this->logger->info("Manual tool 'manual_greeter' called for {$user}");
|
||||||
|
|
||||||
|
return "Hello {$user}, from manual registration!";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manually registered resource that overrides a discovered one.
|
||||||
|
*
|
||||||
|
* @return string content
|
||||||
|
*/
|
||||||
|
public function getPriorityConfigManual(): string
|
||||||
|
{
|
||||||
|
$this->logger->info("Manual resource 'config://priority' read.");
|
||||||
|
|
||||||
|
return 'Manual Priority Config: HIGH (overrides discovered)';
|
||||||
|
}
|
||||||
|
}
|
||||||
36
examples/combined-registration/server.php
Normal file
36
examples/combined-registration/server.php
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/bootstrap.php';
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
use Mcp\Example\CombinedRegistration\ManualHandlers;
|
||||||
|
use Mcp\Server;
|
||||||
|
use Mcp\Server\Session\FileSessionStore;
|
||||||
|
|
||||||
|
$server = Server::builder()
|
||||||
|
->setServerInfo('Combined HTTP Server', '1.0.0')
|
||||||
|
->setLogger(logger())
|
||||||
|
->setContainer(container())
|
||||||
|
->setSession(new FileSessionStore(__DIR__.'/sessions'))
|
||||||
|
->setDiscovery(__DIR__)
|
||||||
|
->addTool([ManualHandlers::class, 'manualGreeter'])
|
||||||
|
->addResource(
|
||||||
|
[ManualHandlers::class, 'getPriorityConfigManual'],
|
||||||
|
'config://priority',
|
||||||
|
'priority_config_manual',
|
||||||
|
)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$response = $server->run(transport());
|
||||||
|
|
||||||
|
shutdown($response);
|
||||||
72
examples/complex-tool-schema/McpEventScheduler.php
Normal file
72
examples/complex-tool-schema/McpEventScheduler.php
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\ComplexToolSchema;
|
||||||
|
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
use Mcp\Example\ComplexToolSchema\Model\EventPriority;
|
||||||
|
use Mcp\Example\ComplexToolSchema\Model\EventType;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
final class McpEventScheduler
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedules a new event.
|
||||||
|
* The inputSchema for this tool will reflect all parameter types and defaults.
|
||||||
|
*
|
||||||
|
* @param string $title the title of the event
|
||||||
|
* @param string $date the date of the event (YYYY-MM-DD)
|
||||||
|
* @param EventType $type the type of event
|
||||||
|
* @param string|null $time the time of the event (HH:MM), optional
|
||||||
|
* @param EventPriority $priority The priority of the event. Defaults to Normal.
|
||||||
|
* @param string[]|null $attendees an optional list of attendee email addresses
|
||||||
|
* @param bool $sendInvites send calendar invites to attendees? Defaults to true if attendees are provided
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> confirmation of the scheduled event
|
||||||
|
*/
|
||||||
|
#[McpTool(name: 'schedule_event')]
|
||||||
|
public function scheduleEvent(
|
||||||
|
string $title,
|
||||||
|
string $date,
|
||||||
|
EventType $type,
|
||||||
|
?string $time = null,
|
||||||
|
EventPriority $priority = EventPriority::Normal,
|
||||||
|
?array $attendees = null,
|
||||||
|
bool $sendInvites = true,
|
||||||
|
): array {
|
||||||
|
$this->logger->info("Tool 'schedule_event' called", compact('title', 'date', 'type', 'time', 'priority', 'attendees', 'sendInvites'));
|
||||||
|
|
||||||
|
// Simulate scheduling logic
|
||||||
|
$eventDetails = [
|
||||||
|
'title' => $title,
|
||||||
|
'date' => $date,
|
||||||
|
'type' => $type->value, // Use enum value
|
||||||
|
'time' => $time ?? 'All day',
|
||||||
|
'priority' => $priority->name, // Use enum name
|
||||||
|
'attendees' => $attendees ?? [],
|
||||||
|
'invites_will_be_sent' => ($attendees && $sendInvites),
|
||||||
|
];
|
||||||
|
|
||||||
|
// In a real app, this would interact with a calendar service
|
||||||
|
$this->logger->info('Event scheduled', ['details' => $eventDetails]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'success' => true,
|
||||||
|
'message' => \sprintf('Event "%s" scheduled successfully for "%s".', $title, $date),
|
||||||
|
'event_details' => $eventDetails,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/complex-tool-schema/Model/EventPriority.php
Normal file
19
examples/complex-tool-schema/Model/EventPriority.php
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\ComplexToolSchema\Model;
|
||||||
|
|
||||||
|
enum EventPriority: int
|
||||||
|
{
|
||||||
|
case Low = 0;
|
||||||
|
case Normal = 1;
|
||||||
|
case High = 2;
|
||||||
|
}
|
||||||
20
examples/complex-tool-schema/Model/EventType.php
Normal file
20
examples/complex-tool-schema/Model/EventType.php
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\ComplexToolSchema\Model;
|
||||||
|
|
||||||
|
enum EventType: string
|
||||||
|
{
|
||||||
|
case Meeting = 'meeting';
|
||||||
|
case Reminder = 'reminder';
|
||||||
|
case Call = 'call';
|
||||||
|
case Other = 'other';
|
||||||
|
}
|
||||||
29
examples/complex-tool-schema/server.php
Normal file
29
examples/complex-tool-schema/server.php
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/usr/bin/env php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once dirname(__DIR__).'/bootstrap.php';
|
||||||
|
chdir(__DIR__);
|
||||||
|
|
||||||
|
use Mcp\Server;
|
||||||
|
use Mcp\Server\Session\FileSessionStore;
|
||||||
|
|
||||||
|
$server = Server::builder()
|
||||||
|
->setServerInfo('Event Scheduler Server', '1.0.0')
|
||||||
|
->setLogger(logger())
|
||||||
|
->setContainer(container())
|
||||||
|
->setSession(new FileSessionStore(__DIR__.'/sessions'))
|
||||||
|
->setDiscovery(__DIR__)
|
||||||
|
->build();
|
||||||
|
|
||||||
|
$response = $server->run(transport());
|
||||||
|
|
||||||
|
shutdown($response);
|
||||||
92
examples/custom-dependencies/McpTaskHandlers.php
Normal file
92
examples/custom-dependencies/McpTaskHandlers.php
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CustomDependencies;
|
||||||
|
|
||||||
|
use Mcp\Capability\Attribute\McpResource;
|
||||||
|
use Mcp\Capability\Attribute\McpTool;
|
||||||
|
use Mcp\Example\CustomDependencies\Service\StatsServiceInterface;
|
||||||
|
use Mcp\Example\CustomDependencies\Service\TaskRepositoryInterface;
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-import-type Task from TaskRepositoryInterface
|
||||||
|
*/
|
||||||
|
final class McpTaskHandlers
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly TaskRepositoryInterface $taskRepo,
|
||||||
|
private readonly StatsServiceInterface $statsService,
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
$this->logger->info('McpTaskHandlers instantiated with dependencies.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new task for a given user.
|
||||||
|
*
|
||||||
|
* @param string $userId the ID of the user
|
||||||
|
* @param string $description the task description
|
||||||
|
*
|
||||||
|
* @return Task the created task details
|
||||||
|
*/
|
||||||
|
#[McpTool(name: 'add_task')]
|
||||||
|
public function addTask(string $userId, string $description): array
|
||||||
|
{
|
||||||
|
$this->logger->info("Tool 'add_task' invoked", ['userId' => $userId]);
|
||||||
|
|
||||||
|
return $this->taskRepo->addTask($userId, $description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists pending tasks for a specific user.
|
||||||
|
*
|
||||||
|
* @param string $userId the ID of the user
|
||||||
|
*
|
||||||
|
* @return Task[] a list of tasks
|
||||||
|
*/
|
||||||
|
#[McpTool(name: 'list_user_tasks')]
|
||||||
|
public function listUserTasks(string $userId): array
|
||||||
|
{
|
||||||
|
$this->logger->info("Tool 'list_user_tasks' invoked", ['userId' => $userId]);
|
||||||
|
|
||||||
|
return $this->taskRepo->getTasksForUser($userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a task as complete.
|
||||||
|
*
|
||||||
|
* @param int $taskId the ID of the task to complete
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> status of the operation
|
||||||
|
*/
|
||||||
|
#[McpTool(name: 'complete_task')]
|
||||||
|
public function completeTask(int $taskId): array
|
||||||
|
{
|
||||||
|
$this->logger->info("Tool 'complete_task' invoked", ['taskId' => $taskId]);
|
||||||
|
$success = $this->taskRepo->completeTask($taskId);
|
||||||
|
|
||||||
|
return ['success' => $success, 'message' => $success ? "Task {$taskId} completed." : "Task {$taskId} not found."];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides current system statistics.
|
||||||
|
*
|
||||||
|
* @return array<string, int> system statistics
|
||||||
|
*/
|
||||||
|
#[McpResource(uri: 'stats://system/overview', name: 'system_stats', mimeType: 'application/json')]
|
||||||
|
public function getSystemStatistics(): array
|
||||||
|
{
|
||||||
|
$this->logger->info("Resource 'stats://system/overview' invoked");
|
||||||
|
|
||||||
|
return $this->statsService->getSystemStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CustomDependencies\Service;
|
||||||
|
|
||||||
|
use Psr\Log\LoggerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-import-type Task from TaskRepositoryInterface
|
||||||
|
*/
|
||||||
|
final class InMemoryTaskRepository implements TaskRepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var array<int, Task>
|
||||||
|
*/
|
||||||
|
private array $tasks = [];
|
||||||
|
private int $nextTaskId = 1;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
private readonly LoggerInterface $logger,
|
||||||
|
) {
|
||||||
|
// Add some initial tasks
|
||||||
|
$this->addTask('user1', 'Buy groceries');
|
||||||
|
$this->addTask('user1', 'Write MCP example');
|
||||||
|
$this->addTask('user2', 'Review PR');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addTask(string $userId, string $description): array
|
||||||
|
{
|
||||||
|
$task = [
|
||||||
|
'id' => $this->nextTaskId++,
|
||||||
|
'userId' => $userId,
|
||||||
|
'description' => $description,
|
||||||
|
'completed' => false,
|
||||||
|
'createdAt' => date('c'),
|
||||||
|
];
|
||||||
|
$this->tasks[$task['id']] = $task;
|
||||||
|
$this->logger->info('Task added', ['id' => $task['id'], 'user' => $userId]);
|
||||||
|
|
||||||
|
return $task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTasksForUser(string $userId): array
|
||||||
|
{
|
||||||
|
return array_values(array_filter($this->tasks, fn ($task) => $task['userId'] === $userId && !$task['completed']));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAllTasks(): array
|
||||||
|
{
|
||||||
|
return array_values($this->tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function completeTask(int $taskId): bool
|
||||||
|
{
|
||||||
|
if (isset($this->tasks[$taskId])) {
|
||||||
|
$this->tasks[$taskId]['completed'] = true;
|
||||||
|
$this->logger->info('Task completed', ['id' => $taskId]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CustomDependencies\Service;
|
||||||
|
|
||||||
|
interface StatsServiceInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<string, int>
|
||||||
|
*/
|
||||||
|
public function getSystemStats(): array;
|
||||||
|
}
|
||||||
34
examples/custom-dependencies/Service/SystemStatsService.php
Normal file
34
examples/custom-dependencies/Service/SystemStatsService.php
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CustomDependencies\Service;
|
||||||
|
|
||||||
|
final class SystemStatsService implements StatsServiceInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly TaskRepositoryInterface $taskRepository,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSystemStats(): array
|
||||||
|
{
|
||||||
|
$allTasks = $this->taskRepository->getAllTasks();
|
||||||
|
$completed = \count(array_filter($allTasks, fn ($task) => $task['completed']));
|
||||||
|
$pending = \count($allTasks) - $completed;
|
||||||
|
|
||||||
|
return [
|
||||||
|
'total_tasks' => \count($allTasks),
|
||||||
|
'completed_tasks' => $completed,
|
||||||
|
'pending_tasks' => $pending,
|
||||||
|
'server_uptime_seconds' => time() - $_SERVER['REQUEST_TIME_FLOAT'], // Approx uptime for CLI script
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the official PHP MCP SDK.
|
||||||
|
*
|
||||||
|
* A collaboration between Symfony and the PHP Foundation.
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Mcp\Example\CustomDependencies\Service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @phpstan-type Task array{id: int, userId: string, description: string, completed: bool, createdAt: string}
|
||||||
|
*/
|
||||||
|
interface TaskRepositoryInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return Task
|
||||||
|
*/
|
||||||
|
public function addTask(string $userId, string $description): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Task[]
|
||||||
|
*/
|
||||||
|
public function getTasksForUser(string $userId): array;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Task[]
|
||||||
|
*/
|
||||||
|
public function getAllTasks(): array;
|
||||||
|
|
||||||
|
public function completeTask(int $taskId): bool;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue