Skip to content

Commit ac4940f

Browse files
feat(core): Add manual registration and invokable class discovery
Implements several enhancements to the MCP server: - Adds manual registration methods to the `Server` class (`withTool`, `withResource`, `withPrompt`, `withResourceTemplate`), allowing programmatic definition of MCP elements alongside attribute discovery. Supports array `[Class::class, 'method']` and invokable class string handlers. - Enables the `Discoverer` to find `#[Mcp*]` attributes placed directly on invokable classes (classes with a public `__invoke` method). Attributes (`McpTool`, `McpResource`, etc.) updated accordingly. - Refactors dependency injection within the `Server`. Core components like `Processor`, `Discoverer`, `Registry`, and `TransportState` now resolve dependencies (Logger, Cache, Config) Just-In-Time from the PSR-11 container. - Clarifies behavior: `withLogger/Cache/Config` methods primarily affect the default `BasicContainer`. When a custom container is used via `withContainer`, these services MUST be registered directly in the custom container. - Adds configuration options to control discovery paths (`withBasePath`, `withScanDirectories`, `withExcludeDirectories`). - Updates `README.md` extensively to document these new features and the updated DI behavior. - Adds comprehensive tests for manual registration and invokable class discovery, and updates existing tests to reflect the DI refactoring. BREAKING CHANGE: The dependency injection mechanism within the `Server` has been refactored. Components now resolve PSR-3/11/16 dependencies JIT from the container. Users providing a custom container via `withContainer()` MUST ensure `LoggerInterface`, `CacheInterface`, and `ConfigurationRepositoryInterface` are registered. The behavior of `withLogger()`, `withCache()`, and `withConfig()` is altered when a custom container is present; configuration should happen directly within the custom container itself. TransportHandler constructors now primarily accept the `Server` instance.
1 parent 1fa0246 commit ac4940f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1829
-1141
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,7 @@ workbench
6161
playground
6262

6363
# Log files
64-
*.log
64+
*.log
65+
66+
# Cache files
67+
cache

README.md

Lines changed: 191 additions & 75 deletions
Large diffs are not rendered by default.

samples/php_http/server.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919

2020
// --- MCP Server Setup ---
2121
$logger = new StreamLogger(__DIR__.'/vanilla_server.log', 'debug');
22-
$server = Server::make()->withLogger($logger)->withBasePath(__DIR__)->discover();
23-
$processor = $server->getProcessor();
24-
$state = $server->getStateManager();
25-
$httpHandler = new HttpTransportHandler($processor, $state, $logger);
22+
$server = Server::make()
23+
->withLogger($logger)
24+
->withBasePath(__DIR__)
25+
->discover();
26+
27+
$httpHandler = new HttpTransportHandler($server);
2628

2729
// --- Basic Routing & Client ID ---
2830
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';

samples/php_stdio/server.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use PhpMcp\Server\Defaults\StreamLogger;
66
use PhpMcp\Server\Server;
7+
use Test\SampleMcpElements;
78

89
// --- Instructions ---
910
// 1. composer install
@@ -24,8 +25,10 @@
2425
$logger = new StreamLogger(__DIR__.'/mcp.log', 'debug');
2526

2627
$server = Server::make()
27-
->withLogger($logger)
2828
->withBasePath(__DIR__)
29+
->withLogger($logger)
30+
->withTool([SampleMcpElements::class, 'simpleTool'], 'greeter')
31+
->withResource([SampleMcpElements::class, 'getUserData'], 'user://data')
2932
->discover();
3033

3134
$exitCode = $server->run('stdio');

samples/reactphp_http/server.php

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
use PhpMcp\Server\Transports\ReactPhpHttpTransportHandler;
88
use Psr\Http\Message\ResponseInterface;
99
use Psr\Http\Message\ServerRequestInterface;
10-
use React\EventLoop\Loop;
1110
use React\Http\HttpServer;
1211
use React\Http\Message\Response;
1312
use React\Promise\Promise;
@@ -34,10 +33,7 @@
3433
->withBasePath(__DIR__)
3534
->discover();
3635

