BuilderIO / BuilderIO/agent-native

Workspace deploy: root /.well-known/* is routed to Dispatch and ignores the app path suffix, so OAuth discovery for a spoke app's MCP server fails with invalid_request

Open
#4,866 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
4.8k
Forks
449
Avg merge
10h 24m
Merged PRs (30d)
883

Description

# Workspace deploy: root `/.well-known/*` is routed to Dispatch and ignores the app path suffix, so OAuth discovery for any spoke app's MCP server lands on Dispatch's authorization server and fails

**Version:** `@agent-native/core` 0.178.1, `dist/deploy/workspace-deploy.js` (Vercel routes: `{ src: "/\\.well-known/(.*)", dest: "/dispatch-server" }`; the Netlify and gateway variants do the same), `dist/mcp/oauth-route.js` (`handleAuthorize`, `getMcpOAuthAudiences`).

**What happens.** In a path-mounted workspace (`/chat`, `/documents`, `/brand-assets`, `/dispatch` on one host), a spoke app's MCP endpoint advertises itself correctly: `GET /chat/mcp` returns `WWW-Authenticate: Bearer resource_metadata="https://host/chat/.well-known/oauth-protected-resource"`, and that document names `authorization_servers: ["https://host/chat"]`, whose `/chat/.well-known/oauth-authorization-server` points at `/chat/mcp/oauth/authorize`. Claude (claude.ai custom connector) resolves the metadata with the RFC 8414 / RFC 9728 path-insertion form at the site root instead: `GET https://host/.well-known/oauth-authorization-server/chat` (and `/.well-known/oauth-protected-resource/chat/mcp`). The deploy routes every `/.well-known/*` request to the Dispatch server, and Dispatch's handler ignores the suffix, so both documents come back with `issuer: https://host/dispatch` and `authorization_endpoint: https://host/dispatch/mcp/oauth/authorize`. Claude then opens `/dispatch/mcp/oauth/authorize?...&resource=https://host/chat/mcp`; Dispatch's `getMcpOAuthAudiences` only contains its own `/dispatch/mcp` prefixes, so `handleAuthorize` answers `{"error":"invalid_request","error_description":"Invalid OAuth authorization request"}`. Observed 2026-09-12 on a Vercel production deployment for the Chat, Documents and Assets connectors; the Dispatch connector works because its resource is its own.

**Why.** Path-insertion discovery is what the RFCs prescribe for resources that live under a path, and popular hosts use it. The root well-known route exists so the workspace has one discovery document, but it is not suffix-aware, and the spoke apps' authorization servers are never reachable through it.

**Expected.** One of: the root `/.well-known/oauth-authorization-server/[/mcp]` and `/.well-known/oauth-protected-resource//mcp` routes forward to that app's own documents (a route per registered workspace app, or a suffix-aware handler in Dispatch); or Dispatch acts as the workspace authorization server for every app and `getMcpOAuthAudiences` accepts every registered app's `//mcp` resource; or the docs state that in a path-mounted workspace only the Dispatch connector supports OAuth hosts and spoke apps need the bearer fallback.

**Impact.** In a path-mounted workspace no spoke app can be added to claude.ai (or any host using path-insertion discovery) as its own connector; users get an opaque `invalid_request` page after clicking Connect.

**Workaround in Joney.** Use the Dispatch connector (`/dispatch/mcp`, verbs `list_apps`, `ask_app`, `open_app`) from claude.ai; for hosts that accept a static header (Claude Code, Cursor), mint a token on `//mcp/connect`.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reading dist/deploy/workspace-deploy.js and compare the Vercel, Netlify, and gateway well-known routes. Then trace handleAuthorize and getMcpOAuthAudiences in dist/mcp/oauth-route.js while reproducing the listed path-insertion discovery requests. Done means a spoke app's discovery documents and OAuth authorization flow resolve to that app instead of Dispatch, or the chosen documented limitation is enforced consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, authentication, cloud
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.