jackwener/maka-agent

mcp: tool discovery livelocks against a server that notifies list_changed after every tools/list

開放

#2,981 建立於 2026年8月13日

 (0 則留言) (0 個反應) (0 位負責人)TypeScript (0 個分叉)github user discovery
bughelp wanted

倉庫指標

星標
 (1 顆星)
PR 合併指標
 (PR 指標待抓取)

描述

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:

  1. 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.
  2. Cap consecutive rediscoveries per connection generation, then stop honouring further notifications and surface the server as degraded.
  3. 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.

貢獻者指南