Follow-up to a review thread on #71 (#71 (comment)).
With DynamicToolCompatibilityMode.DiscoverAndCallShim, one handler serving several initialize-era
sessions transitions each from the intro catalog (discover_tools / call_tool) to the real one on
that session's first tools/list. The transition is connection-local — TryClaimCompatibilityIntro()
is claimed per McpSessionContext, so no session can consume another's intro.
What is not connection-local is the notification. SignalToolListChanged() clears a handler-wide
collection whose SDK subscribers fan out to every attached session, so one session's transition sends
tools/list_changed to every other legacy session and to modern subscribers with no interest in it.
Why this was not fixed in #71
The advertised set a modern client would re-list is unchanged, so there is no invariance consequence;
what leaks is spurious notification traffic. And the whole path sits behind
DynamicToolCompatibility, which is Disabled by default.
It still jars with a release whose subject is connection-scoped state: a connection-local event
fanning out globally is the shape that pull request spent its time removing everywhere else.
Shape
Target request.Server for this one transition rather than the shared routing-change signal. The
guard belongs beside the existing shim tests in Given_McpConcurrentSessions, asserting that a
second session receives no tools/list_changed when the first consumes its intro.
Follow-up to a review thread on #71 (#71 (comment)).
With
DynamicToolCompatibilityMode.DiscoverAndCallShim, one handler serving several initialize-erasessions transitions each from the intro catalog (
discover_tools/call_tool) to the real one onthat session's first
tools/list. The transition is connection-local —TryClaimCompatibilityIntro()is claimed per
McpSessionContext, so no session can consume another's intro.What is not connection-local is the notification.
SignalToolListChanged()clears a handler-widecollection whose SDK subscribers fan out to every attached session, so one session's transition sends
tools/list_changedto every other legacy session and to modern subscribers with no interest in it.Why this was not fixed in #71
The advertised set a modern client would re-list is unchanged, so there is no invariance consequence;
what leaks is spurious notification traffic. And the whole path sits behind
DynamicToolCompatibility, which isDisabledby default.It still jars with a release whose subject is connection-scoped state: a connection-local event
fanning out globally is the shape that pull request spent its time removing everywhere else.
Shape
Target
request.Serverfor this one transition rather than the shared routing-change signal. Theguard belongs beside the existing shim tests in
Given_McpConcurrentSessions, asserting that asecond session receives no
tools/list_changedwhen the first consumes its intro.