Skip to content

feat(remote): honest reverse-MCP logging — declared vs. consumed - #74

Merged
brettchien merged 1 commit into
mainfrom
feat/reverse-mcp-observability
Aug 18, 2026
Merged

feat(remote): honest reverse-MCP logging — declared vs. consumed#74
brettchien merged 1 commit into
mainfrom
feat/reverse-mcp-observability

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

Why

The management connection logged "oab tools published" the moment Studio got a sessionId back from session/new — i.e. when Studio declared the oab server, not when the agent consumed it. So an operator saw "published" while the connected agent reported no oab tools, with nothing in the Activity log to explain the gap.

The oab declaration carries no tools inline — the agent only gets them by connecting back to the declared server over the reverse-MCP tunnel and calling tools/list (which Studio serves from its oab-mcp sidecar). If the agent never connects, no tools — and today that's invisible.

What

Honesty + observability, logging only, no behaviour change:

  • Declaration logoab tools published/republishedoab server (re-)declared (awaiting agent connect). Declared ≠ consumed.
  • Inbound::Connect — log when the agent opens the reverse-MCP tunnel to the oab server (the proof the declaration was consumed).
  • Inbound::Message — log the reverse-MCP call; for tools/list, log the served tool count — the definitive "the agent pulled N oab tools" signal.

Result — the Activity log now distinguishes the two failure modes

  • No Connect / no tools/list after "declared" ⇒ the gateway / agent runtime isn't tunnelling the reverse direction — upstream (openab), not Studio. (This is the current symptom.)
  • tools/list served with 0, or an error ⇒ a Studio-side issue (sidecar/tool wiring).

Verification

src-tauri isn't built locally (its dep tree — tauri + aws-sdk-ec2/s3 — OOMs this box, as noted on #69); CI build-test covers the compile. The change is additive logging using patterns already in the file (app.emit + json!, and_then(Value::as_array) mirroring the existing Value::as_str uses).

🤖 Generated with Claude Code

The management connection logged "oab tools published" the moment Studio got
a sessionId back from session/new — i.e. when Studio *declared* the `oab`
server, not when the agent consumed it. So an operator saw "published" while
the agent reported no oab tools, with nothing in the Activity log to explain
the gap.

The tools only appear once the agent (via the gateway) connects back to the
declared server over the reverse-MCP tunnel and lists them. Make that
observable and fix the wording:

- Declaration log: "oab tools published/republished" → "oab server
  (re-)declared (awaiting agent connect)". Declared ≠ consumed.
- Inbound::Connect: log when the agent opens the reverse-MCP tunnel to the
  oab server — the proof the declaration was consumed.
- Inbound::Message: log the reverse-MCP call; for `tools/list`, log the
  served tool count — the definitive "the agent pulled N oab tools" signal.

Now the Activity log distinguishes the two failure modes: no Connect / no
tools/list after "declared" ⇒ the gateway/agent runtime isn't tunnelling the
reverse direction (upstream); a tools/list served with 0 (or an error) ⇒ a
Studio-side issue. Behaviour is unchanged — logging only.

No local src-tauri build (its dep tree OOMs this box, as with #69); CI
build-test covers the compile. Change is additive logging using patterns
already in the file.

🤖 Generated with [Claude Code](https://claude.com/claude-code)
@brettchien
brettchien merged commit cd5cf91 into main Aug 18, 2026
2 checks passed
@brettchien
brettchien deleted the feat/reverse-mcp-observability branch August 18, 2026 01:16
brettchien added a commit that referenced this pull request Aug 18, 2026
…ng (#75)

Follow-up to #74. Fills the silent gaps a reviewer hits when the Activity log
can't explain a reverse-MCP or turn problem. Logging only, no behaviour change.

- A. tools/call outcome: log the tool name + ok / tool-error / failed(+msg),
  instead of only "a tools/call happened". A failing tool call is the usual
  troubleshooting case and was invisible.
- B. tools/list failure: detect a sidecar error reply and log its message
  instead of mislabelling it "unexpected shape" (that branch now means a
  genuinely odd shape, not an error).
- C. Inbound::Disconnect: log when the agent tears down the reverse-MCP tunnel
  to the oab server — symmetric with #74's Connect log; explains "tools
  vanished" with no error.
- D. Unsupported reverse-MCP method: log when the agent calls a method the oab
  server doesn't serve (replied -32601) — surfaces a capability mismatch.
- E. OutMsg::Cancel: log the operator Stop so Activity distinguishes an
  operator cancel from a gateway cancel or an error drop.

The tunnel-message observability is restructured into one match on the inner
method (list/call/initialize/other) carrying (level, message); `initialize`
stays unlogged (Connect already proves the agent engaged).

No local src-tauri build (dep tree OOMs this box, as with #69/#74); CI
build-test covers the compile. Additive logging using patterns already in the
file (`app.emit` + `json!`, `and_then(Value::as_*)`).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
brettchien added a commit that referenced this pull request Aug 18, 2026
…sions (#77)

#74/#75 revealed the agent DOES connect to the oab server but never calls
tools/list. The stall is between connect and list — the inner MCP initialize
handshake, which #75 deliberately left unlogged. Log it, since MCP requires
the client to initialize right after connecting (it's not the agent's choice).

- initialize: log the client's requested `protocolVersion` vs the version the
  server answered; flag a **PROTOCOL MISMATCH** (warn) when they differ — the
  suspected reason a connected agent aborts before tools/list.
- notifications/initialized: log it (a notification, so it never reached the
  outcome match). Its presence means the handshake completed; its absence
  right after an initialize points at a rejected handshake.

Logging only — no behaviour change. If the log confirms a version mismatch,
the fix (echo the client's protocolVersion instead of the hardcoded
2024-11-05, + advertise tools.listChanged) is a follow-up.

No local src-tauri build (dep tree OOMs this box, as with #74/#75); CI
build-test covers the compile.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant