Files
PaperClipAI/packages
DottaandClaude Opus 5.5 64afd22d82 fix(runner): keep the OpenCode MCP bridge on keep-alive so OpenCode keeps its Paperclip tools (#20921)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - Native OpenCode agents call Paperclip tools through a local MCP
bridge in the runner's OpenCode proxy
> - #20886 made the bridge send `Connection: close` on every response,
as hardening for one stalled parallel tool call that was never
reproduced
> - After #20886 merged, many native OpenCode runs started without any
Paperclip MCP tools
> - Agents then said the Paperclip tools were missing, worked only with
bash and file tools, and never called paperclip_finish
> - This pull request removes the `Connection: close` header and keeps
the delivery diagnostics from #20886
> - The benefit is that OpenCode agents get their Paperclip tools again,
and a recurrence of the original stall still shows in the run log

## Linked Issues or Issue Description

Refs #20886.

**What happened**
In chat eval runs on CI, every OpenCode session before #20886 sent a
first model request of about 34k–36k input tokens (prompt plus the
Paperclip tool schemas). After #20886, about 9 of 25 sessions sent only
about 8k–15k tokens on the same prompts (for example 14,711 for
questions-and-approvals.necessary-question, 15,481 for
cases.cases-disabled, 14,096 for cases.update-case-facts). The prompt
envelope size did not change (about 32.7k characters). Those sessions
made no Paperclip MCP calls: zero tool-delivery records, no
paperclip_finish. The agents' own reasoning said "The paperclip tools
aren't in my toolset". Sessions on a commit without #20886 (8d2e34eac1)
all had the full size.

**Expected behavior**
Every native OpenCode session starts with the Paperclip MCP tools.

**Steps to reproduce**
1. Run several chat-features OpenCode cells on master after #20886.
2. Compare the first usage record of each run (inputTokens plus
cacheReadTokens) and the tool names in the run events.
3. See sessions with about 15k tokens and no paperclip_* tool calls.

## What Changed

- `mcp-bridge.ts`: removed `response.setHeader("Connection", "close")`.
The bridge uses Node's default keep-alive again, as before #20886.
- The per-call delivery diagnostics from #20886 stay, so a recurrence of
the stalled parallel call still shows socket reuse, idle time and
`written` in the run log.
- `mcp-bridge-delivery.test.ts`: the pooled-client test now asserts that
the bridge does not close connections, that a later call reuses a
socket, and that each call still gets a correct delivery record.

## Verification

- `pnpm exec vitest run` for mcp-bridge-delivery, mcp-bridge,
mcp-bridge-diagnostics, opencode-proxy-finish-diagnostics,
opencode-app-server-proxy and opencode-proxy-abandoned-tool-call tests:
45 passed.
- The exact mechanism inside OpenCode/Bun is not reproduced locally (a
macOS Bun client against a `Connection: close` server completed 300
MCP-shaped handshakes without error). The evidence is the before/after
correlation above. The next chat eval runs will show the first-request
token counts again.

## Risks

- The original five-minute stall (one occurrence, cause not proven) can
recur. The diagnostics from #20886 will then name the socket state.
- No persisted run, session or pack state changes.

## Model Used

- Anthropic Claude Opus 5.5 (`claude-opus-5-5`), tool use and code
execution in Claude Code.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-11 14:10:56 -06:00
..