DesktopBridge
Enables local macOS automation via the Model Context Protocol, allowing file operations, system monitoring, shell commands, clipboard access, and screenshots with configurable security restrictions.
README
DesktopBridge 🌉
Local Model Context Protocol server for macOS. Claude (or any MCP host) talks to it over stdio and can:
- Read, write, list, and search files inside allowlisted directories
- Read CPU / memory / disk stats, uptime, and a redacted environment
- List running applications
- Run shell commands with separate stdout/stderr, timeouts, and optional progress streaming
- Read and write the clipboard
- Capture screenshots and list displays
This process has the same OS rights as the user who launched it. Treat it like giving the model a terminal on your Mac, then shrink that blast radius with DESKTOP_BRIDGE_ROOTS.
Requirements
- macOS (clipboard, screenshots, and application listing use Apple tools)
- Node.js 20.19+ (22 LTS recommended)
Install
cd desktop-bridge
npm install
npm run build
npm test
The compiled entrypoint is dist/index.js.
Connect to Claude Desktop
- Build the server (
npm run build). - Open Claude Desktop → Settings → Developer → Edit Config.
- Merge the block from
claude_desktop_config.example.json, replacing the path and usernames:
{
"mcpServers": {
"desktop-bridge": {
"command": "node",
"args": ["/Users/YOU/dev/desktop-bridge/dist/index.js"],
"env": {
"DESKTOP_BRIDGE_ROOTS": "/Users/YOU/Desktop,/Users/YOU/Documents,/Users/YOU/Downloads"
}
}
}
}
- Fully quit and reopen Claude Desktop.
- Confirm desktop-bridge appears under MCP tools (bridge icon 🌉).
Config file on macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
Connect to Claude Code
claude mcp add desktop-bridge -- node /Users/YOU/dev/desktop-bridge/dist/index.js
Or add the same command / args / env block to ~/.claude.json.
Connect to Cursor
Add to ~/.cursor/mcp.json (or the project .cursor/mcp.json):
{
"mcpServers": {
"desktop-bridge": {
"command": "node",
"args": ["/Users/YOU/dev/desktop-bridge/dist/index.js"]
}
}
}
Smoke-test without a host
npm run inspector
That launches the MCP Inspector against the built stdio server. Call list_roots, then get_system_info.
Logs go to stderr only. Do not console.log in this process — stdout is the JSON-RPC channel.
Environment
| Variable | Default | Meaning |
|---|---|---|
DESKTOP_BRIDGE_ROOTS |
~/Desktop, ~/Documents, ~/Downloads (if they exist) |
Comma-separated directories file tools may touch. The OS temp dir is always added so screenshots have a place to land. |
DESKTOP_BRIDGE_MAX_FILE_BYTES |
10485760 |
Max size for a single file read/write (1 KiB–100 MiB). |
DESKTOP_BRIDGE_COMMAND_TIMEOUT_MS |
30000 |
Default run_command timeout (100–300000). |
DESKTOP_BRIDGE_MAX_OUTPUT_BYTES |
1048576 |
Combined stdout+stderr capture cap. Excess output kills the process and sets truncated. |
DESKTOP_BRIDGE_ALLOW_SHELL |
true |
Set false to disable run_command. |
DESKTOP_BRIDGE_RESTRICT_SHELL_CWD |
true |
When true, run_command cwd must sit inside an allowed root. |
DESKTOP_BRIDGE_STATUS_URL |
unset | Heartbeat POST URL for the status site (…/api/heartbeat). |
DESKTOP_BRIDGE_STATUS_TOKEN |
unset | Bearer token matching the site’s HEARTBEAT_TOKEN. |
DESKTOP_BRIDGE_STATUS_INTERVAL_MS |
15000 |
Heartbeat interval (5s–5m). |
Copy .env.example for a commented template. The server reads process env (Claude Desktop env block), not a .env file.
Tools
| Tool | What it does |
|---|---|
list_roots |
Allowed directories and file-size cap |
read_file |
Text (optional line window) or base64 |
write_file |
Create/overwrite/append; optional mkdir -p |
list_directory |
Name, type, size, mtime, mode |
search_files |
Glob on names and/or regex on file contents |
get_system_stats |
CPU %, load, memory, df |
get_system_info |
Host, uptime, user, redacted env |
list_applications |
GUI (or all) processes via System Events |
run_command |
Shell with split stdout/stderr; stream → progress notifications |
read_clipboard / write_clipboard |
pbpaste / pbcopy |
get_display_info |
Display name, main flag, scale, frame |
take_screenshot |
PNG via screencapture; returns an image block when ≤ 5 MiB |
Resources: desktop://roots, desktop://system/info.
Prompts: inspect_desktop, find_file.
Security model
- Files: every path is
realpath'd. The resolved path must stay inside a configured root..., extra slashes, and symlinks that escape are rejected. - Home is not a default root. That keeps
~/.sshand similar out of reach until you add them on purpose. - Shell: still a full user shell. A command can
cdanywhere even when cwd is restricted. Disable it withDESKTOP_BRIDGE_ALLOW_SHELL=falseif you only want file/clipboard/screen tools. - Env: keys matching password/token/secret/key/credential/cookie/session are replaced with
[redacted]. - Stdio: no network listener. The host spawns this process.
macOS permissions
| Feature | Permission |
|---|---|
| Screenshots | Screen Recording for the app that spawned Node (Claude Desktop, Cursor, or Terminal) |
list_applications |
Automation → System Events if macOS prompts |
| Accessibility-heavy apps | may still hide titles; the tool lists process names either way |
If screencapture fails, open System Settings → Privacy & Security → Screen Recording and enable the host app, then restart it.
Development
npm run build # tsc → dist/
npm start # node dist/index.js (stdio)
npm test # compile + node:test
Layout: src/lib/* (path guard, process runner, glob/search), src/tools/* (MCP tools), src/index.ts (stdio entry).
Home
https://home.jameymcelveen.com is the browser start page (web/). Widgets are Lit web components under web/public/components/, tagged jm-*. The isolated catalog is Storybook at https://home.jameymcelveen.com/storybook/ (cd web && npm run storybook locally). Lit is vendored into web/public/vendor/ (npm run vendor / postinstall). Sign-in is @mcelveen.us plus STATUS_PASSWORD.
What is there today, and the dump tray for whatever comes next:
| Piece | Notes |
|---|---|
| Widgets | Lit web components, jm-* prefix. Isolated catalog: Storybook |
| Search | Autofocus. Google completions as you type (same suggestion feed as google.com). Kagi / DDG. Bangs: !g !k !d !gh !yt !w !maps |
| Links | Same tiles as the local landing-page app, plus the properties. Edit as JSON in Settings |
| Weather | Open-Meteo, °F, Florence SC unless you override coords |
| Mac | DesktopBridge heartbeat: online / stale / offline, IPs, load |
| VIN Sweep | Client-side NHTSA decode / recalls / complaints, plus human-only NICB / FL title / iSeeCars taps |
| Scratch | Autosaved notes |
| Word | Daily verse |
Set Chrome/Safari/Firefox homepage to https://home.jameymcelveen.com (browsers will not let the page do it for you). Session cookie lasts 30 days. / focuses search; ⌘K too.
Push to main runs CI, then deploys Vercel (the site) and Railway (heartbeat + saved config).
On the Mac, add to the MCP server env:
DESKTOP_BRIDGE_STATUS_URL=https://home.jameymcelveen.com/api/heartbeat
DESKTOP_BRIDGE_STATUS_TOKEN=<HEARTBEAT_TOKEN>
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。