Path: blob/main/test/mcp/src/automationTools/editor.ts
3520 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { McpServer, RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';6import { ApplicationService } from '../application';7import { z } from 'zod';89/**10* Editor Management Tools11*/12export function applyEditorTools(server: McpServer, appService: ApplicationService): RegisteredTool[] {13const tools: RegisteredTool[] = [];14// Playwright can probably figure this one out15// server.tool(16// 'vscode_automation_editor_open_file',17// 'Open a file in the VS Code editor through quick open',18// {19// fileName: z.string().describe('Name of the file to open (partial names work)')20// },21// async (args) => {22// const { fileName } = args;23// await app.workbench.quickaccess.openFileQuickAccessAndWait(fileName, fileName);24// return {25// content: [{26// type: 'text' as const,27// text: `Opened file: ${fileName}`28// }]29// };30// }31// );3233// This one is critical as Playwright had trouble typing in monaco34tools.push(server.tool(35'vscode_automation_editor_type_text',36'Type text in the currently active editor',37{38text: z.string().describe('The text to type'),39filename: z.string().describe('Filename to target specific editor')40},41async (args) => {42const { text, filename } = args;43const app = await appService.getOrCreateApplication();44await app.workbench.editor.waitForTypeInEditor(filename, text);45return {46content: [{47type: 'text' as const,48text: `Typed text: "${text}"`49}]50};51}52));5354// Doesn't seem particularly useful55// server.tool(56// 'vscode_automation_editor_get_selection',57// 'Get the current selection in the editor',58// {59// filename: z.string().describe('Filename to target specific editor')60// },61// async (args) => {62// const { filename } = args;63// return new Promise((resolve, reject) => {64// const selectionHandler = (selection: { selectionStart: number; selectionEnd: number }) => {65// resolve({66// content: [{67// type: 'text' as const,68// text: `Selection: start=${selection.selectionStart}, end=${selection.selectionEnd}`69// }]70// });71// return true;72// };7374// app.workbench.editor.waitForEditorSelection(filename, selectionHandler).catch(reject);75// });76// }77// );7879// Doesn't seem particularly useful80// server.tool(81// 'vscode_automation_editor_go_to_definition',82// 'Go to definition of symbol at current cursor position',83// {84// filename: z.string().describe('File containing the symbol'),85// term: z.string().describe('The symbol/term to go to definition for'),86// line: z.number().describe('Line number where the symbol is located')87// },88// async (args) => {89// const { filename, term, line } = args;90// await app.workbench.editor.gotoDefinition(filename, term, line);91// return {92// content: [{93// type: 'text' as const,94// text: `Navigated to definition of "${term}" in ${filename} at line ${line}`95// }]96// };97// }98// );99100// Playwright can probably figure this one out101// server.tool(102// 'vscode_automation_editor_peek_definition',103// 'Peek definition of symbol at current cursor position',104// {105// filename: z.string().describe('File containing the symbol'),106// term: z.string().describe('The symbol/term to peek definition for'),107// line: z.number().describe('Line number where the symbol is located')108// },109// async (args) => {110// const { filename, term, line } = args;111// await app.workbench.editor.peekDefinition(filename, term, line);112// return {113// content: [{114// type: 'text' as const,115// text: `Peeked definition of "${term}" in ${filename} at line ${line}`116// }]117// };118// }119// );120121// Playwright can probably figure this one out122// server.tool(123// 'vscode_automation_editor_rename_symbol',124// 'Rename a symbol in the editor',125// {126// filename: z.string().describe('File containing the symbol'),127// line: z.number().describe('Line number where the symbol is located'),128// oldName: z.string().describe('Current name of the symbol'),129// newName: z.string().describe('New name for the symbol')130// },131// async (args) => {132// const { filename, line, oldName, newName } = args;133// await app.workbench.editor.rename(filename, line, oldName, newName);134// return {135// content: [{136// type: 'text' as const,137// text: `Renamed "${oldName}" to "${newName}" in ${filename} at line ${line}`138// }]139// };140// }141// );142143// Playwright can probably figure this one out144// server.tool(145// 'vscode_automation_editor_find_references',146// 'Find all references to a symbol',147// {148// filename: z.string().describe('File containing the symbol'),149// term: z.string().describe('The symbol/term to find references for'),150// line: z.number().describe('Line number where the symbol is located')151// },152// async (args) => {153// const { filename, term, line } = args;154// await app.workbench.editor.findReferences(filename, term, line);155// return {156// content: [{157// type: 'text' as const,158// text: `Found references for "${term}" in ${filename} at line ${line}`159// }]160// };161// }162// );163164// Editor File Management Tools165tools.push(server.tool(166'vscode_automation_editor_new_untitled_file',167'Create a new untitled file',168async () => {169const app = await appService.getOrCreateApplication();170await app.workbench.editors.newUntitledFile();171return {172content: [{173type: 'text' as const,174text: 'Created new untitled file'175}]176};177}178));179180tools.push(server.tool(181'vscode_automation_editor_save_file',182'Save the currently active file',183async () => {184const app = await appService.getOrCreateApplication();185await app.workbench.editors.saveOpenedFile();186return {187content: [{188type: 'text' as const,189text: 'Saved active file'190}]191};192}193));194195// Playwright can probably figure this out196// server.tool(197// 'vscode_automation_editor_select_tab',198// 'Select a specific tab by filename',199// {200// fileName: z.string().describe('Name of the file tab to select')201// },202// async (args) => {203// const { fileName } = args;204// await app.workbench.editors.selectTab(fileName);205// return {206// content: [{207// type: 'text' as const,208// text: `Selected tab: ${fileName}`209// }]210// };211// }212// );213214// Playwright can probably figure this out215// server.tool(216// 'vscode_automation_editor_wait_for_tab',217// 'Wait for a specific tab to appear',218// {219// fileName: z.string().describe('Name of the file tab to wait for'),220// isDirty: z.boolean().optional().describe('Whether to wait for the tab to be dirty (unsaved)')221// },222// async (args) => {223// const { fileName, isDirty = false } = args;224// await app.workbench.editors.waitForTab(fileName, isDirty);225// return {226// content: [{227// type: 'text' as const,228// text: `Tab appeared: ${fileName}${isDirty ? ' (dirty)' : ''}`229// }]230// };231// }232// );233234// Playwright can probably figure this out235// server.tool(236// 'vscode_automation_editor_wait_for_focus',237// 'Wait for an editor to have focus',238// {239// fileName: z.string().describe('Name of the file to wait for focus'),240// retryCount: z.number().optional().describe('Number of retries')241// },242// async (args) => {243// const { fileName, retryCount } = args;244// await app.workbench.editors.waitForEditorFocus(fileName, retryCount);245// return {246// content: [{247// type: 'text' as const,248// text: `Editor has focus: ${fileName}`249// }]250// };251// }252// );253254return tools;255}256257258