37-
$processor = $server->getProcessor();
38-
$state = $server->getStateManager();
39-
40-
$transportHandler = new ReactPhpHttpTransportHandler($processor, $state, $logger, Loop::get());
36+
$transportHandler = new ReactPhpHttpTransportHandler($server);
4137

4238
// --- ReactPHP HTTP Server Setup ---
4339
$postEndpoint = '/mcp/message';

src/Attributes/McpPrompt.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Marks a PHP method as an MCP Prompt generator.
99
* The method should return the prompt messages, potentially using arguments for templating.
1010
*/
11-
#[Attribute(Attribute::TARGET_METHOD)]
11+
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
1212
final class McpPrompt
1313
{
1414
/**
@@ -18,6 +18,5 @@ final class McpPrompt
1818
public function __construct(
1919
public ?string $name = null,
2020
public ?string $description = null,
21-
) {
22-
}
21+
) {}
2322
}

src/Attributes/McpResource.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Marks a PHP class as representing or handling a specific MCP Resource instance.
99
* Used primarily for the 'resources/list' discovery.
1010
*/
11-
#[Attribute(Attribute::TARGET_METHOD)]
11+
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
1212
final class McpResource
1313
{
1414
/**
@@ -17,15 +17,14 @@ final class McpResource
1717
* @param ?string $description An optional description of the resource. Defaults to class DocBlock summary.
1818
* @param ?string $mimeType The MIME type, if known and constant for this resource.
1919
* @param ?int $size The size in bytes, if known and constant.
20-
* @param ?array<string, mixed> $annotations Optional annotations following the MCP spec (e.g., ['audience' => ['user'], 'priority' => 0.5]).
20+
* @param array<string, mixed> $annotations Optional annotations following the MCP spec (e.g., ['audience' => ['user'], 'priority' => 0.5]).
2121
*/
2222
public function __construct(
2323
public string $uri,
2424
public ?string $name = null,
2525
public ?string $description = null,
2626
public ?string $mimeType = null,
2727
public ?int $size = null,
28-
public ?array $annotations = null,
29-
) {
30-
}
28+
public array $annotations = [],
29+
) {}
3130
}

src/Attributes/McpResourceTemplate.php

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,21 @@
88
* Marks a PHP class definition as representing an MCP Resource Template.
99
* This is informational, used for 'resources/templates/list'.
1010
*/
11-
#[Attribute(Attribute::TARGET_METHOD)]
11+
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
1212
final class McpResourceTemplate
1313
{
1414
/**
1515
* @param string $uriTemplate The URI template string (RFC 6570).
1616
* @param ?string $name A human-readable name for the template type. If null, a default might be generated from the method name.
1717
* @param ?string $description Optional description. Defaults to class DocBlock summary.
1818
* @param ?string $mimeType Optional default MIME type for matching resources.
19-
* @param ?array<string, mixed> $annotations Optional annotations following the MCP spec.
19+
* @param array<string, mixed> $annotations Optional annotations following the MCP spec.
2020
*/
2121
public function __construct(
2222
public string $uriTemplate,
2323
public ?string $name = null,
2424
public ?string $description = null,
2525
public ?string $mimeType = null,
26-
public ?array $annotations = null,
27-
) {
28-
}
26+
public array $annotations = [],
27+
) {}
2928
}

src/Attributes/McpTool.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use Attribute;
66

7-
#[Attribute(Attribute::TARGET_METHOD)]
7+
#[Attribute(Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
88
class McpTool
99
{
1010
/**
@@ -14,6 +14,5 @@ class McpTool
1414
public function __construct(
1515
public ?string $name = null,
1616
public ?string $description = null,
17-
) {
18-
}
17+
) {}
1918
}

0 commit comments

Comments
 (0)