sessions_step_out
Step out of the current function during debugging to return to the calling code, requiring an active breakpoint and session ID.
Instructions
Step out of the current function (requires active breakpoint)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | The debug session ID |
Implementation Reference
- src/mcp_debug_tool/server.py:190-203 (registration)Registers the 'sessions_step_out' tool with the MCP SDK, defining its name, description, and input schema requiring 'sessionId'.Tool( name="sessions_step_out", description="Step out of the current function (requires active breakpoint)", inputSchema={ "type": "object", "properties": { "sessionId": { "type": "string", "description": "The debug session ID", }, }, "required": ["sessionId"], }, ),
- src/mcp_debug_tool/server.py:667-721 (handler)MCP tool handler: validates sessionId, calls SessionManager.step_out_async, serializes and returns response as TextContent or error.async def _handle_sessions_step_out(self, arguments: dict) -> list[TextContent]: """ Handler for sessions_step_out tool. Steps out of the current function. """ try: session_id = arguments.get("sessionId") if not session_id: return [ TextContent( type="text", text=json.dumps({ "error": { "type": "ValueError", "message": "sessionId is required", } }), ) ] response = await self.session_manager.step_out_async(session_id) result = response.model_dump() return [ TextContent( type="text", text=json.dumps(result), ) ] except KeyError as e: return [ TextContent( type="text", text=json.dumps({ "error": { "type": "SessionNotFound", "message": str(e), } }), ) ] except Exception as e: logger.exception("Error in step_out") return [ TextContent( type="text", text=json.dumps({ "error": { "type": type(e).__name__, "message": str(e), } }), ) ]
- Core step-out logic in SessionManager: validates DAP session and PAUSED state, calls DAP wrapper's step_out, updates session state and timings.def step_out(self, session_id: str) -> BreakpointResponse: """ Step out of the current function (DAP only). Args: session_id: Session ID Returns: BreakpointResponse with new location and variables Raises: KeyError: If session not found ValueError: If session is not using DAP """ session = self.get_session(session_id) if not session.use_dap: return BreakpointResponse( hit=False, completed=False, error=ExecutionError( type="NotImplementedError", message="Step operations require DAP integration (set useDap=true when creating session)", ), ) if not session.dap_wrapper: return BreakpointResponse( hit=False, completed=False, error=ExecutionError( type="SessionError", message="DAP session not initialized", ), ) if session.status != SessionStatus.PAUSED: return BreakpointResponse( hit=False, completed=False, error=ExecutionError( type="InvalidStateError", message=f"Cannot step from state: {session.status}. Must be PAUSED.", ), ) session.update_status(SessionStatus.RUNNING) with Timer() as timer: try: response = session.dap_wrapper.step_out(timeout=DEFAULT_TIMEOUT_SECONDS) # Update session state if response.hit: session.update_status(SessionStatus.PAUSED) if response.frameInfo: session.update_breakpoint(response.frameInfo.file, response.frameInfo.line) elif response.completed: session.update_status(SessionStatus.COMPLETED) elif response.error: session.update_status(SessionStatus.ERROR) session.update_timings(timer.elapsed_ms) return response except Exception as e: session.update_status(SessionStatus.ERROR) return BreakpointResponse( hit=False, completed=False, error=ExecutionError( type=type(e).__name__, message=str(e), ), )
- Async wrapper that runs the synchronous step_out method in a thread pool for non-blocking MCP handler calls.async def step_out_async(self, session_id: str) -> BreakpointResponse: """ Async wrapper for step_out. Runs the synchronous step_out in a thread pool to avoid blocking. """ return await asyncio.to_thread(self.step_out, session_id)