Add RequestContext and logging (#176)

* Implemented MCP logging specification with auto-injection

* Add RequestContext

* fix tests and style

* Better deprecation

* fix: minor

* Remove ClientAwareInterface

* fix cs

* fix docs

---------

Co-authored-by: Adam Jamiu <jamiuadam120@gmail.com>
This commit is contained in:
Tobias Nyholm 2025-12-16 00:12:02 +01:00 • committed by GitHub
commit a1e0f61b6b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 578 additions and 162 deletions

View file

@ -13,44 +13,21 @@ MCP supports various ways a server can communicate back to a server on top of th
## ClientGateway
Every communication back to client is handled using the `Mcp\Server\ClientGateway` and its dedicated methods per
operation. To use the `ClientGateway` in your code, there are two ways to do so:
operation. To use the `ClientGateway` in your code, you need to use method argument injection for `RequestContext`.
### 1. Method Argument Injection
Every refernce of a MCP element, that translates to an actual method call, can just add an type-hinted argument for the
`ClientGateway` and the SDK will take care to include the gateway in the arguments of the method call:
Every reference of a MCP element, that translates to an actual method call, can just add an type-hinted argument for the
`RequestContext` and the SDK will take care to include the gateway in the arguments of the method call:
```php
use Mcp\Capability\Attribute\McpTool;
use Mcp\Server\ClientGateway;
use Mcp\Server\RequestContext;
class MyService
{
#[McpTool('my_tool', 'My Tool Description')]
public function myTool(ClientGateway $client): string
public function myTool(RequestContext $context): string
{
$client->log(...);
```
### 2. Implementing `ClientAwareInterface`
Whenever a service class of an MCP element implements the interface `Mcp\Server\ClientAwareInterface` the `setClient`
method of that class will get called while handling the reference, and in combination with `Mcp\Server\ClientAwareTrait`
this ends up with code like this:
```php
use Mcp\Capability\Attribute\McpTool;
use Mcp\Server\ClientAwareInterface;
use Mcp\Server\ClientAwareTrait;
class MyService implements ClientAwareInterface
{
use ClientAwareTrait;
#[McpTool('my_tool', 'My Tool Description')]
public function myTool(): string
{
$this->log(...);
$context->getClientGateway()->log(...);
```
## Sampling

View file

@ -166,11 +166,10 @@ $server = Server::builder()
**File**: `examples/client-communication/`
**What it demostrates:**
- Server initiated communcation back to the client
**What it demonstrates:**
- Server initiated communication back to the client
- Logging, sampling, progress and notifications
- 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 of `RequestContext`
### Discovery User Profile

View file

@ -11,6 +11,7 @@ discovery and manual registration methods.
- [Resources](#resources)
- [Resource Templates](#resource-templates)
- [Prompts](#prompts)
- [Logging](#logging)
- [Completion Providers](#completion-providers)
- [Schema Generation and Validation](#schema-generation-and-validation)
- [Discovery vs Manual Registration](#discovery-vs-manual-registration)
@ -504,6 +505,33 @@ public function generatePrompt(string $topic, string $style): array
**Recommendation**: Use `PromptGetException` when you want to communicate specific errors to clients. Any other exception will still be converted to JSON-RPC compliant errors but with generic error messages.
## Logging
The SDK provides support to send structured log messages to clients. All standard PSR-3 log levels are supported.
Level **warning** as the default level.
### Usage
The SDK automatically injects a `RequestContext` instance into handlers. This can be used to create a `ClientLogger`.
```php
use Mcp\Capability\Logger\ClientLogger;
use Mcp\Server\RequestContext;
#[McpTool]
public function processData(string $input, RequestContext $context): array {
$logger = $context->getClientLogger();
$logger->info('Processing started', ['input' => $input]);
$logger->warning('Deprecated API used');
// ... processing logic ...
$logger->info('Processing completed');
return ['result' => 'processed'];
}
```
## Completion Providers
Completion providers help MCP clients offer auto-completion suggestions for Resource Templates and Prompts. Unlike Tools and static Resources (which can be listed via `tools/list` and `resources/list`), Resource Templates and Prompts have dynamic parameters that benefit from completion hints.