From 6ba443c1ea8d9e99b6e895024e867d13a0193528 Mon Sep 17 00:00:00 2001 From: MarcAButler Date: Sat, 16 May 2026 21:08:18 -0400 Subject: [PATCH] Feature: Add ability to get loaded scripts --- CHANGELOG.md | 5 +++++ README.md | 1 + src/debugMCPServer.ts | 12 ++++++++++++ src/debuggingHandler.ts | 34 ++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d824033..e05096d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to DebugMCP will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/). +## [Unreleased] + +### Added +- **`get_loaded_scripts` tool** — returns all scripts currently loaded in the active debug session via the DAP `loadedSources` request. Works on a running session without requiring execution to be paused. Each entry contains `name`, `path` (null for dynamically generated scripts), and `sourceReference` (non-zero when there is no on-disk path). Gracefully returns an error object if there is no active session or if the debug adapter does not support `loadedSources`. + ## [1.0.8] - 2025-03-14 ### Added diff --git a/README.md b/README.md index a16ed39..7ec816c 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ DebugMCP is an MCP server that gives AI coding agents full control over the VS C | **remove_breakpoint** | Remove a breakpoint from a specific line | `fileFullPath` (required)
`line` (required) | | **clear_all_breakpoints** | Remove all breakpoints at once | None | | **list_breakpoints** | List all active breakpoints | None | +| **get_loaded_scripts** | Returns all scripts currently loaded in the active debug session (name, path, sourceReference). Works on a running session without pausing execution. Useful for discovering exact file paths before calling `add_breakpoint`. | None | | **get_variables_values** | Get variables and their values at current execution point | `scope` (optional: 'local', 'global', 'all') | | **evaluate_expression** | Evaluate an expression in debug context | `expression` (required) | diff --git a/src/debugMCPServer.ts b/src/debugMCPServer.ts index 40e33f8..4ea41d1 100644 --- a/src/debugMCPServer.ts +++ b/src/debugMCPServer.ts @@ -183,6 +183,18 @@ export class DebugMCPServer { return { content: [{ type: 'text' as const, text: result }] }; }); + // Get loaded scripts tool + this.mcpServer!.registerTool('get_loaded_scripts', { + description: 'Returns all scripts currently loaded in the active debug session. ' + + 'Does not require the session to be paused — it can be called at any point while a debug session is running. ' + + 'Each entry includes the script name, its file path on disk (or null for dynamically generated scripts), ' + + 'and a sourceReference (non-zero for scripts with no on-disk path). ' + + 'Use this to discover exact file paths before calling add_breakpoint, ' + + 'which avoids unbound breakpoints caused by guessed or incorrect paths.', + }, async () => { + const result = await this.debuggingHandler.handleGetLoadedScripts(); + return { content: [{ type: 'text' as const, text: result }] }; + }); // Get variables tool this.mcpServer!.registerTool('get_variables_values', { description: 'Inspect all variable values at the current execution point. This is your window into program state - see what data looks like at runtime, verify assumptions, identify unexpected values, and understand why code behaves as it does.', diff --git a/src/debuggingHandler.ts b/src/debuggingHandler.ts index dd87bde..e0ff2ab 100644 --- a/src/debuggingHandler.ts +++ b/src/debuggingHandler.ts @@ -23,6 +23,7 @@ export interface IDebuggingHandler { handleListBreakpoints(): Promise; handleGetVariables(args: { scope?: 'local' | 'global' | 'all' }): Promise; handleEvaluateExpression(args: { expression: string }): Promise; + handleGetLoadedScripts(): Promise; } /** @@ -380,6 +381,39 @@ export class DebuggingHandler implements IDebuggingHandler { } } + /** + * Return all scripts currently loaded in the active debug session via the DAP loadedSources request + */ + public async handleGetLoadedScripts(): Promise { + try { + const session = vscode.debug.activeDebugSession; + + if (!session) { + return JSON.stringify({ error: 'No active debug session. Start a debug session first.' }); + } + + let response: { sources: Array<{ name: string; path?: string; sourceReference?: number }> }; + try { + response = await session.customRequest('loadedSources', {}); + } catch (err) { + return JSON.stringify({ + error: 'The active debug adapter does not support loadedSources.', + hint: 'This capability is supported by Node.js, Electron, and Chrome-based debug adapters.', + }); + } + + const sources = (response.sources ?? []).map(s => ({ + name: s.name, + path: s.path ?? null, + sourceReference: s.sourceReference ?? 0, + })); + + return JSON.stringify(sources, null, 2); + } catch (error) { + throw new Error(`Error getting loaded scripts: ${error}`); + } + } + /** * Evaluate an expression in current debug context */