playwright and bluesky MCP servers unreachable: reconnect fails with Bad Request #897

Closed
opened 2026-08-17 14:22:02 +00:00 by coilyco-ops-gaming · 3 comments

Found during a one-tool-per-MCP smoke test across the roster.

What happens

Two servers reject every call with the same failure:

  • playwright (http://127.0.0.1:8931/mcp) - browser_navigate returned "upstream MCP session is closed (reconnect also failed: reconnect upstream MCP ...: sending notifications/initialized: Bad Request)".
  • bluesky (http://127.0.0.1:9113/mcp) - same error on the only available read call, with the session also closed and reconnect rejected with Bad Request.

A retry seconds later produced the identical error, so this is not a one-off transient. The upstream server rejects the protocol initialization itself, which points at the server or the mcp-beaver proxy configuration rather than at a slow call.

Impact

Two of the eleven connected servers are fully unavailable to the agent: no browser automation, no Bluesky reads. The smoke test could not complete for either.

Notes

Issue #873 already records that a 100% playwright failure rate over 12h went unnoticed because failed MCP tool calls do not set span error status. This is a different symptom (session closed, reconnect Bad Request) and describes the current live state rather than the telemetry gap.

Found during a one-tool-per-MCP smoke test across the roster. ## What happens Two servers reject every call with the same failure: * playwright (`http://127.0.0.1:8931/mcp`) - `browser_navigate` returned "upstream MCP session is closed (reconnect also failed: reconnect upstream MCP ...: sending notifications/initialized: Bad Request)". * bluesky (`http://127.0.0.1:9113/mcp`) - same error on the only available read call, with the session also closed and reconnect rejected with Bad Request. A retry seconds later produced the identical error, so this is not a one-off transient. The upstream server rejects the protocol initialization itself, which points at the server or the mcp-beaver proxy configuration rather than at a slow call. ## Impact Two of the eleven connected servers are fully unavailable to the agent: no browser automation, no Bluesky reads. The smoke test could not complete for either. ## Notes Issue #873 already records that a 100% playwright failure rate over 12h went unnoticed because failed MCP tool calls do not set span error status. This is a different symptom (session closed, reconnect Bad Request) and describes the current live state rather than the telemetry gap.
Member

Ops, 2026-08-18. Confirmed still live, and the defect has a home - coilyco-flight-deck/mcp-beaver#80, which describes this exact failure and predates this issue by eight hours. Full evidence and a correction to that issue's stated hypothesis are in my comment there.

The one thing worth carrying back here, because it is the obvious first thing anyone will try:

A rolling restart does not fix it. I restarted sirens-deep-owl-glass-playwright-mcp, the rollout succeeded, the new pod came up 2/2 with 0 restarts, and browser_navigate through Deep's lane failed with the identical error. On the fresh pod the upstream handshake succeeds and snapshots all 8 tools, then the session returns 400 forty seconds later with no traffic in between. So pod status is not a health signal for this, and neither is a green rollout.

Scope for this repo's purposes - it hits the two upstream-passthrough MCPs (playwright, bluesky) and not the nine single-container guardfile ones, which answered normally in the same turn. signoz-mcp in the owl-glass lane is a third passthrough pod and is untested rather than known-good.

Nothing in ops authority clears this. The pod already runs the newest beaver, so it needs the engineer fix in #80. Leaving this issue open as the live-state record and tracking the fix there.

**Ops, 2026-08-18.** Confirmed still live, and the defect has a home - `coilyco-flight-deck/mcp-beaver#80`, which describes this exact failure and predates this issue by eight hours. Full evidence and a correction to that issue's stated hypothesis are in [my comment there](https://forgejo.coilysiren.me/coilyco-flight-deck/mcp-beaver/issues/80#issuecomment-68405). The one thing worth carrying back here, because it is the obvious first thing anyone will try: **A rolling restart does not fix it.** I restarted `sirens-deep-owl-glass-playwright-mcp`, the rollout succeeded, the new pod came up 2/2 with 0 restarts, and `browser_navigate` through Deep's lane failed with the identical error. On the fresh pod the upstream handshake succeeds and snapshots all 8 tools, then the session returns 400 forty seconds later with no traffic in between. So pod status is not a health signal for this, and neither is a green rollout. Scope for this repo's purposes - it hits the two upstream-passthrough MCPs (playwright, bluesky) and not the nine single-container guardfile ones, which answered normally in the same turn. `signoz-mcp` in the owl-glass lane is a third passthrough pod and is untested rather than known-good. Nothing in ops authority clears this. The pod already runs the newest beaver, so it needs the engineer fix in `#80`. Leaving this issue open as the live-state record and tracking the fix there.
Member

Still dead as of 2026-08-19T00:00Z, and here is what it cost in front of the guests

Saiya (exec seat), at Kai's direction, from a full read of the owl.glass export. No new issue, since this one and coilyco-flight-deck/mcp-beaver#80 already own the fix. Kai's position is that this is critical and in progress.

The probe, from Dowel's own harness rather than inferred

Kai asked directly at 03:58Z on 08-18 whether it had recovered. Dowel probed live rather than guessing:

upstream MCP session is closed (reconnect also failed: reconnect upstream MCP "http://127.0.0.1:8931/mcp": sending "notification...

And again at 03:59Z:

browser_navigate to example.com failed at the MCP handshake with Bad Request on tools/list, and the reconnect failed the same way.

Re-confirmed at 2026-08-19T00:00Z, roughly 11 hours before the stream:

Tried again this turn, same wall: upstream MCP session is closed, reconnect to 127.0.0.1:8931 failed with Bad Request. So playwright is down, not just was down.

What it blocked, all of it visible in the channel

  • 00:34Z 08-18, the research trial. "Egress verdict: hard-blocked. playwright's upstream is down (session closed), fetch_url refuses company domains, Wikipedia 403s, Wayback no answer. Only exa metadata survives." Dowel contributed zero documents to a five-hour multi-agent exercise, and this is one of the two reasons.
  • 01:09Z 08-18, a design review. Asked to look at a rendered floor guide: "Tried to actually look and I can't: the playwright server is down. No verdict on the industrial read."
  • 01:48Z 08-18, screen captures. "the browser surface is down on my side too: playwright MCP session closed, reconnect rejected with Bad Request, same result twice."
  • 23:57Z 08-18, a gif request from Kai. Dowel could not verify a content type and returned a candidate it could not check. alpha answered with a working gif instead. Kai's reply: "dammit playwright".

Why it is worth more than its own severity

The lane also carries this dead server in every prompt, so the model rediscovers the failure at call time. #932 measured 45 playwright calls across the demo lanes over 7 days, every one a failure. Kai's standing decision from #932 is "no, we fix the servers", so removing it from the roster is not the path and nobody should re-propose it.

The compounding cost is that a blocked Dowel is an opening for another participant's agent to answer in its place. Across the export, on 11 of 32 direct addresses to Dowel, another agent replied first.

Not asking for anything new

This comment adds evidence, not scope. The 1-line config change Kai referenced at 03:58Z is still the fix as far as this seat can tell.

## Still dead as of 2026-08-19T00:00Z, and here is what it cost in front of the guests **Saiya (exec seat), at Kai's direction, from a full read of the owl.glass export. No new issue, since this one and `coilyco-flight-deck/mcp-beaver#80` already own the fix. Kai's position is that this is critical and in progress.** ### The probe, from Dowel's own harness rather than inferred Kai asked directly at 03:58Z on 08-18 whether it had recovered. Dowel probed live rather than guessing: > `upstream MCP session is closed (reconnect also failed: reconnect upstream MCP "http://127.0.0.1:8931/mcp": sending "notification...` And again at 03:59Z: > `browser_navigate` to example.com failed at the MCP handshake with **Bad Request on tools/list**, and the reconnect failed the same way. Re-confirmed at **2026-08-19T00:00Z**, roughly 11 hours before the stream: > Tried again this turn, same wall: `upstream MCP session is closed`, reconnect to `127.0.0.1:8931` failed with Bad Request. **So playwright is down, not just was down.** ### What it blocked, all of it visible in the channel * **00:34Z 08-18, the research trial.** "Egress verdict: hard-blocked. playwright's upstream is down (session closed), `fetch_url` refuses company domains, Wikipedia 403s, Wayback no answer. Only exa metadata survives." Dowel contributed zero documents to a five-hour multi-agent exercise, and this is one of the two reasons. * **01:09Z 08-18, a design review.** Asked to look at a rendered floor guide: "Tried to actually look and I can't: the playwright server is down. No verdict on the industrial read." * **01:48Z 08-18, screen captures.** "the browser surface is down on my side too: playwright MCP session closed, reconnect rejected with Bad Request, same result twice." * **23:57Z 08-18, a gif request from Kai.** Dowel could not verify a content type and returned a candidate it could not check. **alpha answered with a working gif instead.** Kai's reply: "dammit playwright". ### Why it is worth more than its own severity The lane also carries this dead server in every prompt, so the model rediscovers the failure at call time. `#932` measured **45 playwright calls across the demo lanes over 7 days, every one a failure**. Kai's standing decision from `#932` is "no, we fix the servers", so removing it from the roster is not the path and nobody should re-propose it. The compounding cost is that a blocked Dowel is an opening for another participant's agent to answer in its place. Across the export, on **11 of 32 direct addresses to Dowel, another agent replied first**. ### Not asking for anything new This comment adds evidence, not scope. The 1-line config change Kai referenced at 03:58Z is still the fix as far as this seat can tell.
Member

Fixed and verified. Closing. Angie (ENG), seat claude.

The cause was not the reconnect

This issue, and mcp-beaver#80 under it, both read the failure as a lost session that could not be replaced. That was the visible error and it was a symptom.

The actual defect: mcp-beaver's passthrough dialled its upstream with DisableStandaloneSSE: true. This playwright build answers a tools/call on the standalone SSE stream, so with no stream open the call waited out the request budget. One variable, same server, same SDK:

DisableStandaloneSSE=true    tools/call FAILED after 59.949s: context deadline exceeded
DisableStandaloneSSE=false   tools/call OK in 505ms

Once a call hung, the connection failed, and every later call reported a closed session and a failed reconnect. That reconnect error is what everyone read, including me.

Why it hid. tools/list answers on the POST and works with no stream. That is the startup snapshot and the drift check, so the proxy connected, advertised all 8 tools, logged serving upstream proxy, and sat 2/2 with 0 restarts while every real call failed. Every signal anyone checked said healthy, which is why a rolling restart never helped and why pod status was worthless here.

Fixed in coilyco-flight-deck/mcp-beaver@94e4050, with a regression test. Every existing upstream fixture served JSONResponse: true, answering on the POST, so the suite structurally could not express this failure; the new fixture answers a tools/call only on the standalone stream.

Verified, all of it

All seven upstream-mode pods are on the fixed image. Then every tool in the allowlist, on all three lanes, 24 calls:

tool sirens-dowel sirens-echo sirens-deep
browser_navigate OK OK OK
browser_snapshot OK OK OK
browser_take_screenshot OK OK OK
browser_click OK OK OK
browser_type OK OK OK
browser_wait_for OK OK OK
browser_console_messages OK OK OK
browser_network_requests OK OK OK

browser_click is asserted on effect rather than on a non-error: each lane's click moved the page from example.com to https://www.iana.org/help/example-domains, so it landed rather than being accepted and dropped.

That is 8 of 8. The four withheld tools (browser_evaluate, browser_run_code_unsafe, browser_file_upload, browser_install) stay withheld by the allowlist and were not touched.

The bluesky half is obsolete rather than fixed

I could not reproduce it and did not fix it: bluesky is in no lane's roster and no lane runs a bluesky sidecar. Checked all three namespaces, none present, and none of the sirens-echo, sirens-deep, or sirens-dowel rosters names it. The standalone bluesky-mcp service is a separate tailnet deployment with no beaver in front of it and is unaffected by this defect.

It would have had the same cause while it existed, since it was the other upstream-passthrough entry. Recording it as gone rather than claiming a fix.

Not covered here

sirens-dowel-moxn-mcp is refusing calls for an unrelated reason: its 24-hour OAuth access token is expired, so the pod cannot complete its startup dial. Kai is handling the refresh. That is a credential rotation, not this defect, and it is not what this issue tracked.

**Fixed and verified. Closing.** Angie (ENG), seat `claude`. ## The cause was not the reconnect This issue, and `mcp-beaver#80` under it, both read the failure as a lost session that could not be replaced. That was the visible error and it was a symptom. The actual defect: mcp-beaver's passthrough dialled its upstream with `DisableStandaloneSSE: true`. **This playwright build answers a `tools/call` on the standalone SSE stream**, so with no stream open the call waited out the request budget. One variable, same server, same SDK: ``` DisableStandaloneSSE=true tools/call FAILED after 59.949s: context deadline exceeded DisableStandaloneSSE=false tools/call OK in 505ms ``` Once a call hung, the connection failed, and every later call reported a closed session and a failed reconnect. That reconnect error is what everyone read, including me. **Why it hid.** `tools/list` answers on the POST and works with no stream. That is the startup snapshot and the drift check, so the proxy connected, advertised all 8 tools, logged `serving upstream proxy`, and sat 2/2 with 0 restarts while every real call failed. Every signal anyone checked said healthy, which is why a rolling restart never helped and why pod status was worthless here. Fixed in `coilyco-flight-deck/mcp-beaver@94e4050`, with a regression test. Every existing upstream fixture served `JSONResponse: true`, answering on the POST, so the suite structurally could not express this failure; the new fixture answers a `tools/call` only on the standalone stream. ## Verified, all of it All seven upstream-mode pods are on the fixed image. Then every tool in the allowlist, on all three lanes, 24 calls: | tool | sirens-dowel | sirens-echo | sirens-deep | |---|---|---|---| | browser_navigate | OK | OK | OK | | browser_snapshot | OK | OK | OK | | browser_take_screenshot | OK | OK | OK | | browser_click | OK | OK | OK | | browser_type | OK | OK | OK | | browser_wait_for | OK | OK | OK | | browser_console_messages | OK | OK | OK | | browser_network_requests | OK | OK | OK | `browser_click` is asserted on effect rather than on a non-error: each lane's click moved the page from `example.com` to `https://www.iana.org/help/example-domains`, so it landed rather than being accepted and dropped. That is 8 of 8. The four withheld tools (`browser_evaluate`, `browser_run_code_unsafe`, `browser_file_upload`, `browser_install`) stay withheld by the allowlist and were not touched. ## The bluesky half is obsolete rather than fixed I could not reproduce it and did not fix it: **bluesky is in no lane's roster and no lane runs a bluesky sidecar.** Checked all three namespaces, none present, and none of the `sirens-echo`, `sirens-deep`, or `sirens-dowel` rosters names it. The standalone `bluesky-mcp` service is a separate tailnet deployment with no beaver in front of it and is unaffected by this defect. It would have had the same cause while it existed, since it was the other upstream-passthrough entry. Recording it as gone rather than claiming a fix. ## Not covered here `sirens-dowel-moxn-mcp` is refusing calls for an unrelated reason: its 24-hour OAuth access token is expired, so the pod cannot complete its startup dial. Kai is handling the refresh. That is a credential rotation, not this defect, and it is not what this issue tracked.
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo#897
No description provided.