@@ -13,6 +13,7 @@ import { getErrorMessage } from '@sim/utils/errors'
1313import { getMaxExecutionTimeout } from '@/lib/core/execution-limits'
1414import { getMcpSafeErrorDiagnostics } from '@/lib/mcp/error-diagnostics'
1515import { McpOauthRedirectRequired } from '@/lib/mcp/oauth'
16+ import { createCoordinatedMcpOauthFetch } from '@/lib/mcp/oauth/coordinated-fetch'
1617import { createGuardedMcpFetch , createPinnedPrivateMcpFetch } from '@/lib/mcp/pinned-fetch'
1718import {
1819 type McpClientOptions ,
@@ -21,6 +22,7 @@ import {
2122 type McpConsentRequest ,
2223 type McpConsentResponse ,
2324 McpError ,
25+ McpOauthAuthorizationRequiredError ,
2426 type McpSecurityPolicy ,
2527 type McpServerConfig ,
2628 type McpTool ,
@@ -47,7 +49,10 @@ function classifyConnectionOutcome(
4749 error : unknown ,
4850 authType : McpServerConfig [ 'authType' ]
4951) : ConnectionOutcome {
50- if ( error instanceof McpOauthRedirectRequired ) {
52+ if (
53+ error instanceof McpOauthRedirectRequired ||
54+ error instanceof McpOauthAuthorizationRequiredError
55+ ) {
5156 return 'authorization_required'
5257 }
5358 if ( error instanceof UnauthorizedError ) {
@@ -100,8 +105,15 @@ export class McpClient {
100105 throw new McpError ( 'URL required for Streamable HTTP transport' )
101106 }
102107
103- if ( this . config . authType === 'oauth' && this . authProvider == null ) {
104- throw new McpError ( 'OAuth MCP server requires an authProvider' )
108+ if (
109+ this . config . authType === 'oauth' &&
110+ this . authProvider == null &&
111+ ! options . oauthCredentials
112+ ) {
113+ throw new McpError ( 'OAuth MCP server requires OAuth credentials' )
114+ }
115+ if ( options . oauthCredentials && this . authProvider ) {
116+ throw new McpError ( 'OAuth MCP server must use one authentication strategy' )
105117 }
106118 const useOauth = this . config . authType === 'oauth'
107119 // `resolvedIP` is null only when the hostname still carries an unresolved env-var
@@ -115,10 +127,18 @@ export class McpClient {
115127 : createGuardedMcpFetch ( this . config . url )
116128 : undefined
117129 this . closeGuardedTransport = guarded ?. close
130+ const transportFetch =
131+ useOauth && options . oauthCredentials
132+ ? createCoordinatedMcpOauthFetch ( options . oauthCredentials , {
133+ serverUrl : this . config . url ,
134+ fetch : guarded ?. fetch ?? fetch ,
135+ requestInit : { headers : this . config . headers } ,
136+ } )
137+ : guarded ?. fetch
118138 this . transport = new StreamableHTTPClientTransport ( new URL ( this . config . url ) , {
119139 authProvider : useOauth ? this . authProvider : undefined ,
120140 requestInit : { headers : this . config . headers } ,
121- ...( guarded ? { fetch : guarded . fetch } : { } ) ,
141+ ...( transportFetch ? { fetch : transportFetch } : { } ) ,
122142 } )
123143
124144 this . client = new Client (
0 commit comments