Skip to main content
Glama

Watchtower DAP Windows Debugging

by rlaksana
breakpoints.ts6.01 kB
import { z } from 'zod'; import { Logger } from '../server/logger'; import { MetricsCollector } from '../server/metrics'; import { DapSetBreakpointsRequest, DapSetBreakpointsResponse } from '../schemas/dap-tools.schemas'; /** * dap.setBreakpoints tool implementation * * Manages breakpoints across debugging sessions */ export class DapSetBreakpointsTool { private logger: Logger; private metrics: MetricsCollector; private sessionBreakpoints: Map<string, Map<string, number[]>> = new Map(); constructor() { this.logger = new Logger('dap.setBreakpoints'); this.metrics = MetricsCollector.getInstance(); } /** * Execute the dap.setBreakpoints tool */ async execute(args: any): Promise<DapSetBreakpointsResponse> { this.metrics.startTimer('dap.setBreakpoints.tool'); this.metrics.increment('dap.setBreakpoints.count'); try { // Validate input const validatedArgs = this.validateArgs(args); this.logger.debug('Setting breakpoints', { source: validatedArgs.source, breakpoints: validatedArgs.breakpoints, }); // Store breakpoints for session await this.storeBreakpoints(validatedArgs); // Create response with verification status const verifiedBreakpoints = this.createVerifiedBreakpoints(validatedArgs.breakpoints); this.logger.info('Breakpoints set successfully', { source: validatedArgs.source?.path || 'unknown', count: verifiedBreakpoints.length, }); return this.createSuccessResponse({ breakpoints: verifiedBreakpoints, verified: true, }); } catch (error) { this.logger.error('dap.setBreakpoints failed:', error); this.metrics.increment('dap.setBreakpoints.error.count'); return this.createErrorResponse((error as Error).message); } finally { this.metrics.stopTimer('dap.setBreakpoints.tool'); } } /** * Validate input arguments */ private validateArgs(args: any): DapSetBreakpointsRequest['arguments'] { const schema = z.object({ source: z .object({ path: z.string().optional(), name: z.string().optional(), sourceReference: z.number().optional(), adapterData: z.any().optional(), }) .optional(), breakpoints: z .array( z.object({ id: z.number().optional(), line: z.number(), column: z.number().default(0), endLine: z.number().optional(), endColumn: z.number().optional(), condition: z.string().optional(), hitCondition: z.string().optional(), logMessage: z.string().optional(), verified: z.boolean().optional(), message: z.string().optional(), src: z.string().optional(), encodedMd5: z.string().optional(), adapterData: z.any().optional(), }) ) .optional(), lines: z.array(z.number()).optional(), sourceModified: z.boolean().optional(), // Deprecated fields for backward compatibility breakpoint: z .object({ id: z.number().optional(), line: z.number(), column: z.number().default(0), condition: z.string().optional(), hitCondition: z.string().optional(), logMessage: z.string().optional(), verified: z.boolean().optional(), message: z.string().optional(), }) .optional(), }); const parsed = schema.parse(args); return { ...parsed, __type__: 'SetBreakpointsArguments' as const, }; } /** * Store breakpoints for session */ private async storeBreakpoints(args: DapSetBreakpointsRequest['arguments']): Promise<void> { // Extract session ID from source path or use default const sessionId = args.source?.path || 'default-session'; if (!this.sessionBreakpoints.has(sessionId)) { this.sessionBreakpoints.set(sessionId, new Map()); } const sessionBreakpointMap = this.sessionBreakpoints.get(sessionId)!; // Store breakpoints by source path const sourcePath = args.source?.path || 'unknown'; const lines = args.breakpoints?.map(bp => bp.line) || []; sessionBreakpointMap.set(sourcePath, lines); this.logger.debug('Breakpoints stored', { sessionId, sourcePath, lines, }); } /** * Create verified breakpoints response */ private createVerifiedBreakpoints(inputBreakpoints: any[] = []) { return inputBreakpoints.map((breakpoint, index) => ({ ...breakpoint, id: breakpoint.id || index + 1, verified: true, message: `Breakpoint set at line ${breakpoint.line}`, src: breakpoint.src || `file://${breakpoint.line}`, encodedMd5: '', // Placeholder for MD5 })); } /** * Get breakpoints for a session */ getSessionBreakpoints(sessionId: string): Map<string, number[]> { return this.sessionBreakpoints.get(sessionId) || new Map(); } /** * Clear breakpoints for a session */ clearSessionBreakpoints(sessionId: string): void { this.sessionBreakpoints.delete(sessionId); } /** * Create success response */ private createSuccessResponse(body: any): DapSetBreakpointsResponse { return { type: 'response', seq: 1, command: 'setBreakpoints', request_seq: 1, success: true, body, }; } /** * Create error response */ private createErrorResponse(message: string): DapSetBreakpointsResponse { return { type: 'response', seq: 1, command: 'setBreakpoints', request_seq: 1, success: false, message, body: {}, }; } } // Singleton instance export const dapSetBreakpointsTool = new DapSetBreakpointsTool(); // Tool execution function export async function executeDapSetBreakpoints(args: any): Promise<DapSetBreakpointsResponse> { return await dapSetBreakpointsTool.execute(args); }

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/rlaksana/mcp-watchtower'

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