da-mcp

da-mcp

Cross-platform desktop automation MCP server that lets AI agents capture screenshots, run OCR with UI-element classification, control mouse/keyboard, and launch programs on Linux, macOS, and Windows.

Category
访问服务器

README

da-mcp — Crossplatform Desktop Automation MCP Server

A Model Context Protocol (MCP) server that lets AI agents (OpenCode, Claude Desktop, etc.) interact with a local desktop environment: screenshots, OCR with UI-element classification, mouse/keyboard control, and program launch — on Linux, macOS, and Windows.

Features

12 tools registered under the da_* namespace:

Capture

  • da_screenshot — Capture full screen or a specific display as PNG.
  • da_ocr — Run OCR (Tesseract) on a screenshot and return structured text + UI element classification.
  • da_list_displays — List connected displays with id, bounds, scale factor.

Input

  • da_get_mouse_position — Read current cursor position (X11/Linux uses xdotool getmouselocation --shell, Wayland uses ydotool, macOS/Windows uses robotjs).
  • da_move_mouse — Move the cursor to (x, y).
  • da_click — Click at (x, y) with optional button (left/right/middle/back/forward) and count.
  • da_double_click — Convenience wrapper for double-click.
  • da_drag — Drag from (x1, y1) to (x2, y2).
  • da_scroll — Scroll wheel at (x, y) by (dx, dy).
  • da_type — Type a string at the current focus.
  • da_key — Press a single key or chord (e.g. Ctrl+C).

Launch

  • da_launch — Launch a program by name or path; returns a spawn handle with PID + POSIX signal exit codes (SIGINT=130, SIGTERM=143, SIGHUP=129, SIGKILL=137, SIGQUIT=131, SIGABRT=134).

UI element classification (OCR post-processing)

The da_ocr classifier tags each detected text region with one of:

Category Examples
button "OK", "Cancel", "Apply"
input Text fields, search boxes
label Static descriptive text
checkbox "☑ Enable", "☐ Dark mode"
radio "◉ Local", "○ Network"
menu Top-level menu headers ("File", "Edit")
menu-item Dropdown entries ("New", "Open…")
icon Toolbar / sidebar icons

Architecture

  • Language: TypeScript 7.0 (strict, ESM, Node 22+); exactOptionalPropertyTypes, noUncheckedIndexedAccess, noFallthroughCasesInSwitch all on. Exact version pins (no ^/~).
  • MCP SDK: v2 (@modelcontextprotocol/server@2.0.0) over StdioServerTransport (production) and InMemoryTransport (tests).
  • Module layout (250 LOC ceiling per file):
    • Screenshotsrc/screenshot/{png,backends,index,types}.ts. PNG validation/encoding isolated in png.ts; backend dispatch (node-screenshots → screenshot-desktop → Windows CLI) in backends.ts.
    • OCRsrc/ocr/{cli,index,mock,parse,wasm,types,classify,classify-rules}.ts. CLI backend (runCli), WASM fallback (runWasm), parser, mock; orchestrator in index.ts rethrows as OCR_FAILED when both backends fail.
    • Inputsrc/input/{routing,mouse,keyboard,scroll,drag,types,index}.ts. Shared routing helpers (runCli, resolveRouting, requireTool, loadRobotjs, isMockMode, validateCoords, Routing) in routing.ts; per-input-type operations in dedicated files.
    • Launchsrc/launch/{launch,types}.ts. open(1) + child_process.spawn (shell:false); SIGNAL_EXIT_CODES map for POSIX signal mapping.
    • Platformsrc/platform/{detect,types}.ts. detectPlatform() returns { os, display, tools, home }; assertPlatformSupported() throws PLATFORM_INIT_FAILED on unsupported combos.
    • Serversrc/server.ts. Registers 12 tools, wraps handler results into CallToolResult with structuredContent (Buffers stripped to number[] for JSON-safety), installs SIGINT/SIGTERM shutdown.

Backend dispatch

Capability Primary Fallback 1 Fallback 2
Screenshot (Linux X11) node-screenshots (XCap) screenshot-desktop
Screenshot (Linux Wayland) node-screenshots (XCap portal) screenshot-desktop
Screenshot (macOS) node-screenshots (CG) screencapture
Screenshot (Windows) node-screenshots (GDI) PowerShell BitBlt (windowsCliBackend, ships in backends.ts)
Input (Linux X11) xdotool CLI
Input (Linux Wayland) ydotool CLI wtype (keyboard only)
Input (macOS / Windows) robotjs (native)
OCR (any OS) tesseract CLI tesseract.js@7 WASM

Every spawnSync/spawn call uses shell:false. Permission-gated errors (e.g. macOS ScreenCaptureKit, Windows access denied) are detected via a tightened pattern (screen…permission, screencapturekit, access is denied) and re-thrown as DaMcpError('PERMISSION_DENIED').

