get_variable
Retrieve PHP variable values by name, including nested properties using PHP syntax, for debugging applications with Xdebug.
Instructions
Get a specific variable by name, including nested properties. Use PHP syntax for nested access (e.g., '$user->name', '$array[0]', '$obj->items[2]->value')
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Variable name with $ prefix (e.g., '$user', '$data["key"]', '$obj->property') | |
| context_id | No | Context ID | |
| stack_depth | No | Stack frame depth | |
| max_depth | No | Maximum depth for nested properties | |
| session_id | No | Session ID |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"context_id": {
"default": 0,
"description": "Context ID",
"type": "integer"
},
"max_depth": {
"default": 2,
"description": "Maximum depth for nested properties",
"type": "integer"
},
"name": {
"description": "Variable name with $ prefix (e.g., '$user', '$data[\"key\"]', '$obj->property')",
"type": "string"
},
"session_id": {
"description": "Session ID",
"type": "string"
},
"stack_depth": {
"default": 0,
"description": "Stack frame depth",
"type": "integer"
}
},
"required": [
"name"
],
"type": "object"
}
Implementation Reference
- src/tools/inspection.ts:229-311 (registration)Direct registration of the 'get_variable' tool using McpServer.tool(), defining name, description, input schema, and inline handler function.server.tool( 'get_variable', "Get a specific variable by name, including nested properties. Use PHP syntax for nested access (e.g., '$user->name', '$array[0]', '$obj->items[2]->value')", { name: z .string() .describe( "Variable name with $ prefix (e.g., '$user', '$data[\"key\"]', '$obj->property')" ), context_id: z.number().int().default(0).describe('Context ID'), stack_depth: z.number().int().default(0).describe('Stack frame depth'), max_depth: z .number() .int() .default(2) .describe('Maximum depth for nested properties'), session_id: z.string().optional().describe('Session ID'), }, async ({ name, context_id, stack_depth, max_depth, session_id }) => { const session = sessionManager.resolveSession(session_id); if (!session) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'No active debug session' }), }, ], }; } try { const variable = await session.getVariable(name, { contextId: context_id, stackDepth: stack_depth, maxDepth: max_depth, }); if (!variable) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Variable not found', name, message: `Variable "${name}" does not exist in the current scope`, }), }, ], }; } return { content: [ { type: 'text', text: JSON.stringify( { variable: formatProperty(variable), }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Failed to get variable', message: error instanceof Error ? error.message : String(error), }), }, ], }; } } );
- src/tools/inspection.ts:247-310 (handler)The inline async handler function that executes the get_variable tool logic: resolves the debug session, fetches the variable using session.getVariable, formats it, handles errors, and returns structured content.async ({ name, context_id, stack_depth, max_depth, session_id }) => { const session = sessionManager.resolveSession(session_id); if (!session) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'No active debug session' }), }, ], }; } try { const variable = await session.getVariable(name, { contextId: context_id, stackDepth: stack_depth, maxDepth: max_depth, }); if (!variable) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Variable not found', name, message: `Variable "${name}" does not exist in the current scope`, }), }, ], }; } return { content: [ { type: 'text', text: JSON.stringify( { variable: formatProperty(variable), }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Failed to get variable', message: error instanceof Error ? error.message : String(error), }), }, ], }; } }
- src/tools/inspection.ts:232-246 (schema)Zod schema defining input parameters for the get_variable tool: name (required), context_id, stack_depth, max_depth, session_id.{ name: z .string() .describe( "Variable name with $ prefix (e.g., '$user', '$data[\"key\"]', '$obj->property')" ), context_id: z.number().int().default(0).describe('Context ID'), stack_depth: z.number().int().default(0).describe('Stack frame depth'), max_depth: z .number() .int() .default(2) .describe('Maximum depth for nested properties'), session_id: z.string().optional().describe('Session ID'), },
- src/tools/inspection.ts:12-31 (helper)Helper function to format DBGP Property objects into a JSON-friendly structure, used to serialize the retrieved variable.function formatProperty(prop: Property, depth: number = 0): Record<string, unknown> { const result: Record<string, unknown> = { name: prop.name, type: prop.type, }; if (prop.classname) result.classname = prop.classname; if (prop.value !== undefined) result.value = prop.value; if (prop.numchildren !== undefined && prop.numchildren > 0) { result.numchildren = prop.numchildren; } if (prop.constant) result.constant = true; // Include nested properties if present and not too deep if (prop.properties && prop.properties.length > 0 && depth < 3) { result.children = prop.properties.map((p) => formatProperty(p, depth + 1)); } return result; }
- src/session/session.ts:374-407 (helper)DebugSession.getVariable method called by the tool handler; sends DBGP 'property_get' command to retrieve specific variable by name from the debugger.async getVariable( name: string, options?: { contextId?: number; stackDepth?: number; maxDepth?: number; page?: number; } ): Promise<Property | null> { const args: Record<string, string> = { n: name, }; if (options?.contextId !== undefined) { args['c'] = options.contextId.toString(); } if (options?.stackDepth !== undefined) { args['d'] = options.stackDepth.toString(); } if (options?.maxDepth !== undefined) { args['m'] = options.maxDepth.toString(); } if (options?.page !== undefined) { args['p'] = options.page.toString(); } const response = await this.connection.sendCommand('property_get', args); if (response.error) { return null; } return this.connection.parseProperty(response); }