Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)<br>`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) |

Expand Down
12 changes: 12 additions & 0 deletions src/debugMCPServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.',
Expand Down
34 changes: 34 additions & 0 deletions src/debuggingHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface IDebuggingHandler {
handleListBreakpoints(): Promise<string>;
handleGetVariables(args: { scope?: 'local' | 'global' | 'all' }): Promise<string>;
handleEvaluateExpression(args: { expression: string }): Promise<string>;
handleGetLoadedScripts(): Promise<string>;
}

/**
Expand Down Expand Up @@ -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<string> {
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
*/
Expand Down