@@ -238,6 +238,52 @@ async def exchange_authorization_code(
238238 scope = " " .join (authorization_code .scopes ),
239239 )
240240
241+ async def exchange_client_credentials (self , client : OAuthClientInformationFull , scopes : list [str ]) -> OAuthToken :
242+ """Exchange client credentials for an MCP access token."""
243+ mcp_token = f"mcp_{ secrets .token_hex (32 )} "
244+ self .tokens [mcp_token ] = AccessToken (
245+ token = mcp_token ,
246+ client_id = client .client_id ,
247+ scopes = scopes ,
248+ expires_at = int (time .time ()) + 3600 ,
249+ )
250+ return OAuthToken (
251+ access_token = mcp_token ,
252+ token_type = "Bearer" ,
253+ expires_in = 3600 ,
254+ scope = " " .join (scopes ),
255+ )
256+
257+ async def exchange_token (
258+ self ,
259+ client : OAuthClientInformationFull ,
260+ subject_token : str ,
261+ subject_token_type : str ,
262+ actor_token : str | None ,
263+ actor_token_type : str | None ,
264+ scope : list [str ] | None ,
265+ audience : str | None ,
266+ resource : str | None ,
267+ ) -> OAuthToken :
268+ """Exchange an external token for an MCP access token."""
269+ if not subject_token :
270+ raise ValueError ("Invalid subject token" )
271+
272+ mcp_token = f"mcp_{ secrets .token_hex (32 )} "
273+ self .tokens [mcp_token ] = AccessToken (
274+ token = mcp_token ,
275+ client_id = client .client_id ,
276+ scopes = scope or [self .settings .mcp_scope ],
277+ expires_at = int (time .time ()) + 3600 ,
278+ resource = resource ,
279+ )
280+ return OAuthToken (
281+ access_token = mcp_token ,
282+ token_type = "Bearer" ,
283+ expires_in = 3600 ,
284+ scope = " " .join (scope or [self .settings .mcp_scope ]),
285+ )
286+
241287 async def load_access_token (self , token : str ) -> AccessToken | None :
242288 """Load and validate an access token."""
243289 access_token = self .tokens .get (token )
0 commit comments