provisionMcpServer now GETs /v1/mcp/server first and skips the POST if the
sitebridge_<id> entry already exists. upsertCustomer calls it on every
existing-customer login (fire-and-forget) so pre-existing customers whose
row was created before this code path shipped — or whose LiteLLM entry was
deleted/rebuilt — get their /mcp/ routing restored on next login.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LiteLLM opens a fresh MCP session per tool call. Two concurrent sessions
both send id=1 (tools/list + tools/call) which overwrite each other in
the shared pending-map keyed by the inbound id. One of the two calls
never gets a response and times out.
Assign a monotonic demux-N wire id per forwardMcpCall. The caller's
original id is echoed back in the HTTP response by the route handler.
SB-48
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
LiteLLM opens a fresh MCP session per tools/call: initialize →
notifications/initialized → tools/call. Demux forwarded everything
to the WS unchanged, so:
- notifications/initialized (no id) hung forwardMcpCall waiting on
a response id, and the 200 JSON-RPC body confused the SDK reader
into cancelling the subsequent tools/call ("duplicate response
suppressed").
- initialize added an unnecessary WS round-trip coupled to
extension availability.
Answer initialize locally, return 202 empty for notifications/*,
set explicit Content-Type + Mcp-Session-Id on the handshake.
SB-48
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Builds on push to main, deploys to infra VM via SSH, health-checks
the /health endpoint after restart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LiteLLM rejects server names containing `-`, but customer IDs are
UUIDs. Replace `-` with `_` in both the MCP server alias and key alias.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
At first login, provisionMcpServer() creates a sitebridge-{customer_id}
entry in LiteLLM DB via POST /v1/mcp/server, pointing to the customer's
demux URL. The virtual key is then scoped to ["sitebridge-{customer_id}"]
so LiteLLM routes tool calls only to that customer's WebSocket.
Also adds AGILITON_ACCOUNT_URL config for self-referencing in MCP URLs.
CF-3032
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Use postgres_default, redis_default, agiliton-api external networks.
Remove depends_on (services are in separate compose stacks).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>