refactor: remove dead code and obsolete examples (#76)

- Remove ToolChain, ResourceChain, PromptChain classes
- Remove Collection/Identifier/Metadata interfaces (only used by old Chains)
- Remove ToolCollectionInterface (unused)
- Delete obsolete examples 09-standalone-cli and 10-simple-http-transport
- Fix STDERR handling in bootstrap.php for web environments
- Clean up CHANGELOG.md
This commit is contained in:
Kyrian Obikwelu 2025-09-21 19:23:59 +01:00 • committed by GitHub
commit 9e168832ca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 5 additions and 1050 deletions

View file

@ -1,27 +0,0 @@
# Standalone example app with CLI
This is just for testing and debugging purposes. Different from the other examples, this one does not use the same
autoloader, but installs the SDK via path repository and therefore has mostly decoupled dependencies.
Install dependencies:
```bash
cd /path/to/your/project/examples/09-standalone-cli
composer update
```
Run the CLI with:
```bash
DEBUG=1 php index.php
```
You will see debug outputs to help you understand what is happening.
In this terminal you can now test by adding some JSON strings. See `example-requests.json`.
Run with Inspector:
```bash
npx @modelcontextprotocol/inspector php index.php
```

View file

@ -1,27 +0,0 @@
{
"name": "mcp/cli-server-example",
"description": "An example application for CLI",
"license": "MIT",
"type": "project",
"authors": [
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com"
}
],
"require": {
"php": ">=8.1",
"mcp/sdk": "@dev",
"symfony/console": "^7.2"
},
"minimum-stability": "stable",
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"repositories": [
{ "type": "path", "url": "../../" }
]
}

View file

@ -1,12 +0,0 @@
[
{"jsonrpc": "2.0", "id": 1, "method": "resources/list", "params": []},
{"jsonrpc": "2.0", "id": 2, "method": "resources/read", "params": {"uri": "file:///project/src/main.rs"}},
{"jsonrpc": "2.0", "id": 1, "method": "tools/list"},
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "Current time"}},
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "Current time","arguments": {"format": "Y-m-d"}}},
{"jsonrpc": "2.0", "id": 1, "method": "prompts/list"},
{"jsonrpc": "2.0", "id": 2 ,"method": "prompts/get", "params": {"name": "Greet"}},
{"jsonrpc": "2.0", "id": 2 ,"method": "prompts/get", "params": {"name": "Greet", "arguments": { "firstName": "Tobias" }}}
]

View file

@ -1,35 +0,0 @@
<?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 __DIR__.'/vendor/autoload.php';
use Mcp\Server;
use Mcp\Server\Transport\StdioTransport;
use Symfony\Component\Console as SymfonyConsole;
use Symfony\Component\Console\Output\OutputInterface;
$debug = (bool) ($_SERVER['DEBUG'] ?? false);
// Setup input, output and logger
$output = new SymfonyConsole\Output\ConsoleOutput($debug ? OutputInterface::VERBOSITY_VERY_VERBOSE : OutputInterface::VERBOSITY_NORMAL);
$logger = new SymfonyConsole\Logger\ConsoleLogger($output);
$server = Server::make()
->setServerInfo('Standalone CLI', '1.0.0')
->setLogger($logger)
->setDiscovery(__DIR__, ['.'])
->build();
$transport = new StdioTransport(logger: $logger);
$server->connect($transport);
$transport->listen();

View file

@ -1,55 +0,0 @@
<?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 App;
use Mcp\Capability\PromptChain;
use Mcp\Capability\ResourceChain;
use Mcp\Capability\ToolChain;
use Mcp\Server\MethodHandlerInterface;
use Mcp\Server\NotificationHandler;
use Mcp\Server\RequestHandler;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class Builder
{
/**
* @return list<MethodHandlerInterface>
*/
public static function buildMethodHandlers(): array
{
$promptManager = new PromptChain([
new ExamplePrompt(),
]);
$resourceManager = new ResourceChain([
new ExampleResource(),
]);
$toolManager = new ToolChain([
new ExampleTool(),
]);
return [
new NotificationHandler\InitializedHandler(),
new RequestHandler\InitializeHandler(),
new RequestHandler\PingHandler(),
new RequestHandler\ListPromptsHandler($promptManager),
new RequestHandler\GetPromptHandler($promptManager),
new RequestHandler\ListResourcesHandler($resourceManager),
new RequestHandler\ReadResourceHandler($resourceManager),
new RequestHandler\CallToolHandler($toolManager),
new RequestHandler\ListToolsHandler($toolManager),
];
}
}

