Skip to content

fix(compass-agent): derive LITELLM_MCP_URL from the delivered base URL (RIG-2674) - #587

Open
rigel-mintaka wants to merge 2 commits into
mainfrom
compass-agent/rig-2674-derive-litellm-mcp-url
Open

fix(compass-agent): derive LITELLM_MCP_URL from the delivered base URL (RIG-2674)#587
rigel-mintaka wants to merge 2 commits into
mainfrom
compass-agent/rig-2674-derive-litellm-mcp-url

Conversation

@rigel-mintaka

Copy link
Copy Markdown
Contributor

The fleet mcp.json declares the LiteLLM MCP server as
{ "url": "${LITELLM_MCP_URL}", ... }, expanded from the agent's
process.env at MCP connect. But LITELLM_MCP_URL is a DERIVED var, not a
stored secret: in the wave the personal SOPS loader computes it from
LITELLM_BASE_URL (secrets-env.nix). Compass's keyring delivers
LITELLM_BASE_URL + LITELLM_API_KEY but NOT the derived MCP URL, so in a
live Compass agent ${LITELLM_MCP_URL} expands empty and the LiteLLM MCP
server fails to connect.

Derive it in the agent-env assembly (Matt-ruled option (b)) rather than
seeding a second secret: single source of truth, no base/MCP drift, and
Compass owns the load-bearing path rule in code. The rule mirrors the loader
byte-for-byte: strip one trailing slash, strip a trailing /v1, append
/mcp/. The trailing slash is load-bearing -- LiteLLM 307-redirects /mcp
and MCP clients don't re-POST across the redirect. So
https://host/v1 -> https://host/mcp/.

deriveLitellmMcpUrl is a pure resolver (sibling of resolveModelSelector);
main fills the gap AFTER sourcing the env file and BEFORE the MCP connect,
only when LITELLM_MCP_URL is not already present -- an explicitly-delivered
value still wins (same file-defines-it posture as the env merge). Unset/blank
base derives nothing (no gateway configured).

Tests: pure-resolver unit block (derive, trailing-slash-then-v1 order,
no-/v1 base, load-bearing slash, unset/blank/trim) + two main integration
tests (derive lands in process.env; explicit URL wins). Red-green proven by
mutation on both the call-site guard and the trailing-slash strip. Full
compass-agent suite green for the touched files; no new deps (no FOD bump).

Spec-impact: none (activation of an existing delivery contract; no proto or
public-API change).

Co-authored-by: Matt Wilkinson matt@rigel.build

…L (RIG-2674)

The fleet mcp.json declares the LiteLLM MCP server as
`{ "url": "${LITELLM_MCP_URL}", ... }`, expanded from the agent's
process.env at MCP connect. But `LITELLM_MCP_URL` is a DERIVED var, not a
stored secret: in the wave the personal SOPS loader computes it from
`LITELLM_BASE_URL` (secrets-env.nix). Compass's keyring delivers
`LITELLM_BASE_URL` + `LITELLM_API_KEY` but NOT the derived MCP URL, so in a
live Compass agent `${LITELLM_MCP_URL}` expands empty and the LiteLLM MCP
server fails to connect.

Derive it in the agent-env assembly (Matt-ruled option (b)) rather than
seeding a second secret: single source of truth, no base/MCP drift, and
Compass owns the load-bearing path rule in code. The rule mirrors the loader
byte-for-byte: strip one trailing slash, strip a trailing `/v1`, append
`/mcp/`. The trailing slash is load-bearing -- LiteLLM 307-redirects `/mcp`
and MCP clients don't re-POST across the redirect. So
`https://host/v1` -> `https://host/mcp/`.

`deriveLitellmMcpUrl` is a pure resolver (sibling of `resolveModelSelector`);
`main` fills the gap AFTER sourcing the env file and BEFORE the MCP connect,
only when `LITELLM_MCP_URL` is not already present -- an explicitly-delivered
value still wins (same file-defines-it posture as the env merge). Unset/blank
base derives nothing (no gateway configured).

Tests: pure-resolver unit block (derive, trailing-slash-then-v1 order,
no-/v1 base, load-bearing slash, unset/blank/trim) + two `main` integration
tests (derive lands in process.env; explicit URL wins). Red-green proven by
mutation on both the call-site guard and the trailing-slash strip. Full
compass-agent suite green for the touched files; no new deps (no FOD bump).

Spec-impact: none (activation of an existing delivery contract; no proto or
public-API change).

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Aug 24, 2026

Copy link
Copy Markdown

RIG-2674

@github-actions

github-actions Bot commented Aug 24, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-agent-rig-2674-deriv.compass-eng-docs.pages.dev

Deployed from compass-agent/rig-2674-derive-litellm-mcp-url at bad03d3.

… connect (RIG-2674)

Review-fold: the existing integration test asserted the derived value lands
in process.env only after main() resolves, which would still pass if a future
refactor moved the derive block AFTER the MCP manager connects -- silently
breaking the fix (the connector reads ${LITELLM_MCP_URL} from process.env at
dial time). This adds a test that captures process.env at the connect instant
via the connectMcp seam (main calls it unconditionally, after the env merge
and before session construction), pinning the load-bearing ordering. Non-vacuity:
disabling the derive reds it at the capture point.

Spec-impact: none (test-only; strengthens the RIG-2674 ordering invariant).

Co-authored-by: Matt Wilkinson <matt@rigel.build>
@rigel-mintaka
rigel-mintaka marked this pull request as ready for review August 24, 2026 17:54
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