fix(mcp): dial and serve the MCP gateway tunnel (VA-131, agent half) #132
Loading…
Reference in a new issue
No description provided.
Delete branch "fix/VA-131-mcp-gateway-tunnel"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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 everyPOST /agents/:id/mcptimed out (504). Found during VA-129 macOS validation; cross-platform (the failing paths are platform-agnostic).Three agent-side gaps fixed
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.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.mcp::run): the gateway reads replies as newline-delimited JSON; the agent wrote bare Text frames, sodrive_sessionnever 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-serverdev stack and drove the gateway as the operator:POST /agents/<node>/mcpinitialize→ HTTP 200 in ~47ms, realserverInfo/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.ashxon the agent mTLS listener) - separate PR invervain-server- to work against a full stack; without it the agent dial 404s.Tests
New
expand_value_urlunit tests: expands the bare/mcptunnel.ashxpath; rejects unrooted relatives; existing*-prefixed and absolute cases preserved.clippy --deny warnings+fmtclean.🤖 Generated with Claude Code
https://claude.ai/code/session_01QJiqE8CSatRaZysXtLHeVS