# VSCode Automation MCP Server
[](https://www.npmjs.com/package/vscode-automation-mcp)
[](https://opensource.org/licenses/MIT)
A **Model Context Protocol (MCP)** server that enables AI agents to **automate and control VSCode**: give your AI assistant the ability to interact with the VSCode UI, execute commands, inspect the DOM, read editor content, and perform complex automation workflows.
Built on top of [vscode-extension-tester](https://github.com/redhat-developer/vscode-extension-tester), this mcp server is ideal for:
- **AI-assisted VSCode extension development** - Let AI agents test and interact with your extensions
- **Automated UI testing** - Build automation scripts driven by AI
- **Development workflow automation** - Automate repetitive VSCode tasks
- **Extension debugging** - Inspect UI state, DOM structure, and diagnostics
## 🚀 Features
- **DOM Inspection** - Get the full DOM structure, UI regions, and accessibility tree for AI understanding
- **Execute VSCode Commands** - Run any command from the Command Palette programmatically
- **UI Automation** - Click elements, type text, navigate the UI
- **Keyboard Input** - Press key combinations, shortcuts, and special keys
- **File Operations** - Open files at specific lines and columns
- **Screenshots** - Capture the VSCode window for debugging and verification
- **Element Inspection** - Get detailed information about UI elements
- **Element Queries** - Find multiple elements matching selectors with attributes
- **JavaScript Execution** - Run arbitrary JS in the VSCode window (like DevTools console)
- **Diagnostics** - Access errors and warnings from the Problems panel
- **Editor Content** - Read and verify editor content
- **Webview Support** - Interact with extension webviews
- **Wait & Synchronization** - Wait for elements, text, or idle state
- **Notifications** - Get, dismiss, and handle notifications
- **Dialogs** - Handle InputBox, QuickPick, and confirmation dialogs
- **IntelliSense** - Trigger completions, get items, select suggestions
- **Code Navigation** - Go to definition, hover tooltips, signature help
- **Context Menus** - Open and interact with context menus
- **Output Channels** - Read from VSCode output channels and extension logs
- **Console Logs** - Capture and filter browser console logs
- **Performance Metrics** - Memory usage, DOM stats, timing info
## 📋 Requirements
- **Node.js** >= 18.0.0
- **Internet connection** (for first run to download VSCode and ChromeDriver)
> **Note**: The server automatically downloads a standalone VSCode instance and matching ChromeDriver on first run. It does NOT use your installed VSCode - this ensures consistent behavior and prevents conflicts with your main VSCode instance.
## 📦 Installation
### Quick Start (Recommended)
No installation required! Just add to your MCP client configuration:
```json
{
"mcpServers": {
"vscode-automation": {
"command": "npx",
"args": ["-y", "vscode-automation-mcp@latest"]
}
}
}
```
### Global Installation
```bash
npm install -g vscode-automation-mcp@latest
```
Then run directly:
```bash
vscode-automation-mcp
```
### From Source
```bash
git clone https://github.com/sukarth/vscode-automation-mcp.git
cd vscode-automation-mcp
npm install
npm run build
npm start
```
## ⚙️ Configuration
### Claude Desktop
Add to your Claude Desktop configuration file:
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"vscode-automation": {
"command": "npx",
"args": ["-y", "vscode-automation-mcp@latest"]
}
}
}
```
Or if installed globally:
```json
{
"mcpServers": {
"vscode-automation": {
"command": "vscode-automation-mcp"
}
}
}
```
### VSCode (GitHub Copilot / Copilot Chat)
Add to your VSCode `settings.json` or `.vscode/mcp.json`:
```json
{
"mcp": {
"servers": {
"vscode-automation": {
"command": "npx",
"args": ["-y", "vscode-automation-mcp@latest"]
}
}
}
}
```
### Cursor
Add to Cursor's MCP configuration:
```json
{
"mcpServers": {
"vscode-automation": {
"command": "npx",
"args": ["-y", "vscode-automation-mcp@latest"]
}
}
}
```
### Environment Variables
You can customize the server behavior using environment variables:
| Variable | Description | Default |
|----------|-------------|---------|
| `VSCODE_AUTOMATION_VERSION` | VSCode version to download (e.g., `1.95.0`, `1.85.0`, or `latest`) | `latest` |
| `VSCODE_AUTOMATION_STORAGE_PATH` | Directory to store VSCode and ChromeDriver | System temp dir |
| `VSCODE_AUTOMATION_OFFLINE` | Set to `true` to use cached binaries only | `false` |
| `VSCODE_AUTOMATION_LOG_LEVEL` | Log level: `trace`, `debug`, `info`, `warn`, `error` | `info` |
Example with environment variables:
```json
{
"mcpServers": {
"vscode-automation": {
"command": "npx",
"args": ["-y", "vscode-automation-mcp@latest"],
"env": {
"VSCODE_AUTOMATION_VERSION": "1.95.0",
"VSCODE_AUTOMATION_STORAGE_PATH": "/path/to/storage"
}
}
}
}
```
> **ChromeDriver Compatibility**: The server automatically downloads the correct ChromeDriver version that matches the VSCode/Electron version. You don't need to manage ChromeDriver manually.
## 🛠️ Available Tools
### Command Tools
| Tool | Description |
|------|-------------|
| `vscode_execute_command` | Execute any VSCode command with optional arguments |
| `vscode_list_commands` | List available VSCode commands with optional filter |
### UI Action Tools
| Tool | Description |
|------|-------------|
| `vscode_click_element` | Click a UI element by CSS/XPath/accessibility selector |
| `vscode_type_text` | Type text into an input field or focused element |
| `vscode_open_file` | Open a file in the editor at a specific line/column |
### Inspection Tools
| Tool | Description |
|------|-------------|
| `vscode_take_screenshot` | Capture a screenshot of the VSCode window |
| `vscode_get_element` | Get properties and text of a UI element |
| `vscode_open_webview` | Open an extension's webview panel |
| `vscode_get_diagnostics` | Get all diagnostic messages from Problems panel |
### DOM Inspection Tools
| Tool | Description |
|------|-------------|
| `vscode_get_dom` | Get the full DOM structure of VSCode in tree, HTML, or JSON format |
| `vscode_get_ui_structure` | Get structure of specific UI regions (sidebar, editor, panel, etc.) |
| `vscode_query_elements` | Find all elements matching a CSS selector with attributes |
| `vscode_get_accessibility_tree` | Get the semantic accessibility tree with ARIA roles and labels |
### DOM Navigation Tools
| Tool | Description |
|------|-------------|
| `vscode_get_element_children` | Get direct children or descendants of an element for incremental exploration |
| `vscode_get_element_parents` | Get the parent chain (ancestors) of an element |
| `vscode_get_element_siblings` | Get sibling elements at the same level |
| `vscode_find_interactive_elements` | Find all buttons, inputs, links, tabs within a container |
| `vscode_search_dom` | Search DOM by text, ID, class, aria-label, title, or role |
| `vscode_dump_dom_to_file` | Dump full DOM to a file for incremental exploration by AI |
### JavaScript Execution & DOM Query Tools
| Tool | Description |
|------|-------------|
| `vscode_execute_script` | Execute arbitrary JavaScript in the VSCode window (like DevTools console) |
| `vscode_query_selector` | Direct document.querySelector() / querySelectorAll() wrapper |
| `vscode_get_element_by_id` | Get element by ID (document.getElementById wrapper) |
| `vscode_get_elements_by_class` | Get elements by class name (document.getElementsByClassName wrapper) |
| `vscode_get_elements_by_tag` | Get elements by tag name (document.getElementsByTagName wrapper) |
### Testing Tools
| Tool | Description |
|------|-------------|
| `vscode_get_editor_content` | Get the current editor's text content |
| `vscode_verify_element` | Verify UI element presence and state |
| `vscode_assert_text` | Assert text content in editor or elements |
| `vscode_check_file_open` | Check if a specific file is open |
### Keyboard & Input Tools
| Tool | Description |
|------|-------------|
| `vscode_press_keys` | Press keyboard keys or key combinations (Ctrl+S, Ctrl+Shift+P, Enter, Escape, etc.) |
| `vscode_focus_element` | Focus a UI element by CSS selector |
| `vscode_scroll` | Scroll an element in a direction or to top/bottom |
| `vscode_drag_drop` | Drag and drop between elements |
| `vscode_hover` | Hover over an element for a duration |
### Wait & Sync Tools
| Tool | Description |
|------|-------------|
| `vscode_wait_for_element` | Wait for an element to appear or disappear |
| `vscode_wait_for_text` | Wait for text to appear or disappear in an element |
| `vscode_wait_for_idle` | Wait for VSCode to become idle (no pending operations) |
### Notification & Dialog Tools
| Tool | Description |
|------|-------------|
| `vscode_get_notifications` | Get all visible notifications with type, message, and actions |
| `vscode_dismiss_notification` | Dismiss a notification by index or message text |
| `vscode_handle_dialog` | Handle modal dialogs (InputBox, QuickPick, confirmations) |
| `vscode_get_quick_pick_items` | Get items from the QuickPick/Command Palette |
| `vscode_select_quick_pick_item` | Select a QuickPick item by text or index |
### Extension Testing Tools
| Tool | Description |
|------|-------------|
| `vscode_trigger_hover` | Trigger hover on an element and get tooltip content |
| `vscode_open_context_menu` | Open context menu (right-click) on an element |
| `vscode_get_menu_items` | Get items from visible menus |
| `vscode_click_menu_item` | Click a menu item by text |
| `vscode_get_tooltip` | Get currently visible tooltip content |
| `vscode_trigger_completion` | Trigger IntelliSense/code completion (Ctrl+Space) |
| `vscode_get_completion_items` | Get IntelliSense completion items |
| `vscode_select_completion_item` | Select and accept a completion item |
| `vscode_get_problems_panel` | Get problems from Problems panel with severity and location |
| `vscode_go_to_definition` | Trigger Go to Definition (F12) |
| `vscode_trigger_signature_help` | Trigger signature help (Ctrl+Shift+Space) |
### Debug & Performance Tools
| Tool | Description |
|------|-------------|
| `vscode_get_console_logs` | Get captured console logs (log, info, warn, error, debug) |
| `vscode_clear_console` | Clear captured console logs |
| `vscode_get_output_channels` | List available output channels |
| `vscode_get_output_channel_content` | Read content from an output channel |
| `vscode_get_performance_metrics` | Get performance metrics (memory, timing, DOM stats) |
| `vscode_get_extension_logs` | Get extension-related logs, optionally filtered by extension ID |
| `vscode_get_devtools_info` | Get DevTools-style window/document/navigator info |
### Utility Tools
| Tool | Description |
|------|-------------|
| `vscode_initialize` | Pre-initialize the VSCode driver |
| `vscode_get_status` | Get the current driver status |
## 📖 Usage Examples
### Execute a Command
```typescript
// Save the current file
await vscode_execute_command({ commandId: "workbench.action.files.save" });
// Format the document
await vscode_execute_command({ commandId: "editor.action.formatDocument" });
// Open settings
await vscode_execute_command({ commandId: "workbench.action.openSettings" });
```
### Click UI Elements
```typescript
// Click by CSS selector
await vscode_click_element({
selector: ".explorer-viewlet",
selectorType: "css"
});
// Click by accessibility label
await vscode_click_element({
selector: "Explorer",
selectorType: "accessibility"
});
// Double-click a file
await vscode_click_element({
selector: ".file-item",
selectorType: "css",
doubleClick: true
});
// Right-click for context menu
await vscode_click_element({
selector: ".file-item",
selectorType: "css",
rightClick: true
});
```
### Type Text
```typescript
// Type into the focused element
await vscode_type_text({ text: "Hello, World!" });
// Type into a specific input and press Enter
await vscode_type_text({
text: "search term",
selector: "input.search-input",
pressEnter: true
});
// Clear and type with a delay (for autocomplete)
await vscode_type_text({
text: "import React from 'react'",
clear: true,
delay: 50
});
```
### Open Files
```typescript
// Open a file
await vscode_open_file({ filePath: "/path/to/file.ts" });
// Open a file at a specific line
await vscode_open_file({
filePath: "src/index.ts",
line: 42
});
// Open a file at a specific line and column
await vscode_open_file({
filePath: "src/utils.ts",
line: 10,
column: 5
});
```
### Take Screenshots
```typescript
// Take a screenshot with default name
await vscode_take_screenshot({});
// Take a screenshot with custom filename
await vscode_take_screenshot({
filename: "test-result-screenshot"
});
```
### Get Diagnostics
```typescript
// Get all diagnostics
await vscode_get_diagnostics({});
// Get only errors
await vscode_get_diagnostics({ severity: "error" });
// Get warnings
await vscode_get_diagnostics({ severity: "warning" });
```
### Inspect the DOM (for AI Agents)
```typescript
// Get the full page DOM as a readable tree
await vscode_get_dom({});
// Get DOM of a specific element as JSON
await vscode_get_dom({
selector: ".sidebar",
format: "json",
depth: 5
});
// Get raw HTML of an element
await vscode_get_dom({
selector: ".editor-container",
format: "html"
});
// Get the sidebar structure
await vscode_get_ui_structure({ region: "sidebar" });
// Get the editor area structure with more depth
await vscode_get_ui_structure({
region: "editor",
depth: 8
});
// Find all buttons on the page
await vscode_query_elements({ selector: "button" });
// Find elements with a specific role
await vscode_query_elements({
selector: "[role='tab']",
limit: 10
});
// Get the accessibility tree for semantic understanding
await vscode_get_accessibility_tree({});
// Get accessibility tree of a specific region
await vscode_get_accessibility_tree({
selector: ".sidebar",
depth: 6
});
```
### Incremental DOM Exploration (for Large DOMs)
```typescript
// Step 1: Get top-level children of body
await vscode_get_element_children({ selector: "body" });
// Step 2: Drill into a specific child
await vscode_get_element_children({
selector: ".workbench-container",
depth: 2
});
// Get parent chain to understand context
await vscode_get_element_parents({
selector: ".my-button",
levels: 5
});
// Get siblings (useful for tabs, list items)
await vscode_get_element_siblings({
selector: ".tab:nth-child(2)",
direction: "all"
});
// Find all interactive elements in a region
await vscode_find_interactive_elements({
selector: ".sidebar",
types: ["button", "input", "link"]
});
// Search for elements by text/label
await vscode_search_dom({
query: "Explorer",
searchIn: ["text", "aria-label", "title"]
});
// For very large DOMs: dump to file and read incrementally
await vscode_dump_dom_to_file({
filePath: "/tmp/vscode-dom.json",
format: "json",
depth: 15
});
// Then use file reading tools to explore sections
```
### Execute JavaScript (DevTools Console Style)
```typescript
// Get the document title
await vscode_execute_script({
script: "return document.title"
});
// Get Monaco editor models (VSCode internals)
await vscode_execute_script({
script: "return window.monaco?.editor?.getModels()?.map(m => m.uri.toString())"
});
// Click an element programmatically
await vscode_execute_script({
script: "document.querySelector('.my-button')?.click(); return 'clicked'",
returnType: "string"
});
// Run complex DOM manipulation
await vscode_execute_script({
script: `
const editors = document.querySelectorAll('.editor-instance');
return Array.from(editors).map(e => ({
id: e.id,
visible: e.offsetWidth > 0
}));
`
});
// Access VSCode's internal APIs (if available)
await vscode_execute_script({
script: "return typeof acquireVsCodeApi !== 'undefined'"
});
```
### Simple DOM Queries (querySelector style)
```typescript
// Find a single element
await vscode_query_selector({ selector: ".my-button" });
// Find all matching elements
await vscode_query_selector({ selector: "button", all: true });
// Extract specific properties
await vscode_query_selector({
selector: "input",
all: true,
properties: ["value", "placeholder", "type", "name"]
});
// Get element by ID
await vscode_get_element_by_id({ id: "workbench.parts.editor" });
// Get all elements with a class
await vscode_get_elements_by_class({
className: "editor-container",
limit: 10
});
// Get all buttons
await vscode_get_elements_by_tag({
tagName: "button",
properties: ["textContent", "aria-label", "disabled"]
});
// Get all inputs with their values
await vscode_get_elements_by_tag({
tagName: "input",
properties: ["type", "value", "placeholder", "name"]
});
```
### Keyboard & Input
```typescript
// Press keyboard shortcuts
await vscode_press_keys({ keys: "ctrl+s" }); // Save file
await vscode_press_keys({ keys: "ctrl+shift+p" }); // Command Palette
await vscode_press_keys({ keys: "ctrl+/" }); // Toggle comment
// Press keys multiple times
await vscode_press_keys({ keys: "ArrowDown", count: 5 });
// Focus on a specific element first
await vscode_press_keys({
keys: "Enter",
selector: ".my-button"
});
// Scroll within an element
await vscode_scroll({ direction: "down", amount: 500 });
await vscode_scroll({ selector: ".sidebar", direction: "bottom" });
// Drag and drop
await vscode_drag_drop({
sourceSelector: ".file-item:nth-child(2)",
targetSelector: ".folder-item"
});
// Hover over element
await vscode_hover({
selector: ".status-item",
duration: 1000
});
```
### Waiting & Synchronization
```typescript
// Wait for an element to appear
await vscode_wait_for_element({
selector: ".notification",
timeout: 5000
});
// Wait for element to disappear
await vscode_wait_for_element({
selector: ".loading-spinner",
present: false,
timeout: 10000
});
// Wait for specific text
await vscode_wait_for_text({
text: "Build succeeded",
selector: ".terminal",
timeout: 30000
});
// Wait for VSCode to be idle
await vscode_wait_for_idle({ timeout: 5000 });
```
### Notifications & Dialogs
```typescript
// Get all notifications
await vscode_get_notifications({});
// Dismiss a notification by message
await vscode_dismiss_notification({
messageContains: "Extension installed"
});
// Handle input dialog
await vscode_handle_dialog({
text: "my-new-file.ts",
action: "accept"
});
// Get QuickPick items (Command Palette)
await vscode_press_keys({ keys: "ctrl+shift+p" });
await vscode_get_quick_pick_items({});
// Select a QuickPick item
await vscode_select_quick_pick_item({
text: "Format Document"
});
```
### IntelliSense & Code Navigation
```typescript
// Trigger completion
await vscode_trigger_completion({});
// Get completion items
await vscode_get_completion_items({ limit: 20 });
// Select a completion item
await vscode_select_completion_item({
itemLabel: "console.log"
});
// Go to definition
await vscode_go_to_definition({});
// Trigger signature help
await vscode_trigger_signature_help({});
// Trigger hover and get tooltip
await vscode_trigger_hover({
selector: ".view-line span"
});
// Open context menu
await vscode_open_context_menu({
selector: ".file-item"
});
// Get and click menu items
await vscode_get_menu_items({});
await vscode_click_menu_item({ itemText: "Rename" });
```
### Debug & Performance
```typescript
// Get console logs
await vscode_get_console_logs({ level: "error" });
// Get all recent logs
await vscode_get_console_logs({ limit: 50 });
// Clear console logs
await vscode_clear_console({});
// Get output channels
await vscode_get_output_channels({});
// Read from an output channel
await vscode_get_output_channel_content({
channelName: "Extension Host"
});
// Get extension logs
await vscode_get_extension_logs({
extensionId: "my.extension"
});
// Get performance metrics
await vscode_get_performance_metrics({});
// Get DevTools info
await vscode_get_devtools_info({});
```
### Verify UI State
```typescript
// Check if an element exists and is visible
await vscode_verify_element({
selector: ".explorer-viewlet",
selectorType: "css",
shouldBeVisible: true
});
// Check if element contains specific text
await vscode_verify_element({
selector: ".statusbar",
selectorType: "css",
containsText: "TypeScript"
});
```
### Get Editor Content
```typescript
// Get the content of the active editor
const result = await vscode_get_editor_content({});
// Returns: { content: "...", editor: { fileName: "...", lineCount: ... } }
```
## 🔧 Common Command IDs
Here are some frequently used VSCode command IDs:
### File Operations
- `workbench.action.files.save` - Save file
- `workbench.action.files.saveAll` - Save all files
- `workbench.action.files.newUntitledFile` - New file
- `workbench.action.closeActiveEditor` - Close editor
### Navigation
- `workbench.action.quickOpen` - Quick Open (Ctrl+P)
- `workbench.action.gotoLine` - Go to Line
- `editor.action.revealDefinition` - Go to Definition
### View
- `workbench.action.toggleSidebarVisibility` - Toggle Sidebar
- `workbench.action.togglePanel` - Toggle Panel
- `workbench.action.terminal.toggleTerminal` - Toggle Terminal
### Editor
- `editor.action.formatDocument` - Format Document
- `editor.action.commentLine` - Toggle Line Comment
### Git
- `git.commit` - Git Commit
- `git.push` - Git Push
- `git.pull` - Git Pull
## 🧪 Testing the MCP Server
### Manual Testing
1. **Build the project:**
```bash
npm run build
npm run validate
```
2. **Test with MCP Inspector (recommended):**
```bash
npx @modelcontextprotocol/inspector node dist/index.js
```
This opens a web UI where you can call each tool interactively.
3. **Test with Claude Desktop:**
- Add the server to your Claude Desktop config (see Configuration section)
- Restart Claude Desktop
- Ask Claude to use the vscode_automation tools
4. **Test basic functionality:**
```bash
# Start the server manually to check for startup errors
node dist/index.js
```
The server communicates via stdio, so you won't see output unless there are errors.
### What Gets Tested
- `vscode_get_status` - Always works, returns server state
- `vscode_initialize` - Launches VSCode with WebDriver (requires display)
- All other tools - Require `vscode_initialize` to be called first
### Notes on Testing
- The server uses vscode-extension-tester which launches a real VSCode instance
- First run may take time to download ChromeDriver
- VSCode must be installed on the system
- Requires a display (or virtual display on Linux)
## 🐛 Troubleshooting
### VSCode Not Found
Make sure VSCode is installed and accessible from the command line:
```bash
code --version
```
### ChromeDriver Issues
The server uses ChromeDriver to automate VSCode. If you encounter issues:
1. Make sure Chrome/Chromium is installed
2. The correct ChromeDriver version will be downloaded automatically
3. Check that no other automation tools are conflicting
### Timeout Errors
If operations are timing out:
1. Increase the timeout in the tool options
2. Make sure VSCode has finished loading
3. Call `vscode_initialize` before other operations
### Element Not Found
If selectors aren't finding elements:
1. Use `vscode_take_screenshot` to see the current state
2. Try different selector types (css, xpath, accessibility, text)
3. Check if the element is in a webview (requires different handling)
## 🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## 📄 License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## 🙏 Acknowledgments
- [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol that makes this possible
- [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) - The SDK used to build this server
- [vscode-extension-tester](https://github.com/redhat-developer/vscode-extension-tester) - The automation library powering this server
- [Anthropic](https://anthropic.com/) - For creating Claude and the MCP specification
---
Built with ❤️ by [Sukarth](https://github.com/sukarth)