Universal Screenshot MCP

An MCP (Model Context Protocol) server that provides AI assistants with screenshot capabilities โ both web page capture via Puppeteer and cross-platform system screenshots using native OS tools.
Features
- Web Page Screenshots โ Capture any public URL using a headless Chromium browser
- Cross-Platform System Screenshots โ Fullscreen, window, or region capture using native OS tools (macOS
screencapture, Linux maim/scrot/gnome-screenshot/etc., Windows PowerShell+.NET)
- Security-First Design โ SSRF prevention, path traversal protection, DNS rebinding defense, command injection prevention, and DoS limiting
- MCP Native โ Integrates directly with Claude Desktop, Cursor, and any MCP-compatible client
Requirements
- Node.js >= 18.0.0
- Chromium is downloaded automatically by Puppeteer on first run
| Platform | Required Tools | Notes |
|---|
| macOS | screencapture (built-in) | No additional installation needed |
| Linux | One of: maim, scrot, gnome-screenshot, spectacle, grim, or import (ImageMagick) | maim or scrot recommended for full feature support. For window-by-name capture, also install xdotool. |
| Windows | powershell (built-in) | Uses .NET System.Drawing โ no additional installation needed |
Linux Installation Examples
sudo apt install maim xdotool
sudo dnf install maim xdotool
sudo pacman -S maim xdotool
sudo apt install grim
After installing, you can verify your setup with:
npx universal-screenshot-mcp --doctor
This probes the host and prints copy-pasteable install commands for any missing tools, tailored to your detected distro.
Quick Start
Install from npm
npm install -g universal-screenshot-mcp
Or run directly with npx:
npx universal-screenshot-mcp
Install from Source
git clone https://github.com/sethbang/mcp-screenshot-server.git
cd mcp-screenshot-server
npm install
npm run build
Add the server to your MCP client configuration. For Claude Desktop, edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"screenshot-server": {
"command": "npx",
"args": ["-y", "universal-screenshot-mcp"]
}
}
}
Or if installed from source:
{
"mcpServers": {
"screenshot-server": {
"command": "node",
"args": ["/absolute/path/to/mcp-screenshot-server/build/index.js"]
}
}
}
For Claude Code, register the server with the claude mcp add command:
claude mcp add screenshot-server -- npx -y universal-screenshot-mcp
claude mcp add --scope user screenshot-server -- npx -y universal-screenshot-mcp
Or if installed from source:
claude mcp add screenshot-server -- node /absolute/path/to/mcp-screenshot-server/build/index.js
Verify the server registered with claude mcp list, or check live status from inside a session with /mcp.
For Cursor or other MCP clients, consult their documentation for the equivalent configuration.
The server exposes two MCP tools:
take_screenshot
Captures a web page (or a specific element) via a headless Puppeteer browser.
| Parameter | Type | Required | Description |
|---|
url | string | โ
| URL to capture (http/https only) |
width | number | โ | Viewport width (1โ3840) |
height | number | โ | Viewport height (1โ2160) |
fullPage | boolean | โ | Capture the full scrollable page |
selector | string | โ | CSS selector to capture a specific element |
waitForSelector | string | โ | Wait for this selector before capturing |
waitForTimeout | number | โ | Delay in milliseconds (0โ30000) |
outputPath | string | โ | Output file path (default: ~/Documents/screenshots) |
Example prompt:
Take a screenshot of https://example.com at 1920x1080
take_system_screenshot
Captures the desktop, a specific application window, or a screen region using native OS tools. Works on macOS, Linux, and Windows.
| Parameter | Type | Required | Description |
|---|
mode | enum | โ
| fullscreen, window, or region |
windowId | number | โ | Window ID for window mode |
windowName | string | โ | App name (e.g. "Safari", "Firefox") for window mode |
region | object | โ | { x, y, width, height } for region mode |
display | number | โ | Display number for multi-monitor setups |
includeCursor | boolean | โ | Include the mouse cursor in the capture |
format | enum | โ | png (default) or jpg |
delay | number | โ | Capture delay in seconds (0โ10) |
outputPath | string | โ | Output file path (default: ~/Documents/screenshots) |
| Feature | macOS | Linux | Windows |
|---|
| Fullscreen | โ
| โ
| โ
|
| Region | โ
| โ
(maim, scrot, grim, import) | โ
|
| Window by name | โ
| โ ๏ธ X11 + xdotool | โ ๏ธ best-effort |
| Window by ID | โ
| โ
X11 only | โ ๏ธ HWND |
| Multi-display | โ
| โ ๏ธ tool-dependent | โ
|
| Include cursor | โ
| โ ๏ธ tool-dependent | โ ๏ธ |
| Delay | โ
| โ
| โ
|
Example prompt:
Take a system screenshot of the Safari window
Configuration
Environment Variables
| Variable | Default | Description |
|---|
SCREENSHOT_OUTPUT_DIR | Documents/screenshots | Default output directory relative to ~ |
ALLOW_LOCAL | false | Set to true to allow screenshotting localhost/127.x.x.x/[::1] (useful for local dev servers) |
Output Directories
Screenshots are saved to ~/Documents/screenshots by default (configurable via SCREENSHOT_OUTPUT_DIR). Custom output paths must resolve to one of these allowed directories:
| Directory | Description |
|---|
~/Documents/screenshots | Default output location (configurable) |
~/Desktop/Screenshots | Original default location |
~/Downloads | User downloads folder |
~/Documents | User documents folder |
/tmp | System temp directory |
Security
This server implements multiple layers of security hardening:
| ID | Threat | Mitigation |
|---|
| SEC-001 | SSRF / DNS rebinding | URLs validated against blocked IP ranges; DNS resolved pre-request with IP pinning via --host-resolver-rules; navigation redirects re-validated |
| SEC-003 | Command injection | All subprocesses use execFile (no shell); app names validated against SAFE_APP_NAME_PATTERN |
| SEC-004 | Path traversal | Output paths validated with fs.realpath() symlink resolution; restricted to allowed directories |
| SEC-005 | Denial of service | Concurrent Puppeteer instances limited to 3 via semaphore |
For full details, see docs/security.md.
Development
Scripts
| Command | Description |
|---|
npm run build | Compile TypeScript to build/ |
npm run watch | Recompile on file changes |
npm test | Unit tests (fast, fully mocked) |
npm run test:integration | Integration tests (real DNS/filesystem) |
npm run test:e2e | E2E tests (real Puppeteer/native tools) |
npm run test:all | All test tiers together |
npm run test:linux | Linux e2e via Docker (requires Docker) |
npm run test:watch | Run tests in watch mode |
npm run test:coverage | Run tests with coverage report |
npm run lint | Lint source with ESLint |
npm run inspector | Launch MCP Inspector for debugging |
Project Structure
src/
โโโ index.ts # Entry point โ stdio transport
โโโ server.ts # MCP server factory
โโโ config/
โ โโโ index.ts # Static constants (limits, allowed dirs)
โ โโโ runtime.ts # Singleton semaphore, default directory
โโโ tools/
โ โโโ take-screenshot.ts # Web page capture tool
โ โโโ take-system-screenshot.ts # macOS system capture tool
โโโ types/
โ โโโ index.ts # Shared TypeScript interfaces
โโโ utils/
โ โโโ helpers.ts # Response builders, file utilities
โ โโโ screenshot-provider.ts # Cross-platform provider interface + factory
โ โโโ macos-provider.ts # macOS: screencapture wrapper
โ โโโ linux-provider.ts # Linux: maim/scrot/gnome-screenshot/etc.
โ โโโ windows-provider.ts # Windows: PowerShell + .NET System.Drawing
โ โโโ macos.ts # Window ID lookup via CoreGraphics
โ โโโ semaphore.ts # Async concurrency limiter
โโโ validators/
โโโ path.ts # Output path validation (SEC-004)
โโโ url.ts # URL/SSRF validation (SEC-001)
Testing
Tests use Vitest in three tiers:
- Unit (
npm test) โ Full dependency injection, no real I/O. Fast feedback loop.
- Integration (
npm run test:integration) โ Real DNS resolution, real filesystem with temp directories, real Puppeteer against a local HTTP server.
- E2E (
npm run test:e2e) โ Real native screenshot tools. macOS tests run natively; Linux tests run in Docker via npm run test:linux.
npm test
npm run test:linux
npm run test:all
Debugging with MCP Inspector
This launches the MCP Inspector connected to your built server, allowing you to invoke tools interactively.
License
Apache-2.0 โ Copyright 2026 Seth Bang