@@ -16,7 +16,7 @@ export type FetchLike = (url: string, init?: RequestInit) => Promise<Response>;
1616
1717export interface McpDetection {
1818 url : string ;
19- source : "api-catalog" | "server-card" ;
19+ source : "api-catalog" | "server-card" | "probe" ;
2020 /** "oauth2" | "none" | undefined (unknown) */
2121 auth ?: string ;
2222 authorizationServer ?: string ;
@@ -231,6 +231,20 @@ async function detectMcpOnboarding(fetchImpl: FetchLike, mcpUrl: string): Promis
231231 } ;
232232}
233233
234+ /** Probe the conventional /mcp path; confirm it's actually an MCP endpoint. */
235+ async function discoverMcpEndpoint ( fetchImpl : FetchLike , domain : string ) : Promise < string | undefined > {
236+ const url = `https://${ domain } /mcp` ;
237+ const hit = await get ( fetchImpl , url , {
238+ method : "POST" ,
239+ headers : { "content-type" : "application/json" , accept : "application/json, text/event-stream" } ,
240+ body : JSON . stringify ( { jsonrpc : "2.0" , id : 1 , method : "initialize" , params : { protocolVersion : "2025-06-18" , capabilities : { } , clientInfo : { name : "integrations.sh" , version : "0" } } } ) ,
241+ } ) ;
242+ if ( ! hit ) return undefined ;
243+ const wwwAuth = hit . res . headers . get ( "www-authenticate" ) ?? "" ;
244+ const looksMcp = ( hit . res . status === 401 && / r e s o u r c e _ m e t a d a t a = / . test ( wwwAuth ) ) || ( hit . res . ok && / [ " ' ] ? j s o n r p c / . test ( hit . text ) ) ;
245+ return looksMcp ? url : undefined ;
246+ }
247+
234248// ── orchestration ────────────────────────────────────────────────────────────
235249
236250export async function detect ( domain : string , fetchImpl : FetchLike = fetch ) : Promise < DetectionResult > {
@@ -244,12 +258,14 @@ export async function detect(domain: string, fetchImpl: FetchLike = fetch): Prom
244258 checkApiSchema ( fetchImpl , domain ) . catch ( ( ) => undefined ) ,
245259 checkApiOAuth ( fetchImpl , domain ) . catch ( ( ) => undefined ) ,
246260 ] ) ;
261+ const probedMcp = await discoverMcpEndpoint ( fetchImpl , domain ) . catch ( ( ) => undefined ) ;
247262
248263 // Collect MCP endpoints from the server card + api-catalog, then probe each
249264 // for self-onboarding capability.
250265 const mcpSeen = new Map < string , McpDetection > ( ) ;
251266 if ( serverCard ) mcpSeen . set ( serverCard . url , serverCard ) ;
252267 for ( const url of apiCatalog ?. mcp ?? [ ] ) if ( ! mcpSeen . has ( url ) ) mcpSeen . set ( url , { url, source : "api-catalog" } ) ;
268+ if ( probedMcp && ! mcpSeen . has ( probedMcp ) ) mcpSeen . set ( probedMcp , { url : probedMcp , source : "probe" } ) ;
253269 const mcp = await Promise . all (
254270 [ ...mcpSeen . values ( ) ] . map ( async ( m ) => ( { ...m , ...( await detectMcpOnboarding ( fetchImpl , m . url ) . catch ( ( ) => ( { } ) ) ) } ) ) ,
255271 ) ;
0 commit comments