CedarCopilot wants to merge 3 commits into staging from feat/cedar-mcp-public-resource-url
Live on prod, 1 of 1 surfaces working, less than a day left
Since the deploy, 27 prod OTEL spans matching GET /.well-known/oauth-protected-resource ran with 0 error spans. Libra found no comparable traffic on this surface in the 25h before the deploy, so there is no before-and-after contrast. Confidence is medium because there was no.
Unable to complete verification from the available telemetry: the production API-service queries returned no post-deploy MCP, origin-validation, CORS, or protected-resource records, so there is no positive runtime evidence for the intended behavior.
Libra measured 1 of 1 production surface on prod. Libra checks hourly for 3 days after each deploy.
CEDAR_MCP_PUBLIC_URL, threaded into better-auth's mcp() plugin as the resource override (apps/server/src/lib/auth.ts) and into the trusted-origins allowlist (apps/server/src/lib/trusted-origins.ts)./mcp, served by externalMcpRouter) publish /.well-known/oauth-protected-resource under a Manufact-proxied domain (mcp.cedarcopilot.com) for app store submission, while authorization_servers stays on the existing backend origin , auth can't move there without breaking session cookies.resource falls back to the app origin exactly as it did before this var existed (verified against better-auth's source: resource: options?.resource ?? origin).Traced end-to-end: externalMcpRouter's .well-known/oauth-protected-resource route (apps/server/src/routes/external-mcp.ts) calls better-auth's oAuthProtectedResourceMetadata(auth), which derives authorization_servers from ctx.context.baseURL , statically configured as env.VITE_PUBLIC_BACKEND_URL (apps/server/src/lib/auth.ts:1008), not from the request's Host header. So the split holds regardless of which domain a request arrives on.
This is groundwork only , no DNS/proxy changes yet. The domain cutover (Manufact proxy config, DNS for mcp.cedarcopilot.com, setting this env var in an actual environment) is staged separately per Pietro's explicit ask not to touch production MCP traffic during the transition.
pnpm --filter @zero/server run types , clean on the three touched files (pre-existing unrelated errors in conversationTool.ts on a different in-progress branch, not touched here)CEDAR_MCP_PUBLIC_URL is set in an environment, fetch https://mcp.cedarcopilot.com/.well-known/oauth-protected-resource and confirm resource reads the new domain while authorization_servers still reads api.mail.cedarcopilot.com🤖 Generated with Claude Code
The PR is not safe to merge until the AWS task environment propagates the new MCP public URL to the API process.
### Issue 1
apps/server/src/env.ts:472
The new variable is read from `process.env`, but the AWS ECS task environment is built by `buildServiceEnvironment()`, which does not include `CEDAR_MCP_PUBLIC_URL`. As a result, the value will be undefined in the API process, so better-auth will keep advertising the backend origin and this configuration will have no effect in deployed AWS environments.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
This PR introduces an optional public MCP resource identifier and threads it into better-auth metadata and the trusted-origin allowlist. The server-side wiring is internally consistent, but the repository’s AWS task environment contract does
| Surface | Requests | Errors | p95 | Users | Verdict |
|---|---|---|---|---|---|
| /.well-known/oauth-protected-resource | 24 → 30 | 0 → 0 (0%) | 1 ms → 1 ms | 0 | Working 30 requests since the deploy with 0 errors (0 errors in the 24-request baseline before it). p95 1 ms, was 1 ms. |