mcp-use 1.1.5__py3-none-any.whl → 1.2.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of mcp-use might be problematic. Click here for more details.

@@ -5,16 +5,29 @@ This module provides the main MCPAgent class that integrates all components
5
5
  to provide a simple interface for using MCP tools with different LLMs.
6
6
  """
7
7
 
8
+ import logging
9
+
10
+ from langchain.agents import AgentExecutor, create_tool_calling_agent
11
+ from langchain.globals import set_debug
12
+ from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder
8
13
  from langchain.schema import AIMessage, BaseMessage, HumanMessage, SystemMessage
9
14
  from langchain.schema.language_model import BaseLanguageModel
15
+ from langchain_core.agents import AgentAction, AgentFinish
16
+ from langchain_core.exceptions import OutputParserException
17
+ from langchain_core.tools import BaseTool
18
+ from langchain_core.utils.input import get_color_mapping
10
19
 
11
20
  from mcp_use.client import MCPClient
12
21
  from mcp_use.connectors.base import BaseConnector
13
22
  from mcp_use.session import MCPSession
14
23
 
24
+ from ..adapters.langchain_adapter import LangChainAdapter
15
25
  from ..logging import logger
16
- from .langchain_agent import LangChainAgent
17
- from .prompts.default import DEFAULT_SYSTEM_PROMPT_TEMPLATE
26
+ from .prompts.system_prompt_builder import create_system_message
27
+ from .prompts.templates import DEFAULT_SYSTEM_PROMPT_TEMPLATE, SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE
28
+ from .server_manager import ServerManager
29
+
30
+ set_debug(logger.level == logging.DEBUG)
18
31
 
19
32
 
20
33
  class MCPAgent:
@@ -24,9 +37,6 @@ class MCPAgent:
24
37
  through LangChain's agent framework, with customizable system prompts and conversation memory.
25
38
  """
26
39
 
27
- # Default system prompt template to use if none is provided
28
- DEFAULT_SYSTEM_PROMPT_TEMPLATE = DEFAULT_SYSTEM_PROMPT_TEMPLATE
29
-
30
40
  def __init__(
31
41
  self,
32
42
  llm: BaseLanguageModel,
@@ -37,9 +47,11 @@ class MCPAgent:
37
47
  auto_initialize: bool = False,
38
48
  memory_enabled: bool = True,
39
49
  system_prompt: str | None = None,
40
- system_prompt_template: str | None = None,
50
+ system_prompt_template: str | None = None, # User can still override the template
41
51
  additional_instructions: str | None = None,
42
52
  disallowed_tools: list[str] | None = None,
53
+ use_server_manager: bool = False,
54
+ verbose: bool = False,
43
55
  ):
44
56
  """Initialize a new MCPAgent instance.
45
57
 
@@ -55,10 +67,11 @@ class MCPAgent:
55
67
  system_prompt_template: Template for system prompt with {tool_descriptions} placeholder.
56
68
  additional_instructions: Extra instructions to append to the system prompt.
57
69
  disallowed_tools: List of tool names that should not be available to the agent.
70
+ use_server_manager: Whether to use server manager mode instead of exposing all tools.
58
71
  """
59
72
  self.llm = llm
60
73
  self.client = client
61
- self.connectors = connectors
74
+ self.connectors = connectors or []
62
75
  self.server_name = server_name
63
76
  self.max_steps = max_steps
64
77
  self.auto_initialize = auto_initialize
@@ -66,91 +79,148 @@ class MCPAgent:
66
79
  self._initialized = False
67
80
  self._conversation_history: list[BaseMessage] = []
68
81
  self.disallowed_tools = disallowed_tools or []
69
-
82
+ self.use_server_manager = use_server_manager
83
+ self.verbose = verbose
70
84
  # System prompt configuration
71
- self.system_prompt = system_prompt
72
- self.system_prompt_template = system_prompt_template or self.DEFAULT_SYSTEM_PROMPT_TEMPLATE
85
+ self.system_prompt = system_prompt # User-provided full prompt override
86
+ # User can provide a template override, otherwise use the imported default
87
+ self.system_prompt_template_override = system_prompt_template
73
88
  self.additional_instructions = additional_instructions
74
89
 
75
90
  # Either client or connector must be provided
