66 OAuthTokens ,
77 OAuthTokensSchema ,
88} from '@modelcontextprotocol/sdk/shared/auth.js'
9- import type { OAuthProviderOptions } from './types'
9+ import type { OAuthProviderOptions , StaticOAuthClientMetadata } from './types'
1010import { readJsonFile , writeJsonFile , readTextFile , writeTextFile } from './mcp-auth-config'
11+ import { StaticOAuthClientInformationFull } from './types'
1112import { getServerUrlHash , log , debugLog , DEBUG , MCP_REMOTE_VERSION } from './utils'
1213
1314/**
@@ -21,6 +22,8 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
2122 private clientUri : string
2223 private softwareId : string
2324 private softwareVersion : string
25+ private staticOAuthClientMetadata : StaticOAuthClientMetadata
26+ private staticOAuthClientInfo : StaticOAuthClientInformationFull
2427
2528 /**
2629 * Creates a new NodeOAuthClientProvider
@@ -33,6 +36,8 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
3336 this . clientUri = options . clientUri || 'https://github.com/modelcontextprotocol/mcp-cli'
3437 this . softwareId = options . softwareId || '2e6dc280-f3c3-4e01-99a7-8181dbd1d23d'
3538 this . softwareVersion = options . softwareVersion || MCP_REMOTE_VERSION
39+ this . staticOAuthClientMetadata = options . staticOAuthClientMetadata
40+ this . staticOAuthClientInfo = options . staticOAuthClientInfo
3641 }
3742
3843 get redirectUrl ( ) : string {
@@ -49,6 +54,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
4954 client_uri : this . clientUri ,
5055 software_id : this . softwareId ,
5156 software_version : this . softwareVersion ,
57+ ...this . staticOAuthClientMetadata ,
5258 }
5359 }
5460
@@ -58,6 +64,10 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
5864 */
5965 async clientInformation ( ) : Promise < OAuthClientInformationFull | undefined > {
6066 if ( DEBUG ) await debugLog ( this . serverUrlHash , 'Reading client info' )
67+ if ( this . staticOAuthClientInfo ) {
68+ if ( DEBUG ) await debugLog ( this . serverUrlHash , 'Returning static client info' )
69+ return this . staticOAuthClientInfo
70+ }
6171 const clientInfo = await readJsonFile < OAuthClientInformationFull > ( this . serverUrlHash , 'client_info.json' , OAuthClientInformationFullSchema )
6272 if ( DEBUG ) await debugLog ( this . serverUrlHash , 'Client info result:' , clientInfo ? 'Found' : 'Not found' )
6373 return clientInfo
@@ -81,16 +91,16 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
8191 await debugLog ( this . serverUrlHash , 'Reading OAuth tokens' )
8292 await debugLog ( this . serverUrlHash , 'Token request stack trace:' , new Error ( ) . stack )
8393 }
84-
94+
8595 const tokens = await readJsonFile < OAuthTokens > ( this . serverUrlHash , 'tokens.json' , OAuthTokensSchema )
86-
96+
8797 if ( DEBUG ) {
8898 if ( tokens ) {
8999 const expiresAt = new Date ( tokens . expires_at )
90100 const now = new Date ( )
91101 const expiresAtTime = expiresAt . getTime ( )
92102 const timeLeft = ! isNaN ( expiresAtTime ) ? Math . round ( ( expiresAtTime - now . getTime ( ) ) / 1000 ) : 0
93-
103+
94104 // Alert if expires_at produces an invalid date
95105 if ( isNaN ( expiresAtTime ) ) {
96106 await debugLog ( this . serverUrlHash , '⚠️ WARNING: Invalid expires_at detected while reading tokens ⚠️' , {
@@ -99,8 +109,8 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
99109 stack : new Error ( 'Invalid expires_at timestamp' ) . stack
100110 } )
101111 }
102-
103- await debugLog ( this . serverUrlHash , 'Token result:' , {
112+
113+ await debugLog ( this . serverUrlHash , 'Token result:' , {
104114 found : true ,
105115 hasAccessToken : ! ! tokens . access_token ,
106116 hasRefreshToken : ! ! tokens . refresh_token ,
@@ -112,7 +122,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
112122 await debugLog ( this . serverUrlHash , 'Token result: Not found' )
113123 }
114124 }
115-
125+
116126 return tokens
117127 }
118128
@@ -126,7 +136,7 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
126136 const now = new Date ( )
127137 const expiresAtTime = expiresAt . getTime ( )
128138 const timeLeft = ! isNaN ( expiresAtTime ) ? Math . round ( ( expiresAtTime - now . getTime ( ) ) / 1000 ) : 0
129-
139+
130140 // Alert if expires_at produces an invalid date
131141 if ( isNaN ( expiresAtTime ) ) {
132142 await debugLog ( this . serverUrlHash , '⚠️ WARNING: Invalid expires_at detected in tokens ⚠️' , {
@@ -135,15 +145,15 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
135145 stack : new Error ( 'Invalid expires_at timestamp' ) . stack
136146 } )
137147 }
138-
139- await debugLog ( this . serverUrlHash , 'Saving tokens' , {
148+
149+ await debugLog ( this . serverUrlHash , 'Saving tokens' , {
140150 hasAccessToken : ! ! tokens . access_token ,
141151 hasRefreshToken : ! ! tokens . refresh_token ,
142152 expiresIn : `${ timeLeft } seconds` ,
143153 expiresAt : tokens . expires_at
144154 } )
145155 }
146-
156+
147157 await writeJsonFile ( this . serverUrlHash , 'tokens.json' , tokens )
148158 }
149159
@@ -153,9 +163,9 @@ export class NodeOAuthClientProvider implements OAuthClientProvider {
153163 */
154164 async redirectToAuthorization ( authorizationUrl : URL ) : Promise < void > {
155165 log ( `\nPlease authorize this client by visiting:\n${ authorizationUrl . toString ( ) } \n` )
156-
166+
157167 if ( DEBUG ) await debugLog ( this . serverUrlHash , 'Redirecting to authorization URL' , authorizationUrl . toString ( ) )
158-
168+
159169 try {
160170 await open ( authorizationUrl . toString ( ) )
161171 log ( 'Browser opened automatically.' )
0 commit comments