Skip to content

Commit 275a0bb

Browse files
committed
feat(server): add server lifecycle events
1 parent 50ece31 commit 275a0bb

27 files changed

+1096
-10
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ $server = Server::builder()
255255
- [Transports](docs/transports.md) - STDIO and HTTP transport setup and usage
256256
- [MCP Elements](docs/mcp-elements.md) - Creating tools, resources, and prompts
257257
- [Client Communication](docs/client-communication.md) - Communicating back to the client from server-side
258+
- [Events](docs/events.md) - Hooking into server lifecycle with events
258259

259260
**Learning:**
260261
- [Examples](docs/examples.md) - Comprehensive example walkthroughs

docs/events.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# Events
2+
3+
The MCP SDK provides a PSR-14 compatible event system that allows you to hook into the server's lifecycle. Events enable logging, monitoring, validation, caching, and other custom behaviors.
4+
5+
## Table of Contents
6+
7+
- [Setup](#setup)
8+
- [List Change Events](#list-change-events)
9+
- [Lifecycle Events](#lifecycle-events)
10+
- [Tool Events](#tool-events)
11+
- [Prompt Events](#prompt-events)
12+
- [Resource Events](#resource-events)
13+
- [Server Events](#server-events)
14+
- [Use Cases](#use-cases)
15+
16+
## Setup
17+
18+
Configure an event dispatcher when building your server:
19+
20+
```php
21+
use Mcp\Server;
22+
use Symfony\Component\EventDispatcher\EventDispatcher;
23+
24+
$dispatcher = new EventDispatcher();
25+
26+
// Register your listeners
27+
$dispatcher->addListener(CallToolResultEvent::class, function (CallToolResultEvent $event) {
28+
// Handle event
29+
});
30+
31+
$server = Server::builder()
32+
->setEventDispatcher($dispatcher)
33+
->build();
34+
```
35+
36+
## List Change Events
37+
38+
These events are dispatched when the lists of available capabilities change:
39+
40+
| Event | Description |
41+
|-------|-------------|
42+
| `ToolListChangedEvent` | Dispatched when the list of available tools changes |
43+
| `ResourceListChangedEvent` | Dispatched when the list of available resources changes |
44+
| `ResourceTemplateListChangedEvent` | Dispatched when the list of available resource templates changes |
45+
| `PromptListChangedEvent` | Dispatched when the list of available prompts changes |
46+
47+
These events carry no data and are used to notify clients that they should refresh their capability lists.
48+
49+
```php
50+
use Mcp\Event\ToolListChangedEvent;
51+
52+
$dispatcher->addListener(ToolListChangedEvent::class, function (ToolListChangedEvent $event) {
53+
$logger->info('Tool list has changed, clients should refresh');
54+
});
55+
```
56+
57+
## Lifecycle Events
58+
59+
### Tool Events
60+
61+
Events for the tool call lifecycle:
62+
63+
| Event | Timing | Data |
64+
|-------|----------------------------|------|
65+
| `CallToolRequestEvent` | Before tool execution | `request` |
66+
| `CallToolResultEvent` | After successful execution | `request`, `result` |
67+
| `CallToolExceptionEvent` | On uncaught exception | `request`, `throwable` |
68+
69+
### Prompt Events
70+
71+
Events for the prompt retrieval lifecycle:
72+
73+
| Event | Timing | Data |
74+
|-------|----------------------------|------|
75+
| `GetPromptRequestEvent` | Before prompt execution | `request` |
76+
| `GetPromptResultEvent` | After successful execution | `request`, `result` |
77+
| `GetPromptExceptionEvent` | On uncaught exception | `request`, `throwable` |
78+
79+
### Resource Events
80+
81+
Events for the resource read lifecycle:
82+
83+
| Event | Timing | Data |
84+
|-------|-----------------------|------|
85+
| `ReadResourceRequestEvent` | Before resource read | `request` |
86+
| `ReadResourceResultEvent` | After successful read | `request`, `result` |
87+
| `ReadResourceExceptionEvent` | On uncaught exception | `request`, `throwable` |
88+
89+
## Server Events
90+
91+
| Event | Timing | Data |
92+
|-------|--------|------|
93+
| `InitializeRequestEvent` | When client sends initialize request | `request` (InitializeRequest) |
94+
| `PingRequestEvent` | When client sends ping request | `request` (PingRequest) |
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event;
15+
16+
use Mcp\Schema\Request\InitializeRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
class InitializeRequestEvent
22+
{
23+
public function __construct(
24+
private readonly InitializeRequest $request,
25+
) {
26+
}
27+
28+
public function getRequest(): InitializeRequest
29+
{
30+
return $this->request;
31+
}
32+
}

src/Event/PingRequestEvent.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event;
15+
16+
use Mcp\Schema\Request\PingRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
class PingRequestEvent
22+
{
23+
public function __construct(
24+
private readonly PingRequest $request,
25+
) {
26+
}
27+
28+
public function getRequest(): PingRequest
29+
{
30+
return $this->request;
31+
}
32+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Prompt;
15+
16+
use Mcp\Schema\Request\GetPromptRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
abstract class AbstractGetPromptEvent
22+
{
23+
public function __construct(
24+
private readonly GetPromptRequest $request,
25+
) {
26+
}
27+
28+
public function getRequest(): GetPromptRequest
29+
{
30+
return $this->request;
31+
}
32+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Prompt;
15+
16+
use Mcp\Schema\Request\GetPromptRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
class GetPromptExceptionEvent extends AbstractGetPromptEvent
22+
{
23+
public function __construct(
24+
GetPromptRequest $request,
25+
private readonly \Throwable $throwable,
26+
) {
27+
parent::__construct($request);
28+
}
29+
30+
public function getThrowable(): \Throwable
31+
{
32+
return $this->throwable;
33+
}
34+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Prompt;
15+
16+
/**
17+
* @author Edouard Courty <edouard.courty2@gmail.com>
18+
*/
19+
class GetPromptRequestEvent extends AbstractGetPromptEvent
20+
{
21+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Prompt;
15+
16+
use Mcp\Schema\Request\GetPromptRequest;
17+
use Mcp\Schema\Result\GetPromptResult;
18+
19+
/**
20+
* @author Edouard Courty <edouard.courty2@gmail.com>
21+
*/
22+
class GetPromptResultEvent extends AbstractGetPromptEvent
23+
{
24+
public function __construct(
25+
GetPromptRequest $request,
26+
private readonly GetPromptResult $result,
27+
) {
28+
parent::__construct($request);
29+
}
30+
31+
public function getResult(): GetPromptResult
32+
{
33+
return $this->result;
34+
}
35+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Resource;
15+
16+
use Mcp\Schema\Request\ReadResourceRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
abstract class AbstractReadResourceEvent
22+
{
23+
public function __construct(
24+
private readonly ReadResourceRequest $request,
25+
) {
26+
}
27+
28+
public function getRequest(): ReadResourceRequest
29+
{
30+
return $this->request;
31+
}
32+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the official PHP MCP SDK.
7+
*
8+
* A collaboration between Symfony and the PHP Foundation.
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Mcp\Event\Resource;
15+
16+
use Mcp\Schema\Request\ReadResourceRequest;
17+
18+
/**
19+
* @author Edouard Courty <edouard.courty2@gmail.com>
20+
*/
21+
class ReadResourceExceptionEvent extends AbstractReadResourceEvent
22+
{
23+
public function __construct(
24+
ReadResourceRequest $request,
25+
private readonly \Throwable $throwable,
26+
) {
27+
parent::__construct($request);
28+
}
29+
30+
public function getThrowable(): \Throwable
31+
{
32+
return $this->throwable;
33+
}
34+
}

0 commit comments

Comments
 (0)