modelcontextprotocol / modelcontextprotocol/php-sdk
Add server lifecycle events (ServerStarted / ServerStopped)
还没有人认领这个 Issue。
- 主要语言
- PHP
- 星标
- 1.6k
- 派生
- 173
- 平均合并
- 2 天 49 分钟
- 30 天内合并 PR
- 23
描述
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.
贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
调研方向
从 Server::run($transport) 开始,然后检查 Protocol::handleRequest 和由 Builder 创建的 transport 入口点。检查现有的 Events 及其 dispatching 测试(如果有)。完成的标准是:ServerStartedEvent 在第一个请求之前触发一次,并且 ServerStoppedEvent 在正常退出、发生 exceptions 以及 transport 关闭时从 finally 中触发,同时携带指定的 context。
由索引模型根据 Issue 内容生成。
评估
- 技术栈
- php
- 领域
- api, backend
- Issue 类型
- 功能
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 活跃度
- 冷清
- 描述清晰度
- 基本清楚
- 新手友好度
- 52/100