76
- if not client and len(connectors) == 0:
91
+ if not client and len(self.connectors) == 0:
77
92
  raise ValueError("Either client or connector must be provided")
78
93
 
79
- self._agent: LangChainAgent | None = None
80
- self._sessions: dict[str, MCPSession] | None = None
94
+ # Create the adapter for tool conversion
95
+ self.adapter = LangChainAdapter(disallowed_tools=self.disallowed_tools)
96
+
97
+ # Initialize server manager if requested
98
+ self.server_manager = None
99
+ if self.use_server_manager:
100
+ if not self.client:
101
+ raise ValueError("Client must be provided when using server manager")
102
+ self.server_manager = ServerManager(self.client, self.adapter)
103
+
104
+ # State tracking
105
+ self._agent_executor: AgentExecutor | None = None
106
+ self._sessions: dict[str, MCPSession] = {}
81
107
  self._system_message: SystemMessage | None = None
108
+ self._tools: list[BaseTool] = []
82
109
 
83
110
  async def initialize(self) -> None:
84
111
  """Initialize the MCP client and agent."""
85
- # If using client, get or create a session
86
- if self.client:
87
- # First try to get existing sessions
88
- self._sessions = self.client.get_all_active_sessions()
89
-
90
- # If no active sessions exist, create new ones
91
- if not self._sessions:
92
- self._sessions = await self.client.create_all_sessions()
93
- connectors_to_use = [session.connector for session in self._sessions.values()]
112
+ logger.info("🚀 Initializing MCP agent and connecting to services...")
113
+ # If using server manager, initialize it
114
+ if self.use_server_manager and self.server_manager:
115
+ await self.server_manager.initialize()
116
+ # Get server management tools
117
+ management_tools = await self.server_manager.get_server_management_tools()
118
+ self._tools = management_tools
119
+ logger.info(
120
+ f"🔧 Server manager mode active with {len(management_tools)} management tools"
121
+ )
122
+
123
+ # Create the system message based on available tools
124
+ await self._create_system_message_from_tools(self._tools)
94
125
  else:
95
- # Using direct connector
96
- connectors_to_use = self.connectors
97
- await [c_to_use.connect() for c_to_use in connectors_to_use]
98
- await [c_to_use.initialize() for c_to_use in connectors_to_use]
99
- # Create the system message based on available tools
100
- await self._create_system_message(connectors_to_use)
126
+ # Standard initialization - if using client, get or create sessions
127
+ if self.client:
128
+ # First try to get existing sessions
129
+ self._sessions = self.client.get_all_active_sessions()
130
+ logger.info(f"🔌 Found {len(self._sessions)} existing sessions")
131
+
132
+ # If no active sessions exist, create new ones
133
+ if not self._sessions:
134
+ logger.info("🔄 No active sessions found, creating new ones...")
135
+ self._sessions = await self.client.create_all_sessions()
136
+ logger.info(f"✅ Created {len(self._sessions)} new sessions")
137
+
138
+ # Create LangChain tools directly from the client using the adapter
139
+ self._tools = await self.adapter.create_tools(self.client)
140
+ logger.info(f"🛠️ Created {len(self._tools)} LangChain tools from client")
141
+ else:
142
+ # Using direct connector - only establish connection
143
+ # LangChainAdapter will handle initialization
144
+ connectors_to_use = self.connectors
145
+ logger.info(f"🔗 Connecting to {len(connectors_to_use)} direct connectors...")
146
+ for connector in connectors_to_use:
147
+ if not hasattr(connector, "client") or connector.client is None:
148
+ await connector.connect()
149
+
150
+ # Create LangChain tools using the adapter with connectors
151
+ self._tools = await self.adapter._create_tools_from_connectors(connectors_to_use)
152
+ logger.info(f"🛠️ Created {len(self._tools)} LangChain tools from connectors")
153
+
154
+ # Get all tools for system message generation
155
+ all_tools = self._tools
156
+ logger.info(f"🧰 Found {len(all_tools)} tools across all connectors")
157
+
158
+ # Create the system message based on available tools
159
+ await self._create_system_message_from_tools(all_tools)
101
160
 
102
161
  # Create the agent