Install

# System dependencies (apt/dnf/brew; see scripts/install-system-deps.sh)
sudo ./scripts/install-system-deps.sh

# npm deps
npm install

# Build
npm run build

# Verify type-check (strict mode)
npm run typecheck

# Run all tests (mock mode — skips real native calls)
DA_MCP_TEST_MODE=mock npm test

Run

stdio (default)

The server speaks MCP over stdio. Configure your MCP client to launch node /projects/da-mcp/dist/server.js (or npx tsx src/server.ts for dev).

HTTP (opt-in, token-protected)

Set DA_MCP_TRANSPORT=http to expose the server on http://127.0.0.1:3000/<token>. A 256-bit random token is generated on first start and persisted at:

OS Token path
Linux $XDG_CONFIG_HOME/da-mcp/token or ~/.config/da-mcp/token
macOS ~/Library/Application Support/da-mcp/token
Windows %APPDATA%\da-mcp\token

The token file is created with mode 0o600 (owner-only). Rotate it any time:

node /projects/da-mcp/dist/server.js token regenerate
# → http://127.0.0.1:3000/<43-char-base64url-token>

Override defaults with env vars:

  • DA_MCP_HTTP_HOST — bind address (default 127.0.0.1); supports IPv4, IPv6 ([::1]), and hostname
  • DA_MCP_PORT — port (default 3000)
  • DA_MCP_TOKEN_PATH — override token storage path

The URL is unauthenticated token (bearer-style): anyone with the token can call tools. Bind only to 127.0.0.1 (default) — do not expose this to a network without adding an upstream auth proxy.

OpenCode / Claude Desktop example config

{
  "mcpServers": {
    "da-mcp": {
      "command": "node",
      "args": ["/projects/da-mcp/dist/server.js"],
      "env": {
        "DISPLAY": ":0",
        "DA_MCP_LOG": "info"
      }
    }
  }
}

Cross-platform notes

OS Screenshot Input Notes
Linux X11 node-screenshots (X11 native) xdotool Requires libxtst-dev libpng-dev for robotjs build
Linux Wayland node-screenshots (XCap portal) ydotool (daemon) XWayland fallback if available
macOS node-screenshots (CG) robotjs (CGEvent) First call needs Screen Recording permission (TCC)
Windows node-screenshots (GDI) robotjs (SendInput) VS Build Tools required; PowerShell BitBlt fallback if GDI fails

Development

# Strict type-check (no emit)
npx tsc --noEmit

# All tests in mock mode (CI default)
DA_MCP_TEST_MODE=mock npx vitest run

# Single test file
npx vitest run test/unit/screenshot.test.ts

# Watch mode
npx vitest

Test inventory

  • 18 test files: 15 unit (test/unit/) + 3 e2e (test/e2e/)
  • 216 tests passing / 17 skipped in mock mode (e2e require real X11/tesseract)
  • Test runtime: process.env['DA_MCP_TEST_MODE'] === 'mock' short-circuits native calls; _mock.ts modules inject deterministic native modules

Conventions

  • 250 LOC ceiling per file (measured as non-blank, non-comment lines: awk '!/^[[:space:]]*$/ && !/^[[:space:]]*(\/\/|#|--)/' <file> | wc -l)
  • ESM imports use .js suffix even for .ts source
  • All spawn* calls with shell: false
  • All native errors wrapped in DaMcpError with typed code from ErrorCode union
  • Public surface re-exported from src/screenshot/index.ts and src/input/index.ts — consumers import from there, not from per-operation files
  • Forbidden: as any, @ts-ignore, @ts-expect-error, console.log, shell: true, auto-commits

Environment variables

  • DISPLAY — X11 display (Linux only)
  • WAYLAND_DISPLAY — Wayland display socket
  • DA_MCP_LOG — log level (trace|debug|info|warn|error), default info
  • DA_MCP_TESSERACT_BIN — path to tesseract binary, default tesseract
  • DA_MCP_OCR_BACKENDcli (default) or wasm
  • DA_MCP_TEST_MODEmock skips real native calls in tests; e2e tests skip when set
  • DA_MCP_SCREENSHOT_BACKEND — force a screenshot backend (node-screenshots | screenshot-desktop | windows-cli); default auto-detect
  • DA_MCP_TRANSPORTstdio (default) or http; http enables the opt-in HTTP transport
  • DA_MCP_PORT — HTTP port when DA_MCP_TRANSPORT=http (default 3000)
  • DA_MCP_HTTP_HOST — HTTP bind address (default 127.0.0.1); supports IPv4, IPv6, hostname
  • DA_MCP_TOKEN_PATH — override the auth token storage path

License

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选