3535# Default credential path for Kyma production deployments
3636_CREDENTIALS_DEFAULT_PATH = "/etc/ums/credentials/credentials"
3737
38- # HTTP timeout for token requests and MCP server calls (seconds)
39- _HTTP_TIMEOUT = 30.0
40-
4138# Resource URN for Agent Gateway token scope (hardcoded - production value)
4239_AGW_RESOURCE_URN = "urn:sap:identity:application:provider:name:agent-gateway"
4340
@@ -213,6 +210,7 @@ def _create_ssl_context(certificate: str, private_key: str) -> ssl.SSLContext:
213210def _request_token_mtls (
214211 credentials : CustomerCredentials ,
215212 grant_type : str ,
213+ timeout : float ,
216214 app_tid : str | None = None ,
217215 extra_data : dict | None = None ,
218216) -> str :
@@ -255,7 +253,7 @@ def _request_token_mtls(
255253 try :
256254 with httpx .Client (
257255 verify = ssl_context ,
258- timeout = _HTTP_TIMEOUT ,
256+ timeout = timeout ,
259257 ) as client :
260258 response = client .post (
261259 credentials .token_service_url ,
@@ -293,6 +291,7 @@ def _request_token_mtls(
293291
294292def get_system_token_mtls (
295293 credentials : CustomerCredentials ,
294+ timeout : float ,
296295 app_tid : str | None = None ,
297296) -> str :
298297 """Get system-scoped token using mTLS client credentials flow.
@@ -301,6 +300,7 @@ def get_system_token_mtls(
301300
302301 Args:
303302 credentials: Customer credentials.
303+ timeout: HTTP timeout in seconds.
304304 app_tid: BTP Application Tenant ID of subscriber (optional).
305305
306306 Returns:
@@ -310,6 +310,7 @@ def get_system_token_mtls(
310310 return _request_token_mtls (
311311 credentials ,
312312 grant_type = _GRANT_TYPE_CLIENT_CREDENTIALS ,
313+ timeout = timeout ,
313314 app_tid = app_tid ,
314315 extra_data = {"response_type" : "token" },
315316 )
@@ -318,6 +319,7 @@ def get_system_token_mtls(
318319def exchange_user_token (
319320 credentials : CustomerCredentials ,
320321 user_token : str ,
322+ timeout : float ,
321323 app_tid : str | None = None ,
322324) -> str :
323325 """Exchange user token for AGW-scoped token using jwt-bearer grant.
@@ -328,6 +330,7 @@ def exchange_user_token(
328330 Args:
329331 credentials: Customer credentials.
330332 user_token: User's JWT token to exchange.
333+ timeout: HTTP timeout in seconds.
331334 app_tid: BTP Application Tenant ID of subscriber (optional).
332335
333336 Returns:
@@ -337,6 +340,7 @@ def exchange_user_token(
337340 return _request_token_mtls (
338341 credentials ,
339342 grant_type = _GRANT_TYPE_JWT_BEARER ,
343+ timeout = timeout ,
340344 app_tid = app_tid ,
341345 extra_data = {
342346 "assertion" : user_token ,
@@ -371,6 +375,7 @@ async def _list_server_tools(
371375 url : str ,
372376 auth_token : str ,
373377 dependency : IntegrationDependency ,
378+ timeout : float ,
374379) -> list [MCPTool ]:
375380 """List tools from a single MCP server.
376381
@@ -390,7 +395,7 @@ async def _list_server_tools(
390395 "Authorization" : f"Bearer { auth_token } " ,
391396 "x-correlation-id" : str (uuid .uuid4 ()),
392397 },
393- timeout = _HTTP_TIMEOUT ,
398+ timeout = timeout ,
394399 ) as http_client :
395400 async with streamable_http_client (url , http_client = http_client ) as (
396401 read ,
@@ -427,6 +432,7 @@ async def _list_server_tools(
427432
428433async def get_mcp_tools_customer (
429434 credentials : CustomerCredentials ,
435+ timeout : float ,
430436 app_tid : str | None = None ,
431437) -> list [MCPTool ]:
432438 """List all MCP tools from servers defined in credentials.
@@ -456,7 +462,7 @@ async def get_mcp_tools_customer(
456462 # Get system token for discovery
457463 loop = asyncio .get_running_loop ()
458464 system_token = await loop .run_in_executor (
459- None , get_system_token_mtls , credentials , app_tid
465+ None , get_system_token_mtls , credentials , timeout , app_tid
460466 )
461467
462468 tools : list [MCPTool ] = []
@@ -471,7 +477,7 @@ async def get_mcp_tools_customer(
471477 )
472478
473479 try :
474- server_tools = await _list_server_tools (url , system_token , dep )
480+ server_tools = await _list_server_tools (url , system_token , dep , timeout )
475481 tools .extend (server_tools )
476482 logger .debug ("Loaded %d tool(s) from %s" , len (server_tools ), dep .ord_id )
477483 except Exception :
@@ -487,6 +493,7 @@ async def call_mcp_tool_customer(
487493 credentials : CustomerCredentials ,
488494 tool : MCPTool ,
489495 user_token : str | None ,
496+ timeout : float ,
490497 app_tid : str | None = None ,
491498 ** kwargs ,
492499) -> str :
@@ -513,7 +520,7 @@ async def call_mcp_tool_customer(
513520 if user_token :
514521 # Exchange user token for AGW-scoped token (with principal propagation)
515522 agw_token = await loop .run_in_executor (
516- None , exchange_user_token , credentials , user_token , app_tid
523+ None , exchange_user_token , credentials , user_token , timeout , app_tid
517524 )
518525 else :
519526 # TODO: IBD workaround - use system token when user_token is not available.
@@ -524,15 +531,15 @@ async def call_mcp_tool_customer(
524531 "Principal propagation will NOT work."
525532 )
526533 agw_token = await loop .run_in_executor (
527- None , get_system_token_mtls , credentials , app_tid
534+ None , get_system_token_mtls , credentials , timeout , app_tid
528535 )
529536
530537 async with httpx .AsyncClient (
531538 headers = {
532539 "Authorization" : f"Bearer { agw_token } " ,
533540 "x-correlation-id" : str (uuid .uuid4 ()),
534541 },
535- timeout = _HTTP_TIMEOUT ,
542+ timeout = timeout ,
536543 ) as http_client :
537544 async with streamable_http_client (tool .url , http_client = http_client ) as (
538545 read ,
0 commit comments