diff --git a/src/sap_cloud_sdk/agentgateway/_customer.py b/src/sap_cloud_sdk/agentgateway/_customer.py index be5019ea..e7386c1c 100644 --- a/src/sap_cloud_sdk/agentgateway/_customer.py +++ b/src/sap_cloud_sdk/agentgateway/_customer.py @@ -551,26 +551,42 @@ async def call_mcp_tool_customer( Tool execution result as string. """ logger.info("Calling tool '%s' on server '%s'", tool.name, tool.server_name) + correlation_id: str | None = None - async with httpx.AsyncClient( - headers={ - "Authorization": f"Bearer {auth_token}", - "x-correlation-id": str(uuid.uuid4()), - }, - timeout=timeout, - ) as http_client: - async with streamable_http_client(tool.url, http_client=http_client) as ( - read, - write, - _, - ): - async with ClientSession(read, write) as session: - await session.initialize() - result = await session.call_tool(tool.name, kwargs) + async def _capture_correlation_id(response: httpx.Response) -> None: + nonlocal correlation_id + cid = response.headers.get("x-correlation-id") + if cid: + correlation_id = cid - if not result.content: - logger.warning("Tool '%s' returned empty content", tool.name) - return "" - - first = result.content[0] - return str(getattr(first, "text", "")) + try: + async with httpx.AsyncClient( + headers={ + "Authorization": f"Bearer {auth_token}", + "x-correlation-id": str(uuid.uuid4()), + }, + timeout=timeout, + event_hooks={"response": [_capture_correlation_id]}, + ) as http_client: + async with streamable_http_client(tool.url, http_client=http_client) as ( + read, + write, + _, + ): + async with ClientSession(read, write) as session: + await session.initialize() + result = await session.call_tool(tool.name, kwargs) + + if not result.content: + logger.warning("Tool '%s' returned empty content", tool.name) + return "" + + first = result.content[0] + return str(getattr(first, "text", "")) + except Exception: + logger.exception( + "MCP tool call failed for '%s' (x-correlation-id: %s)", + tool.name, + correlation_id or "unknown", + ) + raise diff --git a/src/sap_cloud_sdk/agentgateway/_lob.py b/src/sap_cloud_sdk/agentgateway/_lob.py index 0ada5b63..b7734f14 100644 --- a/src/sap_cloud_sdk/agentgateway/_lob.py +++ b/src/sap_cloud_sdk/agentgateway/_lob.py @@ -383,26 +383,43 @@ async def call_mcp_tool_lob( Returns: Tool execution result as string. """ - async with httpx.AsyncClient( - headers={ - "Authorization": f"Bearer {user_auth_token}", - "x-correlation-id": str(uuid.uuid4()), - }, - timeout=timeout, - ) as http_client: - async with streamable_http_client(tool.url, http_client=http_client) as ( - read, - write, - _, - ): - async with ClientSession(read, write) as session: - await session.initialize() - result = await session.call_tool(tool.name, kwargs) - if not result.content: - logger.warning("Tool '%s' returned empty content", tool.name) - return "" - first = result.content[0] - return str(getattr(first, "text", "")) + correlation_id: str | None = None + + async def _capture_correlation_id(response: httpx.Response) -> None: + nonlocal correlation_id + cid = response.headers.get("x-correlation-id") + if cid: + correlation_id = cid + + try: + async with httpx.AsyncClient( + headers={ + "Authorization": f"Bearer {user_auth_token}", + "x-correlation-id": str(uuid.uuid4()), + }, + timeout=timeout, + event_hooks={"response": [_capture_correlation_id]}, + ) as http_client: + async with streamable_http_client(tool.url, http_client=http_client) as ( + read, + write, + _, + ): + async with ClientSession(read, write) as session: + await session.initialize() + result = await session.call_tool(tool.name, kwargs) + if not result.content: + logger.warning("Tool '%s' returned empty content", tool.name) + return "" + first = result.content[0] + return str(getattr(first, "text", "")) + except Exception: + logger.error( + "MCP tool call failed for '%s' (x-correlation-id: %s)", + tool.name, + correlation_id or "unknown", + ) + raise async def _fetch_agent_card(