fix(mcp): dial and serve the MCP gateway tunnel (VA-131, agent half) #132

Merged
longjacksonle merged 1 commit from fix/VA-131-mcp-gateway-tunnel into main 2026-07-14 06:13:34 +02:00

Agent half of VA-131. The server's MCP gateway (VS-22) opens a tunnel by telling the agent to dial /mcptunnel.ashx, but the agent never completed it, so every POST /agents/:id/mcp timed out (504). Found during VA-129 macOS validation; cross-platform (the failing paths are platform-agnostic).

Three agent-side gaps fixed

  1. URL expansion (expand_value_url): only *-prefixed relay values were expanded; the gateway's bare /mcptunnel.ashx?… value was treated as absolute and dialed verbatim (schemeless → dial fails). Now any rooted-path value expands against the control-channel scheme+authority; unrooted relatives are rejected.
  2. Rendezvous + usage (open): the gateway raw-pumps the socket (no "c"/"cr" handshake) and its usage byte (7) collides with the agent's RDP code. The agent now recognizes the gateway by its dial path (/mcptunnel.ashx) and runs the MCP server directly, bypassing the relay handshake and usage dispatch.
  3. Reply framing (mcp::run): the gateway reads replies as newline-delimited JSON; the agent wrote bare Text frames, so drive_session never saw a complete line. MCP responses are now newline-terminated (valid JSON, harmless to a frame-delimited consumer).

Verified end-to-end (live dev server, on the box)

Ran a fixed agent against a real vervain-server dev stack and drove the gateway as the operator:

  • POST /agents/<node>/mcp initializeHTTP 200 in ~47ms, real serverInfo/capabilities (was a 30s 504).
  • tools/listHTTP 200, real tool list (works request-scoped, no prior initialize needed).

Requires the server companion (mount /mcptunnel.ashx on the agent mTLS listener) - separate PR in vervain-server - to work against a full stack; without it the agent dial 404s.

Tests

New expand_value_url unit tests: expands the bare /mcptunnel.ashx path; rejects unrooted relatives; existing *-prefixed and absolute cases preserved. clippy --deny warnings + fmt clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS

Agent half of VA-131. The server's MCP gateway (VS-22) opens a tunnel by telling the agent to dial `/mcptunnel.ashx`, but the agent never completed it, so every `POST /agents/:id/mcp` timed out (504). Found during VA-129 macOS validation; cross-platform (the failing paths are platform-agnostic). ## Three agent-side gaps fixed 1. **URL expansion** (`expand_value_url`): only `*`-prefixed relay values were expanded; the gateway's bare `/mcptunnel.ashx?…` value was treated as absolute and dialed verbatim (schemeless → dial fails). Now any rooted-path value expands against the control-channel scheme+authority; unrooted relatives are rejected. 2. **Rendezvous + usage** (`open`): the gateway raw-pumps the socket (no `"c"/"cr"` handshake) and its usage byte (7) collides with the agent's RDP code. The agent now recognizes the gateway by its dial path (`/mcptunnel.ashx`) and runs the MCP server directly, bypassing the relay handshake and usage dispatch. 3. **Reply framing** (`mcp::run`): the gateway reads replies as newline-delimited JSON; the agent wrote bare Text frames, so `drive_session` never saw a complete line. MCP responses are now newline-terminated (valid JSON, harmless to a frame-delimited consumer). ## Verified end-to-end (live dev server, on the box) Ran a fixed agent against a real `vervain-server` dev stack and drove the gateway as the operator: - `POST /agents/<node>/mcp` `initialize` → **HTTP 200** in ~47ms, real `serverInfo`/capabilities (was a 30s 504). - `tools/list` → **HTTP 200**, real tool list (works request-scoped, no prior initialize needed). Requires the **server companion** (mount `/mcptunnel.ashx` on the agent mTLS listener) - separate PR in `vervain-server` - to work against a full stack; without it the agent dial 404s. ## Tests New `expand_value_url` unit tests: expands the bare `/mcptunnel.ashx` path; rejects unrooted relatives; existing `*`-prefixed and absolute cases preserved. `clippy --deny warnings` + `fmt` clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS
fix(mcp): dial and serve the MCP gateway tunnel (VA-131, agent half)
All checks were successful
Check / fmt + clippy + tests (pull_request) Successful in 4m18s
Create release / Create release from merged PR (pull_request) Has been skipped
fd9e65f840
The server's MCP gateway (VS-22) opens a tunnel by telling the agent to dial /mcptunnel.ashx, but the agent never completed it, so every MCP request 504'd. Three agent-side gaps, all fixed here:

- expand_value_url only expanded `*`-prefixed relay values, so the gateway's bare `/mcptunnel.ashx?...` value produced a schemeless URL and the dial failed. Expand any rooted-path value against the control-channel scheme+authority (reject unrooted relatives).
- The gateway rendezvous raw-pumps the socket with no "c"/"cr" handshake, and its usage byte (7) collides with the agent's RDP code. Recognize the gateway by its dial path (/mcptunnel.ashx) and run the MCP server directly, bypassing the relay handshake and usage dispatch.
- The gateway reads replies as newline-delimited JSON; the agent wrote bare Text frames, so no reply was ever recognized. Newline-terminate each MCP response frame (valid JSON, harmless to frame-delimited consumers).

Verified end-to-end against a live dev server: POST /agents/<node>/mcp initialize and tools/list both return HTTP 200 with real payloads (was a 30s 504). Needs the server companion (mount /mcptunnel.ashx on the agent mTLS listener) to work against a full stack. Cross-platform; surfaced during VA-129.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS
longjacksonle scheduled this pull request to auto merge when all checks succeed 2026-07-14 06:11:58 +02:00
longjacksonle deleted branch fix/VA-131-mcp-gateway-tunnel 2026-07-14 06:13:34 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
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
psa-systems/vervain-agent!132
No description provided.