vscode-mcp-comprehensive
Version:
Comprehensive MCP server exposing all VSCode features to AI agents with 101 tools including advanced debugging and console access
511 lines • 21.3 kB
JavaScript
import * as vscode from 'vscode';
export class EditorTools {
constructor(server) {
this.server = server;
this.registerTools();
}
registerTools() {
// Get active editor
this.server.registerTool('editor_get_active', 'Get active text editor', {
type: 'object',
properties: {},
}, this.getActiveEditor.bind(this));
// Get all editors
this.server.registerTool('editor_get_all', 'Get all open editors', {
type: 'object',
properties: {},
}, this.getAllEditors.bind(this));
// Get editor text
this.server.registerTool('editor_get_text', 'Get editor text content', {
type: 'object',
properties: {
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
range: {
type: 'object',
description: 'Text range to get (optional, gets all text if not provided)',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
},
}, this.getEditorText.bind(this));
// Set editor text
this.server.registerTool('editor_set_text', 'Replace entire editor content', {
type: 'object',
properties: {
text: { type: 'string', description: 'New text content' },
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['text'],
}, this.setEditorText.bind(this));
// Insert text
this.server.registerTool('editor_insert_text', 'Insert text at position', {
type: 'object',
properties: {
text: { type: 'string', description: 'Text to insert' },
position: {
type: 'object',
description: 'Position to insert at',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['text', 'position'],
}, this.insertText.bind(this));
// Replace text
this.server.registerTool('editor_replace_text', 'Replace text in range', {
type: 'object',
properties: {
text: { type: 'string', description: 'Replacement text' },
range: {
type: 'object',
description: 'Range to replace',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['text', 'range'],
}, this.replaceText.bind(this));
// Delete text
this.server.registerTool('editor_delete_text', 'Delete text in range', {
type: 'object',
properties: {
range: {
type: 'object',
description: 'Range to delete',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['range'],
}, this.deleteText.bind(this));
// Get selection
this.server.registerTool('editor_get_selection', 'Get current selection', {
type: 'object',
properties: {
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
}, this.getSelection.bind(this));
// Set selection
this.server.registerTool('editor_set_selection', 'Set selection range', {
type: 'object',
properties: {
selection: {
type: 'object',
description: 'Selection to set',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['selection'],
}, this.setSelection.bind(this));
// Get cursor position
this.server.registerTool('editor_get_cursor_position', 'Get cursor position', {
type: 'object',
properties: {
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
}, this.getCursorPosition.bind(this));
// Set cursor position
this.server.registerTool('editor_set_cursor_position', 'Set cursor position', {
type: 'object',
properties: {
position: {
type: 'object',
description: 'Position to set cursor at',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['position'],
}, this.setCursorPosition.bind(this));
// Format document
this.server.registerTool('editor_format_document', 'Format entire document', {
type: 'object',
properties: {
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
}, this.formatDocument.bind(this));
// Format selection
this.server.registerTool('editor_format_selection', 'Format selected text', {
type: 'object',
properties: {
range: {
type: 'object',
description: 'Range to format (optional, uses current selection if not provided)',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
}, this.formatSelection.bind(this));
// Fold range
this.server.registerTool('editor_fold_range', 'Fold code section', {
type: 'object',
properties: {
range: {
type: 'object',
description: 'Range to fold',
properties: {
start: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
end: {
type: 'object',
properties: {
line: { type: 'number' },
character: { type: 'number' },
},
required: ['line', 'character'],
},
},
required: ['start', 'end'],
},
uri: { type: 'string', description: 'Editor URI (optional, uses active if not provided)' },
},
required: ['range'],
}, this.foldRange.bind(this));
}
getEditor(uri) {
if (uri) {
const targetUri = vscode.Uri.parse(uri);
return vscode.window.visibleTextEditors.find(editor => editor.document.uri.toString() === targetUri.toString());
}
return vscode.window.activeTextEditor;
}
async getActiveEditor() {
try {
const editor = vscode.window.activeTextEditor;
if (!editor) {
return this.server.createSuccessResponse(null, 'No active editor');
}
const editorInfo = {
uri: editor.document.uri.toString(),
fileName: editor.document.fileName,
languageId: editor.document.languageId,
lineCount: editor.document.lineCount,
isDirty: editor.document.isDirty,
selection: this.server.convertRange(editor.selection),
visibleRanges: editor.visibleRanges.map(range => this.server.convertRange(range)),
};
return this.server.createSuccessResponse(editorInfo);
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async getAllEditors() {
try {
const editors = vscode.window.visibleTextEditors.map(editor => ({
uri: editor.document.uri.toString(),
fileName: editor.document.fileName,
languageId: editor.document.languageId,
lineCount: editor.document.lineCount,
isDirty: editor.document.isDirty,
selection: this.server.convertRange(editor.selection),
}));
return this.server.createSuccessResponse(editors);
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async getEditorText(args) {
try {
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
let text;
if (args.range) {
const range = this.server.toVSCodeRange(args.range);
text = editor.document.getText(range);
}
else {
text = editor.document.getText();
}
return this.server.createSuccessResponse({ text, uri: editor.document.uri.toString() });
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async setEditorText(args) {
try {
this.server.validateRequiredParams(args, ['text']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const fullRange = new vscode.Range(editor.document.positionAt(0), editor.document.positionAt(editor.document.getText().length));
await editor.edit(editBuilder => {
editBuilder.replace(fullRange, args.text);
});
return this.server.createSuccessResponse({ success: true }, 'Editor text replaced');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async insertText(args) {
try {
this.server.validateRequiredParams(args, ['text', 'position']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const position = this.server.toVSCodePosition(args.position);
await editor.edit(editBuilder => {
editBuilder.insert(position, args.text);
});
return this.server.createSuccessResponse({ success: true }, 'Text inserted');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async replaceText(args) {
try {
this.server.validateRequiredParams(args, ['text', 'range']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const range = this.server.toVSCodeRange(args.range);
await editor.edit(editBuilder => {
editBuilder.replace(range, args.text);
});
return this.server.createSuccessResponse({ success: true }, 'Text replaced');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async deleteText(args) {
try {
this.server.validateRequiredParams(args, ['range']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const range = this.server.toVSCodeRange(args.range);
await editor.edit(editBuilder => {
editBuilder.delete(range);
});
return this.server.createSuccessResponse({ success: true }, 'Text deleted');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async getSelection(args) {
try {
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const selection = {
start: this.server.convertPosition(editor.selection.start),
end: this.server.convertPosition(editor.selection.end),
anchor: this.server.convertPosition(editor.selection.anchor),
active: this.server.convertPosition(editor.selection.active),
isEmpty: editor.selection.isEmpty,
isSingleLine: editor.selection.isSingleLine,
};
return this.server.createSuccessResponse(selection);
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async setSelection(args) {
try {
this.server.validateRequiredParams(args, ['selection']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const range = this.server.toVSCodeRange(args.selection);
editor.selection = new vscode.Selection(range.start, range.end);
return this.server.createSuccessResponse({ success: true }, 'Selection set');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async getCursorPosition(args) {
try {
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const position = this.server.convertPosition(editor.selection.active);
return this.server.createSuccessResponse(position);
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async setCursorPosition(args) {
try {
this.server.validateRequiredParams(args, ['position']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const position = this.server.toVSCodePosition(args.position);
editor.selection = new vscode.Selection(position, position);
return this.server.createSuccessResponse({ success: true }, 'Cursor position set');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async formatDocument(args) {
try {
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
await vscode.commands.executeCommand('editor.action.formatDocument');
return this.server.createSuccessResponse({ success: true }, 'Document formatted');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async formatSelection(args) {
try {
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
if (args.range) {
const range = this.server.toVSCodeRange(args.range);
editor.selection = new vscode.Selection(range.start, range.end);
}
await vscode.commands.executeCommand('editor.action.formatSelection');
return this.server.createSuccessResponse({ success: true }, 'Selection formatted');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
async foldRange(args) {
try {
this.server.validateRequiredParams(args, ['range']);
const editor = this.getEditor(args.uri);
if (!editor) {
return this.server.createErrorResponse('No editor found');
}
const range = this.server.toVSCodeRange(args.range);
editor.selection = new vscode.Selection(range.start, range.end);
await vscode.commands.executeCommand('editor.fold');
return this.server.createSuccessResponse({ success: true }, 'Range folded');
}
catch (error) {
return this.server.createErrorResponse(error);
}
}
}
//# sourceMappingURL=editorTools.js.map