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.
- 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, Linuxmaim/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
- 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 |
# Ubuntu/Debian (recommended)
sudo apt install maim xdotool
# Fedora
sudo dnf install maim xdotool
# Arch Linux
sudo pacman -S maim xdotool
# Wayland (Sway, etc.)
sudo apt install grimnpm install -g universal-screenshot-mcpOr run directly with npx:
npx universal-screenshot-mcpgit clone https://github.com/sethbang/mcp-screenshot-server.git
cd mcp-screenshot-server
npm install
npm run buildAdd 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 Cursor or other MCP clients, consult their documentation for the equivalent configuration.
The server exposes two MCP tools:
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: ~/Desktop/Screenshots) |
Example prompt:
Take a screenshot of https://example.com at 1920x1080
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: ~/Desktop/Screenshots) |
| Feature | macOS | Linux | Windows |
|---|---|---|---|
| Fullscreen | ✅ | ✅ | ✅ |
| Region | ✅ | ✅ (maim, scrot, grim, import) | ✅ |
| Window by name | ✅ | ||
| Window by ID | ✅ | ✅ X11 only | |
| Multi-display | ✅ | ✅ | |
| Include cursor | ✅ | ||
| Delay | ✅ | ✅ | ✅ |
Example prompt:
Take a system screenshot of the Safari window
Screenshots are saved to ~/Desktop/Screenshots by default. Custom output paths must resolve to one of these allowed directories:
| Directory | Description |
|---|---|
~/Desktop/Screenshots |
Default output location |
~/Downloads |
User downloads folder |
~/Documents |
User documents folder |
/tmp |
System temp directory |
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.
| Command | Description |
|---|---|
npm run build |
Compile TypeScript to build/ |
npm run watch |
Recompile on file changes |
npm test |
Run tests with Vitest |
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 |
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)
Tests use Vitest with full dependency injection — no real network calls, filesystem access, or subprocess execution in tests.
npm testnpm run inspectorThis launches the MCP Inspector connected to your built server, allowing you to invoke tools interactively.
Apache-2.0 — Copyright 2026 Seth Bang