You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 0c184ad
Browse filesBrowse the repository at this point in the historyBrowse files
authored
[Server] Allow context propagation into handler fibers (#670)
* [Server] Allow context propagation into handler fibers
Signed-off-by: bbdu3 <ergouyang854@gamil.com>
* [Server] Free a discarded handler fiber right away
* [Server] Wrap the handler instead of creating the fiber for context propagation
---------
Signed-off-by: bbdu3 <ergouyang854@gamil.com>
Co-authored-by: bbdu3 <ergouyang854@gamil.com>
Co-authored-by: Christopher Hertel <mail@christopher-hertel.de>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,6 +33,7 @@ All notable changes to `mcp/sdk` will be documented in this file.
33
33
* Add a `binder` argument to `Builder::setRequestState()` binding the modern era's `requestState` to the request it was minted for, as the 2026-07-28 specification recommends: the binder's value is covered by the state's MAC, and a state echoed on a request that binds to another value is refused like a forged one. `OriginatingRequestBinder` binds the authenticated principal, the method, the tool, prompt or resource, and a digest of the arguments; a token without a subject fails closed, and a `subject` resolver identifies users by another claim. `RequestStateBinderInterface` takes custom bindings. Without a binder, nothing changes.
34
34
* Rotate the `requestState` signing key without failing the calls in flight: `Builder::setRequestState()` and `RequestStateCodec` take a list of keys, the first signing and every key verifying. The wire format is unchanged, and a single key works as before.
35
35
* Log the name of a called tool at info level, so a server logging at INFO shows which tool is called. Its arguments stay at debug level, logged only once the tool is found and its input is valid.
36
+
* Add `Builder::setFiberContext()` and `Mcp\Server\Fiber\FiberContextInterface` to carry execution context, e.g. the active OpenTelemetry context, into handler fibers in both protocol eras.
36
37
* Event loops
37
38
* Add `Builder::setFiberScheduler()` and `Mcp\Server\Fiber\FiberSchedulerInterface`: under an event loop — Revolt (AMPHP), ReactPHP's async — a request handler awaiting I/O suspends its fiber for the loop, and the server now waits through the scheduler until the handler suspends for the server again or returns. The scheduler must wake the server on a later turn of the loop; the guide shows one for Revolt and one for ReactPHP, and the limits under an event loop.
38
39
* Fix the server resuming a request handler's fiber that the runtime had suspended: the handler's await returned early or threw (`Must call resume() or throw() before calling suspend() again`), and the runtime later resumed a fiber that had moved on — under Revolt, terminating the event loop. Without a scheduler, such a handler now fails the request with a `LogicException` naming `Builder::setFiberScheduler()`. `Protocol::__construct()` and `StatelessProtocol::__construct()` take the scheduler as optional last argument.
The returned closure must call `$handler` once and return its result. The `finally` block also runs when the server
385
+
discards a suspended fiber.
386
+
387
+
Under an event loop, every request runs in its own fiber, so OpenTelemetry raises the same warning in `wrap()`. Activate
388
+
a context in that fiber first, for example with `Context::getRoot()->activate()`. Fibers that a handler starts itself
389
+
(e.g. with `Amp\async()`) don't get the context.
350
390
351
391
## Complete Example
352
392
@@ -427,6 +467,7 @@ $server = Server::builder()
427
467
|`setContainer()`| container | Set PSR-11 container |
428
468
|`setEventDispatcher()`| eventDispatcher | Set PSR-14 event dispatcher, see [Events](../advanced/events.md)|
429
469
|`setFiberScheduler()`| scheduler | Wait on an event loop (Revolt, ReactPHP) while a handler awaits I/O, see [Fiber Scheduler](#fiber-scheduler)|
470
+
|`setFiberContext()`| context | Carry execution context into handler fibers, see [Fiber Context](#fiber-context)|
430
471
|`setSchemaGenerator()`| schemaGenerator | Replace the generator that builds input schemas from PHP types, see [Schema generation](../servers/schemas.md)|
431
472
|`setSchemaValidator()`| schemaValidator | Replace the validator for tool arguments and structured output, see [Schema generation](../servers/schemas.md)|
432
473
|`setReferenceHandler()`| referenceHandler | Replace the class that calls the handlers of tools, resources and prompts |
0 commit comments