Skip to main content
Glama
integratedMcpServer.ts12.5 kB
import * as vscode from 'vscode'; import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, CallToolRequest, } from '@modelcontextprotocol/sdk/types.js'; /** * MCP Server that runs directly within the VSCode extension * This has direct access to VSCode APIs without needing inter-process communication */ export class IntegratedMcpServer { private server: Server; private transport: StdioServerTransport | undefined; constructor() { this.server = new Server({ name: 'vscode-debugger-mcp', version: '1.0.0', capabilities: { tools: {}, }, }); this.setupToolHandlers(); } private setupToolHandlers() { // List available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'add_breakpoint', description: 'Add a breakpoint to a specific file and line number', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Absolute path to the file where breakpoint should be added' }, lineNumber: { type: 'number', description: 'Line number where breakpoint should be added (1-based)' }, condition: { type: 'string', description: 'Optional condition for the breakpoint' } }, required: ['filePath', 'lineNumber'] } }, { name: 'remove_breakpoint', description: 'Remove a breakpoint from a specific file and line number', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Absolute path to the file where breakpoint should be removed' }, lineNumber: { type: 'number', description: 'Line number where breakpoint should be removed (1-based)' } }, required: ['filePath', 'lineNumber'] } }, { name: 'start_debugging', description: 'Start debugging with a specific configuration', inputSchema: { type: 'object', properties: { configurationName: { type: 'string', description: 'Name of the debug configuration to use' }, workspaceFolderPath: { type: 'string', description: 'Path to the workspace folder' } }, required: [] } }, { name: 'stop_debugging', description: 'Stop the current debugging session', inputSchema: { type: 'object', properties: { sessionId: { type: 'string', description: 'Optional session ID to stop specific session' } }, required: [] } } ] }; }); // Handle tool calls this.server.setRequestHandler(CallToolRequestSchema, async (request: CallToolRequest) => { const { name, arguments: args } = request.params; try { switch (name) { case 'add_breakpoint': return await this.addBreakpoint(args); case 'remove_breakpoint': return await this.removeBreakpoint(args); case 'start_debugging': return await this.startDebugging(args); case 'stop_debugging': return await this.stopDebugging(args); default: throw new Error(`Unknown tool: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `Error executing ${name}: ${error instanceof Error ? error.message : String(error)}` } ] }; } }); } private async addBreakpoint(args: any) { const { filePath, lineNumber, condition } = args; try { const uri = vscode.Uri.file(filePath); const position = new vscode.Position(lineNumber - 1, 0); const location = new vscode.Location(uri, position); const breakpoint = new vscode.SourceBreakpoint(location, true, condition); vscode.debug.addBreakpoints([breakpoint]); return { content: [ { type: 'text', text: `Successfully added breakpoint at ${filePath}:${lineNumber}${condition ? ` with condition: ${condition}` : ''}` } ] }; } catch (error) { throw new Error(`Failed to add breakpoint: ${error instanceof Error ? error.message : String(error)}`); } } private async removeBreakpoint(args: any) { const { filePath, lineNumber } = args; try { const uri = vscode.Uri.file(filePath); const breakpoints = vscode.debug.breakpoints; const toRemove = breakpoints.filter((bp: vscode.Breakpoint) => { if (bp instanceof vscode.SourceBreakpoint) { return bp.location.uri.fsPath === uri.fsPath && bp.location.range.start.line === lineNumber - 1; } return false; }); if (toRemove.length > 0) { vscode.debug.removeBreakpoints(toRemove); return { content: [ { type: 'text', text: `Successfully removed breakpoint at ${filePath}:${lineNumber}` } ] }; } else { return { content: [ { type: 'text', text: `No breakpoint found at ${filePath}:${lineNumber}` } ] }; } } catch (error) { throw new Error(`Failed to remove breakpoint: ${error instanceof Error ? error.message : String(error)}`); } } private async startDebugging(args: any) { const { configurationName, workspaceFolderPath } = args; try { let workspaceFolder: vscode.WorkspaceFolder | undefined; if (workspaceFolderPath) { const uri = vscode.Uri.file(workspaceFolderPath); workspaceFolder = vscode.workspace.getWorkspaceFolder(uri); } else { workspaceFolder = vscode.workspace.workspaceFolders?.[0]; } if (!workspaceFolder) { throw new Error('No workspace folder found'); } // Get debug configurations const configurations = vscode.workspace.getConfiguration('launch', workspaceFolder.uri); const launchConfig = configurations.get('configurations') as any[]; let debugConfig: any; if (configurationName) { debugConfig = launchConfig?.find(config => config.name === configurationName); if (!debugConfig) { throw new Error(`Debug configuration '${configurationName}' not found`); } } else { debugConfig = launchConfig?.[0]; if (!debugConfig) { throw new Error('No debug configurations found'); } } const success = await vscode.debug.startDebugging(workspaceFolder, debugConfig); if (success) { return { content: [ { type: 'text', text: `Successfully started debugging with configuration: ${debugConfig.name || 'default'}` } ] }; } else { throw new Error('Failed to start debugging session'); } } catch (error) { throw new Error(`Failed to start debugging: ${error instanceof Error ? error.message : String(error)}`); } } private async stopDebugging(args: any) { const { sessionId } = args; try { if (sessionId) { const session = vscode.debug.activeDebugSession; if (session && session.id === sessionId) { await vscode.debug.stopDebugging(session); return { content: [ { type: 'text', text: `Successfully stopped debugging session: ${sessionId}` } ] }; } else { throw new Error(`Debug session with ID '${sessionId}' not found or not active`); } } else { const session = vscode.debug.activeDebugSession; if (session) { await vscode.debug.stopDebugging(session); return { content: [ { type: 'text', text: 'Successfully stopped active debugging session' } ] }; } else { return { content: [ { type: 'text', text: 'No active debugging session to stop' } ] }; } } } catch (error) { throw new Error(`Failed to stop debugging: ${error instanceof Error ? error.message : String(error)}`); } } public start() { this.transport = new StdioServerTransport(); this.server.connect(this.transport); console.error('Integrated MCP Debugger Server started'); } public stop() { if (this.transport) { this.transport.close(); this.transport = undefined; } console.error('Integrated MCP Debugger Server stopped'); } }

Latest Blog Posts

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/davidfirst/vscode-mcp-debugger'

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