@@ -5,12 +5,13 @@ import { IdentityProvider, isPlatformPrincipal } from "@executor-js/api/server";
55import {
66 authenticated ,
77 McpAuthProvider ,
8- mcpResourceFromPathname ,
8+ mcpResourceFromRequest ,
99 mcpResourcePath ,
10+ OAUTH_PROTECTED_RESOURCE_PREFIX ,
11+ scopedMcpRoutePaths ,
1012 unauthorized ,
1113 type AuthOutcome ,
1214 type McpDiscoveryRoute ,
13- type McpResource ,
1415 type Principal ,
1516} from "@executor-js/host-mcp" ;
1617
@@ -57,14 +58,9 @@ import { MCP_ORIGINAL_PATH_HEADER, mcpResourcePathFromOriginalPath } from "./org
5758// stay on the Better Auth handler mounted at /api/auth — NOT in this seam.
5859// ---------------------------------------------------------------------------
5960
60- const PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource" ;
61- // One metadata doc per scoped MCP sub-resource kind (the default doc is the
62- // bare well-known path itself, Better Auth's convention).
63- const SCOPED_PROTECTED_RESOURCE_METADATA_PATHS = [
64- `${ PROTECTED_RESOURCE_METADATA_PATH } /mcp/toolkits/:slug` ,
65- `${ PROTECTED_RESOURCE_METADATA_PATH } /mcp/integrations/:slugs` ,
66- `${ PROTECTED_RESOURCE_METADATA_PATH } /mcp/tools/:toolId` ,
67- ] as const ;
61+ // The default doc is the bare well-known path itself (Better Auth's
62+ // convention); scoped docs sit under `<prefix>/mcp/...`.
63+ const PROTECTED_RESOURCE_METADATA_PATH = OAUTH_PROTECTED_RESOURCE_PREFIX ;
6864const AUTHORIZATION_SERVER_METADATA_PATH = "/.well-known/oauth-authorization-server" ;
6965
7066const parseRoles = ( role : string | null | undefined ) : ReadonlyArray < string > =>
@@ -99,26 +95,11 @@ const originalOrgScopedPathFor = (request: Request): string | null => {
9995 return header ? mcpResourcePathFromOriginalPath ( header ) : null ;
10096} ;
10197
102- /**
103- * The scoped MCP resource a bare request names, read off its own path (the
104- * transport path or its metadata doc), or `null` for the default endpoint.
105- * The grammar is the shared one from host-mcp.
106- */
107- const scopedResourceFor = ( request : Request ) : McpResource | null => {
108- const pathname = new URL ( request . url ) . pathname ;
109- const bare = pathname . startsWith ( PROTECTED_RESOURCE_METADATA_PATH )
110- ? pathname . slice ( PROTECTED_RESOURCE_METADATA_PATH . length )
111- : pathname ;
112- const resource = mcpResourceFromPathname ( bare ) ;
113- return resource === null || resource . kind === "default" ? null : resource ;
114- } ;
98+ const isScopedRequest = ( request : Request ) : boolean =>
99+ mcpResourceFromRequest ( request ) . kind !== "default" ;
115100
116- const mcpResourcePathFor = ( request : Request ) : string => {
117- const orgScoped = originalOrgScopedPathFor ( request ) ;
118- if ( orgScoped ) return orgScoped ;
119- const scoped = scopedResourceFor ( request ) ;
120- return scoped ? mcpResourcePath ( scoped ) : "/mcp" ;
121- } ;
101+ const mcpResourcePathFor = ( request : Request ) : string =>
102+ originalOrgScopedPathFor ( request ) ?? mcpResourcePath ( mcpResourceFromRequest ( request ) ) ;
122103
123104/**
124105 * Absolute protected-resource metadata URL for the 401 challenge. Derive the
@@ -131,9 +112,8 @@ const resourceMetadataUrlFor = (baseURL: string | undefined, request: Request):
131112 const origin = baseURL && baseURL . length > 0 ? baseURL : new URL ( request . url ) . origin ;
132113 const orgScoped = originalOrgScopedPathFor ( request ) ;
133114 if ( orgScoped ) return `${ origin } ${ PROTECTED_RESOURCE_METADATA_PATH } ${ orgScoped } ` ;
134- const scoped = scopedResourceFor ( request ) ;
135- return scoped
136- ? `${ origin } ${ PROTECTED_RESOURCE_METADATA_PATH } ${ mcpResourcePath ( scoped ) } `
115+ return isScopedRequest ( request )
116+ ? `${ origin } ${ PROTECTED_RESOURCE_METADATA_PATH } ${ mcpResourcePathFor ( request ) } `
137117 : `${ origin } ${ PROTECTED_RESOURCE_METADATA_PATH } ` ;
138118} ;
139119
@@ -150,7 +130,7 @@ const scopedProtectedResourceMetadata = (
150130 response : Response ,
151131 baseURL : string | undefined ,
152132) : Effect . Effect < Response > => {
153- if ( scopedResourceFor ( request ) === null ) return Effect . succeed ( response ) ;
133+ if ( ! isScopedRequest ( request ) ) return Effect . succeed ( response ) ;
154134 return Effect . promise ( async ( ) => {
155135 const body = ( await response . json ( ) ) as Record < string , unknown > ;
156136 const headers = new Headers ( response . headers ) ;
@@ -189,7 +169,7 @@ export const selfHostMcpAuth: Layer.Layer<McpAuthProvider, never, BetterAuth | I
189169 ) ;
190170 const discoveryRoutes : ReadonlyArray < McpDiscoveryRoute > = [
191171 { path : PROTECTED_RESOURCE_METADATA_PATH , handler : protectedResourceMetadata } ,
192- ...SCOPED_PROTECTED_RESOURCE_METADATA_PATHS . map ( ( path ) => ( {
172+ ...scopedMcpRoutePaths ( ` ${ PROTECTED_RESOURCE_METADATA_PATH } /mcp` ) . map ( ( path ) => ( {
193173 path,
194174 handler : protectedResourceMetadata ,
195175 } ) ) ,
0 commit comments