list_supported_languages
Discover available programming languages for debugging with metadata to identify compatible options for step-through debugging using the Debug Adapter Protocol.
Instructions
List all supported debugging languages with metadata
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/server.ts:1173-1217 (handler)The main handler function for the 'list_supported_languages' tool. It queries the adapter registry for installed and available languages, fetches metadata, and returns a comprehensive list including package names, installation status, and display information.private async handleListSupportedLanguages(): Promise<ServerResult> { try { const adapterRegistry = this.getAdapterRegistry(); // Get installed languages via dynamic registry if available const installed = await this.getSupportedLanguagesAsync(); // Also surface known adapters with install status if available from registry let available: Array<{ language: string; package: string; installed: boolean; description?: string }> = installed.map(lang => ({ language: lang, package: `@debugmcp/adapter-${lang}`, installed: true })); if (adapterRegistry) { const dyn = adapterRegistry as unknown as { listAvailableAdapters?: () => Promise<Array<{ name: string; packageName: string; description?: string; installed: boolean }>> }; if (typeof dyn.listAvailableAdapters === 'function') { try { const meta = await dyn.listAvailableAdapters!(); available = meta.map(m => ({ language: m.name, package: m.packageName, installed: m.installed, description: m.description })); } catch (e) { this.logger.warn('Failed to query detailed adapter metadata; returning installed list only', { error: (e as Error)?.message }); } } } // Also build simple metadata array for backward compatibility with previous payload shape const languageMetadata = await this.getLanguageMetadata(); return { content: [{ type: 'text', text: JSON.stringify({ success: true, installed, available, languages: languageMetadata, // backward-compatible field with display info count: installed.length }) }] }; } catch (error) { this.logger.error('Failed to list supported languages', { error }); throw new McpError(McpErrorCode.InternalError, `Failed to list supported languages: ${(error as Error).message}`); } }
- src/server.ts:445-445 (schema)The schema definition for the 'list_supported_languages' tool, registered in the list tools response. It takes no input parameters.{ name: 'list_supported_languages', description: 'List all supported debugging languages with metadata', inputSchema: { type: 'object', properties: {} } },
- src/server.ts:432-486 (registration)Registration of all tools including 'list_supported_languages' in the MCP server's ListToolsRequest handler. Dynamically includes supported languages in the create_debug_session schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => { this.logger.debug('Handling ListToolsRequest'); // Get supported languages dynamically - deferred until request time const supportedLanguages = await this.getSupportedLanguagesAsync(); // Generate dynamic descriptions for path parameters const fileDescription = this.getPathDescription('source file'); const scriptPathDescription = this.getPathDescription('script'); return { 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:105-142 (helper)Helper method that retrieves the list of supported languages, considering dynamic discovery, disabled languages, and container environment specifics.private async getSupportedLanguagesAsync(): Promise<string[]> { const disabled = getDisabledLanguages(); const filter = (langs: readonly string[]) => this.filterDisabledLanguages(langs, disabled); const adapterRegistry = this.getAdapterRegistry(); // Guard against undefined registry in certain test environments if (!adapterRegistry) { return filter(getDefaultLanguages()); } // Prefer dynamic discovery if available on the concrete registry const dynRegistry = adapterRegistry as unknown as { listLanguages?: () => Promise<string[]> }; const maybeList = dynRegistry.listLanguages; if (typeof maybeList === 'function') { try { const langs = await maybeList.call(adapterRegistry); if (Array.isArray(langs) && langs.length > 0) { const normalized = process.env.MCP_CONTAINER === 'true' ? ensureLanguage(langs, 'python') : langs; return filter(normalized); } } catch (e) { this.logger.warn('Dynamic adapter language discovery failed, falling back to registered languages', { error: (e as Error)?.message }); } } // Fallback to already-registered factories (may be empty until first use) const langs = adapterRegistry.getSupportedLanguages?.() || []; if (langs.length > 0) { // In container runtime, ensure python is advertised even if not yet registered (preload may be async) if (process.env.MCP_CONTAINER === 'true') { return filter(ensureLanguage(langs, 'python')); } return filter(langs); } // Final fallback to known defaults for UX (ensure python listed in container) if (process.env.MCP_CONTAINER === 'true') { return filter(ensureLanguage(getDefaultLanguages(), 'python')); } return filter(getDefaultLanguages()); }
- src/server.ts:145-183 (helper)Helper method that generates metadata (display name, version, executable info) for each supported language.private async getLanguageMetadata(): Promise<LanguageMetadata[]> { const languages = await this.getSupportedLanguagesAsync(); // Map to metadata - in future, this info can come directly from adapter registry return languages.map((lang: string) => { switch (lang) { case 'python': return { id: 'python', displayName: 'Python', version: '1.0.0', requiresExecutable: true, defaultExecutable: 'python' }; case 'mock': return { id: 'mock', displayName: 'Mock', version: '1.0.0', requiresExecutable: false }; case 'javascript': return { id: 'javascript', displayName: 'JavaScript/TypeScript', version: '1.0.0', requiresExecutable: true, defaultExecutable: 'node' }; default: return { id: lang, displayName: lang.charAt(0).toUpperCase() + lang.slice(1), version: '1.0.0', requiresExecutable: true }; } }); }