Context
Surfaced during the writing of the Deployment Cookbook (#10800).
The Problem
The MCP servers currently do not know their own public-facing canonical URLs. This creates a gap for OAuth redirect_uri generation and Server-Sent Events (SSE) callback advertising, where the server must tell the client how to reach it externally.
The Architectural Reality
TransportService and OAuth routes currently rely on relative paths or incoming request headers (Host), which can be masked by reverse proxies.
The Fix
Introduce a NEO_PUBLIC_URL or equivalent configuration variable so the MCP server can definitively resolve its external identity.
Acceptance Criteria
Out of Scope
Dynamic DNS resolution.
Contract Ledger (T3)
Per canonical specification in learn/agentos/contract-ledger.md. Authored 2026-05-06 via batch-Ledger-upgrade pass on cookbook follow-ups (#10801-#10805) — proposed by @neo-opus-4-7 (systemic gap A2A) and explicitly delegated to body-incorporation by @neo-gemini-3-1-pro per ticket-create-workflow §11 Authorship Respect delegation pattern.
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback / Edge Case |
Docs |
Evidence |
aiConfig.publicUrl (new config field across both KB + MC config templates) — env var name NEO_PUBLIC_URL (or NEO_KB_PUBLIC_URL / NEO_MC_PUBLIC_URL if per-server URLs differ; final naming coordinated with #10808 ergonomics direction). Consumers: ai/mcp/server/shared/services/TransportService.mjs (SSE callback URL advertising) + ai/mcp/server/shared/services/AuthService.mjs and OAuth route handlers (redirect_uri generation) + healthcheck database.topology.coordinates if relevant. |
#10802, parent #9999, surfacing PR #10806 cookbook (operator's "does a server need to know its URL?" question — Section 4 IdP Setup + Section 1 Architecture). |
Server reads NEO_PUBLIC_URL at boot (e.g., https://my-proxy.example.com/mc) and uses it as the canonical identity for: (a) OAuth redirect_uri registration during OIDC handshake, (b) SSE endpoint URL advertised to MCP clients during connect, (c) self-referential URL composition in healthcheck or related diagnostic surfaces. Independent of Host header (which can be reverse-proxy-masked or stripped). |
If NEO_PUBLIC_URL is unset, fall back to constructing URL from incoming Host header (current behavior preserved for backwards-compat + local dev where host-header is reliable). Log a warning at boot recommending explicit config for production deployments. If both per-server and shared-prefix env vars are set, prefer per-server with deprecation warning. Empty-string set should be treated as unset (not as "advertise no URL"). |
Update learn/agentos/MemoryCoreMcpAuth.md (OAuth redirect_uri integration section) + learn/agentos/SharedDeployment.md (env var inventory + Authentication section) + DeploymentCookbook.md Section 1 (Architecture Picture) + Section 4 (Identity Provider Setup) — both cross-reference NEO_PUBLIC_URL for OAuth redirect_uri provisioning. |
L2 unit-test in test/playwright/unit/ai/mcp/server/shared/services/AuthService.spec.mjs (or Server.spec.mjs) — verify redirect_uri uses aiConfig.publicUrl when set; falls back to Host header when unset. Optional L3 — once integration test fixture lands (#10805), end-to-end OAuth flow against canonical URL verifies the wire-format. |
Origin Session ID: 88a6ed3a-b1b9-461a-aaf3-7c9984bd12e7
Retrieval Hint: Deployment Cookbook gap surfacing
Context
Surfaced during the writing of the Deployment Cookbook (#10800).
The Problem
The MCP servers currently do not know their own public-facing canonical URLs. This creates a gap for OAuth
redirect_urigeneration and Server-Sent Events (SSE) callback advertising, where the server must tell the client how to reach it externally.The Architectural Reality
TransportServiceand OAuth routes currently rely on relative paths or incoming request headers (Host), which can be masked by reverse proxies.The Fix
Introduce a
NEO_PUBLIC_URLor equivalent configuration variable so the MCP server can definitively resolve its external identity.Acceptance Criteria
redirect_urigeneration.Out of Scope
Dynamic DNS resolution.
Contract Ledger (T3)
Per canonical specification in
learn/agentos/contract-ledger.md. Authored 2026-05-06 via batch-Ledger-upgrade pass on cookbook follow-ups (#10801-#10805) — proposed by @neo-opus-4-7 (systemic gap A2A) and explicitly delegated to body-incorporation by @neo-gemini-3-1-pro perticket-create-workflow §11Authorship Respect delegation pattern.aiConfig.publicUrl(new config field across both KB + MC config templates) — env var nameNEO_PUBLIC_URL(orNEO_KB_PUBLIC_URL/NEO_MC_PUBLIC_URLif per-server URLs differ; final naming coordinated with #10808 ergonomics direction). Consumers:ai/mcp/server/shared/services/TransportService.mjs(SSE callback URL advertising) +ai/mcp/server/shared/services/AuthService.mjsand OAuth route handlers (redirect_urigeneration) + healthcheckdatabase.topology.coordinatesif relevant.NEO_PUBLIC_URLat boot (e.g.,https://my-proxy.example.com/mc) and uses it as the canonical identity for: (a) OAuthredirect_uriregistration during OIDC handshake, (b) SSE endpoint URL advertised to MCP clients during connect, (c) self-referential URL composition in healthcheck or related diagnostic surfaces. Independent ofHostheader (which can be reverse-proxy-masked or stripped).NEO_PUBLIC_URLis unset, fall back to constructing URL from incomingHostheader (current behavior preserved for backwards-compat + local dev where host-header is reliable). Log a warning at boot recommending explicit config for production deployments. If both per-server and shared-prefix env vars are set, prefer per-server with deprecation warning. Empty-string set should be treated as unset (not as "advertise no URL").learn/agentos/MemoryCoreMcpAuth.md(OAuth redirect_uri integration section) +learn/agentos/SharedDeployment.md(env var inventory + Authentication section) +DeploymentCookbook.mdSection 1 (Architecture Picture) + Section 4 (Identity Provider Setup) — both cross-referenceNEO_PUBLIC_URLfor OAuth redirect_uri provisioning.test/playwright/unit/ai/mcp/server/shared/services/AuthService.spec.mjs(orServer.spec.mjs) — verifyredirect_uriusesaiConfig.publicUrlwhen set; falls back to Host header when unset. Optional L3 — once integration test fixture lands (#10805), end-to-end OAuth flow against canonical URL verifies the wire-format.Origin Session ID: 88a6ed3a-b1b9-461a-aaf3-7c9984bd12e7 Retrieval Hint: Deployment Cookbook gap surfacing