diff --git a/composer.json b/composer.json index 30a94724..7f25eee7 100644 --- a/composer.json +++ b/composer.json @@ -52,17 +52,17 @@ }, "autoload-dev": { "psr-4": { - "Mcp\\Example\\HttpCombinedRegistration\\": "examples/http-combined-registration/", - "Mcp\\Example\\HttpComplexToolSchema\\": "examples/http-complex-tool-schema/", - "Mcp\\Example\\HttpDiscoveryUserProfile\\": "examples/http-discovery-userprofile/", - "Mcp\\Example\\HttpSchemaShowcase\\": "examples/http-schema-showcase/", - "Mcp\\Example\\StdioCachedDiscovery\\": "examples/stdio-cached-discovery/", - "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\\CachedDiscovery\\": "examples/cached-discovery/", + "Mcp\\Example\\ClientCommunication\\": "examples/client-communication/", + "Mcp\\Example\\CombinedRegistration\\": "examples/combined-registration/", + "Mcp\\Example\\ComplexToolSchema\\": "examples/complex-tool-schema/", + "Mcp\\Example\\CustomDependencies\\": "examples/custom-dependencies/", "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/" } }, diff --git a/docs/examples.md b/docs/examples.md index a242b9a8..e004636e 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -7,10 +7,7 @@ specific features and can be run independently to understand how the SDK works. - [Getting Started](#getting-started) - [Running Examples](#running-examples) -- [STDIO Examples](#stdio-examples) -- [HTTP Examples](#http-examples) -- [Advanced Patterns](#advanced-patterns) -- [Testing and Debugging](#testing-and-debugging) +- [Examples](#examples) ## Getting Started @@ -26,28 +23,30 @@ composer install ## 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 # 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 -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 -# 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 # 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 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":{}}}' ``` -## STDIO Examples +## Examples ### Discovery Calculator -**File**: `examples/stdio-discovery-calculator/` +**File**: `examples/discovery-calculator/` **What it demonstrates:** - Attribute-based discovery using `#[McpTool]` and `#[McpResource]` @@ -87,14 +86,14 @@ public function getConfiguration(): array **Usage:** ```bash # 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 -**File**: `examples/stdio-explicit-registration/` +**File**: `examples/explicit-registration/` **What it demonstrates:** - Manual registration of tools, resources, and prompts @@ -111,7 +110,7 @@ $server = Server::builder() ### Environment Variables -**File**: `examples/stdio-env-variables/` +**File**: `examples/env-variables/` **What it demonstrates:** - Environment variable integration @@ -125,7 +124,7 @@ $server = Server::builder() ### Custom Dependencies -**File**: `examples/stdio-custom-dependencies/` +**File**: `examples/custom-dependencies/` **What it demonstrates:** - Dependency injection with PSR-11 containers @@ -145,7 +144,7 @@ $server = Server::builder() ### Cached Discovery -**File**: `examples/stdio-cached-discovery/` +**File**: `examples/cached-discovery/` **What it demonstrates:** - Discovery caching for improved performance @@ -165,7 +164,7 @@ $server = Server::builder() ### Client Communication -**File**: `examples/stdio-client-communication/` +**File**: `examples/client-communication/` **What it demostrates:** - 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 tool method via method argument injection -## HTTP Examples - ### Discovery User Profile -**File**: `examples/http-discovery-userprofile/` +**File**: `examples/discovery-userprofile/` **What it demonstrates:** - HTTP transport with StreamableHttpTransport @@ -205,7 +202,7 @@ public function generateBio(string $userId, string $tone = 'professional'): arra **Usage:** ```bash # 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 npx @modelcontextprotocol/inspector http://localhost:8000 @@ -215,7 +212,7 @@ npx @modelcontextprotocol/inspector http://localhost:8000 ### Combined Registration -**File**: `examples/http-combined-registration/` +**File**: `examples/combined-registration/` **What it demonstrates:** - Mixing attribute discovery with manual registration @@ -232,7 +229,7 @@ $server = Server::builder() ### Complex Tool Schema -**File**: `examples/http-complex-tool-schema/` +**File**: `examples/complex-tool-schema/` **What it demonstrates:** - Advanced JSON schema definitions @@ -255,7 +252,7 @@ public function scheduleEvent(array $eventData): array ### Schema Showcase -**File**: `examples/http-schema-showcase/` +**File**: `examples/schema-showcase/` **What it demonstrates:** - Comprehensive JSON schema features diff --git a/examples/README.md b/examples/README.md index 96b8773b..27874d71 100644 --- a/examples/README.md +++ b/examples/README.md @@ -3,14 +3,15 @@ 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. +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: ```bash -# For examples using STDIO transport -php examples/stdio-discovery-calculator/server.php +# For using the STDIO transport: +php examples/discovery-calculator/server.php -# For examples using Streamable HTTP transport -php -S localhost:8000 examples/http-discovery-userprofile/server.php +# For using the Streamable HTTP transport: +php -S localhost:8000 examples/discovery-userprofile/server.php ``` 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: ```bash -npx @modelcontextprotocol/inspector php examples/stdio-discovery-calculator/server.php +npx @modelcontextprotocol/inspector php examples/discovery-calculator/server.php ``` ## Debugging @@ -29,5 +30,5 @@ directory. With the Inspector you can set the environment variables like this: ```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 ``` diff --git a/examples/bootstrap.php b/examples/bootstrap.php index e4a4b98d..8c0508ab 100644 --- a/examples/bootstrap.php +++ b/examples/bootstrap.php @@ -9,7 +9,13 @@ * file that was distributed with this source code. */ +use Http\Discovery\Psr17Factory; +use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; 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\LoggerInterface; @@ -21,6 +27,31 @@ exit(1); }); +/** + * @return TransportInterface|TransportInterface + */ +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 { return new class extends AbstractLogger { diff --git a/examples/stdio-cached-discovery/CachedCalculatorElements.php b/examples/cached-discovery/CachedCalculatorElements.php similarity index 96% rename from examples/stdio-cached-discovery/CachedCalculatorElements.php rename to examples/cached-discovery/CachedCalculatorElements.php index 1da3d277..ef67b0ff 100644 --- a/examples/stdio-cached-discovery/CachedCalculatorElements.php +++ b/examples/cached-discovery/CachedCalculatorElements.php @@ -11,7 +11,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCachedDiscovery; +namespace Mcp\Example\CachedDiscovery; use Mcp\Capability\Attribute\McpTool; use Mcp\Exception\ToolCallException; diff --git a/examples/stdio-cached-discovery/server.php b/examples/cached-discovery/server.php similarity index 85% rename from examples/stdio-cached-discovery/server.php rename to examples/cached-discovery/server.php index 38b5e9ce..1d6c1e16 100644 --- a/examples/stdio-cached-discovery/server.php +++ b/examples/cached-discovery/server.php @@ -16,7 +16,7 @@ chdir(__DIR__); use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; +use Mcp\Server\Session\FileSessionStore; use Symfony\Component\Cache\Adapter\PhpFilesAdapter; use Symfony\Component\Cache\Psr16Cache; @@ -25,14 +25,13 @@ $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(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/stdio-client-communication/ClientAwareService.php b/examples/client-communication/ClientAwareService.php similarity index 97% rename from examples/stdio-client-communication/ClientAwareService.php rename to examples/client-communication/ClientAwareService.php index ebb797aa..3733614e 100644 --- a/examples/stdio-client-communication/ClientAwareService.php +++ b/examples/client-communication/ClientAwareService.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioClientCommunication; +namespace Mcp\Example\ClientCommunication; use Mcp\Capability\Attribute\McpTool; use Mcp\Schema\Content\TextContent; diff --git a/examples/stdio-client-communication/server.php b/examples/client-communication/server.php similarity index 89% rename from examples/stdio-client-communication/server.php rename to examples/client-communication/server.php index 596da5ad..7d586bad 100644 --- a/examples/stdio-client-communication/server.php +++ b/examples/client-communication/server.php @@ -17,12 +17,13 @@ use Mcp\Schema\ServerCapabilities; use Mcp\Server; use Mcp\Server\ClientGateway; -use Mcp\Server\Transport\StdioTransport; +use Mcp\Server\Session\FileSessionStore; $server = Server::builder() - ->setServerInfo('STDIO Client Communication Demo', '1.0.0') + ->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( @@ -56,8 +57,6 @@ function (string $dataset, ClientGateway $client): array { ) ->build(); -$transport = new StdioTransport(); +$result = $server->run(transport()); -$status = $server->run($transport); - -exit($status); +shutdown($result); diff --git a/examples/http-combined-registration/DiscoveredElements.php b/examples/combined-registration/DiscoveredElements.php similarity index 95% rename from examples/http-combined-registration/DiscoveredElements.php rename to examples/combined-registration/DiscoveredElements.php index 7d030679..f7142466 100644 --- a/examples/http-combined-registration/DiscoveredElements.php +++ b/examples/combined-registration/DiscoveredElements.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpCombinedRegistration; +namespace Mcp\Example\CombinedRegistration; use Mcp\Capability\Attribute\McpResource; use Mcp\Capability\Attribute\McpTool; diff --git a/examples/http-combined-registration/ManualHandlers.php b/examples/combined-registration/ManualHandlers.php similarity index 95% rename from examples/http-combined-registration/ManualHandlers.php rename to examples/combined-registration/ManualHandlers.php index 21f86e9d..65a86bc6 100644 --- a/examples/http-combined-registration/ManualHandlers.php +++ b/examples/combined-registration/ManualHandlers.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpCombinedRegistration; +namespace Mcp\Example\CombinedRegistration; use Psr\Log\LoggerInterface; diff --git a/examples/http-combined-registration/server.php b/examples/combined-registration/server.php similarity index 67% rename from examples/http-combined-registration/server.php rename to examples/combined-registration/server.php index 2c3184a6..02f26a4e 100644 --- a/examples/http-combined-registration/server.php +++ b/examples/combined-registration/server.php @@ -13,15 +13,9 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Http\Discovery\Psr17Factory; -use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; -use Mcp\Example\HttpCombinedRegistration\ManualHandlers; +use Mcp\Example\CombinedRegistration\ManualHandlers; use Mcp\Server; use Mcp\Server\Session\FileSessionStore; -use Mcp\Server\Transport\StreamableHttpTransport; - -$psr17Factory = new Psr17Factory(); -$request = $psr17Factory->createServerRequestFromGlobals(); $server = Server::builder() ->setServerInfo('Combined HTTP Server', '1.0.0') @@ -37,8 +31,6 @@ ) ->build(); -$transport = new StreamableHttpTransport($request); - -$response = $server->run($transport); +$response = $server->run(transport()); -(new SapiEmitter())->emit($response); +shutdown($response); diff --git a/examples/http-complex-tool-schema/McpEventScheduler.php b/examples/complex-tool-schema/McpEventScheduler.php similarity index 93% rename from examples/http-complex-tool-schema/McpEventScheduler.php rename to examples/complex-tool-schema/McpEventScheduler.php index a9b3edc7..253ff5cb 100644 --- a/examples/http-complex-tool-schema/McpEventScheduler.php +++ b/examples/complex-tool-schema/McpEventScheduler.php @@ -9,11 +9,11 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpComplexToolSchema; +namespace Mcp\Example\ComplexToolSchema; use Mcp\Capability\Attribute\McpTool; -use Mcp\Example\HttpComplexToolSchema\Model\EventPriority; -use Mcp\Example\HttpComplexToolSchema\Model\EventType; +use Mcp\Example\ComplexToolSchema\Model\EventPriority; +use Mcp\Example\ComplexToolSchema\Model\EventType; use Psr\Log\LoggerInterface; final class McpEventScheduler diff --git a/examples/http-complex-tool-schema/Model/EventPriority.php b/examples/complex-tool-schema/Model/EventPriority.php similarity index 87% rename from examples/http-complex-tool-schema/Model/EventPriority.php rename to examples/complex-tool-schema/Model/EventPriority.php index 1654be0e..e46a69da 100644 --- a/examples/http-complex-tool-schema/Model/EventPriority.php +++ b/examples/complex-tool-schema/Model/EventPriority.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpComplexToolSchema\Model; +namespace Mcp\Example\ComplexToolSchema\Model; enum EventPriority: int { diff --git a/examples/http-complex-tool-schema/Model/EventType.php b/examples/complex-tool-schema/Model/EventType.php similarity index 88% rename from examples/http-complex-tool-schema/Model/EventType.php rename to examples/complex-tool-schema/Model/EventType.php index 5711662d..eaf0f431 100644 --- a/examples/http-complex-tool-schema/Model/EventType.php +++ b/examples/complex-tool-schema/Model/EventType.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpComplexToolSchema\Model; +namespace Mcp\Example\ComplexToolSchema\Model; enum EventType: string { diff --git a/examples/http-complex-tool-schema/server.php b/examples/complex-tool-schema/server.php similarity index 64% rename from examples/http-complex-tool-schema/server.php rename to examples/complex-tool-schema/server.php index b6d29378..92f80b61 100644 --- a/examples/http-complex-tool-schema/server.php +++ b/examples/complex-tool-schema/server.php @@ -13,14 +13,8 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Http\Discovery\Psr17Factory; -use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Mcp\Server; use Mcp\Server\Session\FileSessionStore; -use Mcp\Server\Transport\StreamableHttpTransport; - -$psr17Factory = new Psr17Factory(); -$request = $psr17Factory->createServerRequestFromGlobals(); $server = Server::builder() ->setServerInfo('Event Scheduler Server', '1.0.0') @@ -30,8 +24,6 @@ ->setDiscovery(__DIR__) ->build(); -$transport = new StreamableHttpTransport($request); - -$response = $server->run($transport); +$response = $server->run(transport()); -(new SapiEmitter())->emit($response); +shutdown($response); diff --git a/examples/stdio-custom-dependencies/McpTaskHandlers.php b/examples/custom-dependencies/McpTaskHandlers.php similarity index 93% rename from examples/stdio-custom-dependencies/McpTaskHandlers.php rename to examples/custom-dependencies/McpTaskHandlers.php index 65d2f003..00127a78 100644 --- a/examples/stdio-custom-dependencies/McpTaskHandlers.php +++ b/examples/custom-dependencies/McpTaskHandlers.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCustomDependencies; +namespace Mcp\Example\CustomDependencies; use Mcp\Capability\Attribute\McpResource; use Mcp\Capability\Attribute\McpTool; -use Mcp\Example\StdioCustomDependencies\Service\StatsServiceInterface; -use Mcp\Example\StdioCustomDependencies\Service\TaskRepositoryInterface; +use Mcp\Example\CustomDependencies\Service\StatsServiceInterface; +use Mcp\Example\CustomDependencies\Service\TaskRepositoryInterface; use Psr\Log\LoggerInterface; /** diff --git a/examples/stdio-custom-dependencies/Service/InMemoryTaskRepository.php b/examples/custom-dependencies/Service/InMemoryTaskRepository.php similarity index 97% rename from examples/stdio-custom-dependencies/Service/InMemoryTaskRepository.php rename to examples/custom-dependencies/Service/InMemoryTaskRepository.php index 63ce8611..dbf3b6ab 100644 --- a/examples/stdio-custom-dependencies/Service/InMemoryTaskRepository.php +++ b/examples/custom-dependencies/Service/InMemoryTaskRepository.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCustomDependencies\Service; +namespace Mcp\Example\CustomDependencies\Service; use Psr\Log\LoggerInterface; diff --git a/examples/stdio-custom-dependencies/Service/StatsServiceInterface.php b/examples/custom-dependencies/Service/StatsServiceInterface.php similarity index 87% rename from examples/stdio-custom-dependencies/Service/StatsServiceInterface.php rename to examples/custom-dependencies/Service/StatsServiceInterface.php index a7e8b276..079f7e23 100644 --- a/examples/stdio-custom-dependencies/Service/StatsServiceInterface.php +++ b/examples/custom-dependencies/Service/StatsServiceInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCustomDependencies\Service; +namespace Mcp\Example\CustomDependencies\Service; interface StatsServiceInterface { diff --git a/examples/stdio-custom-dependencies/Service/SystemStatsService.php b/examples/custom-dependencies/Service/SystemStatsService.php similarity index 94% rename from examples/stdio-custom-dependencies/Service/SystemStatsService.php rename to examples/custom-dependencies/Service/SystemStatsService.php index 5a766792..5cd44880 100644 --- a/examples/stdio-custom-dependencies/Service/SystemStatsService.php +++ b/examples/custom-dependencies/Service/SystemStatsService.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCustomDependencies\Service; +namespace Mcp\Example\CustomDependencies\Service; final class SystemStatsService implements StatsServiceInterface { diff --git a/examples/stdio-custom-dependencies/Service/TaskRepositoryInterface.php b/examples/custom-dependencies/Service/TaskRepositoryInterface.php similarity index 93% rename from examples/stdio-custom-dependencies/Service/TaskRepositoryInterface.php rename to examples/custom-dependencies/Service/TaskRepositoryInterface.php index 6c091be1..7216634c 100644 --- a/examples/stdio-custom-dependencies/Service/TaskRepositoryInterface.php +++ b/examples/custom-dependencies/Service/TaskRepositoryInterface.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioCustomDependencies\Service; +namespace Mcp\Example\CustomDependencies\Service; /** * @phpstan-type Task array{id: int, userId: string, description: string, completed: bool, createdAt: string} diff --git a/examples/stdio-custom-dependencies/server.php b/examples/custom-dependencies/server.php similarity index 63% rename from examples/stdio-custom-dependencies/server.php rename to examples/custom-dependencies/server.php index 4ebd4cbd..cd450e51 100644 --- a/examples/stdio-custom-dependencies/server.php +++ b/examples/custom-dependencies/server.php @@ -13,14 +13,14 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Mcp\Example\StdioCustomDependencies\Service\InMemoryTaskRepository; -use Mcp\Example\StdioCustomDependencies\Service\StatsServiceInterface; -use Mcp\Example\StdioCustomDependencies\Service\SystemStatsService; -use Mcp\Example\StdioCustomDependencies\Service\TaskRepositoryInterface; +use Mcp\Example\CustomDependencies\Service\InMemoryTaskRepository; +use Mcp\Example\CustomDependencies\Service\StatsServiceInterface; +use Mcp\Example\CustomDependencies\Service\SystemStatsService; +use Mcp\Example\CustomDependencies\Service\TaskRepositoryInterface; use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; +use Mcp\Server\Session\FileSessionStore; -logger()->info('Starting MCP Custom Dependencies (Stdio) Server...'); +logger()->info('Starting MCP Custom Dependencies Server...'); $container = container(); @@ -32,15 +32,14 @@ $server = Server::builder() ->setServerInfo('Task Manager Server', '1.0.0') - ->setLogger(logger()) ->setContainer($container) + ->setSession(new FileSessionStore(__DIR__.'/sessions')) + ->setLogger(logger()) ->setDiscovery(__DIR__) ->build(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/custom-method-handlers/server.php b/examples/custom-method-handlers/server.php index 7554a0a7..62f41df9 100644 --- a/examples/custom-method-handlers/server.php +++ b/examples/custom-method-handlers/server.php @@ -18,9 +18,9 @@ use Mcp\Schema\ServerCapabilities; use Mcp\Schema\Tool; use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; +use Mcp\Server\Session\FileSessionStore; -logger()->info('Starting MCP Custom Method Handlers (Stdio) Server...'); +logger()->info('Starting MCP Custom Method Handlers Server...'); $toolDefinitions = [ 'say_hello' => new Tool( @@ -56,16 +56,15 @@ $server = Server::builder() ->setServerInfo('Custom Handlers Server', '1.0.0') - ->setLogger(logger()) ->setContainer(container()) + ->setSession(new FileSessionStore(__DIR__.'/sessions')) + ->setLogger(logger()) ->setCapabilities($capabilities) ->addRequestHandlers([$listToolsHandler, $callToolHandler]) ->build(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/stdio-discovery-calculator/McpElements.php b/examples/discovery-calculator/McpElements.php similarity index 99% rename from examples/stdio-discovery-calculator/McpElements.php rename to examples/discovery-calculator/McpElements.php index 21330313..6276de57 100644 --- a/examples/stdio-discovery-calculator/McpElements.php +++ b/examples/discovery-calculator/McpElements.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioDiscoveryCalculator; +namespace Mcp\Example\DiscoveryCalculator; use Mcp\Capability\Attribute\McpResource; use Mcp\Capability\Attribute\McpTool; diff --git a/examples/stdio-discovery-calculator/server.php b/examples/discovery-calculator/server.php similarity index 71% rename from examples/stdio-discovery-calculator/server.php rename to examples/discovery-calculator/server.php index 3f113489..c6d75e4d 100644 --- a/examples/stdio-discovery-calculator/server.php +++ b/examples/discovery-calculator/server.php @@ -14,22 +14,21 @@ chdir(__DIR__); use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; +use Mcp\Server\Session\FileSessionStore; -logger()->info('Starting MCP Stdio Calculator Server...'); +logger()->info('Starting MCP Calculator Server...'); $server = Server::builder() - ->setServerInfo('Stdio Calculator', '1.1.0', 'Basic Calculator over STDIO transport.') + ->setServerInfo('Calculator', '1.1.0', 'Basic Calculator') ->setInstructions('This server supports basic arithmetic operations: add, subtract, multiply, and divide. Send JSON-RPC requests to perform calculations.') ->setContainer(container()) + ->setSession(new FileSessionStore(__DIR__.'/sessions')) ->setLogger(logger()) ->setDiscovery(__DIR__) ->build(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/http-discovery-userprofile/McpElements.php b/examples/discovery-userprofile/McpElements.php similarity index 97% rename from examples/http-discovery-userprofile/McpElements.php rename to examples/discovery-userprofile/McpElements.php index 933bd51e..8418f09a 100644 --- a/examples/http-discovery-userprofile/McpElements.php +++ b/examples/discovery-userprofile/McpElements.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpDiscoveryUserProfile; +namespace Mcp\Example\DiscoveryUserProfile; use Mcp\Capability\Attribute\CompletionProvider; use Mcp\Capability\Attribute\McpPrompt; @@ -39,7 +39,7 @@ final class McpElements public function __construct( private readonly LoggerInterface $logger, ) { - $this->logger->debug('HttpDiscoveryUserProfile McpElements instantiated.'); + $this->logger->debug('DiscoveryUserProfile McpElements instantiated.'); } /** diff --git a/examples/http-discovery-userprofile/UserIdCompletionProvider.php b/examples/discovery-userprofile/UserIdCompletionProvider.php similarity index 92% rename from examples/http-discovery-userprofile/UserIdCompletionProvider.php rename to examples/discovery-userprofile/UserIdCompletionProvider.php index 37b1c5b7..69dfe4f0 100644 --- a/examples/http-discovery-userprofile/UserIdCompletionProvider.php +++ b/examples/discovery-userprofile/UserIdCompletionProvider.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpDiscoveryUserProfile; +namespace Mcp\Example\DiscoveryUserProfile; use Mcp\Capability\Completion\ProviderInterface; diff --git a/examples/http-discovery-userprofile/server.php b/examples/discovery-userprofile/server.php similarity index 86% rename from examples/http-discovery-userprofile/server.php rename to examples/discovery-userprofile/server.php index c958bfb9..48033716 100644 --- a/examples/http-discovery-userprofile/server.php +++ b/examples/discovery-userprofile/server.php @@ -13,14 +13,8 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Http\Discovery\Psr17Factory; -use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Mcp\Server; use Mcp\Server\Session\FileSessionStore; -use Mcp\Server\Transport\StreamableHttpTransport; - -$psr17Factory = new Psr17Factory(); -$request = $psr17Factory->createServerRequestFromGlobals(); $server = Server::builder() ->setServerInfo('HTTP User Profiles', '1.0.0') @@ -72,8 +66,6 @@ function (): array { ) ->build(); -$transport = new StreamableHttpTransport($request); - -$response = $server->run($transport); +$response = $server->run(transport()); -(new SapiEmitter())->emit($response); +shutdown($response); diff --git a/examples/stdio-env-variables/EnvToolHandler.php b/examples/env-variables/EnvToolHandler.php similarity index 97% rename from examples/stdio-env-variables/EnvToolHandler.php rename to examples/env-variables/EnvToolHandler.php index 49c914d5..f7cad817 100644 --- a/examples/stdio-env-variables/EnvToolHandler.php +++ b/examples/env-variables/EnvToolHandler.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioEnvVariables; +namespace Mcp\Example\EnvVariables; use Mcp\Capability\Attribute\McpTool; diff --git a/examples/stdio-env-variables/server.php b/examples/env-variables/server.php similarity index 81% rename from examples/stdio-env-variables/server.php rename to examples/env-variables/server.php index 13c36bcf..48c43825 100644 --- a/examples/stdio-env-variables/server.php +++ b/examples/env-variables/server.php @@ -14,18 +14,17 @@ chdir(__DIR__); use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; /* |-------------------------------------------------------------------------- - | MCP Stdio Environment Variable Example Server + | MCP Environment Variable Example Server |-------------------------------------------------------------------------- | | This server demonstrates how to use environment variables to modify tool | behavior. The MCP client can set the APP_MODE environment variable to | control the server's behavior. | - | Configure your MCP Client (eg. Cursor) for this server like this: + | Configure your MCP Client (e.g. Cursor) for this server like this: | | { | "mcpServers": { @@ -47,7 +46,7 @@ | */ -logger()->info('Starting MCP Stdio Environment Variable Example Server...'); +logger()->info('Starting MCP Environment Variable Example Server...'); $server = Server::builder() ->setServerInfo('Env Var Server', '1.0.0') @@ -55,10 +54,8 @@ ->setDiscovery(__DIR__) ->build(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/stdio-explicit-registration/SimpleHandlers.php b/examples/explicit-registration/SimpleHandlers.php similarity index 97% rename from examples/stdio-explicit-registration/SimpleHandlers.php rename to examples/explicit-registration/SimpleHandlers.php index 0a119e77..0fe385c1 100644 --- a/examples/stdio-explicit-registration/SimpleHandlers.php +++ b/examples/explicit-registration/SimpleHandlers.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\StdioExplicitRegistration; +namespace Mcp\Example\ExplicitRegistration; use Psr\Log\LoggerInterface; diff --git a/examples/stdio-explicit-registration/server.php b/examples/explicit-registration/server.php similarity index 80% rename from examples/stdio-explicit-registration/server.php rename to examples/explicit-registration/server.php index 2189bf16..5a61feef 100644 --- a/examples/stdio-explicit-registration/server.php +++ b/examples/explicit-registration/server.php @@ -13,15 +13,14 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Mcp\Example\StdioExplicitRegistration\SimpleHandlers; +use Mcp\Example\ExplicitRegistration\SimpleHandlers; use Mcp\Schema\ServerCapabilities; use Mcp\Server; -use Mcp\Server\Transport\StdioTransport; -logger()->info('Starting MCP Manual Registration (Stdio) Server...'); +logger()->info('Starting MCP Manual Registration Server...'); $server = Server::builder() - ->setServerInfo('Manual Reg Server', '1.0.0') + ->setServerInfo('Explicit Registration Server', '1.0.0') ->setLogger(logger()) ->setContainer(container()) ->addTool([SimpleHandlers::class, 'echoText'], 'echo_text') @@ -41,10 +40,8 @@ )) ->build(); -$transport = new StdioTransport(logger: logger()); - -$result = $server->run($transport); +$result = $server->run(transport()); logger()->info('Server listener stopped gracefully.', ['result' => $result]); -exit($result); +shutdown($result); diff --git a/examples/http-client-communication/server.php b/examples/http-client-communication/server.php deleted file mode 100644 index 12f18eec..00000000 --- a/examples/http-client-communication/server.php +++ /dev/null @@ -1,116 +0,0 @@ -createServerRequestFromGlobals(); - -$sessionDir = __DIR__.'/sessions'; -$capabilities = new ServerCapabilities(logging: true, tools: true); -$logger = logger(); - -$server = Server::builder() - ->setServerInfo('HTTP Client Communication Demo', '1.0.0') - ->setLogger($logger) - ->setContainer(container()) - ->setSession(new FileSessionStore($sessionDir)) - ->setCapabilities($capabilities) - ->addTool( - function (string $projectName, array $milestones, ClientGateway $client): array { - $client->log(LoggingLevel::Info, sprintf('Preparing project briefing for "%s"', $projectName)); - - $totalSteps = max(1, count($milestones)); - - foreach ($milestones as $index => $milestone) { - $progress = ($index + 1) / $totalSteps; - $message = sprintf('Analyzing milestone "%s"', $milestone); - - $client->progress(progress: $progress, total: 1, message: $message); - - usleep(150_000); // Simulate work being done - } - - $prompt = sprintf( - 'Draft a concise stakeholder briefing for the project "%s". Highlight key milestones: %s. Focus on risks and next steps.', - $projectName, - implode(', ', $milestones) - ); - - $result = $client->sample( - message: $prompt, - maxTokens: 400, - timeout: 90, - options: ['temperature' => 0.4] - ); - - $content = $result->content instanceof TextContent ? trim((string) $result->content->text) : ''; - - $client->log(LoggingLevel::Info, 'Briefing ready, returning to caller.'); - - return [ - 'project' => $projectName, - 'milestones_reviewed' => $milestones, - 'briefing' => $content, - 'model' => $result->model, - 'stop_reason' => $result->stopReason, - ]; - }, - name: 'prepare_project_briefing', - description: 'Compile a stakeholder briefing with live logging, progress updates, and LLM sampling.' - ) - ->addTool( - function (string $serviceName, ClientGateway $client): array { - $client->log(LoggingLevel::Info, sprintf('Starting maintenance checks for "%s"', $serviceName)); - - $steps = [ - 'Verifying health metrics', - 'Checking recent deployments', - 'Reviewing alert stream', - 'Summarizing findings', - ]; - - foreach ($steps as $index => $step) { - $progress = ($index + 1) / count($steps); - - $client->progress(progress: $progress, total: 1, message: $step); - - usleep(120_000); // Simulate work being done - } - - $client->log(LoggingLevel::Info, sprintf('Maintenance checks complete for "%s"', $serviceName)); - - return [ - 'service' => $serviceName, - 'status' => 'operational', - 'notes' => 'No critical issues detected during automated sweep.', - ]; - }, - name: 'run_service_maintenance', - description: 'Simulate service maintenance with logging and progress notifications.' - ) - ->build(); - -$transport = new StreamableHttpTransport($request, logger: $logger); - -$response = $server->run($transport); - -(new SapiEmitter())->emit($response); diff --git a/examples/http-schema-showcase/SchemaShowcaseElements.php b/examples/schema-showcase/SchemaShowcaseElements.php similarity index 99% rename from examples/http-schema-showcase/SchemaShowcaseElements.php rename to examples/schema-showcase/SchemaShowcaseElements.php index d19bfa1f..6c7a4b93 100644 --- a/examples/http-schema-showcase/SchemaShowcaseElements.php +++ b/examples/schema-showcase/SchemaShowcaseElements.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -namespace Mcp\Example\HttpSchemaShowcase; +namespace Mcp\Example\SchemaShowcase; use Mcp\Capability\Attribute\McpTool; use Mcp\Capability\Attribute\Schema; diff --git a/examples/http-schema-showcase/server.php b/examples/schema-showcase/server.php similarity index 63% rename from examples/http-schema-showcase/server.php rename to examples/schema-showcase/server.php index 6b38a3c2..b908cebd 100644 --- a/examples/http-schema-showcase/server.php +++ b/examples/schema-showcase/server.php @@ -13,14 +13,8 @@ require_once dirname(__DIR__).'/bootstrap.php'; chdir(__DIR__); -use Http\Discovery\Psr17Factory; -use Laminas\HttpHandlerRunner\Emitter\SapiEmitter; use Mcp\Server; use Mcp\Server\Session\FileSessionStore; -use Mcp\Server\Transport\StreamableHttpTransport; - -$psr17Factory = new Psr17Factory(); -$request = $psr17Factory->createServerRequestFromGlobals(); $server = Server::builder() ->setServerInfo('Schema Showcase', '1.0.0') @@ -30,8 +24,6 @@ ->setDiscovery(__DIR__) ->build(); -$transport = new StreamableHttpTransport($request); - -$response = $server->run($transport); +$response = $server->run(transport()); -(new SapiEmitter())->emit($response); +shutdown($response); diff --git a/src/Server/Transport/TransportInterface.php b/src/Server/Transport/TransportInterface.php index 400c453e..5a874a76 100644 --- a/src/Server/Transport/TransportInterface.php +++ b/src/Server/Transport/TransportInterface.php @@ -16,7 +16,7 @@ use Symfony\Component\Uid\Uuid; /** - * @template TResult + * @template-covariant TResult * * @phpstan-type FiberReturn (Response|Error) * @phpstan-type FiberResume (FiberReturn|null) diff --git a/tests/Inspector/Http/HttpClientCommunicationTest.php b/tests/Inspector/Http/HttpClientCommunicationTest.php index 0b396e2e..ba287fd0 100644 --- a/tests/Inspector/Http/HttpClientCommunicationTest.php +++ b/tests/Inspector/Http/HttpClientCommunicationTest.php @@ -59,6 +59,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/http-client-communication/server.php'; + return \dirname(__DIR__, 3).'/examples/client-communication/server.php'; } } diff --git a/tests/Inspector/Http/HttpCombinedRegistrationTest.php b/tests/Inspector/Http/HttpCombinedRegistrationTest.php index 932c200b..36f133cd 100644 --- a/tests/Inspector/Http/HttpCombinedRegistrationTest.php +++ b/tests/Inspector/Http/HttpCombinedRegistrationTest.php @@ -45,6 +45,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/http-combined-registration/server.php'; + return \dirname(__DIR__, 3).'/examples/combined-registration/server.php'; } } diff --git a/tests/Inspector/Http/HttpComplexToolSchemaTest.php b/tests/Inspector/Http/HttpComplexToolSchemaTest.php index 93f3ca30..6c104e28 100644 --- a/tests/Inspector/Http/HttpComplexToolSchemaTest.php +++ b/tests/Inspector/Http/HttpComplexToolSchemaTest.php @@ -82,6 +82,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/http-complex-tool-schema/server.php'; + return \dirname(__DIR__, 3).'/examples/complex-tool-schema/server.php'; } } diff --git a/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php b/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php index abffbacd..b0ffef81 100644 --- a/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php +++ b/tests/Inspector/Http/HttpDiscoveryUserProfileTest.php @@ -67,6 +67,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/http-discovery-userprofile/server.php'; + return \dirname(__DIR__, 3).'/examples/discovery-userprofile/server.php'; } } diff --git a/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php b/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php index 41f224a9..5db629e4 100644 --- a/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php +++ b/tests/Inspector/Http/HttpInspectorSnapshotTestCase.php @@ -21,14 +21,12 @@ abstract class HttpInspectorSnapshotTestCase extends InspectorSnapshotTestCase protected function setUp(): void { - parent::setUp(); $this->startServer(); } protected function tearDown(): void { $this->stopServer(); - parent::tearDown(); } abstract protected function getServerScript(): string; diff --git a/tests/Inspector/Http/HttpSchemaShowcaseTest.php b/tests/Inspector/Http/HttpSchemaShowcaseTest.php index e4b137da..9ed61ae1 100644 --- a/tests/Inspector/Http/HttpSchemaShowcaseTest.php +++ b/tests/Inspector/Http/HttpSchemaShowcaseTest.php @@ -87,7 +87,7 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/http-schema-showcase/server.php'; + return \dirname(__DIR__, 3).'/examples/schema-showcase/server.php'; } protected function normalizeTestOutput(string $output, ?string $testName = null): string diff --git a/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php b/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php index ede61ed3..438a3f8e 100644 --- a/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php +++ b/tests/Inspector/Stdio/StdioCachedDiscoveryTest.php @@ -88,6 +88,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/stdio-cached-discovery/server.php'; + return \dirname(__DIR__, 3).'/examples/cached-discovery/server.php'; } } diff --git a/tests/Inspector/Stdio/StdioCustomDependenciesTest.php b/tests/Inspector/Stdio/StdioCustomDependenciesTest.php index e4285e27..d2f64c0d 100644 --- a/tests/Inspector/Stdio/StdioCustomDependenciesTest.php +++ b/tests/Inspector/Stdio/StdioCustomDependenciesTest.php @@ -55,7 +55,7 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/stdio-custom-dependencies/server.php'; + return \dirname(__DIR__, 3).'/examples/custom-dependencies/server.php'; } protected function normalizeTestOutput(string $output, ?string $testName = null): string diff --git a/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php b/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php index 8a62b2c6..87ce549c 100644 --- a/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php +++ b/tests/Inspector/Stdio/StdioDiscoveryCalculatorTest.php @@ -45,6 +45,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/stdio-discovery-calculator/server.php'; + return \dirname(__DIR__, 3).'/examples/discovery-calculator/server.php'; } } diff --git a/tests/Inspector/Stdio/StdioEnvVariablesTest.php b/tests/Inspector/Stdio/StdioEnvVariablesTest.php index 97601d1a..c46eb753 100644 --- a/tests/Inspector/Stdio/StdioEnvVariablesTest.php +++ b/tests/Inspector/Stdio/StdioEnvVariablesTest.php @@ -50,6 +50,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/stdio-env-variables/server.php'; + return \dirname(__DIR__, 3).'/examples/env-variables/server.php'; } } diff --git a/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php b/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php index 103d3e67..1cb8179b 100644 --- a/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php +++ b/tests/Inspector/Stdio/StdioExplicitRegistrationTest.php @@ -77,6 +77,6 @@ public static function provideMethods(): array protected function getServerScript(): string { - return \dirname(__DIR__, 3).'/examples/stdio-explicit-registration/server.php'; + return \dirname(__DIR__, 3).'/examples/explicit-registration/server.php'; } }