View file

@ -1,60 +0,0 @@
<?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 App;
use Mcp\Capability\Prompt\MetadataInterface;
use Mcp\Capability\Prompt\PromptGetterInterface;
use Mcp\Schema\Content\PromptMessage;
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Enum\Role;
use Mcp\Schema\Request\GetPromptRequest;
use Mcp\Schema\Result\GetPromptResult;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class ExamplePrompt implements MetadataInterface, PromptGetterInterface
{
public function get(GetPromptRequest $request): GetPromptResult
{
$firstName = $request->arguments['firstName'] ?? null;
return new GetPromptResult(
[new PromptMessage(
Role::User,
new TextContent(\sprintf('Hello %s', $firstName ?? 'World')),
)],
$this->getDescription(),
);
}
public function getName(): string
{
return 'Greet';
}
public function getDescription(): ?string
{
return 'Greet a person with a nice message';
}
public function getArguments(): array
{
return [
[
'name' => 'first name',
'description' => 'The name of the person to greet',
'required' => false,
],
];
}
}

View file

@ -1,56 +0,0 @@
<?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 App;
use Mcp\Capability\Resource\MetadataInterface;
use Mcp\Capability\Resource\ResourceReaderInterface;
use Mcp\Schema\Content\TextResourceContents;
use Mcp\Schema\Request\ReadResourceRequest;
use Mcp\Schema\Result\ReadResourceResult;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class ExampleResource implements MetadataInterface, ResourceReaderInterface
{
public function read(ReadResourceRequest $request): ReadResourceResult
{
return new ReadResourceResult([
new TextResourceContents($this->getUri(), null, 'Content of My Resource'),
]);
}
public function getUri(): string
{
return 'file:///project/src/main.rs';
}
public function getName(): string
{
return 'my-resource';
}
public function getDescription(): ?string
{
return 'This is just an example';
}
public function getMimeType(): ?string
{
return null;
}
public function getSize(): ?int
{
return null;
}
}

View file

@ -1,60 +0,0 @@
<?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 App;
use Mcp\Capability\Tool\MetadataInterface;
use Mcp\Capability\Tool\ToolCallerInterface;
use Mcp\Schema\Content\TextContent;
use Mcp\Schema\Request\CallToolRequest;
use Mcp\Schema\Result\CallToolResult;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
*/
class ExampleTool implements MetadataInterface, ToolCallerInterface
{
public function call(CallToolRequest $request): CallToolResult
{
$format = $request->arguments['format'] ?? 'Y-m-d H:i:s';
return new CallToolResult([
new TextContent(
(new \DateTime('now', new \DateTimeZone('UTC')))->format($format),
),
]);
}
public function getName(): string
{
return 'Current time';
}
public function getDescription(): string
{
return 'Returns the current time in UTC';
}
public function getInputSchema(): array
{
return [
'type' => 'object',
'properties' => [
'format' => [
'type' => 'string',
'description' => 'The format of the time, e.g. "Y-m-d H:i:s"',
'default' => 'Y-m-d H:i:s',
],
],
'required' => [],
];
}
}

View file

