Skip to main content
Glama

Watchtower DAP Windows Debugging

by rlaksana
start.ts6.18 kB
import { z } from 'zod'; import { Logger } from '../server/logger'; import { MetricsCollector } from '../server/metrics'; import { SessionManager } from '../server/session-manager'; import { createNodeJSAdapter } from '../adapters/nodejs-adapter'; import { DapStartRequest, DapStartResponse } from '../schemas/dap-tools.schemas'; /** * dap.start tool implementation * * Handles both launch and attach configurations for Node.js debugging */ export class DapStartTool { private logger: Logger; // private config: ConfigManager; // Unused for now private metrics: MetricsCollector; private sessionManager: SessionManager; constructor() { this.logger = new Logger('dap.start'); // this.config = ConfigManager.getInstance(); // Unused for now this.metrics = MetricsCollector.getInstance(); this.sessionManager = new SessionManager(); } /** * Execute the dap.start tool */ async execute(args: any): Promise<DapStartResponse> { this.metrics.startTimer('dap.start.tool'); this.metrics.increment('dap.start.count'); try { // Validate input const validatedArgs = this.validateArgs(args); this.logger.info('Starting debugging session', { program: validatedArgs.program, processId: validatedArgs.processId, }); // Handle launch configuration (assume launch for now) return await this.handleLaunch(validatedArgs); } catch (error) { this.logger.error('dap.start failed:', error); this.metrics.increment('dap.start.error.count'); return this.createErrorResponse((error as Error).message); } finally { this.metrics.stopTimer('dap.start.tool'); } } /** * Validate input arguments */ private validateArgs(args: any): DapStartRequest['arguments'] { const schema = z.object({ type: z.enum(['launch', 'attach']), program: z.string().optional(), processId: z.number().optional(), cwd: z.string().optional(), args: z.array(z.string()).optional(), noDebug: z.boolean().default(false), sourceMaps: z.boolean().default(true), skipFiles: z.array(z.string()).optional(), console: z.enum(['internalConsole', 'integratedTerminal', 'externalTerminal']).optional(), }); const parsed = schema.parse(args); return { ...parsed, __type__: 'LaunchRequestArguments' as const, }; } /** * Handle launch configuration */ private async handleLaunch(config: DapStartRequest['arguments']): Promise<DapStartResponse> { // Validate launch configuration if (!config.program) { throw new Error('program is required for launch debugging'); } this.logger.debug('Starting Node.js launch debugging', { program: config.program }); // Create Node.js adapter const adapter = createNodeJSAdapter(); await adapter.initialize(); // Create DAP launch request const launchRequest: DapStartRequest = { type: 'request', seq: 1, command: 'launch', arguments: { __type__: 'LaunchRequestArguments', program: config.program, cwd: config.cwd || process.cwd(), args: config.args || [], noDebug: config.noDebug, sourceMaps: config.sourceMaps, skipFiles: config.skipFiles || [], console: config.console || 'internalConsole', // Node.js specific runtimeExecutable: 'node', runtimeArgs: [], }, }; // Launch through session manager const { sessionId, capabilities } = await this.sessionManager.handleLaunchRequest(launchRequest); // Start adapter await adapter.launch(launchRequest); // Update session with adapter info await this.sessionManager.activateSession(sessionId, 1); this.logger.info('Debugging session started', { sessionId, program: config.program }); return this.createSuccessResponse({ sessionId, capabilities, }); } /** * Handle attach configuration */ // private async handleAttach(config: DapStartRequest['arguments']): Promise<DapStartResponse> { // Unused for now // // Validate attach configuration // if (!config.processId) { // throw new Error('processId is required for attach debugging'); // } // // this.logger.debug('Starting Node.js attach debugging', { processId: config.processId }); // // // Create Node.js adapter // const adapter = createNodeJSAdapter(); // await adapter.initialize(); // // // Create DAP attach request // const attachRequest = { // type: 'request' as const, // seq: 1, // command: 'attach', // arguments: { // __type__: 'AttachRequestArguments', // processId: config.processId, // cwd: config.cwd || process.cwd(), // sourceMaps: config.sourceMaps, // skipFiles: config.skipFiles || [], // }, // }; // // // Attach through session manager // const { sessionId, capabilities } = await this.sessionManager.handleAttachRequest(attachRequest); // // // Start adapter // await adapter.attach(attachRequest); // // // Update session with adapter info // await this.sessionManager.activateSession(sessionId, 1); // // this.logger.info('Debugging session attached', { sessionId, processId: config.processId }); // // return this.createSuccessResponse({ // sessionId, // capabilities, // }); // } /** * Create success response */ private createSuccessResponse(body: any): any { return { type: 'response' as const, seq: 1, command: 'launch', request_seq: 1, success: true, body, }; } /** * Create error response */ private createErrorResponse(message: string): any { return { type: 'response' as const, seq: 1, command: 'launch', request_seq: 1, success: false, message, body: {}, }; } } // Singleton instance export const dapStartTool = new DapStartTool(); // Tool execution function export async function executeDapStart(args: any): Promise<DapStartResponse> { return await dapStartTool.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