get_variables
Retrieve variable values and details from a specific debugging scope using the variablesReference identifier to inspect program state during debugging sessions.
Instructions
Get variables (scope is variablesReference: number)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sessionId | Yes | ||
| scope | Yes | The variablesReference number from a StackFrame or Variable |
Implementation Reference
- src/server.ts:793-829 (handler)MCP tool handler for 'get_variables': validates input, fetches variables via session manager, logs, and returns JSON response.case 'get_variables': { if (!args.sessionId || args.scope === undefined) { throw new McpError(McpErrorCode.InvalidParams, 'Missing required parameters'); } try { const variables = await this.getVariables(args.sessionId, args.scope); // Log variable inspection (truncate large values) const truncatedVars = variables.map(v => ({ name: v.name, type: v.type, value: v.value.length > 200 ? v.value.substring(0, 200) + '... (truncated)' : v.value })); this.logger.info('debug:variables', { sessionId: args.sessionId, sessionName: this.getSessionName(args.sessionId), variablesReference: args.scope, variableCount: variables.length, variables: truncatedVars.slice(0, 10), // Log first 10 variables timestamp: Date.now() }); result = { content: [{ type: 'text', text: JSON.stringify({ success: true, variables, count: variables.length, variablesReference: args.scope }) }] }; } 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 { // Re-throw unexpected errors throw error; } } break;
- src/server.ts:478-478 (schema)Tool schema definition for 'get_variables' including input schema, description, and parameters (sessionId, scope). Included in list_tools response.{ 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'] } },
- src/server.ts:443-486 (registration)Registration of all MCP tools including 'get_variables' schema in the ListToolsRequest handler.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'] } }, ], }; });
- src/server.ts:285-288 (helper)Server wrapper method for getVariables that validates session existence before delegating to SessionManager.public async getVariables(sessionId: string, variablesReference: number): Promise<Variable[]> { this.validateSession(sessionId); return this.sessionManager.getVariables(sessionId, variablesReference); }
- Core implementation of getVariables: sends DAP 'variables' request to the debug proxy, parses response, handles errors and empty responses.async getVariables(sessionId: string, variablesReference: number): Promise<Variable[]> { const session = this._getSessionById(sessionId); this.logger.info(`[SM getVariables ${sessionId}] Entered. variablesReference: ${variablesReference}, Current state: ${session.state}`); if (!session.proxyManager || !session.proxyManager.isRunning()) { this.logger.warn(`[SM getVariables ${sessionId}] No active proxy.`); return []; } if (session.state !== SessionState.PAUSED) { this.logger.warn(`[SM getVariables ${sessionId}] Session not paused. State: ${session.state}.`); return []; } try { this.logger.info(`[SM getVariables ${sessionId}] Sending DAP 'variables' for variablesReference ${variablesReference}.`); const response = await session.proxyManager.sendDapRequest<DebugProtocol.VariablesResponse>('variables', { variablesReference }); this.logger.info(`[SM getVariables ${sessionId}] DAP 'variables' response received. Body:`, response?.body); if (response && response.body && response.body.variables) { const vars = response.body.variables.map((v: DebugProtocol.Variable) => ({ name: v.name, value: v.value, type: v.type || "<unknown_type>", variablesReference: v.variablesReference, expandable: v.variablesReference > 0 })); this.logger.info(`[SM getVariables ${sessionId}] Parsed variables:`, vars.map(v => ({name: v.name, value: v.value, type: v.type}))); return vars; } this.logger.warn(`[SM getVariables ${sessionId}] No variables in response body for reference ${variablesReference}. Response:`, response); return []; } catch (error) { this.logger.error(`[SM getVariables ${sessionId}] Error getting variables:`, error); return []; } }