103
- self._agent = LangChainAgent(
104
- connectors=connectors_to_use,
105
- llm=self.llm,
106
- max_steps=self.max_steps,
107
- system_message=(self._system_message.content if self._system_message else None),
162
+ self._agent_executor = self._create_agent()
163
+ self._initialized = True
164
+ logger.info("✨ Agent initialization complete")
165
+
166
+ async def _create_system_message_from_tools(self, tools: list[BaseTool]) -> None:
167
+ """Create the system message based on provided tools using the builder."""
168
+ # Use the override if provided, otherwise use the imported default
169
+ default_template = self.system_prompt_template_override or DEFAULT_SYSTEM_PROMPT_TEMPLATE
170
+ # Server manager template is now also imported
171
+ server_template = SERVER_MANAGER_SYSTEM_PROMPT_TEMPLATE
172
+
173
+ # Delegate creation to the imported function
174
+ self._system_message = create_system_message(
175
+ tools=tools,
176
+ system_prompt_template=default_template,
177
+ server_manager_template=server_template, # Pass the imported template
178
+ use_server_manager=self.use_server_manager,
108
179
  disallowed_tools=self.disallowed_tools,
180
+ user_provided_prompt=self.system_prompt,
181
+ additional_instructions=self.additional_instructions,
109
182
  )
110
183
 
111
- # Initialize the agent
112
- await self._agent.initialize()
113
- self._initialized = True
184
+ # Update conversation history if memory is enabled
185
+ if self.memory_enabled:
186
+ history_without_system = [
187
+ msg for msg in self._conversation_history if not isinstance(msg, SystemMessage)
188
+ ]
189
+ self._conversation_history = [self._system_message] + history_without_system
114
190
 
115
- async def _create_system_message(self, connectors: list[BaseConnector]) -> None:
116
- """Create the system message based on available tools.
191
+ def _create_agent(self) -> AgentExecutor:
192
+ """Create the LangChain agent with the configured system message.
117
193
 
118
- Args:
119
- connector: The connector with available tools.
194
+ Returns:
195
+ An initialized AgentExecutor.
120
196
  """
121
- # If a complete system prompt was provided, use it directly
122
- if self.system_prompt:
123
- self._system_message = SystemMessage(content=self.system_prompt)
124
- return
125
-
126
- # Otherwise, build the system prompt from the template and tool descriptions
127
- tool_descriptions = []
128
- for connector in connectors:
129
- tools = connector.tools
130
- # Generate tool descriptions
131
- for tool in tools:
132
- # Skip disallowed tools
133
- if tool.name in self.disallowed_tools:
134
- continue
135
-
136
- # Escape curly braces in the description by doubling them
137
- # (sometimes e.g. blender mcp they are used in the description)
138
- description = (
139
- f"- {tool.name}: {tool.description.replace('{', '{{').replace('}', '}}')}"
140
- )
141
- tool_descriptions.append(description)
142
-
143
- # Format the system prompt template with tool descriptions
144
- system_prompt = self.system_prompt_template.format(
145
- tool_descriptions="\n".join(tool_descriptions)
197
+ logger.debug(f"Creating new agent with {len(self._tools)} tools")
198
+
199
+ system_content = "You are a helpful assistant"
200
+ if self._system_message:
201
+ system_content = self._system_message.content
202
+
203
+ prompt = ChatPromptTemplate.from_messages(
204
+ [
205
+ ("system", system_content),
206
+ MessagesPlaceholder(variable_name="chat_history"),
207
+ ("human", "{input}"),
208
+ MessagesPlaceholder(variable_name="agent_scratchpad"),
209
+ ]
146
210
  )
147
211
 
148
- # Add any additional instructions
149
- if self.additional_instructions:
150
- system_prompt += f"\n\n{self.additional_instructions}"
212
+ tool_names = [tool.name for tool in self._tools]
213
+ logger.info(f"🧠 Agent ready with tools: {', '.join(tool_names)}")
214
+
215
+ # Use the standard create_tool_calling_agent
216
+ agent = create_tool_calling_agent(llm=self.llm, tools=self._tools, prompt=prompt)
151
217
 
152
- # Create the system message
153
- self._system_message = SystemMessage(content=system_prompt)
218
+ # Use the standard AgentExecutor
219
+ executor = AgentExecutor(
220
+ agent=agent, tools=self._tools, max_iterations=self.max_steps, verbose=self.verbose
221
+ )
222
+ logger.debug(f"Created agent executor with max_iterations={self.max_steps}")
223
+ return executor
154
224
 
155
225
  def get_conversation_history(self) -> list[BaseMessage]:
156
226
  """Get the current conversation history.
@@ -165,7 +235,7 @@ class MCPAgent:
165
235
  self._conversation_history = []
166
236
 
167
237
  # Re-add the system message if it exists
168
- if self._system_message:
238
+ if self._system_message and self.memory_enabled:
169
239
  self._conversation_history = [self._system_message]
170
240
 
171
241
  def add_to_history(self, message: BaseMessage) -> None:
@@ -174,7 +244,8 @@ class MCPAgent:
174
244
  Args:
175
245
  message: The message to add.
176
246
  """
177
- self._conversation_history.append(message)
247
+ if self.memory_enabled:
248
+ self._conversation_history.append(message)
178
249
 
179
250
  def get_system_message(self) -> SystemMessage | None:
180
251
  """Get the current system message.
@@ -192,9 +263,21 @@ class MCPAgent:
192
263
  """
193
264
  self._system_message = SystemMessage(content=message)
194
265
 
195
- # Update the agent if initialized
196
- if self._agent:
197
- self._agent.set_system_message(message)
266
+ # Update conversation history if memory is enabled
267
+ if self.memory_enabled:
268
+ # Remove old system message if it exists
269
+ history_without_system = [
270
+ msg for msg in self._conversation_history if not isinstance(msg, SystemMessage)
271
+ ]
272
+ self._conversation_history = history_without_system
273
+
274
+ # Add new system message
275
+ self._conversation_history.insert(0, self._system_message)
276
+
277
+ # Recreate the agent with the new system message if initialized
278
+ if self._initialized and self._tools:
279
+ self._agent_executor = self._create_agent()
280
+ logger.debug("Agent recreated with new system message")
198
281
 
199
282
  def set_disallowed_tools(self, disallowed_tools: list[str]) -> None:
200
283
  """Set the list of tools that should not be available to the agent.
@@ -205,6 +288,7 @@ class MCPAgent:
205
288
  disallowed_tools: List of tool names that should not be available.
206
289
  """
207
290
  self.disallowed_tools = disallowed_tools
291
+ self.adapter.disallowed_tools = disallowed_tools
208
292
 
209
293
  # If the agent is already initialized, we need to reinitialize it
210
294
  # to apply the changes to the available tools
@@ -230,7 +314,7 @@ class MCPAgent:
230
314
  manage_connector: bool = True,
231
315
  external_history: list[BaseMessage] | None = None,
232
316
  ) -> str:
233
- """Run a query using the MCP tools.
317
+ """Run a query using the MCP tools with unified step-by-step execution.
234
318
 
235
319
  This method handles connecting to the MCP server, initializing the agent,
236
320
  running the query, and then cleaning up the connection.
@@ -253,19 +337,28 @@ class MCPAgent:
253
337
 
254
338
  try:
255
339
  # Initialize if needed
256
- if manage_connector and (not self._initialized or not self._agent):
257
- logger.debug("Initializing agent before running query")
340
+ if manage_connector and not self._initialized:
258
341
  await self.initialize()
259
342
  initialized_here = True
260
343
  elif not self._initialized and self.auto_initialize:
261
- logger.debug("Auto-initializing agent before running query")
262
344
  await self.initialize()
263
345
  initialized_here = True
264
346
 
265
347
  # Check if initialization succeeded
266
- if not self._agent:
348
+ if not self._agent_executor:
267
349
  raise RuntimeError("MCP agent failed to initialize")
268
350
 
351
+ steps = max_steps or self.max_steps
352
+ if self._agent_executor:
353
+ self._agent_executor.max_iterations = steps
354
+
355
+ display_query = (
356
+ query[:50].replace("\n", " ") + "..."
357
+ if len(query) > 50
358
+ else query.replace("\n", " ")
359
+ )
360
+ logger.info(f"💬 Received query: '{display_query}'")
361
+
269
362
  # Add the user query to conversation history if memory is enabled
270
363
  if self.memory_enabled:
271
364
  self.add_to_history(HumanMessage(content=query))
@@ -275,74 +368,164 @@ class MCPAgent:
275
368
  external_history if external_history is not None else self._conversation_history
276
369
  )
277
370
 
278
- # Convert messages to format expected by LangChain
371
+ # Convert messages to format expected by LangChain agent input
372
+ # Exclude the main system message as it's part of the agent's prompt
279
373
  langchain_history = []
280
374
  for msg in history_to_use:
281
375
  if isinstance(msg, HumanMessage):
282
- langchain_history.append({"type": "human", "content": msg.content})
376
+ langchain_history.append(msg)
283
377
  elif isinstance(msg, AIMessage):
284
- langchain_history.append({"type": "ai", "content": msg.content})
285
- elif isinstance(msg, SystemMessage) and msg != self._system_message:
286
- # Include system messages other than the main one
287
- # which is already included in the agent's prompt
288
- langchain_history.append({"type": "system", "content": msg.content})
289
- # Other message types can be handled here if needed
290
-
291
- # Run the query with the specified max_steps or default
292
- logger.debug(f"Running query with max_steps={max_steps or self.max_steps}")
293
- result = await self._agent.run(
294
- query=query,
295
- max_steps=max_steps,
296
- chat_history=langchain_history,
378
+ langchain_history.append(msg)
379
+
380
+ intermediate_steps: list[tuple[AgentAction, str]] = []
381
+ inputs = {"input": query, "chat_history": langchain_history}
382
+
383
+ # Construct a mapping of tool name to tool for easy lookup
384
+ name_to_tool_map = {tool.name: tool for tool in self._tools}
385
+ color_mapping = get_color_mapping(
386
+ [tool.name for tool in self._tools], excluded_colors=["green", "red"]
297
387
  )
298
388
 
299
- # Add the response to conversation history if memory is enabled
389
+ logger.info(f"🏁 Starting agent execution with max_steps={steps}")
390
+
391
+ for step_num in range(steps):
392
+ # --- Check for tool updates if using server manager ---
393
+ if self.use_server_manager and self.server_manager:
394
+ current_tools = await self.server_manager.get_all_tools()
395
+ current_tool_names = {tool.name for tool in current_tools}
396
+ existing_tool_names = {tool.name for tool in self._tools}
397
+
398
+ if current_tool_names != existing_tool_names:
399
+ logger.info(
400
+ f"🔄 Tools changed before step {step_num + 1}, updating agent. "
401
+ f"New tools: {', '.join(current_tool_names)}"
402
+ )
403
+ self._tools = current_tools
404
+ # Regenerate system message with ALL current tools
405
+ await self._create_system_message_from_tools(self._tools)
406
+ # Recreate the agent executor with the new tools and system message
407
+ self._agent_executor = self._create_agent()
408
+ self._agent_executor.max_iterations = steps
409
+ # Update maps for this iteration
410
+ name_to_tool_map = {tool.name: tool for tool in self._tools}
411
+ color_mapping = get_color_mapping(
412
+ [tool.name for tool in self._tools], excluded_colors=["green", "red"]
413
+ )
414
+
415
+ logger.info(f"🔍 Step {step_num + 1}/{steps}")
416
+
417
+ # --- Plan and execute the next step ---
418
+ try:
419
+ # Use the internal _atake_next_step which handles planning and execution
420
+ # This requires providing the necessary context like maps and intermediate steps
421
+ next_step_output = await self._agent_executor._atake_next_step(
422
+ name_to_tool_map=name_to_tool_map,
423
+ color_mapping=color_mapping,
424
+ inputs=inputs,
425
+ intermediate_steps=intermediate_steps,
426
+ run_manager=None,
427
+ )
428
+
429
+ # Process the output
430
+ if isinstance(next_step_output, AgentFinish):
431
+ logger.info(f"✅ Agent finished at step {step_num + 1}")
432
+ result = next_step_output.return_values.get("output", "No output generated")
433
+ break
434
+
435
+ # If it's actions/steps, add to intermediate steps
436
+ intermediate_steps.extend(next_step_output)
437
+
438
+ # Log tool calls
439
+ for action, output in next_step_output:
440
+ tool_name = action.tool
441
+ tool_input_str = str(action.tool_input)
442
+ # Truncate long inputs for readability
443
+ if len(tool_input_str) > 100:
444
+ tool_input_str = tool_input_str[:97] + "..."
445
+ logger.info(f"🔧 Tool call: {tool_name} with input: {tool_input_str}")
446
+ # Truncate long outputs for readability
447
+ output_str = str(output)
448
+ if len(output_str) > 100:
449
+ output_str = output_str[:97] + "..."
450
+ output_str = output_str.replace("\n", " ")
451
+ logger.info(f"📄 Tool result: {output_str}")
452
+
453
+ # Check for return_direct on the last action taken
454
+ if len(next_step_output) > 0:
455
+ last_step: tuple[AgentAction, str] = next_step_output[-1]
456
+ tool_return = self._agent_executor._get_tool_return(last_step)
457
+ if tool_return is not None:
458
+ logger.info(f"🏆 Tool returned directly at step {step_num + 1}")
459
+ result = tool_return.return_values.get("output", "No output generated")
460
+ break
461
+
462
+ except OutputParserException as e:
463
+ logger.error(f"❌ Output parsing error during step {step_num + 1}: {e}")
464
+ result = f"Agent stopped due to a parsing error: {str(e)}"
465
+ break
466
+ except Exception as e:
467
+ logger.error(f"❌ Error during agent execution step {step_num + 1}: {e}")
468
+ import traceback
469
+
470
+ traceback.print_exc()
471
+ result = f"Agent stopped due to an error: {str(e)}"
472
+ break
473
+
474
+ # --- Loop finished ---
475
+ if not result:
476
+ logger.warning(f"⚠️ Agent stopped after reaching max iterations ({steps})")
477
+ result = f"Agent stopped after reaching the maximum number of steps ({steps})."
478
+
479
+ # Add the final response to conversation history if memory is enabled
300
480
  if self.memory_enabled:
301
481
  self.add_to_history(AIMessage(content=result))
302
482
 
483
+ logger.info("🎉 Agent execution complete")
303
484
  return result
304
485
 
305
486
  except Exception as e:
306
- logger.error(f"Error running query: {e}")
307
- # If we initialized in this method and there was an error,
308
- # make sure to clean up
487
+ logger.error(f"Error running query: {e}")
309
488
  if initialized_here and manage_connector:
310
- logger.debug("Cleaning up resources after initialization error")
489
+ logger.info("🧹 Cleaning up resources after initialization error in run")
311
490
  await self.close()
312
491
  raise
313
492
 
314
493
  finally:
315
- # Clean up resources if we're managing the connector and
316
- # we're not using a client that manages sessions
494
+ # Clean up if necessary (e.g., if not using client-managed sessions)
317
495
  if manage_connector and not self.client and not initialized_here:
318
- logger.debug("Closing agent after query completion")
496
+ logger.info("🧹 Closing agent after query completion")
319
497
  await self.close()
320
498
 
321
499
  async def close(self) -> None:
322
500
  """Close the MCP connection with improved error handling."""
501
+ logger.info("🔌 Closing agent and cleaning up resources...")
323
502
  try:
324
- if self._agent:
325
- # Clean up the agent first
326
- logger.debug("Cleaning up agent")
327
- self._agent = None
503
+ # Clean up the agent first
504
+ self._agent_executor = None
505
+ self._tools = []
328
506
 
329
507
  # If using client with session, close the session through client
330
- if self.client and self._sessions:
331
- logger.debug("Closing session through client")
508
+ if self.client:
509
+ logger.info("🔄 Closing sessions through client")
332
510
  await self.client.close_all_sessions()
333
- self._session = None
511
+ self._sessions = {}
334
512
  # If using direct connector, disconnect
335
513
  elif self.connectors:
336
514
  for connector in self.connectors:
337
- logger.debug("Disconnecting connector")
515
+ logger.info("🔄 Disconnecting connector")
338
516
  await connector.disconnect()
339
517
 
518
+ # Clear adapter tool cache
519
+ if hasattr(self.adapter, "_connector_tool_map"):
520
+ self.adapter._connector_tool_map = {}
521
+
340
522
  self._initialized = False
341
- logger.debug("Agent closed successfully")
523
+ logger.info("👋 Agent closed successfully")
342
524
 
343
525
  except Exception as e:
344
- logger.error(f"Error during agent closure: {e}")
526
+ logger.error(f"Error during agent closure: {e}")
345
527
  # Still try to clean up references even if there was an error
346
- self._agent = None
347
- self._session = None
528
+ self._agent_executor = None
529
+ self._tools = []
530
+ self._sessions = {}
348
531
  self._initialized = False