Add server lifecycle events (ServerStarted / ServerStopped)
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
Start at Server::run($transport), then inspect Protocol::handleRequest and the Builder-created transport entry points. Review the existing events and their dispatching tests, if present. Done means ServerStartedEvent fires once before the first request and ServerStoppedEvent fires from finally on clean exit, exceptions, and transport close, carrying the specified context.
Written by the indexing model from the issue text.
Description
Problem
The SDK currently dispatches only request-scoped events (RequestEvent, ResponseEvent, ErrorEvent, list-changed events). There is no hook that fires once per Server::run() invocation.
Consumers that need one-time setup/teardown per server boot must either:
- Duplicate the logic in every transport's entry point (HTTP controller, CLI command, custom transports), or
- Subscribe to
RequestEvent+ matchingResponseEvent/ErrorEventand deal with per-request overhead, fiber suspension, and every error path.
Proposal
Add two events in Mcp\Event:
ServerStartedEvent— dispatched at the top ofServer::run($transport), before the first request is read. Exposes the server and transport.ServerStoppedEvent— dispatched just beforeServer::run()returns, in afinallyso it fires on clean exit, thrown exceptions, and transport close. Exposes the exit code and any captured throwable.
Use cases
- Identity / impersonation: switch the current user of a host framework (Drupal, Symfony Security) once when the server boots. This is our concrete motivation — without a lifecycle hook we either patch every transport or pay the cost of switching on every
RequestEvent. - Metrics / observability: increment
mcp_server_started_total, start a run-duration timer, emit a "server up" log line including registered tool/prompt/resource counts. - Resource management: warm caches, acquire leases, open long-lived connections at start; release them at stop.
Alternatives considered
- Use
RequestEventas a pseudo-start hook — works but is per-request. Adds overhead to what is logically a one-shot, and requires pairing withResponseEvent/ErrorEventfor cleanup. Fiber suspension (Protocol::handleRequest, early return on$fiber->isSuspended()) means the terminal event can be delayed or skipped from the subscriber's perspective. - Subclassing
Server— not portable; transports and framework integrations instantiateServerdirectly via theBuilder. - Transport-level hooks — would require a change in every transport implementation (Stdio, StreamableHttp, any custom transport) rather than in one place in
Server::run().
Backward compatibility
Purely additive. Subscribers that don't care about the new events are unaffected. No public API changes to existing events or handlers.
- Dominant language
- PHP
- Stars
- 1.6k
- Forks
- 173
- Avg merge
- 2d 49m
- Merged PRs (30d)
- 23
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from modelcontextprotocol/php-sdk
-
[Server] Handler type uses bare Closure, hard to decorate RegistryInterface under strict PHPStan OpenServer
Difficulty 1/5 Under an hour Newbie friendliness 78/100
modelcontextprotocol/php-sdk#468 · 2 comments ·
-
needs confirmation needs maintainer action Server
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
modelcontextprotocol/php-sdk#398 · 1 reaction ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
modelcontextprotocol/php-sdk#370 ·
-
enhancement
Difficulty 4/5 3-5 days Newbie friendliness 55/100
modelcontextprotocol/php-sdk#510 · 1 comment ·
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 45/100
modelcontextprotocol/php-sdk#504 ·
All issues in modelcontextprotocol/php-sdk
Similar issues
-
a11y admissions.uiowa.edu needs grooming SiteImprove best practice
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
-
Save States Menu Open
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
pluginsGLPI/datainjection#673 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
octobercms/october#6130 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
getgrav/grav-plugin-form#656 ·