Skip to content

Add org-scoped MCP routes for the cloud app#878

Merged
RhysSullivan merged 1 commit into
mainfrom
rs/mcp-org-scoped-routes
Jun 1, 2026
Merged

Add org-scoped MCP routes for the cloud app#878
RhysSullivan merged 1 commit into
mainfrom
rs/mcp-org-scoped-routes

Conversation

@RhysSullivan
Copy link
Copy Markdown
Owner

Let an MCP client pin a specific organization in the URL (/<org_id>/mcp)
instead of relying on the organization claim in the OAuth access token. This
unblocks clients that hold a single sign-in session but need to target one of
several organizations.

Server:

  • Serve /<org_id>/mcp and the matching
    /.well-known/oauth-protected-resource/<org_id>/mcp discovery document
    alongside the existing bare /mcp.
  • Take the organization from the URL when present, falling back to the token
    claim otherwise. Membership is verified against the auth provider on every
    request, so the URL is a selector, not a trust boundary.
  • Consolidate MCP path ownership behind one predicate shared by the request
    middleware, the handler, and the test worker. Only org_-shaped segments are
    claimed, so unrelated /<segment>/mcp paths still fall through to routing.

Frontend:

  • The cloud "Connect your MCP client" page and the install card now hand out the
    org-scoped URL. The shared install card stays unscoped for local/desktop,
    where there is no organization.

Tests cover org-scoped discovery metadata, URL-supplied organization, membership
denial before session creation, non-org paths falling through, and org-scoped
URL/command rendering.

Draft: interim org-id form; migrates to organization handles once URL-based org
routing lands.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jun 1, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
executor-marketing 1b638a4 Commit Preview URL

Branch Preview URL
Jun 01 2026, 07:45 AM

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jun 1, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
executor-cloud 1b638a4 Jun 01 2026, 07:46 AM

Copy link
Copy Markdown
Owner Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jun 1, 2026

Open in StackBlitz

@executor-js/cli

npm i https://pkg.pr.new/@executor-js/cli@878

@executor-js/config

npm i https://pkg.pr.new/@executor-js/config@878

@executor-js/execution

npm i https://pkg.pr.new/@executor-js/execution@878

@executor-js/sdk

npm i https://pkg.pr.new/@executor-js/sdk@878

@executor-js/codemode-core

npm i https://pkg.pr.new/@executor-js/codemode-core@878

@executor-js/runtime-quickjs

npm i https://pkg.pr.new/@executor-js/runtime-quickjs@878

@executor-js/plugin-file-secrets

npm i https://pkg.pr.new/@executor-js/plugin-file-secrets@878

@executor-js/plugin-graphql

npm i https://pkg.pr.new/@executor-js/plugin-graphql@878

@executor-js/plugin-keychain

npm i https://pkg.pr.new/@executor-js/plugin-keychain@878

@executor-js/plugin-mcp

npm i https://pkg.pr.new/@executor-js/plugin-mcp@878

@executor-js/plugin-onepassword

npm i https://pkg.pr.new/@executor-js/plugin-onepassword@878

@executor-js/plugin-openapi

npm i https://pkg.pr.new/@executor-js/plugin-openapi@878

executor

npm i https://pkg.pr.new/executor@878

commit: 1b638a4

Let an MCP client pin a specific organization in the URL (`/<org_id>/mcp`)
instead of relying on the organization claim in the OAuth access token. This
unblocks clients that hold a single sign-in session but need to target one of
several organizations.

Server:
- Serve `/<org_id>/mcp` and the matching
  `/.well-known/oauth-protected-resource/<org_id>/mcp` discovery document
  alongside the existing bare `/mcp`.
- Take the organization from the URL when present, falling back to the token
  claim otherwise. Membership is verified against the auth provider on every
  request, so the URL is a selector, not a trust boundary.
- Consolidate MCP path ownership behind one predicate shared by the request
  middleware, the handler, and the test worker. Only `org_`-shaped segments are
  claimed, so unrelated `/<segment>/mcp` paths still fall through to routing.

Frontend:
- The cloud "Connect your MCP client" page and the install card now hand out the
  org-scoped URL. The shared install card stays unscoped for local/desktop,
  where there is no organization.

Tests cover org-scoped discovery metadata, URL-supplied organization, membership
denial before session creation, non-org paths falling through, and org-scoped
URL/command rendering.

Draft: interim org-id form; migrates to organization handles once URL-based org
routing lands.
@RhysSullivan RhysSullivan force-pushed the rs/mcp-org-scoped-routes branch from 90b3538 to 1b638a4 Compare June 1, 2026 07:44
@RhysSullivan RhysSullivan marked this pull request as ready for review June 1, 2026 07:44
@RhysSullivan RhysSullivan merged commit f892e2e into main Jun 1, 2026
11 checks passed
RhysSullivan pushed a commit that referenced this pull request Jun 1, 2026
Resolves the conflict with #878 (org-scoped MCP routes), which added URL-pinned
org selection to the monolithic apps/cloud/src/mcp.ts this branch had already
split into the shared @executor-js/host-mcp envelope + cloud seams.

The feature is preserved, re-implemented cloud-only on the new architecture
(the shared envelope stays org-agnostic so self-host/CF are untouched):
- mcp/mount.ts: classifyMcpPath is now org-aware (recognizes /org_xxx/mcp and
  the org-scoped protected-resource doc; only org_-shaped segments claimed) and
  a new prepareMcpOrgScope rewrites an org-scoped path to the bare path the
  envelope routes, carrying the URL-pinned org in an internal header.
- mcp/auth.ts: MCP_ORGANIZATION_HEADER + reader, org-scoped resource/metadata URL
  builders, org-aware bearerChallengeFor.
- mcp/auth-provider.ts: resourceMetadataUrl, the discovery doc, finishAuthorized,
  and the 401 challenge all take the org from the header (falling back to the
  token claim); membership is still re-checked per request, so the URL is a
  selector, not a trust boundary.
- start.ts + testing/test-worker.ts: apply prepareMcpOrgScope at the dispatch
  boundary; old mcp.ts deleted.

Verified: typecheck 38/38, lint clean, mcp-flow 22/22 (incl. the org-scoped
routing + membership-denial cases), cloud node MCP 24/24, reachability 4/4,
react mcp-install-card 11/11.
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