a macOS-only MCP server that enables AI agents to capture screenshots of applications, or the entire system.
Peekaboo is a macOS-only MCP server that enables AI agents to capture screenshots of applications, windows, or the entire system, with optional visual question answering through local or remote AI models.
Peekaboo bridges the gap between AI assistants and visual content on your screen. Without visual capabilities, AI agents are fundamentally limited when debugging UI issues or understanding what's happening on screen. Peekaboo solves this by giving AI agents the ability to:
Read more about the design philosophy and implementation details in the blog post.
Or manually add to your Cursor settings:
{
"mcpServers": {
"peekaboo": {
"command": "npx",
"args": [
"-y",
"@steipete/peekaboo-mcp"
],
"env": {
"PEEKABOO_AI_PROVIDERS": "openai/gpt-4o,ollama/llava:latest",
"OPENAI_API_KEY": "your-openai-api-key-here"
}
}
}
}
Edit your Claude Desktop configuration file:
~/Library/Application Support/Claude/claude_desktop_config.json
%APPDATA%\Claude\claude_desktop_config.json
Add the Peekaboo configuration:
{
"mcpServers": {
"peekaboo": {
"command": "npx",
"args": [
"-y",
"@steipete/peekaboo-mcp"
],
"env": {
"PEEKABOO_AI_PROVIDERS": "openai/gpt-4o,ollama/llava:latest",
"OPENAI_API_KEY": "your-openai-api-key-here"
}
}
}
}
Then restart Claude Desktop.
Peekaboo can be configured using environment variables:
{
"PEEKABOO_AI_PROVIDERS": "openai/gpt-4o,ollama/llava:latest",
"OPENAI_API_KEY": "your-openai-api-key-here",
"PEEKABOO_LOG_LEVEL": "debug",
"PEEKABOO_LOG_FILE": "~/Library/Logs/peekaboo-mcp-debug.log",
"PEEKABOO_DEFAULT_SAVE_PATH": "~/Pictures/PeekabooCaptures",
"PEEKABOO_CONSOLE_LOGGING": "true",
"PEEKABOO_CLI_TIMEOUT": "30000",
"PEEKABOO_CLI_PATH": "/opt/custom/peekaboo"
}
Variable | Description | Default |
---|---|---|
PEEKABOO_AI_PROVIDERS | JSON string defining AI providers for image analysis (see AI Analysis). | "" (disabled) |
PEEKABOO_LOG_LEVEL | Logging level (trace, debug, info, warn, error, fatal). | info |
PEEKABOO_LOG_FILE | Path to the server's log file. If the specified directory is not writable, falls back to the system temp directory. | ~/Library/Logs/peekaboo-mcp.log |
PEEKABOO_DEFAULT_SAVE_PATH | Default directory for saving captured images when no path is specified. | System temp directory |
PEEKABOO_OLLAMA_BASE_URL | Base URL for the Ollama API server. Only needed if Ollama is running on a non-default address. | http://localhost:11434 |
PEEKABOO_CONSOLE_LOGGING | Boolean ("true" /"false" ) for development console logs. | "false" |
PEEKABOO_CLI_TIMEOUT | Timeout in milliseconds for Swift CLI operations. Prevents hanging processes. | 30000 (30 seconds) |
PEEKABOO_CLI_PATH | Optional override for the Swift peekaboo CLI executable path. | (uses bundled CLI) |
The PEEKABOO_AI_PROVIDERS
environment variable is your gateway to unlocking Peekaboo's analytical abilities for both the dedicated analyze
tool and the image
tool (when a question
is supplied with an image capture). It should be a string defining the AI providers and their default models. For example:
PEEKABOO_AI_PROVIDERS="openai/gpt-4o,ollama/llava:latest,anthropic/claude-3-haiku-20240307"
Or using semicolon separators:
PEEKABOO_AI_PROVIDERS="openai/gpt-4o;ollama/llava:latest;anthropic/claude-3-haiku-20240307"
Each entry follows the format provider_name/model_identifier
. You can use either commas (,
) or semicolons (;
) as separators.
provider_name
: Currently supported values are ollama
(for local Ollama instances) and openai
. Support for anthropic
is planned.model_identifier
: The specific model to use for that provider (e.g., llava:latest
, gpt-4o
).The analyze
tool and the image
tool (when a question
is provided) will use these configurations. If the provider_config
argument in these tools is set to \"auto\"
(the default for analyze
, and an option for image
), Peekaboo will try providers from PEEKABOO_AI_PROVIDERS
in the order they are listed, checking for necessary API keys (like OPENAI_API_KEY
) or service availability (like Ollama running at http://localhost:11434
or the URL specified in PEEKABOO_OLLAMA_BASE_URL
).
You can override the model or pick a specific provider listed in PEEKABOO_AI_PROVIDERS
using the provider_config
argument in the analyze
or image
tools. (The system will still verify its operational readiness, e.g., API key presence or service availability.)
Ollama provides powerful local AI models that can analyze your screenshots without sending data to the cloud.
# Install via Homebrew
brew install ollama
# Or download from https://ollama.ai
# Start the Ollama service
ollama serve
For powerful machines, LLaVA (Large Language and Vision Assistant) is the recommended model:
# Download the latest LLaVA model (recommended for best quality)
ollama pull llava:latest
# Alternative LLaVA versions
ollama pull llava:7b-v1.6
ollama pull llava:13b-v1.6 # Larger, more capable
ollama pull llava:34b-v1.6 # Largest, most powerful (requires significant RAM)
For less beefy machines, Qwen2-VL provides excellent performance with lower resource requirements:
# Download Qwen2-VL 7B model (great balance of quality and performance)
ollama pull qwen2-vl:7b
Model Size Guide:
qwen2-vl:7b
- ~4GB download, ~6GB RAM required (excellent for lighter machines)llava:7b
- ~4.5GB download, ~8GB RAM requiredllava:13b
- ~8GB download, ~16GB RAM requiredllava:34b
- ~20GB download, ~40GB RAM requiredAdd Ollama to your Claude Desktop configuration:
{
"mcpServers": {
"peekaboo": {
"command": "npx",
"args": [
"-y",
"@steipete/peekaboo-mcp@beta"
],
"env": {
"PEEKABOO_AI_PROVIDERS": "ollama/llava:latest"
}
}
}
}
For less powerful machines (using Qwen2-VL):
{
"mcpServers": {
"peekaboo": {
"command": "npx",
"args": [
"-y",
"@steipete/peekaboo-mcp@beta"
],
"env": {
"PEEKABOO_AI_PROVIDERS": "ollama/qwen2-vl:7b"
}
}
}
}
Multiple AI Providers (Ollama + OpenAI):
{
"env": {
"PEEKABOO_AI_PROVIDERS": "ollama/llava:latest,openai/gpt-4o",
"OPENAI_API_KEY": "your-api-key-here"
}
}
Peekaboo requires specific macOS permissions to function:
For macOS Sequoia (15.0+):
For macOS Sonoma (14.0) and earlier:
Applications that need permission:
/Applications/Utilities/Terminal.app
/Applications/Claude.app
/Applications/Visual Studio Code.app
/Applications/Cursor.app
For macOS Sequoia (15.0+):
For macOS Sonoma (14.0) and earlier:
The easiest way to test Peekaboo is with the MCP Inspector:
# Test with OpenAI (recommended)
OPENAI_API_KEY="your-key" PEEKABOO_AI_PROVIDERS="openai/gpt-4o" npx @modelcontextprotocol/inspector npx -y @steipete/peekaboo-mcp
# Test with local Ollama
PEEKABOO_AI_PROVIDERS="ollama/llava:latest" npx @modelcontextprotocol/inspector npx -y @steipete/peekaboo-mcp
This launches an interactive web interface where you can test all of Peekaboo's tools and see their responses in real-time.
# Commune with the Swift spirit directly
./peekaboo --help
# Check the spectral server's pulse
./peekaboo list server_status --json-output
# Capture a soul (requires permission wards)
./peekaboo image --mode screen --format png
# Open the portal for testing
peekaboo-mcp
Expected output:
{
"success": true,
"data": {
"swift_cli_available": true,
"permissions": {
"screen_recording": true
},
"system_info": {
"macos_version": "14.0"
}
}
}
Peekaboo provides three main tools for AI agents:
image
- Capture ScreenshotsCaptures macOS screen content with automatic shadow/frame removal.
Important: Screen captures cannot use format: "data"
due to the large size of screen images causing JavaScript stack overflow errors. Screen captures always save to files, either to a specified path or a temporary directory. When format: "data"
is requested for screen captures, the tool automatically falls back to PNG format and saves to a file with a warning message explaining the fallback.
Examples:
// Capture entire screen (must save to file)
await use_mcp_tool("peekaboo", "image", {
app_target: "screen:0",
path: "~/Desktop/screenshot.png"
});
// Capture specific app window with analysis (can use format: "data")
await use_mcp_tool("peekaboo", "image", {
app_target: "Safari",
question: "What website is currently open?",
format: "data"
});
// Capture window by title
await use_mcp_tool("peekaboo", "image", {
app_target: "Notes:WINDOW_TITLE:Meeting Notes",
path: "~/Desktop/notes.png"
});
// Capture frontmost window of currently active application
await use_mcp_tool("peekaboo", "image", {
app_target: "frontmost",
format: "png"
});
// Capture by Process ID (useful for multiple instances)
await use_mcp_tool("peekaboo", "image", {
app_target: "PID:663",
path: "~/Desktop/process.png"
});
Peekaboo automatically filters out browser helper processes when searching for common browsers (Chrome, Safari, Firefox, Edge, Brave, Arc, Opera). This prevents confusing errors when helper processes like "Google Chrome Helper (Renderer)" are matched instead of the main browser application.
Examples:
// ā
Finds main Chrome browser, not helpers
await use_mcp_tool("peekaboo", "image", {
app_target: "Chrome"
});
// ā Old behavior: Could match "Google Chrome Helper (Renderer)"
// Result: "no capturable windows were found"
// ā
New behavior: Finds "Google Chrome" or shows "Chrome browser is not running"
Browser-Specific Error Messages:
Peekaboo intelligently manages output paths to prevent file overwrites while respecting your intentions:
Key Principle: Single vs Multiple Captures
When you provide a specific file path (e.g., ~/Desktop/screenshot.png
), Peekaboo determines whether to use it exactly or add metadata based on the capture context:
Single Capture ā Exact Path
app_target: "frontmost"
Multiple Captures ā Metadata Added
mode: "multi"
or multiple windows exist)Examples:
// SINGLE CAPTURES - Use exact path
// ================================
// One window of Safari
await use_mcp_tool("peekaboo", "image", {
app_target: "Safari",
path: "~/Desktop/browser.png"
});
// Result: ~/Desktop/browser.png ā
// Specific screen (when you have only one monitor)
await use_mcp_tool("peekaboo", "image", {
app_target: "screen:0",
path: "~/Desktop/myscreen.png"
});
// Result: ~/Desktop/myscreen.png ā
// Frontmost window
await use_mcp_tool("peekaboo", "image", {
app_target: "frontmost",
path: "~/Desktop/active.png"
});
// Result: ~/Desktop/active.png ā
// MULTIPLE CAPTURES - Add metadata
// ================================
// All windows of Safari (mode: multi)
await use_mcp_tool("peekaboo", "image", {
app_target: "Safari",
mode: "multi",
path: "~/Desktop/browser.png"
});
// Results: ~/Desktop/browser_Safari_window_0_20250610_120000.png
// ~/Desktop/browser_Safari_window_1_20250610_120000.png
// All screens (multiple monitors)
await use_mcp_tool("peekaboo", "image", {
app_target: "screen", // or omit app_target
path: "~/Desktop/monitor.png"
});
// Results: ~/Desktop/monitor_1_20250610_120000.png
// ~/Desktop/monitor_2_20250610_120000.png
// DIRECTORY PATHS - Always use generated names
// ============================================
// Directory path (note trailing slash)
await use_mcp_tool("peekaboo", "image", {
app_target: "Safari",
path: "~/Desktop/screenshots/"
});
// Result: ~/Desktop/screenshots/Safari_20250610_120000.png
Long Filename Protection:
Peekaboo automatically handles filesystem limitations:
Example:
// Very long filename with emoji
await use_mcp_tool("peekaboo", "image", {
app_target: "Safari",
path: "~/Desktop/" + "šÆ".repeat(100) + "_screenshot.png"
});
// Result: Filename safely truncated to fit 255-byte limit
// while preserving valid UTF-8 characters
Format Validation:
list
- System InformationLists running applications, windows, or server status.
Examples:
// List all running applications
await use_mcp_tool("peekaboo", "list", {
item_type: "running_applications"
});
// List windows of specific app
await use_mcp_tool("peekaboo", "list", {
item_type: "application_windows",
app: "Preview"
});
// List windows by Process ID
await use_mcp_tool("peekaboo", "list", {
item_type: "application_windows",
app: "PID:663"
});
// Check server status
await use_mcp_tool("peekaboo", "list", {
item_type: "server_status"
});
analyze
- AI Vision AnalysisAnalyzes existing images using configured AI models.
Examples:
// Analyze with auto-selected provider
await use_mcp_tool("peekaboo", "analyze", {
image_path: "~/Desktop/screenshot.png",
question: "What applications are visible?"
});
// Force specific provider
await use_mcp_tool("peekaboo", "analyze", {
image_path: "~/Desktop/diagram.jpg",
question: "Explain this diagram",
provider_config: {
type: "ollama",
model: "llava:13b"
}
});
Peekaboo includes comprehensive test suites for both TypeScript and Swift components:
# Run all tests (requires macOS and Swift binary for integration tests)
npm test
# Run only unit tests (works on any platform)
npm run test:unit
# Run TypeScript-only tests (skips Swift-dependent tests, works on Linux)
npm run test:typescript
# Watch mode for TypeScript-only tests
npm run test:typescript:watch
# Run with coverage
npm run test:coverage
# Run Swift CLI tests (macOS only)
npm run test:swift
# Run full integration tests (TypeScript + Swift)
npm run test:integration
SKIP_SWIFT_TESTS=true
: Force skip Swift-dependent testsCI=true
: Automatically skips Swift-dependent testsHaunting | Exorcism |
---|---|
Permission denied errors during image capture | Grant Screen Recording permission in System Settings ā Privacy & Security. Ensure the correct application (Terminal, Claude, VS Code, etc.) is added and checked. Restart the app after changing permissions. |
Window capture issues (wrong window, focus problems) | Grant Accessibility permission if using capture_focus: "foreground" or for more reliable window targeting. |
Swift CLI unavailable or PEEKABOO_CLI_PATH issues | Ensure the peekaboo binary is at the root of the NPM package, or if PEEKABOO_CLI_PATH is set, verify it points to a valid executable. You can test the Swift CLI directly: path/to/peekaboo --version . If missing or broken, rebuild: cd peekaboo-cli && swift build -c release (then place binary appropriately or update PEEKABOO_CLI_PATH ). |
AI analysis failed | Check your PEEKABOO_AI_PROVIDERS environment variable for correct format and valid provider/model pairs. Ensure API keys (e.g., OPENAI_API_KEY ) are set if using cloud providers. Verify local services like Ollama are running (PEEKABOO_OLLAMA_BASE_URL ). Check the server logs (PEEKABOO_LOG_FILE or console if PEEKABOO_CONSOLE_LOGGING="true" ) for detailed error messages from the AI provider. |
Command not found: peekaboo-mcp | If installed globally, ensure your system's PATH includes the global npm binaries directory. If running from a local clone, use node dist/index.js or a configured npm script. For npx , ensure the package name @steipete/peekaboo-mcp is correct. |
General weirdness or unexpected behavior | Check the Peekaboo MCP server logs! The default location is ~/Library/Logs/peekaboo-mcp.log (or what you set in PEEKABOO_LOG_FILE ). Set PEEKABOO_LOG_LEVEL=debug for maximum detail. |
# Enable debug logging
OPENAI_API_KEY="your-key" PEEKABOO_AI_PROVIDERS="openai/gpt-4o" PEEKABOO_LOG_LEVEL=debug PEEKABOO_CONSOLE_LOGGING=true npx @steipete/peekaboo-mcp
# Check permissions
./peekaboo list server_status --json-output
# Clone the repository
git clone https://github.com/steipete/peekaboo.git
cd peekaboo
# Install dependencies
npm install
# Build TypeScript
npm run build
# Build Swift CLI
cd peekaboo-cli
swift build -c release
cp .build/release/peekaboo ../peekaboo
cd ..
# Optional: Install globally
npm link
For development, you can run Peekaboo locally:
{
"mcpServers": {
"peekaboo_local": {
"command": "peekaboo-mcp",
"args": [],
"env": {
"PEEKABOO_LOG_LEVEL": "debug",
"PEEKABOO_CONSOLE_LOGGING": "true"
}
}
}
}
Alternatively, running directly with node
:
{
"mcpServers": {
"peekaboo_local_node": {
"command": "node",
"args": [
"/Users/steipete/Projects/Peekaboo/dist/index.js"
],
"env": {
"PEEKABOO_LOG_LEVEL": "debug",
"PEEKABOO_CONSOLE_LOGGING": "true"
}
}
}
}
Remember to use absolute paths and unique server names to avoid conflicts with the npm version.
For simple screenshot capture without MCP integration:
osascript peekaboo.scpt
Note: This legacy version doesn't include AI analysis or MCP features.
For MCP clients other than Claude Desktop:
{
"server": {
"command": "node",
"args": ["/path/to/peekaboo/dist/index.js"],
"env": {
"PEEKABOO_AI_PROVIDERS": "openai/gpt-4o,ollama/llava",
"OPENAI_API_KEY": "your-openai-api-key-here"
}
}
}
image
- Screenshot CaptureCaptures macOS screen content and optionally analyzes it. Window shadows/frames are automatically excluded.
Parameters:
app_target
(string, optional): Specifies the capture target. If omitted or empty, captures all screens.
"screen:INDEX"
: Captures the screen at the specified zero-based index (e.g., "screen:0"
). (Note: Index selection from multiple screens is planned for full support in the Swift CLI)."frontmost"
: Captures the frontmost window of the currently active application."AppName"
: Captures all windows of the application named AppName
(e.g., "Safari"
, "com.apple.Safari"
). Fuzzy matching is used."PID:ProcessID"
: Captures all windows of the application with the specified process ID (e.g., "PID:663"
). Useful when multiple instances of the same app are running."AppName:WINDOW_TITLE:Title"
: Captures the window of AppName
that has the specified Title
(e.g., "Notes:WINDOW_TITLE:My Important Note"
)."AppName:WINDOW_INDEX:Index"
: Captures the window of AppName
at the specified zero-based Index
(e.g., "Preview:WINDOW_INDEX:0"
for the frontmost window of Preview).path
(string, optional): Base absolute path for saving the captured image(s). If format
is "data"
and path
is also provided, the image is saved to this path (as a PNG) AND Base64 data is returned. If a question
is provided and path
is omitted, a temporary path is used for capture, and the file is deleted after analysis.question
(string, optional): If provided, the captured image will be analyzed. The server automatically selects an AI provider from those configured in the PEEKABOO_AI_PROVIDERS
environment variable.format
(string, optional, default: "png"
): Specifies the output image format or data return type.
"png"
or "jpg"
: Saves the image to the specified path
in the chosen format. For application captures: if path
is not provided, behaves like "data"
. For screen captures: always saves to file."data"
: Returns Base64 encoded PNG data of the image directly in the MCP response. If path
is also specified, a PNG file is also saved to that path
. Note: Screen captures cannot use this format and will automatically fall back to PNG file format."png"
.capture_focus
(string, optional, default: "background"
): Controls window focus behavior during capture.
"background"
: Captures without altering the current window focus (default)."foreground"
: Attempts to bring the target application/window to the foreground before capture. This might be necessary for certain applications or to ensure a specific window is captured if multiple are open.Behavior with question
(AI Analysis):
question
is provided, the tool will capture the image (saving it to path
if specified, or a temporary path otherwise).PEEKABOO_AI_PROVIDERS
environment variable (trying them in order until one succeeds).analysis_text
in the response. Image data (Base64) is NOT returned in the content
array when a question is asked.Output Structure (Simplified):
content
: Can contain ImageContentItem
(if format: "data"
or path
was omitted, and no question
) and/or TextContentItem
(for summaries, analysis text, warnings).saved_files
: Array of objects, each detailing a file saved to path
(if path
was provided).analysis_text
: Text from AI (if question
was asked).model_used
: AI model identifier (if question
was asked).For detailed parameter documentation, see docs/spec.md.
PID:XXX
syntaxPeekaboo/
āāā src/ # Node.js MCP Server (TypeScript)
ā āāā index.ts # Main MCP server entry point
ā āāā tools/ # Individual tool implementations
ā ā āāā image.ts # Screen capture tool
ā ā āāā analyze.ts # AI analysis tool
ā ā āāā list.ts # Application/window listing
ā āāā utils/ # Utility modules
ā ā āāā peekaboo-cli.ts # Swift CLI integration
ā ā āāā ai-providers.ts # AI provider management
ā ā āāā server-status.ts # Server status utilities
ā āāā types/ # Shared type definitions
āāā peekaboo-cli/ # Native Swift CLI
ā āāā Sources/peekaboo/ # Swift source files
ā āāā main.swift # CLI entry point
ā āāā ImageCommand.swift # Image capture implementation
ā āāā ListCommand.swift # Application listing
ā āāā Models.swift # Data structures
ā āāā ApplicationFinder.swift # App discovery logic
ā āāā WindowManager.swift # Window management
ā āāā PermissionsChecker.swift # macOS permissions
ā āāā JSONOutput.swift # JSON response formatting
āāā package.json # Node.js dependencies
āāā tsconfig.json # TypeScript configuration
āāā README.md # This file
The Swift CLI outputs structured JSON when called with --json-output
:
{
"success": true,
"data": {
"applications": [
{
"app_name": "Safari",
"bundle_id": "com.apple.Safari",
"pid": 1234,
"is_active": true,
"window_count": 2
}
]
},
"debug_logs": ["Found 50 applications"]
}
The Node.js server provides:
Peekaboo respects macOS security:
# Test Swift CLI directly
./peekaboo list apps --json-output | head -20
# Test MCP server
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | node dist/index.js
# Build TypeScript
npm run build
# Build Swift CLI
cd peekaboo-cli && swift build
PEEKABOO_AI_PROVIDERS
environment variable for analysis featuresMIT License - see LICENSE file for details.
git checkout -b feature/amazing-feature
)git commit -m 'Add amazing feature'
)git push origin feature/amazing-feature
)Created by Peter Steinberger - @steipete
Read more about Peekaboo's design and implementation in the blog post.
Dynamic and reflective problem-solving through thought sequences
Time and timezone conversion capabilities
The only platform you need to get paid - all payments in one place, invoicing and accounting reconciliations with Adfin.
Marketing insights and audience analysis from Audiense reports, covering demographic, cultural, influencer, and content engagement analysis.
MCP server for the Computer-Use Agent (CUA), allowing you to run CUA through Claude Desktop or other MCP clients.
Generate high-quality text-to-speech and text-to-voice outputs using the DAISYS platform.
Interact with task, doc, and project data in Dart, an AI-native project management tool
Contract and template management for drafting, reviewing, and sending binding contracts.
Perform queries and entity operations in your Fibery workspace.
Human-in-the-loop platform - Allow AI agents and automations to send requests for approval to your gotoHuman inbox.