Desktop MCP
README.md
# Desktop MCP
<img src="assets/icon.png" width="96" alt="Desktop MCP icon">
Screen size and screenshots for AI agents. Works two ways:
- **VS Code extension** — registers two Language Model Tools, so GitHub Copilot Chat (agent mode) can call them directly.
- **MCP server** — the same two tools over stdio, so Claude Code, Grok, Cursor, Windsurf, Cline or any other MCP client can use them.
No PowerShell, no external binaries: capture is done by the native [`node-screenshots`](https://www.npmjs.com/package/node-screenshots) addon, encoding by [`sharp`](https://www.npmjs.com/package/sharp).
## Tools
### `get_screen_size`
Returns the screen geometry in pixels:
```json
{
"platform": "win32",
"virtualScreen": { "x": 0, "y": 0, "width": 3200, "height": 2000 },
"displays": [
{
"index": 0,
"id": 65537,
"name": "Unknown Monitor 65537",
"primary": true,
"scaleFactor": 2,
"rotation": 0,
"bounds": { "x": 0, "y": 0, "width": 3200, "height": 2000 }
}
]
}
```
`virtualScreen` is the bounding box of all displays; its origin can be negative on multi-monitor setups.
### `capture_screenshot`
| Argument | Type | Description |
|---|---|---|
| `region` | `{ x, y, width, height }` | Rectangle in pixels, relative to the virtual screen origin. Omit for the whole screen. |
| `display` | `number` | Display index from `get_screen_size`. Ignored when `region` is set. |
| `format` | `"png" \| "jpeg"` | Default `png`. |
| `quality` | `number` | JPEG quality 1–100, default 90. |
| `savePath` | `string` | Absolute path to also save the image to. |
Returns the image plus a JSON metadata block (actual region, size, byte count, saved path). Regions that span several monitors are stitched together; regions are clipped to the screen.
### Enabling and disabling tools
Each tool can be turned off in **Settings → Desktop MCP → Tools**:
| Setting | Default | Effect when `false` |
|---|---|---|
| `desktopMcp.tools.getScreenSize` | `true` | `getScreenSize` / `get_screen_size` is hidden from agents |
| `desktopMcp.tools.captureScreenshot` | `true` | `captureScreenshot` / `capture_screenshot` is hidden from agents |
A disabled tool is removed from the tool list (`tools/list` for MCP, the Copilot tool picker for VS Code). If an agent calls it anyway, it gets a normal result explaining that the user disabled it, e.g.:
> Tool "get_screen_size" is disabled by the user in the Desktop MCP settings. Do not retry it; ask the user to enable it in Settings → Desktop MCP → Tools if it is needed.
For the standalone server the same filter is available through the `DESKTOP_MCP_DISABLED_TOOLS` environment variable (comma-separated tool names).
## Use with GitHub Copilot in VS Code
1. Install the extension (see below).
2. Open Copilot Chat in **Agent** mode and ask, e.g. *"take a screenshot of the top-left 800x600 of my screen"*.
3. The tools appear as `getScreenSize` / `captureScreenshot` and can also be referenced with `#getScreenSize` / `#captureScreenshot`.
## Use with Claude Code, Grok, Cursor, Cline, ...
There are two transports. **stdio is the default and needs no port** — the client starts the process itself. HTTP mode is there if you prefer a long-running local server on a port (like other desktop MCP bridges).
### Option A — stdio (recommended)
```json
{
"mcpServers": {
"desktop": {
"command": "node",
"args": ["C:/shared-data/reps/mcp-screenshot/bin/desktop-mcp.js"]
}
}
}
```
- **Claude Code**: `claude mcp add desktop -- node C:/shared-data/reps/mcp-screenshot/bin/desktop-mcp.js`
- **Grok / Cursor / Windsurf / Cline**: add the same `mcpServers` entry to the client's MCP config file.
- **VS Code itself**: set `desktopMcp.registerMcpServer` to `true` to expose the server through the extension, or add the JSON above to `.vscode/mcp.json`.
### Option B — HTTP on a local port
The extension starts the HTTP server **automatically** when VS Code activates it (`desktopMcp.httpServer`, default `true`), so after installing the extension you only need to point the client at the URL:
```json
{
"mcpServers": {
"desktop": {
"type": "http",
"url": "http://127.0.0.1:7841/mcp"
}
}
}
```
- **Claude Code**: `claude mcp add --transport http desktop http://127.0.0.1:7841/mcp`
- Health check: `curl http://127.0.0.1:7841/health` → `{"ok":true,"name":"desktop-mcp"}`
- Change the port with `desktopMcp.httpPort`, or turn autostart off with `desktopMcp.httpServer: false`.
### Commands (Ctrl+Shift+P)
| Command | What it does |
|---|---|
| `Desktop MCP: Install MCP` | Pick MCP clients (Claude Code, Codex, Grok, Copilot, Cursor, Cline, Roo, Windsurf, Antigravity) and write/refresh the `desktop-mcp` entry in each config |
| `Desktop MCP: Server: Start` | Starts the HTTP server on the configured port |
| `Desktop MCP: Server: Stop` | Stops it |
| `Desktop MCP: Server: Status` | Shows the URL and health check result |
| `Desktop MCP: Server: Set Port` | Asks for a port (1–65535), saves it to settings and restarts the server |
Changing `desktopMcp.httpPort` in Settings also restarts the server automatically.
### Install MCP
`Desktop MCP: Install MCP` shows a multi-select list of clients. Already-configured clients are pre-selected and marked `already configured — will be updated`, so running it again after a port change rewrites the URL everywhere.
| Client | Config file | Entry |
|---|---|---|
| Claude Code | `~/.claude.json` | `mcpServers.desktop-mcp` → `{ type: "http", url }` |
| Codex | `~/.codex/config.toml` | `[mcp_servers.desktop-mcp]` → `url`, `enabled` |
| Grok | `~/.grok/config.toml` | `[mcp_servers.desktop-mcp]` → `url`, `enabled` |
| GitHub Copilot (VS Code) | `<User>/mcp.json` | `servers.desktop-mcp` → `{ type: "http", url }` |
| GitHub Copilot CLI | `~/.copilot/mcp-config.json` | `mcpServers.desktop-mcp` → `{ type: "http", url, tools: ["*"] }` |
| Cursor | `Cursor/User/globalStorage/cursor.mcp/settings/mcp_settings.json` (fallback `~/.cursor/mcp.json`) | `mcpServers.desktop-mcp` → `streamableHttp` |
| Cline | `Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` | `mcpServers.desktop-mcp` → `streamableHttp` |
| Roo Code | `Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json` | `mcpServers.desktop-mcp` → `streamableHttp` |
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | `mcpServers.desktop-mcp` → `streamableHttp` |
| Antigravity | `~/.gemini/antigravity/mcp_config.json` | `mcpServers.desktop-mcp` → `streamableHttp` |
Existing keys in those files are preserved; only the `desktop-mcp` entry is added or overwritten.
If you don't want to keep VS Code open, run the server standalone instead:
```bash
node bin/desktop-mcp.js --http # http://127.0.0.1:7841/mcp
node bin/desktop-mcp.js --http --port 7841 # explicit port
node bin/desktop-mcp.js --http --host 0.0.0.0 # expose on the network (not recommended)
```
The HTTP transport is stateless: every request gets its own server instance, so several agents can connect at once. It binds to `127.0.0.1` by default — anyone who can reach the port can take screenshots of your desktop, so do not expose it publicly.
### Run by hand
```bash
node bin/desktop-mcp.js # MCP over stdio
node bin/desktop-mcp.js --help # usage
```
## Install the extension
```bash
npm install
npx @vscode/vsce package
code --install-extension desktop-mcp-0.1.0.vsix
```
Or press `F5` in VS Code with this folder open to run it from source.
## Platform notes
- **Windows / macOS / Linux (X11)** — supported by `node-screenshots`.
- **Wayland** — screen capture may be restricted by the compositor; X11 sessions work.
- Coordinates are physical pixels. On high-DPI displays `scaleFactor` is reported so you can convert from logical coordinates.
## Tests
```bash
npm test # stdio + HTTP MCP servers, extension wiring against a stubbed vscode API
npm run test:e2e # real VS Code instance: registers tools, captures a screenshot
```
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues