From 4273e2c73be952a203499a9cea76b4b67788866b Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Mon, 7 Sep 2026 09:30:00 +0300 Subject: [PATCH] docs(adr): record that FastMCP 4 fired ADR 0001's revisit trigger add_extension/ServerExtension.lifespan satisfies the trigger's second clause, but ServerExtension.identifier is advertised under ServerCapabilities.extensions, so adopting it would announce a protocol capability the bootstrapper does not implement. Narrow the trigger to a hook that is not client-visible. --- ...-fastmcp-teardown-via-provider-lifespan.md | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/docs/adr/0001-fastmcp-teardown-via-provider-lifespan.md b/docs/adr/0001-fastmcp-teardown-via-provider-lifespan.md index 051b001..ecd9829 100644 --- a/docs/adr/0001-fastmcp-teardown-via-provider-lifespan.md +++ b/docs/adr/0001-fastmcp-teardown-via-provider-lifespan.md @@ -25,6 +25,26 @@ The accepted cost is semantic: `Provider` is FastMCP's general extension abstrac resources and prompts, and using one purely for a shutdown callback is thin. A one-line comment at the registration site says so. -**Revisit trigger:** FastMCP grows a first-class shutdown hook (an `on_shutdown` API, or a -documented public way to compose a lifespan post-construction). At that point the provider is the -indirect route and should be replaced by the direct one. +## FastMCP 4 fired the trigger, and the replacement was rejected + +FastMCP 4 added `FastMCP.add_extension(extension: ServerExtension)`, whose +`ServerExtension.lifespan()` is documented as "A context manager entered with the server's lifespan, +exited on shutdown", to "start and stop resources an extension owns". That is literally the second +clause of this ADR's original trigger, "a documented public way to compose a lifespan +post-construction". The first clause did not fire: `on_shutdown` and `on_startup` are still absent +in 4.0.3. + +Rejected: **switch `_TeardownProvider` to a `ServerExtension`.** It trades a thin misuse for a +client-visible one. `ServerExtension.identifier` is a required reverse-DNS string, validated at +registration, and its own comment states it is "advertised under `ServerCapabilities.extensions`". +Registering one purely for a shutdown callback would announce a protocol capability the bootstrapper +does not implement, where the `Provider` route's thinness is invisible outside the process. A +teardown hook must not change what the server tells its clients it can do. + +Reinforcing it: the `fastmcp` extra declares an unbounded `"fastmcp"`, so `ServerExtension` may not +exist at runtime. Adopting it would force a `fastmcp>=4` floor on an optional extra to buy a +semantically worse hook. + +**Revisit trigger:** FastMCP grows a shutdown hook that is neither client-visible nor tied to +another abstraction's semantics, most likely an `on_shutdown` API. `add_extension` does not qualify +and should not be revisited on version bumps alone.