Skip to content

Fix/rest low severity nits 92#199

Open
James-Z-Zhang00 wants to merge 2 commits into
Mnexa-AI:mainfrom
James-Z-Zhang00:fix/rest-low-severity-nits-92
Open

Fix/rest low severity nits 92#199
James-Z-Zhang00 wants to merge 2 commits into
Mnexa-AI:mainfrom
James-Z-Zhang00:fix/rest-low-severity-nits-92

Conversation

@James-Z-Zhang00

Copy link
Copy Markdown
Contributor

Summary

Two low-severity follow-up nits from #92 (MCP HTTP server v0.2 polish):

  1. evictOldest swallows close errors — the LRU eviction in Sessions fire-and-forgot the delete with void this.delete(id) and, unlike the
    sibling gc()/shutdown() paths, never attached a .catch(). A rejecting transport.close() would surface as an unhandled promise rejection
    (which can terminate the process under Node's default behavior). Now caught and logged to stderr at warn.

  2. Hardcoded https:// discovery scheme — the OAuth protected-resource discovery URLs (resource field and WWW-Authenticate: resource_metadata) were hardcoded to https://{Host}, which is correct behind the prod Caddy front but wrong for any non-TLS deployment that
    doesn't set MCP_PUBLIC_URL. The scheme is now derived from X-Forwarded-Proto via Express's trust proxy, defaulting to "loopback"
    (configurable with the new E2A_TRUST_PROXY env var).

This is a correctness fix, not a security fix: the old hardcoded scheme had no spoofing risk (a constant can't be forged). The trust proxy: loopback gate is included so that reading X-Forwarded-Proto can't be abused by a forged header from an untrusted hop — it preserves the old
code's un-spoofability while gaining accuracy. In prod (Caddy terminates TLS, forwards over localhost with X-Forwarded-Proto: https) the
advertised URL is unchanged.

Operational risk

Low. No data, auth, billing, or external integrations touched.

  • Behavior change: a deployment that serves plain HTTP without setting MCP_PUBLIC_URL will now advertise http://... in discovery (the
    real scheme) instead of https://.... This is strictly more correct; the only deployments affected were already misconfigured (advertising https
    they couldn't serve). MCP_PUBLIC_URL continues to override everything.
  • Prod unchanged: Caddy sends X-Forwarded-Proto: https over loopback → trust proxy: "loopback" honors it → advertised URL stays
    https://....
  • New knob: E2A_TRUST_PROXY (default "loopback"); operators behind a non-loopback proxy set it to their proxy's address/subnet, a hop
    count, or a preset.
  • Out-of-repo assumption: the default relies on Caddy forwarding over localhost and replacing (not appending) X-Forwarded-Proto — that
    config lives in e2a-ops, not here. Worth a glance on that side.
  • Rollback: revert the commits; no migrations or persisted state involved.

Test plan

  • npm run build --workspace @e2a/mcp-server — clean (no tsc errors)
  • npm test --workspace @e2a/mcp-server — 126 passing (8 files)
  • evictOldest regression: new test evicts an entry whose close() rejects; asserts the entry is still removed and the warning is logged (no unhandled rejection)
  • Discovery scheme: no X-Forwarded-Proto → falls back to the real connection scheme
  • Discovery scheme: trusted (loopback) X-Forwarded-Proto: https → advertised as https
  • Discovery scheme: trustProxy: false + spoofed X-Forwarded-Proto: https → header dropped, falls back to http
  • parseTrustProxy config: default loopback, booleans, integer hop-count, preset/CIDR passthrough

@James-Z-Zhang00 James-Z-Zhang00 requested a review from jiashuoz as a code owner June 8, 2026 15:33
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