ghost-mcp
Health Warn
- License — License: NOASSERTION
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Pass
- Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
The Ghost in the Machine - An MCP (Model Context Protocol) server that exposes OS-level UI automation capabilities to AI clients.
Ghost MCP Server
The Ghost in the Machine - An MCP (Model Context Protocol) server that exposes OS-level UI automation capabilities to AI clients.
License: Free for personal and hobby use (PolyForm Noncommercial). Commercial use requires a license — contact Peter Isberg.
Overview
Ghost MCP allows AI assistants like Claude to control your computer's mouse, keyboard, and screen. This enables automation of legacy applications, GUI testing, and any task that requires interacting with applications that don't have APIs.
Features
- 🖱️ Mouse Control: Move cursor, click, double-click, scroll
- ⌨️ Keyboard Control: Type text, press individual keys
- 📸 Screen Capture: Take screenshots with optional region selection
- 🔍 OCR: Find screen text and UI elements with Tesseract (always built in)
- 🔐 Token Authentication: Requires a secret token before the server will start
- 📋 Audit Logging: Tamper-evident JSON Lines log of every tool call, auth failure, and lifecycle event
- 🛡️ Failsafe: Emergency shutdown by moving mouse to top-left corner (0,0)
- 📝 Structured Storytelling Logging: Narrative-driven audit of agent actions written to stderr and a configurable log file.
- 🌐 Dual Transport: stdio (default) or HTTP/SSE for web-based clients
Available Tools
AI routing guide: Before automating a UI, read
docs/routing_prompt.mdfor critical safety rules, decision tables, optimal tool sequences, and when to use learning mode. The server also delivers this guide automatically to AI clients via theghost_mcp_guideMCP prompt on connect.
| Tool | Description | Parameters | OCR |
|---|---|---|---|
get_screen_size |
Get screen resolution and DPI scale factor. | None | — |
move_mouse |
Move mouse cursor to absolute coordinates or Visual ID. | x, y, id |
— |
click |
Click mouse at current cursor position. Use move_mouse first. |
button (left/right/middle) |
— |
click_at |
Move mouse to coordinates or Visual ID and click in one operation. | x, y, id, button |
— |
double_click |
Move mouse to coordinates or Visual ID and double-click. | x, y, id |
— |
scroll |
Move mouse to (x, y) and scroll. 🚫 NO-PEEK RULE: Do not use for peeking after learn_screen. |
x, y, direction, amount |
— |
type_text |
Type text via keyboard into focused element. | text, press_enter |
— |
click_and_type |
Move mouse to coordinates or Visual ID, click, and type. | x, y, id, text, button, delay_ms, press_enter |
— |
press_key |
Press a single key or shortcut (e.g. Enter, Tab, Ctrl+C). | key |
— |
take_screenshot |
Capture raw screenshot. Visual-only tasks. 🚫 NOT FOR UI ANALYSIS. Use get_annotated_view for IDs. |
x, y, width, height, quality |
— |
scroll_until_text |
Scroll in one bounded call until OCR finds the target text or max_scrolls is reached. |
text, direction, amount, max_scrolls, scroll_x, scroll_y, x, y, width, height, nth, grayscale, element_type |
✓ |
find_elements |
Read all visible text elements with coordinates and types. Fast alternative to screenshots for understanding screen content. | x, y, width, height, element_type |
✓ |
find_and_click |
Find text on screen and click its center. Smart matching, auto-cached regions (10–25× faster on repeat), loop protection (max 25 calls/session). | text, button, nth, x, y, width, height, element_type, scroll_direction, max_scrolls, next_page_keys, max_pages, select_best |
✓ |
find_click_and_type |
Find a label or placeholder, click the associated input field, and type immediately. | text, type_text, x_offset, y_offset, press_enter, delay_ms, scroll_direction, scroll_amount, max_scrolls, scroll_x, scroll_y, element_type |
✓ |
find_and_click_all |
Click multiple distinct elements atomically in one call. Use for checking several checkboxes or clicking a sequence of known buttons — not for trying alternative labels. | texts (array), button, delay_ms, element_type |
✓ |
wait_for_text |
Wait for text to appear or disappear. Always use this after actions that trigger a UI change instead of fixed delays. | text, visible, timeout_ms, x, y, width, height, element_type |
✓ |
click_until_text_appears |
Click coordinates and retry until confirmation text appears or max_clicks is reached. Prevents infinite click loops. |
x, y, wait_for_text, button, timeout_ms, max_clicks |
✓ |
execute_workflow |
Execute multiple sequential steps sharing one learned screen map. 3–6× faster than individual calls when all steps are on the same screen. | steps (array), clear_view_after |
✓ |
learn_screen |
Scan UI: Index full interface (all scroll pages) and cache element map. Default max_pages: 3. | x, y, width, height, max_pages, scroll_amount |
✓ |
get_learned_view |
Map Text/IDs: Return machine-readable inventory of all elements (on and off-screen). | None | — |
get_annotated_view |
Verify IDs: Return screenshot with [ID] visual_id overlays. ONLY source for interactive IDs. | page_index, x, y, width, height |
✓ |
clear_learned_view |
Discard the current learned view. Call after navigation or significant UI changes to prevent stale positions. | None | — |
set_learning_mode |
Enable or disable learning mode at runtime. When enabled, the first OCR call auto-scans the screen. | enabled |
— |
smart_click |
Convenience wrapper: runs learn_screen then find_and_click in one call. Use for a single click on an unfamiliar screen; use learn_screen explicitly for multi-step sessions. |
text, button, nth |
✓ |
get_region_cache_stats |
Return cache statistics (hits, misses, hit rate). Use to monitor region cache effectiveness. | None | — |
clear_region_cache |
Clear all cached regions. Use after screen resolution changes or UI layout rearrangement. | None | — |
Tesseract required: tools marked ✓ in the OCR column require Tesseract to be installed and
TESSDATA_PREFIXset. The installation scripts handle this automatically. See Prerequisites.
🛡️ Safety Features & Loop Protection
Ghost MCP includes built-in safeguards to prevent infinite retry loops and runaway automation:
Global Call Limit (25 calls/session)
WARNING: Only 5 tool calls remaining before forced stop.
MAXIMUM TOOL CALLS REACHED (25). Stop and try a completely different approach.
Consecutive Failure Detection (3 strikes)
GIVE UP RECOMMENDATION: Failed 3 times with "Submit". STOP trying this text.
Try: (1) find_elements to see actual text, (2) shorter search term,
(3) scroll_direction if off-screen, or (4) completely different approach.
Repeated Click Detection (5 clicks at same spot)
{
"success": true,
"warning": {
"should_stop": true,
"reason": "Clicked same coordinates (403,767) 5 times in 30 seconds",
"click_count": 5,
"message": "You've clicked this spot 5 times. Verify this is correct before continuing."
}
}
Enhanced Error Responses
Every error now includes:
consecutive_failures: How many times this search failedremaining_calls: Calls left before forced stopsuggestion: Actionable next step (scroll_may_help,no_matches_found, etc.)candidates: All OCR-detected text with confidence scores
Response Example on Failure
{
"error": "text \"Submit\" not found...",
"candidates": [
{"text": "Submit", "score": 100, "x": 50, "y": 50}
],
"suggestion": "scroll_may_help",
"consecutive_failures": 2,
"remaining_calls": 18
}
🎯 Smart OCR Matching
Ghost MCP uses an intelligent scoring system to find the best match for your text:
How it works:
Instead of simple substring matching, every OCR-detected word is scored:
| Score | Match Type | Example |
|---|---|---|
| 1000 | Exact match | Searching "Click Me!" finds "Click Me!" |
| 500 | Prefix match | Searching "Click" finds "Click Me!" |
| 400 | Suffix match | Searching "Click" finds "Button Click" |
| 300 | Standalone word | Searching "Click" finds "Button Click" (separate word) |
| 200 | Multi-word (all found) | Searching "Save Changes" finds both words |
| 100 | Substring with boundaries | Weaker match |
| 50 | Inside another word | Lowest priority (avoided) |
Why it matters:
❌ OLD BEHAVIOR: Search "Click" → clicks "Button Click Tests" header
✅ NEW BEHAVIOR: Search "Click" → clicks standalone "Click Me!" button
The system:
- Scores all matches using the table above
- Sorts by score (best first), then by area (smaller = more precise)
- Returns the best match for your click
Production-ready: Handles real-world UI with headers, labels, and buttons that share common text.
⚡ Performance Optimization: Region Cache
Ghost MCP automatically optimizes repeated UI interactions using region caching:
How it works:
- When
find_and_clicksuccessfully finds a button, it caches the screen region - Subsequent calls with the same text scan only the cached region (not the full screen)
- Cache entries include screen resolution — automatically invalidated if resolution changes
- LRU eviction keeps the 100 most recently used entries
Performance impact:
- First call: Full screen OCR scan (~1920×1080)
- Cached calls: Small region scan (~100×50) — 10-25x faster
Monitoring cache:
// Check cache statistics
{
"tool": "get_region_cache_stats"
}
// Response: {"entries":5,"hits":12,"misses":3,"hit_rate":80.0,"evictions":0}
When to clear cache:
- Screen resolution changed
- UI layout was significantly rearranged
- Cache returning stale results
// Clear all cached regions
{
"tool": "clear_region_cache"
}
// Response: {"success":true,"message":"Region cache cleared"}
Cache behavior:
- Case-insensitive: "Save", "SAVE", "save" use the same entry
- Auto-invalidates on screen resolution change
- 24-hour expiration for stale entries
- Thread-safe with RWMutex protection
🎯 Element Type Filtering
Ghost MCP supports element type filtering to target specific UI component types in search operations. This allows you to narrow results to only the type of element you're looking for, improving accuracy and reducing false matches.
Supported element types:
| Type | Description | Example Use Case |
|---|---|---|
button |
Clickable action elements | "Submit", "Save", "Cancel" buttons |
input |
Text input fields | Form fields, search boxes |
checkbox |
Checkboxes (☐ ☑ ✓) | Agreement checkboxes, toggles |
radio |
Radio buttons (○ ● ◉) | Single-selection option groups |
dropdown |
Dropdown menus (▼) | Select menus, comboboxes |
toggle |
Toggle switches (ON/OFF) | Settings toggles, switches |
slider |
Sliders/range controls | Volume sliders, range inputs |
label |
Field labels (usually ending with ":") | "Email:", "Name:" labels |
heading |
Section/page headings | Page titles, section headers |
link |
Hyperlinks | Navigation links, anchor text |
value |
Numeric or status values | Prices, scores, counters |
text |
General body text | Paragraphs, descriptions |
Usage examples:
// Find only buttons, ignoring labels and headings that contain the same text
{
"tool": "find_and_click",
"arguments": {
"text": "Save",
"element_type": "button"
}
}
// Get all input fields on a form
{
"tool": "find_elements",
"arguments": {
"element_type": "input"
}
}
// Wait for a specific label to appear
{
"tool": "wait_for_text",
"arguments": {
"text": "Success:",
"element_type": "label"
}
}
// Find and type into an input field
{
"tool": "find_click_and_type",
"arguments": {
"text": "Email:",
"type_text": "[email protected]",
"element_type": "input"
}
}
How it works:
- Element types are inferred from text patterns, dimensions, and context
- Filtering happens during OCR processing — only matching elements are returned
- Works with all search features: scrolling, multi-page, and caching
- If no element of the specified type is found, returns "not found" error
When to use:
- Multiple elements share the same text but have different types (e.g., "Submit" as both a button and a label)
- You want to target only specific UI components
- You need to discover all form fields, buttons, or other specific element types
Prerequisites
The installation scripts (install.ps1 for Windows, install.sh for Linux) automatically install all required dependencies.
If building manually, you'll need:
- Go 1.24+ - Download Go
- C Compiler - For RobotGo (GUI automation library)
- Tesseract OCR + Leptonica - Required for OCR tools (
find_elements,find_and_click); always built in
Platform-Specific Dependencies
Windows
Required: MinGW-w64 GCC Compiler
Install via Chocolatey (recommended):
# Run as Administrator
choco install mingw -y
Tesseract OCR is required (always built in). Install via vcpkg (the install script does this automatically):
# Install vcpkg and Tesseract (MinGW-compatible triplet)
git clone https://github.com/Microsoft/vcpkg.git $env:USERPROFILE\vcpkg
cd $env:USERPROFILE\vcpkg
.\bootstrap-vcpkg.bat -disableMetrics
$env:CC = "C:\ProgramData\mingw64\mingw64\bin\gcc.exe"
$env:CXX = "C:\ProgramData\mingw64\mingw64\bin\g++.exe"
.\vcpkg install tesseract:x64-mingw-dynamic leptonica:x64-mingw-dynamic
# Download English language data for Tesseract
$tessdata = "$env:USERPROFILE\vcpkg\installed\x64-mingw-dynamic\share\tessdata"
Invoke-WebRequest "https://github.com/tesseract-ocr/tessdata_fast/raw/main/eng.traineddata" -OutFile "$tessdata\eng.traineddata"
# Set required environment variables (persist across reboots)
[System.Environment]::SetEnvironmentVariable("TESSDATA_PREFIX", "$env:USERPROFILE\vcpkg\installed\x64-mingw-dynamic\share\tessdata", "User")
[System.Environment]::SetEnvironmentVariable("CGO_CPPFLAGS", "-I$env:USERPROFILE/vcpkg/installed/x64-mingw-dynamic/include", "User")
[System.Environment]::SetEnvironmentVariable("CGO_LDFLAGS", "-L$env:USERPROFILE/vcpkg/installed/x64-mingw-dynamic/lib", "User")
macOS
# Install Xcode Command Line Tools
xcode-select --install
# Tesseract OCR (required)
brew install tesseract leptonica
# Grant accessibility permissions (required for automation)
# System Settings → Privacy & Security → Accessibility → Add Terminal/your IDE
Linux
Ubuntu/Debian:
# X11 automation libraries
sudo apt-get install libx11-dev xorg-dev libxtst-dev libpng-dev
# Tesseract OCR (required)
sudo apt-get install tesseract-ocr libleptonica-dev libtesseract-dev
Fedora:
sudo dnf install libX11-devel libXtst-devel libpng-devel
sudo dnf install tesseract tesseract-devel leptonica-devel
Arch Linux:
sudo pacman -S libx11 libxtst libpng
sudo pacman -S tesseract tesseract-data-eng
Installation
Quick Install (Recommended)
We provide automated installation scripts that handle all dependencies and configuration:
Windows
# Run PowerShell as Administrator
.\install.ps1
The installer will:
- Install MinGW (GCC compiler) via Chocolatey
- Install Tesseract OCR via vcpkg (x64-mingw-dynamic triplet)
- Download English language data (
eng.traineddata) and setTESSDATA_PREFIX - Build the binary and copy runtime DLLs
- Generate auth token
- Configure environment variables
- Display MCP client configuration
Linux
chmod +x install.sh
./install.sh
The installer will:
- Detect your package manager (apt/dnf/yum/pacman/zypper)
- Install GCC, X11 development libraries, and Tesseract OCR
- Build the binary
- Generate auth token
- Save environment configuration to
~/.config/ghost-mcp/env - Display MCP client configuration
OCR Support
OCR (find_elements, find_and_click) is always built in. The installer sets up Tesseract automatically, including downloading the English language data file and setting TESSDATA_PREFIX.
Manual Build
If you prefer to build manually:
# Clone or navigate to the project directory
cd ghost-mcp
# Download dependencies
go mod download
# Build (Windows — requires MinGW and Tesseract via vcpkg, see Prerequisites)
go build -o ghost-mcp.exe ./cmd/ghost-mcp/
# Build (macOS/Linux)
go build -o ghost-mcp ./cmd/ghost-mcp/
On Windows, set CGO_CPPFLAGS and CGO_LDFLAGS before building (see the Windows prerequisites section above). Also copy the runtime DLLs next to the binary:
Copy-Item "$env:USERPROFILE\vcpkg\installed\x64-mingw-dynamic\bin\*.dll" . -Force
Configuration
MCP Client Configuration (mcp.json)
Add this to your MCP client configuration to connect to Ghost MCP:
For Claude Desktop (Windows)
{
"mcpServers": {
"ghost-mcp": {
"command": "C:\\path\\to\\ghost-mcp.exe",
"args": [],
"env": {
"GHOST_MCP_TOKEN": "your-secret-token-here",
"TESSDATA_PREFIX": "C:\\Users\\<you>\\vcpkg\\installed\\x64-mingw-dynamic\\share\\tessdata"
}
}
}
}
For Claude Desktop (macOS/Linux)
{
"mcpServers": {
"ghost-mcp": {
"command": "/absolute/path/to/ghost-mcp",
"args": [],
"env": {
"GHOST_MCP_TOKEN": "your-secret-token-here",
"TESSDATA_PREFIX": "/usr/share/tesseract-ocr/5/tessdata"
}
}
}
}
Replace
your-secret-token-herewith the same value you generated forGHOST_MCP_TOKEN.
Configuration File Locations
| Platform | Config Location |
|---|---|
| Windows | %APPDATA%\Claude\mcp.json |
| macOS | ~/Library/Application Support/Claude/mcp.json |
| Linux | ~/.config/Claude/mcp.json |
Environment Variables
| Variable | Description | Default |
|---|---|---|
GHOST_MCP_TOKEN |
Required. Secret authentication token. Server refuses to start without it. | (none — must be set) |
TESSDATA_PREFIX |
Required for OCR. Directory that directly contains eng.traineddata (NOT its parent). |
(none — OCR will fail if unset) |
GHOST_MCP_OCR_FORMAT |
Injection format for sending screen buffers to OCR engine natively (bmp or png) |
bmp (lossless, uncompressed speed) |
GHOST_MCP_AUDIT_LOG |
Directory for audit log files. Created automatically if absent. | <UserConfigDir>/ghost-mcp/audit/ |
GHOST_MCP_LOG_FILE |
Path to the storyteller log file. | application.log |
GHOST_MCP_LOG_LEVEL |
Log verbosity (DEBUG, INFO, WARN, ERROR). |
INFO |
GHOST_MCP_VISUAL |
Show visual cursor pulse on mouse actions (1 = on) |
0 (disabled) |
GHOST_MCP_KEEP_SCREENSHOTS |
Keep screenshot files on disk after use (1 = keep, default deletes them) |
0 (deleted after use) |
GHOST_MCP_SCREENSHOT_DIR |
Directory where screenshot files are written | System temp directory |
GHOST_MCP_TRANSPORT |
Transport mode: stdio or http |
stdio |
GHOST_MCP_HTTP_ADDR |
Listen address for HTTP/SSE mode | localhost:8080 |
GHOST_MCP_HTTP_BASE_URL |
Public base URL advertised to SSE clients | http://<addr> |
GHOST_MCP_LEARNING |
Learning mode (0 = off, 1 = on). When on, the first OCR call auto-scans the screen and all subsequent calls use the cached element map (10–25× faster). |
1 (on by default; set 0 to disable) |
Security note:
GHOST_MCP_TOKENmust be set to a random secret. Generate one with:# Linux/macOS export GHOST_MCP_TOKEN=$(openssl rand -hex 32) # Windows (PowerShell) $env:GHOST_MCP_TOKEN = -join ((1..32) | % { '{0:x}' -f (Get-Random -Max 256) })Then add it to the
envblock of your MCP client configuration (see examples below).
Usage
Starting the Server
The server runs via stdio and is typically started by your MCP client automatically. To test manually:
# Run the server (will wait for stdin/stdout communication)
./ghost-mcp
# With debug logging
GHOST_MCP_LOG_LEVEL=DEBUG ./ghost-mcp
Example Tool Calls
Once connected, AI clients can use the tools like this:
// Find text on screen and click it — start here for any click task
{
"tool": "find_and_click",
"arguments": {"text": "Save"}
}
// Response: {"success": true, "found": "Save", "x": 960, "y": 540, "button": "left", "occurrence": 1}
// If not found, the error includes closest OCR matches and the searched region.
// Move and click in one call
{
"tool": "click_at",
"arguments": {"x": 960, "y": 540, "button": "left"}
}
// Response: {"success": true, "button": "left", "x": 960, "y": 540}
// Double-click to open a file
{
"tool": "double_click",
"arguments": {"x": 960, "y": 540}
}
// Response: {"success": true, "x": 960, "y": 540}
// Scroll down in a list
{
"tool": "scroll",
"arguments": {"x": 960, "y": 540, "direction": "down", "amount": 5}
}
// Response: {"success": true, "x": 960, "y": 540, "direction": "down", "amount": 5}
// Type text into the focused field
{
"tool": "type_text",
"arguments": {"text": "Hello, World!"}
}
// Response: {"success": true, "characters_typed": 13}
// Press Enter key
{
"tool": "press_key",
"arguments": {"key": "enter"}
}
// Response: {"success": true, "key": "enter"}
// Take screenshot — returns JSON metadata + PNG image content
{
"tool": "take_screenshot"
}
// Response: {"success": true, "filepath": "/tmp/ghost-mcp-screenshot-....png", "width": 1920, "height": 1080}
// (image data returned as a separate image/png content block)
// Find all text elements on screen
{
"tool": "find_elements"
}
// Response: {"success": true, "elements": [{"text": "Save", "x": 940, "y": 530, "width": 40, "height": 20, "center_x": 960, "center_y": 540, "confidence": 98.5}, ...]}
Security
🔐 Token Authentication
Ghost MCP controls your mouse, keyboard, and screen — so it requires authentication before it will serve any requests.
How it works:
- Set
GHOST_MCP_TOKENto a random secret string in your shell and in your MCP client'senvconfig block. - The server reads the token at startup and refuses to start if it is not set.
- Every MCP request is validated against the startup token via a server hook. If the environment variable is cleared or altered after startup, all subsequent requests are rejected.
What this protects against:
- Running the server without prior configuration (no token → no service)
- Unauthorized processes that can execute the binary but don't know the token value
Generating a token:
# Linux/macOS
openssl rand -hex 32
# Windows (PowerShell)
-join ((1..32) | % { '{0:x}' -f (Get-Random -Max 256) })
Use the output as the value for GHOST_MCP_TOKEN in both your shell environment and your MCP client's env block.
📋 Audit Logging
Ghost MCP writes a tamper-evident audit trail for every event: tool invocations, authentication failures, client connections, and server lifecycle events.
Log format: JSON Lines (one JSON object per line), one file per UTC day.
Default location:
| Platform | Default path |
|---|---|
| Windows | %AppData%\ghost-mcp\audit\ghost-mcp-audit-YYYY-MM-DD.jsonl |
| macOS | ~/Library/Application Support/ghost-mcp/audit/ghost-mcp-audit-YYYY-MM-DD.jsonl |
| Linux | ~/.config/ghost-mcp/audit/ghost-mcp-audit-YYYY-MM-DD.jsonl |
Override with GHOST_MCP_AUDIT_LOG=/your/dir.
Example log entries:
// Server startup
{"seq":1,"timestamp":"2025-01-15T09:00:00.123Z","event":"SERVER_START","params":{"platform":"linux/amd64","version":"1.0.0"},"prev_hash":"0000...","hash":"a3f2..."}
// Client connected (from MCP initialize handshake)
{"seq":2,"timestamp":"2025-01-15T09:00:01.456Z","event":"CLIENT_CONNECTED","client_id":"claude-desktop","params":{"client_name":"claude-desktop","client_version":"1.0"},"prev_hash":"a3f2...","hash":"b7c1..."}
// Tool invocation with parameters
{"seq":3,"timestamp":"2025-01-15T09:00:05.789Z","event":"TOOL_CALL","tool":"type_text","client_id":"claude-desktop","params":{"text":"Hello world"},"prev_hash":"b7c1...","hash":"c9d4..."}
// Screenshot audit trail
{"seq":4,"timestamp":"2025-01-15T09:00:06.012Z","event":"SCREENSHOT_REQUESTED","tool":"take_screenshot","client_id":"claude-desktop","prev_hash":"c9d4...","hash":"d2e5..."}
// Authentication failure
{"seq":5,"timestamp":"2025-01-15T09:00:10.345Z","event":"AUTH_FAILURE","error":"invalid or missing GHOST_MCP_TOKEN","prev_hash":"d2e5...","hash":"e8f3..."}
Tamper detection: Each entry carries:
hash— SHA-256 of the entry's own contentprev_hash— hash of the previous entry (hash chain)
If any entry is modified, deleted, or reordered, the chain breaks. Verify a log file with:
# Verify integrity of a specific log file
# (built-in to the ghost-mcp source — see VerifyLogFile in audit.go)
go run . verify-log /path/to/ghost-mcp-audit-2025-01-15.jsonl
Logged events:
| Event | Trigger |
|---|---|
SERVER_START |
Server starts |
SERVER_STOP |
Server shuts down |
CLIENT_CONNECTED |
MCP initialize handshake completes |
TOOL_CALL |
Tool invoked (includes sanitized parameters) |
TOOL_SUCCESS |
Tool completed successfully |
TOOL_FAILURE |
Tool returned an error result |
SCREENSHOT_REQUESTED |
take_screenshot tool succeeded |
AUTH_FAILURE |
Request rejected due to missing/invalid token |
REQUEST_ERROR |
MCP-level error (unknown tool, malformed request) |
HTTP/SSE Transport
By default Ghost MCP communicates over stdio, which is the standard MCP transport used by Claude Desktop. Set GHOST_MCP_TRANSPORT=http to start an HTTP/SSE server instead.
Configuration
{
"mcpServers": {
"ghost-mcp": {
"command": "C:\\path\\to\\ghost-mcp.exe",
"env": {
"GHOST_MCP_TOKEN": "your-secret-token-here",
"GHOST_MCP_TRANSPORT": "http",
"GHOST_MCP_HTTP_ADDR": "localhost:8080",
"GHOST_MCP_HTTP_BASE_URL": "http://localhost:8080"
}
}
}
}
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/sse |
GET | Open SSE stream (MCP connection) |
/message |
POST | Send MCP messages |
Authentication
HTTP mode uses the same GHOST_MCP_TOKEN as Bearer authentication. Every request must include:
Authorization: Bearer <your-token>
Requests without a valid Bearer token are rejected with HTTP 401 and logged as AUTH_FAILURE events in the audit log.
Example with curl
# Open SSE stream (keep this running in a terminal)
curl -N -H "Authorization: Bearer $GHOST_MCP_TOKEN" http://localhost:8080/sse
# Send an MCP initialize message
curl -X POST \
-H "Authorization: Bearer $GHOST_MCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","clientInfo":{"name":"test","version":"1.0"},"capabilities":{}}}' \
"http://localhost:8080/message?sessionId=<session-id-from-sse>"
Safety Features
🛡️ Failsafe Mechanism
Ghost MCP includes an emergency shutdown feature:
- Trigger: Move your mouse to the absolute top-left corner of the screen (coordinates 0,0)
- Effect: The server will log an error and initiate graceful shutdown
- Purpose: Prevents runaway AI automation loops from causing damage
⚠️ WARNING: Do not move your mouse to (0,0) during normal operation!
📝 Structured Storytelling Logging
Ghost MCP implement a unique "storytelling" approach to logging. Instead of dry technical errors, INFO logs narrate the agent's intent, progress, and outcomes in a narrative style.
How it works:
- All logs are written to stderr (as required by the MCP protocol to keep stdout clean).
- All logs are simultaneously written to a narrative log file (default:
application.log).
Check the log file for a blow-by-blow account of the agent's "journey":
time=2024-04-06T19:26:26 level=INFO msg="Agent is searching for 'Submit' button"
time=2024-04-06T19:26:27 level=INFO msg="Success: Found 'Submit' at (450, 720)"
time=2024-04-06T19:26:27 level=INFO msg="ACTION COMPLETE: find_and_click 'Submit' at (450, 720)"
Troubleshooting
Common Issues
"Permission Denied" or "Access Denied"
- macOS: Grant accessibility permissions in System Settings
- Linux: Ensure you have X11 permissions (
xhost +for testing) - Windows: Run as Administrator if needed
"RobotGo initialization failed"
- Verify platform-specific dependencies are installed (see Prerequisites)
- Check that no other application is blocking accessibility APIs
MCP Client Can't Connect
- Verify the binary path in mcp.json is correct
- Ensure the binary is executable (
chmod +x ghost-mcpon Unix) - Check that no firewall is blocking stdio communication
Screenshots Fail
- Ensure sufficient disk space in temp directory
- Verify write permissions to system temp folder
OCR Fails / find_elements Returns Error
TESSDATA_PREFIXmust point to the directory that directly containseng.traineddata(not its parent)- On Windows with vcpkg:
TESSDATA_PREFIX=%USERPROFILE%\vcpkg\installed\x64-mingw-dynamic\share\tessdata - On Linux:
TESSDATA_PREFIX=/usr/share/tesseract-ocr/5/tessdata(verify withfind /usr/share -name eng.traineddata) - Verify:
ls $TESSDATA_PREFIX\eng.traineddatashould find the file - Check the server startup log — it prints the value of
TESSDATA_PREFIXat start - Set
GHOST_MCP_KEEP_SCREENSHOTS=1to keep the image files OCR is processing for manual inspection
Debug Mode
Enable verbose logging for troubleshooting:
{
"mcpServers": {
"ghost-mcp": {
"command": "/path/to/ghost-mcp",
"env": {
"GHOST_MCP_LOG_LEVEL": "DEBUG"
}
}
}
}
Development
Running Tests
Ghost MCP includes comprehensive tests including a test fixture GUI for integration testing.
# Windows
test_runner.bat # Unit tests only
test_runner.bat integration # Integration tests (requires GCC)
test_runner.bat all # All tests
test_runner.bat fixture # Start fixture server
# macOS/Linux
chmod +x test_runner.sh
./test_runner.sh
./test_runner.sh integration
./test_runner.sh all
./test_runner.sh fixture
# Direct go test
go test -v -short ./... # Unit tests
set INTEGRATION=1 && go test -v ./... # Integration tests (Windows)
export INTEGRATION=1 && go test -v ./... # Integration tests (Unix)
For detailed testing documentation, see TESTING.md.
Building for Release
# Windows
GOOS=windows GOARCH=amd64 go build -o ghost-mcp.exe -ldflags="-s -w" ./cmd/ghost-mcp/
# macOS
GOOS=darwin GOARCH=amd64 go build -o ghost-mcp -ldflags="-s -w" ./cmd/ghost-mcp/
# Linux
GOOS=linux GOARCH=amd64 go build -o ghost-mcp -ldflags="-s -w" ./cmd/ghost-mcp/
Architecture
See ARCHITECTURE.md for detailed information about:
- Server structure and components
- MCP protocol implementation
- Tool handling flow
- Failsafe mechanism design
Documentation
| Document | Description |
|---|---|
| README.md | Getting started and usage |
| USAGE.md | Interactive examples and API reference |
| ARCHITECTURE.md | System design and internals |
| TESTING.md | Testing guide and fixture docs |
License
See LICENSE file for details.
Contributing
Contributions welcome! Please ensure:
- All tests pass (
go test ./...) - Code follows Go formatting (
go fmt ./...) - No linting errors (
go vet ./...) - Documentation is updated for new features
Acknowledgments
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found