Address review feedback on ce99f58:
- Merge the two '### Added' blocks in [Unreleased] into one (Keep a
Changelog: each category appears once). New 2026-07-06 entries now
sit at the top of the existing Added block.
- Add missing period after 'required SSE headers' in the liveness
verification prose (was a run-on sentence).
7.7 KiB
description, tags, last_updated
| description | tags | last_updated | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Session record (2026-07-06): triaged Caddy journald warnings on onlyoffice.localhost/mcp showing "context canceled" SSE aborts (~1.5ms) from opencode 1.17.13 MCP client against the OnlyOffice MCP server on :3847. Verified upstream liveness, opened GitLab issue #92 in satware/mcp/onlyoffice, and documented the Caddy reverse-proxy as a manual override. |
|
2026-07-06 |
Caddy "context canceled" on onlyoffice.localhost/mcp - investigation - 2026-07-06
Summary
Caddy (systemd caddy.service) on mw-manjaro-pf is emitting a high
volume of warn-level journald entries: aborting with incomplete response ... error: "reading: context canceled" for GET /mcp requests
on https://onlyoffice.localhost. Each abort fires ~1.5ms after the
request is forwarded to the upstream localhost:3847 (OnlyOffice MCP
server). The upstream is alive and correctly rejects non-SSE GETs with
HTTP 406, so this is a stream-lifecycle issue, not a server-down issue.
Investigation handed off to the OnlyOffice MCP repo as GitLab issue #92. This workstation's Caddy reverse-proxy config is now recorded as a manual override (not Ansible-managed).
Incident
| Field | Value |
|---|---|
| Symptom | Repeated context canceled warnings in journalctl -u caddy |
| Caddy site | https://onlyoffice.localhost -> reverse_proxy localhost:3847 |
| Upstream | localhost:3847 (OnlyOffice MCP server) |
| Request | GET /mcp with Accept: text/event-stream |
| Client | opencode/1.17.13 (MCP streamable-HTTP transport) |
| MCP protocol | 2025-11-25 |
| Abort duration | ~1.5ms (request forwarded, then read context canceled) |
| Frequency | Multiple per minute, across distinct Mcp-Session-Id values |
Evidence
Caddy log sample (recurring)
{
"level": "warn",
"logger": "http.handlers.reverse_proxy",
"msg": "aborting with incomplete response",
"upstream": "localhost:3847",
"duration": 0.00173631,
"request": {
"method": "GET",
"host": "onlyoffice.localhost",
"uri": "/mcp",
"headers": {
"Accept": ["text/event-stream"],
"Mcp-Protocol-Version": ["2025-11-25"],
"Mcp-Session-Id": ["a5e859b4-01f1-4c24-81bb-78ee02d74357"],
"User-Agent": ["opencode/1.17.13"],
"Via": ["1.1 Caddy"]
}
},
"error": "reading: context canceled"
}
Observed Mcp-Session-Id values (each retried over several minutes):
a5e859b4..., 4bfbb912..., 3c4a0454..., 08397c3d...,
ed762f08..., b0fae341....
Upstream liveness verification
$ ss -tlnp | grep :3847
LISTEN 0 4096 0.0.0.0:3847 0.0.0.0:*
$ curl -sS -o /dev/null -w "HTTP %{http_code} in %{time_total}s\n" \
--max-time 3 http://localhost:3847/mcp
HTTP 406 in 0.004665s
HTTP 406 is expected for a plain GET without the required SSE headers. The MCP server is alive and rejecting non-SSE requests correctly.
Diagnosis
Root cause (not yet confirmed - under investigation)
Five candidate hypotheses, listed in the GitLab issue. The leading
suspect is client-side disconnect: opencode 1.17.13 opens the SSE
stream then immediately closes it (the ~1.5ms duration is too short for
a genuine read). Secondary suspects are server-side stream teardown,
MCP protocol-version mismatch (2025-11-25), Caddy HTTP/1.1 framing of
SSE, or a client session-pool bug creating and abandoning sessions.
Why this workstation's concern
The Caddy reverse-proxy is the boundary that surfaces the symptom. Even if the root cause is client- or server-side, the local config matters because:
- Caddy logs are being polluted with warn-level noise (masks real errors).
- The reverse-proxy block has no SSE-specific tuning (
flush_interval, explicit HTTP/1.1 transport) that could mask or mitigate upstream misbehavior. - The Caddy config at
/etc/caddy/conf.d/localhost-dev.confis not Ansible-managed by this repo - it is a manual override that must be recorded (seedocs/tech/manual-overrides.md).
Environment
| Component | Version / Value |
|---|---|
| Host | mw-manjaro-pf (mw-pfeddersheim-workstation) |
| OS | Manjaro Linux, Wayland session |
| Caddy | systemd caddy.service, active since 2026-07-02 |
| Caddy config | /etc/caddy/Caddyfile + /etc/caddy/conf.d/localhost-dev.conf |
| TLS cert | mkcert pair at /etc/caddy/localhost{,-key}.pem |
| Upstream | localhost:3847 (OnlyOffice MCP server, process TBD) |
| MCP client | opencode/1.17.13 |
| MCP protocol | 2025-11-25 (streamable HTTP transport) |
*.localhost sites configured
All defined in /etc/caddy/conf.d/localhost-dev.conf (14 sites total):
| Site | Backend / Handler |
|---|---|
mcp.localhost |
reverse_proxy localhost:50880 |
artifacts.localhost |
file_server browse root /var/www/artifacts |
onlyoffice.localhost |
reverse_proxy localhost:3847 (subject of this issue) |
project-1.localhost ... project-10.localhost |
respond "project-N - placeholder" (10 reserved) |
demo.satware.com.localhost |
reverse_proxy localhost:38081 (webdevops/php-apache-dev container) |
Handoff
GitLab issue
| Item | Value |
|---|---|
| Project | satware/mcp/onlyoffice (gitlab.satware.com) |
| Issue | #92 |
| Title | Investigation: Caddy reports 'context canceled' on onlyoffice.localhost/mcp SSE stream (~1.5ms aborts) |
| Labels | bug, investigation, mcp |
| State | open |
The issue body contains the full evidence, 5 hypotheses, 7 investigation
tasks, and a proposed Caddy mitigation (flush_interval -1 +
transport http { versions 1.1 }).
Next actions (assigned to OnlyOffice MCP repo)
- Identify the process listening on
:3847(sudo ss -tlnp | grep 3847). - Collect server-side logs for the
Mcp-Session-Idvalues cited above. - Reproduce with
curl -N -H "Accept: text/event-stream" -H "Mcp-Protocol-Version: 2025-11-25" https://onlyoffice.localhost/mcp. - Check opencode 1.17.13 changelog for MCP SSE session bugs.
- Verify Caddy
reverse_proxySSE tuning (proposed block in issue #92). - Confirm whether
notifications/initializedround-trip completes. - Log the negotiated MCP protocol version server-side.
Local documentation updates
| File | Change |
|---|---|
docs/tech/manual-overrides.md |
Added row for /etc/caddy/ config (not Ansible-managed) |
docs/tech/stack.md |
Added "Local Dev Services" section listing Caddy + *.localhost sites |
CHANGELOG.md |
Added [Unreleased] -> Added entry |
| GitLab issue #92 | Created with full evidence + hypotheses + tasks |
Proposed Caddy mitigation (to test on this workstation)
https://onlyoffice.localhost {
tls /etc/caddy/localhost.pem /etc/caddy/localhost-key.pem
reverse_proxy localhost:3847 {
flush_interval -1
transport http {
versions 1.1
}
}
}
flush_interval -1 disables Caddy's buffering so SSE events flush to the
client immediately; transport http { versions 1.1 } pins the upstream
leg to HTTP/1.1 (Caddy logs already show HTTP/1.1 for the upstream, this
makes it explicit and avoids HTTP/2 SSE framing surprises).
Not applied yet - pending GitLab issue #92 resolution to avoid masking the root cause.
References
- GitLab issue: https://gitlab.satware.com/satware/mcp/onlyoffice/-/work_items/92
- Caddy config:
/etc/caddy/conf.d/localhost-dev.conf - Local skill:
caddy(~/.config/opencode/skills/caddy/SKILL.md) - MCP transport spec: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
- Manual overrides:
docs/tech/manual-overrides.md - Software stack:
docs/tech/stack.md