set_breakpoint
Set PHP debugging breakpoints with conditions and hit counts to pause execution at specific lines for inspection.
Instructions
Set a breakpoint in PHP code. Supports line breakpoints and conditional breakpoints with hit counts. Can be set before a debug session starts - breakpoints will be applied when a session connects.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Full file path (use container path for Docker, e.g., /var/www/html/index.php) | |
| line | Yes | Line number for the breakpoint | |
| condition | No | Optional PHP condition expression (e.g., '$x > 10' or '$user !== null') | |
| hit_value | No | Hit count value - break after this many hits | |
| hit_condition | No | Hit condition: >= (break when hits >= value), == (break on exact hit), % (break every N hits) | |
| session_id | No | Session ID (uses active session if not specified) |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"condition": {
"description": "Optional PHP condition expression (e.g., '$x > 10' or '$user !== null')",
"type": "string"
},
"file": {
"description": "Full file path (use container path for Docker, e.g., /var/www/html/index.php)",
"type": "string"
},
"hit_condition": {
"description": "Hit condition: >= (break when hits >= value), == (break on exact hit), % (break every N hits)",
"enum": [
">=",
"==",
"%"
],
"type": "string"
},
"hit_value": {
"description": "Hit count value - break after this many hits",
"type": "integer"
},
"line": {
"description": "Line number for the breakpoint",
"exclusiveMinimum": 0,
"type": "integer"
},
"session_id": {
"description": "Session ID (uses active session if not specified)",
"type": "string"
}
},
"required": [
"file",
"line"
],
"type": "object"
}
Implementation Reference
- src/tools/breakpoints.ts:47-133 (handler)Main handler for 'set_breakpoint' tool: resolves session or uses pending breakpoints, sets line breakpoint with optional condition and hit counts, returns JSON with breakpoint info or error.async ({ file, line, condition, hit_value, hit_condition, session_id }) => { const session = sessionManager.resolveSession(session_id); // If no active session, store as pending breakpoint if (!session) { const pendingBp = pendingBreakpoints.addLineBreakpoint(file, line, { condition, hitValue: hit_value, hitCondition: hit_condition as HitCondition, }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, pending: true, message: 'Breakpoint stored as pending - will be applied when a debug session connects', breakpoint: { id: pendingBp.id, type: 'line', file, line, condition: condition || null, hitValue: hit_value || null, hitCondition: hit_condition || null, enabled: pendingBp.enabled, }, }, null, 2 ), }, ], }; } try { const breakpoint = await session.setLineBreakpoint(file, line, { condition, hitValue: hit_value, hitCondition: hit_condition as HitCondition, }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, breakpoint: { id: breakpoint.id, type: breakpoint.type, file, line, condition: condition || null, hitValue: hit_value || null, hitCondition: hit_condition || null, resolved: breakpoint.resolved, state: breakpoint.state, }, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Failed to set breakpoint', message: error instanceof Error ? error.message : String(error), file, line, }), }, ], }; } }
- src/tools/breakpoints.ts:20-46 (schema)Zod input schema defining parameters for set_breakpoint: file, line, optional condition, hit_value, hit_condition, session_id.{ file: z .string() .describe( 'Full file path (use container path for Docker, e.g., /var/www/html/index.php)' ), line: z.number().int().positive().describe('Line number for the breakpoint'), condition: z .string() .optional() .describe("Optional PHP condition expression (e.g., '$x > 10' or '$user !== null')"), hit_value: z .number() .int() .optional() .describe('Hit count value - break after this many hits'), hit_condition: z .enum(['>=', '==', '%']) .optional() .describe( 'Hit condition: >= (break when hits >= value), == (break on exact hit), % (break every N hits)' ), session_id: z .string() .optional() .describe('Session ID (uses active session if not specified)'), },
- src/tools/breakpoints.ts:17-134 (registration)Direct registration of the 'set_breakpoint' tool using server.tool() in registerBreakpointTools function.server.tool( 'set_breakpoint', 'Set a breakpoint in PHP code. Supports line breakpoints and conditional breakpoints with hit counts. Can be set before a debug session starts - breakpoints will be applied when a session connects.', { file: z .string() .describe( 'Full file path (use container path for Docker, e.g., /var/www/html/index.php)' ), line: z.number().int().positive().describe('Line number for the breakpoint'), condition: z .string() .optional() .describe("Optional PHP condition expression (e.g., '$x > 10' or '$user !== null')"), hit_value: z .number() .int() .optional() .describe('Hit count value - break after this many hits'), hit_condition: z .enum(['>=', '==', '%']) .optional() .describe( 'Hit condition: >= (break when hits >= value), == (break on exact hit), % (break every N hits)' ), session_id: z .string() .optional() .describe('Session ID (uses active session if not specified)'), }, async ({ file, line, condition, hit_value, hit_condition, session_id }) => { const session = sessionManager.resolveSession(session_id); // If no active session, store as pending breakpoint if (!session) { const pendingBp = pendingBreakpoints.addLineBreakpoint(file, line, { condition, hitValue: hit_value, hitCondition: hit_condition as HitCondition, }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, pending: true, message: 'Breakpoint stored as pending - will be applied when a debug session connects', breakpoint: { id: pendingBp.id, type: 'line', file, line, condition: condition || null, hitValue: hit_value || null, hitCondition: hit_condition || null, enabled: pendingBp.enabled, }, }, null, 2 ), }, ], }; } try { const breakpoint = await session.setLineBreakpoint(file, line, { condition, hitValue: hit_value, hitCondition: hit_condition as HitCondition, }); return { content: [ { type: 'text', text: JSON.stringify( { success: true, breakpoint: { id: breakpoint.id, type: breakpoint.type, file, line, condition: condition || null, hitValue: hit_value || null, hitCondition: hit_condition || null, resolved: breakpoint.resolved, state: breakpoint.state, }, }, null, 2 ), }, ], }; } catch (error) { return { content: [ { type: 'text', text: JSON.stringify({ error: 'Failed to set breakpoint', message: error instanceof Error ? error.message : String(error), file, line, }), }, ], }; } } );
- src/tools/index.ts:56-56 (registration)Top-level call to registerBreakpointTools in registerAllTools, which includes set_breakpoint registration.registerBreakpointTools(server, ctx.sessionManager, ctx.pendingBreakpoints);
- PendingBreakpointsManager.addLineBreakpoint: creates and stores pending line breakpoint when no debug session is active.addLineBreakpoint( file: string, line: number, options?: { condition?: string; hitValue?: number; hitCondition?: HitCondition; } ): PendingBreakpoint { const id = `pending_${++this.breakpointIdCounter}`; const bp: PendingBreakpoint = { id, type: 'line', file, line, condition: options?.condition, hitValue: options?.hitValue, hitCondition: options?.hitCondition, enabled: true, createdAt: new Date(), }; this.pendingBreakpoints.set(id, bp); logger.info(`Pending breakpoint added: ${id} at ${file}:${line}`); this.emit('breakpointAdded', bp); return bp; }