mcp: tool discovery livelocks against a server that notifies list_changed after every tools/list
#2.981 aberto em 13 de ago. de 2026
Métricas do repositório
- Stars
- (1 estrela)
- Métricas de merge de PR
- (Métricas PR pendentes)
Description
Context
A server that emits tools/list_changed after every tools/list response livelocks tool discovery. Each notification schedules another discovery pass, whose response triggers the next notification, with no bound on the loop.
Measured with a probe server that notifies on every list: ~2000 tools/list round trips in 4 seconds, sync() never settling, and the manager unable to remove that server from the configuration — the removal sync queues behind a discovery that never finishes.
This is pre-existing, not a regression. I found it while reviewing #2663 and initially took it for a regression from installing the change handler before initial discovery; it is not. The same probe against origin/main produces the same ~2000-iteration loop. Noted in that review as out of scope there.
Severity
P2. Unlike most items in this class, something on main genuinely misbehaves rather than merely lacking protection: discovery hangs and configuration reconciliation stalls behind it. Held at P2 because triggering requires a server that notifies on every list — real servers notify on actual change — and it self-recovers the moment the server stops notifying. It has been in place a long time with no report.
Fix
Bound the rediscovery loop. Options, roughly in order of preference:
- Debounce
list_changed— collapse notifications that arrive while a discovery for the same server is in flight or within a short window after it completes. - Cap consecutive rediscoveries per connection generation, then stop honouring further notifications and surface the server as degraded.
- At minimum, let a pending configuration sync preempt an in-flight discovery, so a misbehaving server can always be removed.
(3) is worth having regardless of (1) and (2): the manager should never be unable to drop a server.
Verification
A probe server whose tools/list handler schedules sendToolListChanged() on every call. Assert that list round trips stay bounded, that sync() settles, and that a follow-up sync() removing the server completes.