|
23 | 23 | import httpx |
24 | 24 | from mcp import ClientSession |
25 | 25 | from mcp.client.streamable_http import streamable_http_client |
| 26 | +from mcp.shared.exceptions import McpError |
26 | 27 |
|
27 | 28 | from sap_cloud_sdk.agentgateway._dependencies_resolver import ( |
28 | 29 | EnvironmentDependenciesResolver, |
29 | 30 | IntegrationDependenciesResolver, |
30 | 31 | ) |
31 | 32 | from sap_cloud_sdk.agentgateway._models import ( |
| 33 | + JsonRpcError, |
32 | 34 | CustomerCredentials, |
33 | 35 | IntegrationDependency, |
34 | 36 | MCPTool, |
@@ -680,15 +682,42 @@ def _log_mcp_server_error(ord_id: str, exc: BaseException) -> None: |
680 | 682 | _log_mcp_server_error(ord_id, inner) |
681 | 683 | return |
682 | 684 | if isinstance(exc, httpx.HTTPStatusError): |
| 685 | + try: |
| 686 | + body = exc.response.text |
| 687 | + except httpx.ResponseNotRead: |
| 688 | + body = None |
| 689 | + rpc_error = JsonRpcError.parse(body) if body else None |
| 690 | + if rpc_error: |
| 691 | + logger.error( |
| 692 | + "Failed to load tools from %s — %s returned HTTP %d [JSON-RPC %d]: %s", |
| 693 | + ord_id, |
| 694 | + exc.request.url, |
| 695 | + exc.response.status_code, |
| 696 | + rpc_error.code, |
| 697 | + rpc_error.message, |
| 698 | + ) |
| 699 | + else: |
| 700 | + logger.error( |
| 701 | + "Failed to load tools from %s — %s returned HTTP %d: %s", |
| 702 | + ord_id, |
| 703 | + exc.request.url, |
| 704 | + exc.response.status_code, |
| 705 | + body[:500] if body else "(response body not available)", |
| 706 | + ) |
| 707 | + elif isinstance(exc, McpError): |
683 | 708 | logger.error( |
684 | | - "Failed to load tools from %s (HTTP %d): %s", |
| 709 | + "Failed to load tools from %s — JSON-RPC %d: %s", |
685 | 710 | ord_id, |
686 | | - exc.response.status_code, |
687 | | - exc.response.text[:500], |
| 711 | + exc.error.code, |
| 712 | + exc.error.message, |
688 | 713 | ) |
689 | 714 | else: |
690 | | - logger.exception( |
691 | | - "Failed to load tools from %s — skipping", ord_id, exc_info=exc |
| 715 | + logger.error( |
| 716 | + "Failed to load tools from %s — %s: %s", |
| 717 | + ord_id, |
| 718 | + type(exc).__name__, |
| 719 | + exc, |
| 720 | + exc_info=exc, |
692 | 721 | ) |
693 | 722 |
|
694 | 723 |
|
@@ -796,13 +825,20 @@ async def call_mcp_tool_customer( |
796 | 825 | result = await session.call_tool(tool.name, kwargs) |
797 | 826 |
|
798 | 827 | if not result.content: |
799 | | - logger.warning("Tool '%s' returned empty content", tool.name) |
| 828 | + logger.warning( |
| 829 | + "Tool '%s' on '%s' returned empty content", tool.name, tool.url |
| 830 | + ) |
800 | 831 | return "" |
801 | 832 |
|
802 | 833 | first = result.content[0] |
803 | 834 | text = str(getattr(first, "text", "")) |
804 | 835 |
|
805 | 836 | if result.isError: |
806 | | - logger.error("Tool '%s' returned an error: %s", tool.name, text) |
| 837 | + logger.error( |
| 838 | + "Tool '%s' on '%s' returned an error: %s", |
| 839 | + tool.name, |
| 840 | + tool.url, |
| 841 | + text, |
| 842 | + ) |
807 | 843 |
|
808 | 844 | return text |
0 commit comments