3232 CustomerCredentials ,
3333 IntegrationDependency ,
3434 MCPTool ,
35+ MCPToolFilter ,
3536)
3637from sap_cloud_sdk .agentgateway ._token_cache import _TokenCache
3738from sap_cloud_sdk .agentgateway .exceptions import AgentGatewaySDKError
@@ -642,7 +643,7 @@ async def _list_server_tools(
642643 async with streamable_http_client (url , http_client = http_client ) as (
643644 read ,
644645 write ,
645- _ ,
646+ * _ ,
646647 ):
647648 async with ClientSession (read , write ) as session :
648649 init_result = await session .initialize ()
@@ -672,10 +673,30 @@ async def _list_server_tools(
672673 ]
673674
674675
676+ def _log_mcp_server_error (ord_id : str , exc : BaseException ) -> None :
677+ # Unwrap ExceptionGroup from anyio to surface the real HTTP error body
678+ if isinstance (exc , BaseExceptionGroup ):
679+ for inner in exc .exceptions :
680+ _log_mcp_server_error (ord_id , inner )
681+ return
682+ if isinstance (exc , httpx .HTTPStatusError ):
683+ logger .error (
684+ "Failed to load tools from %s (HTTP %d): %s" ,
685+ ord_id ,
686+ exc .response .status_code ,
687+ exc .response .text [:500 ],
688+ )
689+ else :
690+ logger .exception (
691+ "Failed to load tools from %s — skipping" , ord_id , exc_info = exc
692+ )
693+
694+
675695async def get_mcp_tools_customer (
676696 credentials : CustomerCredentials ,
677697 system_token : str ,
678698 timeout : float ,
699+ filter : MCPToolFilter | None = None ,
679700) -> list [MCPTool ]:
680701 """List all MCP tools from servers defined in credentials.
681702
@@ -686,19 +707,24 @@ async def get_mcp_tools_customer(
686707 credentials: Customer credentials with integrationDependencies.
687708 system_token: Pre-fetched raw system token for authentication.
688709 timeout: HTTP timeout in seconds for MCP server calls.
710+ filter: Optional MCPToolFilter narrowing results by tool name or ORD ID.
711+ If None or empty, all tools are included.
689712
690713 Returns:
691714 List of MCPTool objects from all servers.
692-
693- Raises:
694- AgentGatewaySDKError: If integrationDependencies is empty.
695715 """
716+ f = filter or MCPToolFilter ()
696717 dependencies = credentials .integration_dependencies
697718
698719 if not dependencies :
699- raise AgentGatewaySDKError (
720+ logger . warning (
700721 "integrationDependencies is empty in credentials — no MCP servers configured."
701722 )
723+ return []
724+
725+ if f .ord_ids :
726+ ord_ids_set = set (f .ord_ids )
727+ dependencies = [d for d in dependencies if d .ord_id in ord_ids_set ]
702728
703729 logger .info ("Discovering tools from %d MCP server(s)" , len (dependencies ))
704730
@@ -717,8 +743,13 @@ async def get_mcp_tools_customer(
717743 server_tools = await _list_server_tools (url , system_token , timeout )
718744 tools .extend (server_tools )
719745 logger .debug ("Loaded %d tool(s) from %s" , len (server_tools ), dep .ord_id )
720- except Exception :
721- logger .exception ("Failed to load tools from %s — skipping" , dep .ord_id )
746+ except Exception as exc :
747+ _log_mcp_server_error (dep .ord_id , exc )
748+
749+ # Post-fetch filter: tool names are only known after fetching
750+ if f .names :
751+ names_set = set (f .names )
752+ tools = [t for t in tools if t .name in names_set ]
722753
723754 logger .info (
724755 "Loaded %d MCP tool(s) from %d server(s)" , len (tools ), len (dependencies )
@@ -758,7 +789,7 @@ async def call_mcp_tool_customer(
758789 async with streamable_http_client (tool .url , http_client = http_client ) as (
759790 read ,
760791 write ,
761- _ ,
792+ * _ ,
762793 ):
763794 async with ClientSession (read , write ) as session :
764795 await session .initialize ()
@@ -769,4 +800,9 @@ async def call_mcp_tool_customer(
769800 return ""
770801
771802 first = result .content [0 ]
772- return str (getattr (first , "text" , "" ))
803+ text = str (getattr (first , "text" , "" ))
804+
805+ if result .isError :
806+ logger .error ("Tool '%s' returned an error: %s" , tool .name , text )
807+
808+ return text
0 commit comments