Summary
pyproject.toml silences DeprecationWarning for libtmux.*, libtmux_mcp.*, and tests. Because library deprecations are raised with stacklevel pointing at the caller, those three module patterns are exactly where a deprecation this project needs to act on gets attributed — so the filters suppress the signal rather than third-party noise. They are already hiding a real one.
The filters
pyproject.toml#L258-L263:
filterwarnings = [
"ignore:The frontend.Option(Parser)? class.*:DeprecationWarning::",
"ignore::DeprecationWarning:libtmux.*:",
"ignore::DeprecationWarning:libtmux_mcp.*:",
"ignore::DeprecationWarning:tests:",
]
The first entry is a narrow, message-scoped filter for a docutils warning and is fine. The other three are blanket category filters scoped by module.
Why this suppresses the wrong thing
A warning's module is matched against the __name__ of the frame the warning is attributed to, which stacklevel controls. Libraries raise deprecations with stacklevel=2 so the warning points at the line that used the deprecated API — which for this project is a module under libtmux_mcp.* or a test body under tests. The filters therefore hit precisely the warnings that indicate this codebase needs to change, while a warning raised from an unrelated package still surfaces.
Compounding it, FastMCPDeprecationWarning subclasses DeprecationWarning, so the category filters catch FastMCP's own deprecations too:
FastMCPDeprecationWarning.__mro__ -> (FastMCPDeprecationWarning, DeprecationWarning, Warning, ...)
issubclass(FastMCPDeprecationWarning, DeprecationWarning) -> True
Verified by A/B probe under the repo's real config — two tests in one run, one warning emitted from each namespace:
| Warning attributed to |
Result |
libtmux_mcp.server |
suppressed, absent from the warnings summary |
some_other_package.thing |
surfaces normally |
It is already hiding something
Removing the three blanket entries and running the suite: 801 passed, 2 warnings, both real and both previously invisible.
tests/test_wait_for_tools.py#L57-L58:
DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for
removal in Python 3.16; use inspect.iscoroutinefunction() instead
Nothing else warns. The suppression is buying no quiet — it is costing exactly one signal, and that signal is a scheduled removal from the standard library.
Why it matters now
SEP-2596 obliges Tier 1 SDKs to "emit a runtime warning when a deprecated feature is exercised, using the language's idiomatic mechanism (for example Python's DeprecationWarning)" once a feature enters the Deprecated state. That machinery is about to start firing, against a suite configured not to listen:
- Spec revision
2026-07-28 deprecates Roots, Sampling, and Logging (SEP-2577).
mcp 2.0.0 is targeted for the same date; it removes the mcp.types submodule in favour of a standalone package and drops camelCase attribute access on protocol models.
fastmcp v4 is in alpha against the <4.0.0 ceiling this project pins.
There is real exposure behind those: 13 .inputSchema reads across tests/test_history.py and tests/test_spawn_tools_history.py, mcp.types imports in src/libtmux_mcp/middleware.py, and _client_label() reading client identity off the initialize handshake that 2026-07-28 removes. None of it breaks today — fastmcp 3.4.4 pins mcp<2.0, so 2.x cannot resolve into this environment — but the warnings are how that transition is supposed to announce itself.
Proposed change
- Delete the three blanket
ignore::DeprecationWarning:<module>: entries. Keep the message-scoped docutils filter.
- Replace
asyncio.iscoroutinefunction with inspect.iscoroutinefunction at the two call sites.
Deliberately not proposing error::DeprecationWarning. This project pins two fast-moving pre-2.0 dependencies, and escalating to an error means an upstream patch release can turn CI red with no local change. Visible-but-not-fatal restores the signal without handing release timing control of the build to upstream. Worth revisiting once mcp 2.x and fastmcp v4 have settled.
Summary
pyproject.tomlsilencesDeprecationWarningforlibtmux.*,libtmux_mcp.*, andtests. Because library deprecations are raised withstacklevelpointing at the caller, those three module patterns are exactly where a deprecation this project needs to act on gets attributed — so the filters suppress the signal rather than third-party noise. They are already hiding a real one.The filters
pyproject.toml#L258-L263:The first entry is a narrow, message-scoped filter for a docutils warning and is fine. The other three are blanket category filters scoped by module.
Why this suppresses the wrong thing
A warning's
moduleis matched against the__name__of the frame the warning is attributed to, whichstacklevelcontrols. Libraries raise deprecations withstacklevel=2so the warning points at the line that used the deprecated API — which for this project is a module underlibtmux_mcp.*or a test body undertests. The filters therefore hit precisely the warnings that indicate this codebase needs to change, while a warning raised from an unrelated package still surfaces.Compounding it,
FastMCPDeprecationWarningsubclassesDeprecationWarning, so the category filters catch FastMCP's own deprecations too:Verified by A/B probe under the repo's real config — two tests in one run, one warning emitted from each namespace:
libtmux_mcp.serversome_other_package.thingIt is already hiding something
Removing the three blanket entries and running the suite: 801 passed, 2 warnings, both real and both previously invisible.
tests/test_wait_for_tools.py#L57-L58:Nothing else warns. The suppression is buying no quiet — it is costing exactly one signal, and that signal is a scheduled removal from the standard library.
Why it matters now
SEP-2596 obliges Tier 1 SDKs to "emit a runtime warning when a deprecated feature is exercised, using the language's idiomatic mechanism (for example Python's
DeprecationWarning)" once a feature enters the Deprecated state. That machinery is about to start firing, against a suite configured not to listen:2026-07-28deprecates Roots, Sampling, and Logging (SEP-2577).mcp2.0.0 is targeted for the same date; it removes themcp.typessubmodule in favour of a standalone package and drops camelCase attribute access on protocol models.fastmcpv4 is in alpha against the<4.0.0ceiling this project pins.There is real exposure behind those: 13
.inputSchemareads acrosstests/test_history.pyandtests/test_spawn_tools_history.py,mcp.typesimports insrc/libtmux_mcp/middleware.py, and_client_label()reading client identity off theinitializehandshake that2026-07-28removes. None of it breaks today —fastmcp3.4.4 pinsmcp<2.0, so 2.x cannot resolve into this environment — but the warnings are how that transition is supposed to announce itself.Proposed change
ignore::DeprecationWarning:<module>:entries. Keep the message-scoped docutils filter.asyncio.iscoroutinefunctionwithinspect.iscoroutinefunctionat the two call sites.Deliberately not proposing
error::DeprecationWarning. This project pins two fast-moving pre-2.0 dependencies, and escalating to an error means an upstream patch release can turn CI red with no local change. Visible-but-not-fatal restores the signal without handing release timing control of the build to upstream. Worth revisiting oncemcp2.x andfastmcpv4 have settled.