99from agent_framework import ChatAgent , ChatMessage , ChatMessageStoreProtocol , MCPStreamableHTTPTool
1010from agent_framework .azure import AzureOpenAIChatClient
1111from agent_framework .openai import OpenAIChatClient
12+ import httpx
1213
1314from microsoft_agents .hosting .core import Authorization , TurnContext
1415
2425)
2526
2627
28+ # Default timeout for MCP server HTTP requests (in seconds)
29+ MCP_HTTP_CLIENT_TIMEOUT_SECONDS = 90.0
30+
31+
2732class McpToolRegistrationService :
2833 """
2934 Provides MCP tool registration services for Agent Framework agents.
@@ -46,6 +51,7 @@ def __init__(self, logger: Optional[logging.Logger] = None):
4651 logger = self ._logger
4752 )
4853 self ._connected_servers = []
54+ self ._http_clients : List [httpx .AsyncClient ] = []
4955
5056 async def add_tool_servers_to_agent (
5157 self ,
@@ -114,11 +120,17 @@ async def add_tool_servers_to_agent(
114120 self ._orchestrator_name
115121 )
116122
117- # Create and configure MCPStreamableHTTPTool
123+ # Create httpx client with auth headers configured
124+ http_client = httpx .AsyncClient (
125+ headers = headers , timeout = MCP_HTTP_CLIENT_TIMEOUT_SECONDS
126+ )
127+ self ._http_clients .append (http_client )
128+
129+ # Create and configure MCPStreamableHTTPTool with http_client
118130 mcp_tools = MCPStreamableHTTPTool (
119131 name = server_name ,
120132 url = config .url ,
121- headers = headers ,
133+ http_client = http_client ,
122134 description = f"MCP tools from { server_name } " ,
123135 )
124136
@@ -339,12 +351,21 @@ async def send_chat_history_from_store(
339351 async def cleanup (self ):
340352 """Clean up any resources used by the service."""
341353 try :
354+ # Close MCP server connections
342355 for plugin in self ._connected_servers :
343356 try :
344357 if hasattr (plugin , "close" ):
345358 await plugin .close ()
346359 except Exception as cleanup_ex :
347- self ._logger .debug (f"Error during cleanup: { cleanup_ex } " )
360+ self ._logger .debug (f"Error during plugin cleanup: { cleanup_ex } " )
348361 self ._connected_servers .clear ()
362+
363+ # Close httpx clients to prevent connection/file descriptor leaks
364+ for http_client in self ._http_clients :
365+ try :
366+ await http_client .aclose ()
367+ except Exception as client_ex :
368+ self ._logger .debug (f"Error closing http client: { client_ex } " )
369+ self ._http_clients .clear ()
349370 except Exception as ex :
350371 self ._logger .debug (f"Error during service cleanup: { ex } " )
0 commit comments