@ -1,118 +0,0 @@
<?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\HttpTransportExample;
use Mcp\Capability\Attribute\McpPrompt;
use Mcp\Capability\Attribute\McpResource;
use Mcp\Capability\Attribute\McpTool;
class McpElements
{
public function __construct()
{
}
/**
* Get the current server time.
*/
#[McpTool(name: 'current_time')]
public function getCurrentTime(string $format = 'Y-m-d H:i:s'): string
{
try {
return date($format);
} catch (\Exception $e) {
return date('Y-m-d H:i:s'); // fallback
}
}
/**
* Calculate simple math operations.
*/
#[McpTool(name: 'calculate')]
public function calculate(float $a, float $b, string $operation): float|string
{
return match (strtolower($operation)) {
'add', '+' => $a + $b,
'subtract', '-' => $a - $b,
'multiply', '*' => $a * $b,
'divide', '/' => 0 != $b ? $a / $b : 'Error: Division by zero',
default => 'Error: Unknown operation. Use: add, subtract, multiply, divide',
};
}
/**
* Server information resource.
*
* @return array{status: string, timestamp: int, version: string, transport: string, uptime: int}
*/
#[McpResource(
uri: 'info://server/status',
name: 'server_status',
description: 'Current server status and information',
mimeType: 'application/json'
)]
public function getServerStatus(): array
{
return [
'status' => 'running',
'timestamp' => time(),
'version' => '1.0.0',
'transport' => 'HTTP',
'uptime' => time() - $_SERVER['REQUEST_TIME'],
];
}
/**
* Configuration resource.
*
* @return array{debug: bool, environment: string, timezone: string, locale: string}
*/
#[McpResource(
uri: 'config://app/settings',
name: 'app_config',
description: 'Application configuration settings',
mimeType: 'application/json'
)]
public function getAppConfig(): array
{
return [
'debug' => $_SERVER['DEBUG'] ?? false,
'environment' => $_SERVER['APP_ENV'] ?? 'production',
'timezone' => date_default_timezone_get(),
'locale' => 'en_US',
];
}
/**
* Greeting prompt.
*
* @return array{role: string, content: string}
*/
#[McpPrompt(
name: 'greet',
description: 'Generate a personalized greeting message'
)]
public function greetPrompt(string $firstName = 'World', string $timeOfDay = 'day'): array
{
$greeting = match (strtolower($timeOfDay)) {
'morning' => 'Good morning',
'afternoon' => 'Good afternoon',
'evening', 'night' => 'Good evening',
default => 'Hello',
};
return [
'role' => 'user',
'content' => "# {$greeting}, {$firstName}!\n\nWelcome to our MCP HTTP Server example. This demonstrates how to use the Model Context Protocol over HTTP transport.",
];
}
}

View file

@ -1,24 +0,0 @@
# HTTP MCP Server Example
This example demonstrates how to use the MCP SDK with HTTP transport using the StreamableHttpTransport. It provides a complete HTTP-based MCP server that can handle JSON-RPC requests over HTTP POST.
## Usage
**Step 1: Start the HTTP server**
```bash
cd examples/10-simple-http-transport
php -S localhost:8000 server.php
```
**Step 2: Connect with MCP Inspector**
```bash
npx @modelcontextprotocol/inspector http://localhost:8000
```
## Available Features
- **Tools**: `current_time`, `calculate`
- **Resources**: `info://server/status`, `config://app/settings`
- **Prompts**: `greet`

View file

@ -1,40 +0,0 @@
<?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 Laminas\HttpHandlerRunner\Emitter\SapiEmitter;
use Mcp\Server;
use Mcp\Server\Session\FileSessionStore;
use Mcp\Server\Transport\StreamableHttpTransport;
use Nyholm\Psr7\Factory\Psr17Factory;
use Nyholm\Psr7Server\ServerRequestCreator;
$psr17Factory = new Psr17Factory();
$creator = new ServerRequestCreator($psr17Factory, $psr17Factory, $psr17Factory, $psr17Factory);
$request = $creator->fromGlobals();
$server = Server::make()
->setServerInfo('HTTP MCP Server', '1.0.0', 'MCP Server over HTTP transport')
->setContainer(container())
->setSession(new FileSessionStore(__DIR__.'/sessions'))
->setDiscovery(__DIR__, ['.'])
->build();
$transport = new StreamableHttpTransport($request, $psr17Factory, $psr17Factory);
$server->connect($transport);
$response = $transport->listen();
(new SapiEmitter())->emit($response);

View file

@ -44,9 +44,9 @@ function logger(): LoggerInterface
if ($_SERVER['FILE_LOG'] ?? false) {
file_put_contents('dev.log', $logMessage, \FILE_APPEND);
} elseif (defined('STDERR')) {
fwrite(\STDERR, $logMessage);
}
fwrite(\STDERR, $logMessage);
}
};
}