fix(#2038): don't treat MCP 'pending' status as degraded
pending is the claude CLI's normal init-event race for a freshly spawned stdio server (status reported before the handshake completes, then flips to connected moments later in the same turn — see anthropics/claude-agent-sdk-typescript#368). flagging it fired on nearly every turn for all three configured servers with zero actual impact, which is why #2038's persistent-vs-one-turn repro question looked answered when it wasn't — that was this false positive, not the real bug.
This commit is contained in:
parent
a80d0b0fed
commit
ee072149c9
1 changed files with 32 additions and 6 deletions
|
|
@ -677,9 +677,18 @@ impl Bus {
|
|||
/// never touches the session. It exists because the harness is
|
||||
/// otherwise blind to the init event — the only place claude reports
|
||||
/// MCP-server status — so a dropped/failed stdio bridge (e.g. matrix
|
||||
/// after a core bounce) went silent. Emitted every degraded turn on
|
||||
/// purpose: whether it persists across fresh turns is the signal that
|
||||
/// picks the real fix.
|
||||
/// after a core bounce) went silent.
|
||||
///
|
||||
/// `pending` is deliberately NOT treated as degraded: it's the claude
|
||||
/// CLI's normal init-event race for a freshly spawned stdio server
|
||||
/// (status is reported before the handshake completes, then flips to
|
||||
/// `connected` moments later in the same turn — see the upstream
|
||||
/// claude-agent-sdk-typescript repo, issue number 368, for confirmation).
|
||||
/// Flagging it fired on nearly every turn for all three configured
|
||||
/// servers with zero actual impact (confirmed: tools kept working),
|
||||
/// which is why the MCP-dropped-after-restart tracker issue's
|
||||
/// persistent-vs-one-turn repro question looked answered "persistent"
|
||||
/// when it wasn't — that was this false positive, not the real bug.
|
||||
pub(crate) fn observe_mcp_health(&self, v: &serde_json::Value) {
|
||||
if v.get("type").and_then(|t| t.as_str()) != Some("system")
|
||||
|| v.get("subtype").and_then(|s| s.as_str()) != Some("init")
|
||||
|
|
@ -886,8 +895,11 @@ impl Default for Bus {
|
|||
/// Compare the configured MCP server names against the `{name -> status}`
|
||||
/// map parsed from the init event, returning display strings for the
|
||||
/// degraded ones: a configured server absent from the report was dropped
|
||||
/// entirely; one present with a non-`connected` status failed to register.
|
||||
/// Pure so it's unit-testable without a live `Bus`.
|
||||
/// entirely; one present with a non-`connected`, non-`pending` status
|
||||
/// failed to register. `pending` is excluded — it's the CLI's normal
|
||||
/// init-event race for a server still completing its handshake, not a
|
||||
/// failure (see the doc comment on `observe_mcp_health`). Pure so it's
|
||||
/// unit-testable without a live `Bus`.
|
||||
fn degraded_mcp_servers(
|
||||
configured: &[String],
|
||||
reported: &std::collections::HashMap<&str, &str>,
|
||||
|
|
@ -895,7 +907,7 @@ fn degraded_mcp_servers(
|
|||
configured
|
||||
.iter()
|
||||
.filter_map(|name| match reported.get(name.as_str()).copied() {
|
||||
Some("connected") => None,
|
||||
Some("connected" | "pending") => None,
|
||||
Some(status) => Some(format!("{name} ({status})")),
|
||||
None => Some(format!("{name} (absent)")),
|
||||
})
|
||||
|
|
@ -963,4 +975,18 @@ mod tests {
|
|||
.collect();
|
||||
assert!(super::degraded_mcp_servers(&configured, &reported).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn degraded_mcp_servers_ignores_pending() {
|
||||
// `pending` is the CLI's normal init-event race for a stdio server
|
||||
// still completing its handshake (flips to `connected` moments
|
||||
// later in the same turn) — not a real failure, per the
|
||||
// MCP-dropped-after-restart tracker issue.
|
||||
use std::collections::HashMap;
|
||||
let configured = ["hyperhive".to_owned(), "matrix".to_owned()];
|
||||
let reported: HashMap<&str, &str> = [("hyperhive", "pending"), ("matrix", "pending")]
|
||||
.into_iter()
|
||||
.collect();
|
||||
assert!(super::degraded_mcp_servers(&configured, &reported).is_empty());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue