Skip to main content
Glama

step_into

Execute a single step into a function call during debugging to examine internal execution flow and identify issues in Python, JavaScript, or Rust code.

Instructions

Step into

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
sessionIdYes

Implementation Reference

  • src/server.ts:431-486 (registration)
    Registration of the 'step_into' tool in the MCP server's listTools response, including schema definition (inputSchema requires sessionId).
    private registerTools(): void {
      this.server.setRequestHandler(ListToolsRequestSchema, async () => {
        this.logger.debug('Handling ListToolsRequest');
        
        // Get supported languages dynamically - deferred until request time
        const supportedLanguages = await this.getSupportedLanguagesAsync();
        
        // Generate dynamic descriptions for path parameters
        const fileDescription = this.getPathDescription('source file');
        const scriptPathDescription = this.getPathDescription('script');
        
        return {
          tools: [
            { name: 'create_debug_session', description: 'Create a new debugging session', inputSchema: { type: 'object', properties: { language: { type: 'string', enum: supportedLanguages, description: 'Programming language for debugging' }, name: { type: 'string', description: 'Optional session name' }, executablePath: {type: 'string', description: 'Path to language executable (optional, will auto-detect if not provided)'} }, required: ['language'] } },
            { name: 'list_supported_languages', description: 'List all supported debugging languages with metadata', inputSchema: { type: 'object', properties: {} } },
            { name: 'list_debug_sessions', description: 'List all active debugging sessions', inputSchema: { type: 'object', properties: {} } },
            { name: 'set_breakpoint', description: 'Set a breakpoint. Setting breakpoints on non-executable lines (structural, declarative) may lead to unexpected behavior', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, file: { type: 'string', description: fileDescription }, line: { type: 'number', description: 'Line number where to set breakpoint. Executable statements (assignments, function calls, conditionals, returns) work best. Structural lines (function/class definitions), declarative lines (imports), or non-executable lines (comments, blank lines) may cause unexpected stepping behavior' }, condition: { type: 'string' } }, required: ['sessionId', 'file', 'line'] } },
            { name: 'start_debugging', description: 'Start debugging a script', inputSchema: { 
                type: 'object', 
                properties: { 
                  sessionId: { type: 'string' }, 
                  scriptPath: { type: 'string', description: scriptPathDescription }, 
                  args: { type: 'array', items: { type: 'string' } }, 
                  dapLaunchArgs: { 
                    type: 'object', 
                    properties: { 
                      stopOnEntry: { type: 'boolean' },
                      justMyCode: { type: 'boolean' } 
                    },
                    additionalProperties: true
                  },
                  dryRunSpawn: { type: 'boolean' },
                  adapterLaunchConfig: {
                    type: 'object',
                    description: 'Optional adapter-specific launch configuration overrides',
                    additionalProperties: true
                  }
                }, 
                required: ['sessionId', 'scriptPath'] 
              } 
            },
            { name: 'close_debug_session', description: 'Close a debugging session', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'step_over', description: 'Step over', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'step_into', description: 'Step into', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'step_out', description: 'Step out', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'continue_execution', description: 'Continue execution', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'pause_execution', description: 'Pause execution (Not Implemented)', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
            { name: 'get_variables', description: 'Get variables (scope is variablesReference: number)', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, scope: { type: 'number', description: "The variablesReference number from a StackFrame or Variable" } }, required: ['sessionId', 'scope'] } },
            { name: 'get_local_variables', description: 'Get local variables for the current stack frame. This is a convenience tool that returns just the local variables without needing to traverse stack->scopes->variables manually', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, includeSpecial: { type: 'boolean', description: 'Include special/internal variables like this, __proto__, __builtins__, etc. Default: false' } }, required: ['sessionId'] } },
            { name: 'get_stack_trace', description: 'Get stack trace', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, includeInternals: { type: 'boolean', description: 'Include internal/framework frames (e.g., Node.js internals). Default: false for cleaner output.' } }, required: ['sessionId'] } },
            { name: 'get_scopes', description: 'Get scopes for a stack frame', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, frameId: { type: 'number', description: "The ID of the stack frame from a stackTrace response" } }, required: ['sessionId', 'frameId'] } },
            { name: 'evaluate_expression', description: 'Evaluate expression in the current debug context. Expressions can read and modify program state', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, expression: { type: 'string' }, frameId: { type: 'number', description: 'Optional stack frame ID for evaluation context. Must be a frame ID from a get_stack_trace response. If not provided, uses the current (top) frame automatically' } }, required: ['sessionId', 'expression'] } },
            { name: 'get_source_context', description: 'Get source context around a specific line in a file', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' }, file: { type: 'string', description: fileDescription }, line: { type: 'number', description: 'Line number to get context for' }, linesContext: { type: 'number', description: 'Number of lines before and after to include (default: 5)' } }, required: ['sessionId', 'file', 'line'] } },
          ],
        };
      });
  • Schema for 'step_into' tool: requires sessionId string.
    { name: 'step_into', description: 'Step into', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
    { name: 'step_out', description: 'Step out', inputSchema: { type: 'object', properties: { sessionId: { type: 'string' } }, required: ['sessionId'] } },
  • MCP tool handler dispatch for 'step_into': validates sessionId, calls DebugMcpServer.stepInto() which delegates to SessionManager.stepInto().
    case 'step_over':
    case 'step_into':
    case 'step_out': {
      if (!args.sessionId) {
        throw new McpError(McpErrorCode.InvalidParams, 'Missing required sessionId');
      }
    
      try {
        let stepResult: { success: boolean; state: string; error?: string; data?: unknown; };
        if (toolName === 'step_over') {
          stepResult = await this.stepOver(args.sessionId);
        } else if (toolName === 'step_into') {
          stepResult = await this.stepInto(args.sessionId);
        } else {
          stepResult = await this.stepOut(args.sessionId);
        }
    
        // Build response with location and line context if available
        const stepType = toolName.replace('step_', '').replace('_', ' ');
        const response: Record<string, unknown> = {
          success: stepResult.success,
          message: `Stepped ${stepType}`,
          state: stepResult.state
        };
    
        // Extract location from result data
        const resultData = stepResult.data as { message?: string; location?: { file: string; line: number; column?: number } } | undefined;
        const location = resultData?.location;
    
        if (location) {
          response.location = location;
    
          // Try to get line context
          try {
            const lineContext = await this.lineReader.getLineContext(
              location.file,
              location.line,
              { contextLines: 2 }
            );
    
            if (lineContext) {
              response.context = {
                lineContent: lineContext.lineContent,
                surrounding: lineContext.surrounding
              };
            }
          } catch (contextError) {
            // Log but don't fail if we can't get context
            this.logger.debug('Could not get line context for step result', {
              file: location.file,
              line: location.line,
              error: contextError
            });
          }
        }
    
        result = { content: [{ type: 'text', text: JSON.stringify(response) }] };
      } catch (error) {
        // Handle validation errors specifically
        if (error instanceof SessionTerminatedError ||
            error instanceof SessionNotFoundError ||
            error instanceof ProxyNotRunningError) {
          result = { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error.message }) }] };
        } else if (error instanceof Error) {
          // Handle other expected errors (like "Failed to step over")
          result = { content: [{ type: 'text', text: JSON.stringify({ success: false, error: error.message }) }] };
        } else {
          // Re-throw unexpected errors
          throw error;
        }
      }
      break;
    }
  • DebugMcpServer.stepInto(): wrapper that validates session and calls SessionManager.stepInto.
    public async stepInto(sessionId: string): Promise<{ success: boolean; state: string; error?: string; data?: unknown; }> {
      this.validateSession(sessionId);
      const result = await this.sessionManager.stepInto(sessionId);
      if (!result.success) {
        throw new Error(result.error || 'Failed to step into');
      }
      return result;
  • SessionManagerOperations.stepInto(): core logic - sends DAP 'stepIn' request via proxyManager, waits for 'stopped' event.
    async stepInto(sessionId: string): Promise<DebugResult> {
      const session = this._getSessionById(sessionId);
    
      // Check if session is terminated
      if (session.sessionLifecycle === SessionLifecycleState.TERMINATED) {
        throw new SessionTerminatedError(sessionId);
      }
    
      const threadId = session.proxyManager?.getCurrentThreadId();
      this.logger.info(
        `[SM stepInto ${sessionId}] Entered. Current state: ${session.state}, ThreadID: ${threadId}`
      );
    
      if (!session.proxyManager || !session.proxyManager.isRunning()) {
        throw new ProxyNotRunningError(sessionId, 'step into');
      }
      if (session.state !== SessionState.PAUSED) {
        this.logger.warn(`[SM stepInto ${sessionId}] Not paused. State: ${session.state}`);
        return { success: false, error: 'Not paused', state: session.state };
      }
      if (typeof threadId !== 'number') {
        this.logger.warn(`[SM stepInto ${sessionId}] No current thread ID.`);
        return { success: false, error: 'No current thread ID', state: session.state };
      }
    
      this.logger.info(`[SM stepInto ${sessionId}] Sending DAP 'stepIn' for threadId ${threadId}`);
    
      try {
        return await this._executeStepOperation(session, sessionId, {
          command: 'stepIn',
          threadId,
          logTag: 'stepInto',
          successMessage: 'Step into completed.',
        });
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : String(error);
        this.logger.error(`[SM stepInto ${sessionId}] Error during step:`, error);
        this._updateSessionState(session, SessionState.ERROR);
        return { success: false, error: errorMessage, state: session.state };
      }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/debugmcpdev/mcp-debugger'

If you have feedback or need assistance with the MCP directory API, please join our Discord server