MCPcopy Create free account
hub / github.com/IBM/mcp-cli / start_tool_execution

Method start_tool_execution

src/mcp_cli/display/manager.py:198–256  ·  view source on GitHub ↗

Start displaying tool execution. Args: name: Tool name arguments: Tool arguments

(self, name: str, arguments: dict)

Source from the content-addressed store, hash-verified

196 # ==================== TOOL EXECUTION OPERATIONS ====================
197
198 async def start_tool_execution(self, name: str, arguments: dict) -> None:
199 """Start displaying tool execution.
200
201 Args:
202 name: Tool name
203 arguments: Tool arguments
204 """
205
206 from mcp_cli.chat.models import ToolExecutionState
207
208 # Acquire render lock to prevent race conditions during transition
209 # This ensures the refresh loop doesn't render between clearing and setting tool state
210 async with self._render_lock:
211 # If transitioning from streaming to tool execution, clear streaming display
212 if self.streaming_state and self.streaming_state.is_active:
213 self._do_clear_display()
214
215 # Clear any stale streaming state (even if not active)
216 # This ensures we don't have leftover state from previous operations
217 if self.streaming_state:
218 self.streaming_state = None
219
220 # Reset ALL display state to ensure clean start
221 # This is critical after Rich output which may leave cursor in unexpected state
222 self._last_status = ""
223 self._last_line_count = 0
224 self._showing_thinking = False
225 self._last_reasoning_preview = ""
226
227 # Set tool execution state while still holding the lock
228 self.tool_execution = ToolExecutionState(
229 name=name, arguments=arguments, start_time=time.time()
230 )
231
232 # Create live status display for tool execution
233 # This handles terminal control properly even when other output occurs
234 from chuk_term.ui import LiveStatus
235
236 self._tool_status = LiveStatus(refresh_per_second=10, transient=True)
237 self._tool_status.start()
238
239 # Stop any existing refresh loop before starting a new one
240 # This ensures we don't have competing loops trying to render
241 if self._refresh_task and not self._refresh_task.done():
242 self._refresh_active = False
243 try:
244 await asyncio.wait_for(self._refresh_task, timeout=0.5)
245 except asyncio.TimeoutError:
246 self._refresh_task.cancel()
247 try:
248 await self._refresh_task
249 except asyncio.CancelledError:
250 pass
251 self._refresh_task = None
252
253 self._refresh_active = True
254 await self._start_refresh_loop()
255

Callers 2

Calls 4

_do_clear_displayMethod · 0.95
_start_refresh_loopMethod · 0.95
ToolExecutionStateClass · 0.90
startMethod · 0.80

Tested by 2