Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,7 @@ $server = Server::builder()
- [Transports](docs/transports.md) - STDIO and HTTP transport setup and usage
- [MCP Elements](docs/mcp-elements.md) - Creating tools, resources, and prompts
- [Client Communication](docs/client-communication.md) - Communicating back to the client from server-side
- [Events](docs/events.md) - Hooking into server lifecycle with events

**Learning:**
- [Examples](docs/examples.md) - Comprehensive example walkthroughs
Expand Down
94 changes: 94 additions & 0 deletions docs/events.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Events

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.

## Table of Contents

- [Setup](#setup)
- [List Change Events](#list-change-events)
- [Lifecycle Events](#lifecycle-events)
- [Tool Events](#tool-events)
- [Prompt Events](#prompt-events)
- [Resource Events](#resource-events)
- [Server Events](#server-events)
- [Use Cases](#use-cases)

## Setup

Configure an event dispatcher when building your server:

```php
use Mcp\Server;
use Symfony\Component\EventDispatcher\EventDispatcher;

$dispatcher = new EventDispatcher();

// Register your listeners
$dispatcher->addListener(CallToolResultEvent::class, function (CallToolResultEvent $event) {
// Handle event
});

$server = Server::builder()
->setEventDispatcher($dispatcher)
->build();
```

## List Change Events

These events are dispatched when the lists of available capabilities change:

| Event | Description |
|-------|-------------|
| `ToolListChangedEvent` | Dispatched when the list of available tools changes |
| `ResourceListChangedEvent` | Dispatched when the list of available resources changes |
| `ResourceTemplateListChangedEvent` | Dispatched when the list of available resource templates changes |
| `PromptListChangedEvent` | Dispatched when the list of available prompts changes |

These events carry no data and are used to notify clients that they should refresh their capability lists.

```php
use Mcp\Event\ToolListChangedEvent;

$dispatcher->addListener(ToolListChangedEvent::class, function (ToolListChangedEvent $event) {
$logger->info('Tool list has changed, clients should refresh');
});
```

## Lifecycle Events

### Tool Events

Events for the tool call lifecycle:

| Event | Timing | Data |
|-------|----------------------------|------|
| `CallToolRequestEvent` | Before tool execution | `request` |
| `CallToolResultEvent` | After successful execution | `request`, `result` |
| `CallToolExceptionEvent` | On uncaught exception | `request`, `throwable` |

### Prompt Events

Events for the prompt retrieval lifecycle:

| Event | Timing | Data |
|-------|----------------------------|------|
| `GetPromptRequestEvent` | Before prompt execution | `request` |
| `GetPromptResultEvent` | After successful execution | `request`, `result` |
| `GetPromptExceptionEvent` | On uncaught exception | `request`, `throwable` |

### Resource Events

Events for the resource read lifecycle:

| Event | Timing | Data |
|-------|-----------------------|------|
| `ReadResourceRequestEvent` | Before resource read | `request` |
| `ReadResourceResultEvent` | After successful read | `request`, `result` |
| `ReadResourceExceptionEvent` | On uncaught exception | `request`, `throwable` |

## Server Events

| Event | Timing | Data |
|-------|--------|------|
| `InitializeRequestEvent` | When client sends initialize request | `request` (InitializeRequest) |
| `PingRequestEvent` | When client sends ping request | `request` (PingRequest) |
32 changes: 32 additions & 0 deletions src/Event/InitializeRequestEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/*
* 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\Event;

use Mcp\Schema\Request\InitializeRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class InitializeRequestEvent
{
public function __construct(
private readonly InitializeRequest $request,
) {
}

public function getRequest(): InitializeRequest
{
return $this->request;
}
}
32 changes: 32 additions & 0 deletions src/Event/PingRequestEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/*
* 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\Event;

use Mcp\Schema\Request\PingRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class PingRequestEvent
{
public function __construct(
private readonly PingRequest $request,
) {
}

public function getRequest(): PingRequest
{
return $this->request;
}
}
32 changes: 32 additions & 0 deletions src/Event/Prompt/AbstractGetPromptEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Prompt;

use Mcp\Schema\Request\GetPromptRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
abstract class AbstractGetPromptEvent
{
public function __construct(
private readonly GetPromptRequest $request,
) {
}

public function getRequest(): GetPromptRequest
{
return $this->request;
}
}
34 changes: 34 additions & 0 deletions src/Event/Prompt/GetPromptExceptionEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Prompt;

use Mcp\Schema\Request\GetPromptRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class GetPromptExceptionEvent extends AbstractGetPromptEvent
{
public function __construct(
GetPromptRequest $request,
private readonly \Throwable $throwable,
) {
parent::__construct($request);
}

public function getThrowable(): \Throwable
{
return $this->throwable;
}
}
21 changes: 21 additions & 0 deletions src/Event/Prompt/GetPromptRequestEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Prompt;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class GetPromptRequestEvent extends AbstractGetPromptEvent
{
}
35 changes: 35 additions & 0 deletions src/Event/Prompt/GetPromptResultEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Prompt;

use Mcp\Schema\Request\GetPromptRequest;
use Mcp\Schema\Result\GetPromptResult;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class GetPromptResultEvent extends AbstractGetPromptEvent
{
public function __construct(
GetPromptRequest $request,
private readonly GetPromptResult $result,
) {
parent::__construct($request);
}

public function getResult(): GetPromptResult
{
return $this->result;
}
}
32 changes: 32 additions & 0 deletions src/Event/Resource/AbstractReadResourceEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Resource;

use Mcp\Schema\Request\ReadResourceRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
abstract class AbstractReadResourceEvent
{
public function __construct(
private readonly ReadResourceRequest $request,
) {
}

public function getRequest(): ReadResourceRequest
{
return $this->request;
}
}
34 changes: 34 additions & 0 deletions src/Event/Resource/ReadResourceExceptionEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Resource;

use Mcp\Schema\Request\ReadResourceRequest;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class ReadResourceExceptionEvent extends AbstractReadResourceEvent
{
public function __construct(
ReadResourceRequest $request,
private readonly \Throwable $throwable,
) {
parent::__construct($request);
}

public function getThrowable(): \Throwable
{
return $this->throwable;
}
}
21 changes: 21 additions & 0 deletions src/Event/Resource/ReadResourceRequestEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

/*
* 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\Event\Resource;

/**
* @author Edouard Courty <edouard.courty2@gmail.com>
*/
class ReadResourceRequestEvent extends AbstractReadResourceEvent
{
}
Loading