mac-bridge-mcp

mac-bridge-mcp

An MCP server that runs on a Mac and exposes a small, sharp set of tools (shell, file transfer, binary execution, screenshots) over a token-protected network port.

Category
访问服务器

README

🌉 mac-bridge-mcp

Let an AI securely drive a macOS machine, from anywhere.

An MCP server that runs on a Mac and exposes a small, sharp set of tools (shell, file transfer, binary execution, screenshots) over a token-protected network port. Point your AI client at it and it can build, test, and automate on macOS, even when your AI is running on Windows or Linux.

License: MIT Python MCP

   your machine (Windows / Linux / Mac)            the Mac you want to control
 ┌────────────────────────────────────┐           ┌────────────────────────────┐
 │  AI client (MCP host)              │  HTTP +   │      mac-bridge-mcp        │
 │  e.g. Claude Desktop, an agent     │ ───────►  │  ┌──────────────────────┐  │
 │                                    │  bearer   │  │ IP allowlist → token │  │
 │  "build & test my binary on macOS" │  token    │  └──────────┬───────────┘  │
 │                                    │ ◄───────  │     shell · files · exec   │
 └────────────────────────────────────┘  results  └────────────────────────────┘

⚠️ Warning - this is remote code execution on the host Mac, by design. Anyone who can reach the port and has the token gets the equivalent of a shell. Run it only on machines you own, keep the port off the public internet, and read the Security model before exposing it anywhere. The token is as sensitive as an SSH key.

Table of contents

Why

If you ship software that has to run on both Windows and macOS, you constantly need "the other OS" in the loop, to compile a native binary, run the test suite, reproduce a platform-specific bug, or grab a screenshot of how something renders. mac-bridge-mcp puts a Mac one tool-call away from whatever AI you're already working with, so a single conversation can drive both platforms.

The original motivation was cross-platform security research. When an AI reviews source code that compiles on Windows, Linux, and macOS, it will sometimes surface a vulnerability that only manifests on macOS, and then have no way to confirm it. Lacking access to a macOS system, it can't compile the affected code, run a proof-of-concept, and check whether the finding is genuine or a false positive. mac-bridge-mcp closes that gap: it gives the AI a real Mac to compile, test, and verify on, so macOS-specific findings can be triaged on the actual operating system instead of guessed at.

It speaks MCP's Streamable HTTP transport, so any MCP-capable client can use it, locally or across the network.

Features

  • Real macOS control - shell commands, direct binary execution, file read/write, directory listing, and screen capture.
  • Two security gates - an optional source-IP allowlist (with CIDR support) in front of a constant-time bearer-token check.
  • Built-in TLS - serve HTTPS directly from a cert + key, or rely on an SSH tunnel / VPN. No reverse proxy required.
  • Optional filesystem jail - confine every operation under one directory.
  • Works across machines - drive a Mac from Windows or Linux over an SSH tunnel or a private VPN.
  • Tiny and readable - one dependency-light Python module, easy to audit and extend.
  • Client-agnostic - works with any MCP host, with a drop-in mcp-remote config for stdio-only clients.

Quickstart

On the Mac (the machine you want to control):

# 1. Get the code and install the two dependencies
git clone https://github.com/YOUR_USERNAME/mac-bridge-mcp
cd mac-bridge-mcp
pip install fastmcp uvicorn        # or: pip install -r requirements.txt

# 2. Generate a token and run the server
export MCP_BRIDGE_TOKEN="$(python3 -c 'import secrets;print(secrets.token_urlsafe(32))')"
echo "Token: $MCP_BRIDGE_TOKEN"    # copy this
python3 src/mac_bridge_mcp/server.py

With the default MCP_BRIDGE_HOST=127.0.0.1, the server is reachable only from the Mac itself. To connect from another machine, open an SSH tunnel and point your client at the local end of it:

ssh -L 8765:127.0.0.1:8765 you@your-mac     # then connect to http://127.0.0.1:8765/mcp

If you bind to an address your other machine can already reach, for example the Mac's Tailscale or LAN IP via MCP_BRIDGE_HOST, you don't need the tunnel. Just connect straight to http://<that-ip>:8765/mcp. In that case encrypt the connection by enabling TLS / HTTPS (or keep it on a trusted private network/VPN), and never bind to a public address (see the Security model).

Installation

From source:

git clone https://github.com/YOUR_USERNAME/mac-bridge-mcp
cd mac-bridge-mcp
pip install -e .

Requires Python 3.10+ on macOS.

Configuration

Everything is configured through environment variables (or a local .env, see .env.example).

Variable Default Purpose
MCP_BRIDGE_TOKEN random Shared secret ("password"). Set it to keep it stable across restarts.
MCP_BRIDGE_HOST 127.0.0.1 Bind address. Do not use 0.0.0.0 on an untrusted network.
MCP_BRIDGE_PORT 8765 Listen port.
MCP_BRIDGE_PATH /mcp URL path for the MCP endpoint.
MCP_BRIDGE_SHELL /bin/zsh Shell used by run_command.
MCP_BRIDGE_ALLOW_IPS unset Comma-separated IPs/CIDRs allowed to connect. Unset = any IP (token still required).
MCP_BRIDGE_ROOT unset Confine all file/binary operations under this directory.
MCP_BRIDGE_TLS_CERT unset Path to a PEM certificate. Set with MCP_BRIDGE_TLS_KEY to serve HTTPS.
MCP_BRIDGE_TLS_KEY unset Path to the certificate's private key (PEM).
MCP_BRIDGE_TLS_KEY_PASSWORD unset Password for the private key, if it is encrypted.
MCP_BRIDGE_TRUST_FORWARDED unset Read client IP from X-Forwarded-For. ONLY behind a proxy you control.

Connecting your AI client

The server and your AI usually run on different machines. Two cases:

Your client supports remote / HTTP MCP servers directly - point it at http://<host>:8765/mcp and add the header Authorization: Bearer <token>.

Your client only launches local stdio servers (the classic Claude Desktop pattern), use the mcp-remote bridge, which runs locally and forwards to the remote server. See examples/claude_desktop_config.json:

{
  "mcpServers": {
    "mac-bridge": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://MAC_IP_OR_HOST:8765/mcp",
        "--header", "Authorization: Bearer YOUR_TOKEN_HERE"
      ]
    }
  }
}

Test before wiring up an AI with the MCP Inspector (no model required):

npx @modelcontextprotocol/inspector
# URL: http://127.0.0.1:8765/mcp   (transport: Streamable HTTP)
# Header: Authorization: Bearer <token>

...or run the included smoke test:

TOKEN=your-token ./examples/smoke_test.sh

Tools

Tool Description
system_info macOS version, CPU architecture (arm64 / x86_64), hostname, user. Call first.
run_command Run a shell command; returns stdout, stderr, exit code, timeout flag.
run_binary Execute a binary directly with verbatim args (no shell parsing).
list_dir List a directory with type, size, and mode for each entry.
read_file Read a file as text, or base64 for binaries.
write_file Write a file; base64_encoded + make_executable for pushing binaries.
screenshot Capture the screen as a base64 PNG (needs Screen Recording permission).

Every tool returns a structured result and handles its own errors, so the AI gets a clean signal instead of a stack trace.

Example: cross-platform binary test loop

A typical "I built it on Windows, does it work on macOS?" round-trip:

  1. system_info - confirm arch is arm64 vs x86_64.
  2. write_file - push your built artifact (base64, make_executable=true).
  3. run_binary - run it with test arguments; inspect stdout / exit_code.
  4. read_file - pull back any output files it produced.

Because the AI sees the architecture first, it can pick the right build and even recompile via run_command (clang, cargo build, go build, ...) before testing.

🔐 Security model

Requests pass through two gates, in order, on every request:

  1. IP allowlist (MCP_BRIDGE_ALLOW_IPS) - a peer outside the list is rejected with 403 before the token is even compared. Supports single addresses and CIDR ranges, IPv4 and IPv6.
  2. Bearer token - checked with a constant-time comparison; missing/wrong gives 401.

An optional filesystem jail (MCP_BRIDGE_ROOT) then confines every path argument to a chosen directory.

What IP does the server actually see?

  • SSH tunnel - traffic arrives from 127.0.0.1 (the tunnel exit on the Mac), so include 127.0.0.1/::1 in the allowlist; your real gate there is the SSH login itself.

  • Tailscale / WireGuard / LAN - the server sees the client's real address, so the allowlist is meaningful. Pin it to your client's VPN IP or LAN subnet:

    export MCP_BRIDGE_ALLOW_IPS="127.0.0.1,::1,100.64.0.0/10,192.168.1.0/24"
    

Operating rules of thumb

  • Keep MCP_BRIDGE_HOST=127.0.0.1; reach the server via SSH tunnel or a private VPN. Never put it on the public internet.
  • Use a long random token; rotate it if it leaks; never commit .env.
  • Run as a normal user, not root.
  • Encrypt the connection. The server can serve HTTPS itself (see TLS / HTTPS), or you can rely on an SSH tunnel / VPN for encryption. Don't send the token over plain HTTP across a network. Leave MCP_BRIDGE_TRUST_FORWARDED off unless a reverse proxy you control sets it.

TLS / HTTPS

The server has built-in TLS, point it at a certificate and key and it serves https:// directly, no reverse proxy required:

export MCP_BRIDGE_TLS_CERT="/path/to/server.crt"
export MCP_BRIDGE_TLS_KEY="/path/to/server.key"
python3 src/mac_bridge_mcp/server.py        # now on https://...

Three easy ways to get a certificate, best first:

  • Tailscale (recommended): if you reach the Mac over Tailscale, run tailscale cert <machine>.<tailnet>.ts.net. You get a real, trusted certificate with no client-side configuration, clients verify it normally.

  • mkcert (LAN): mkcert installs a local CA and issues certs your machines trust. Good for a home/office LAN.

  • Self-signed: run examples/gen_self_signed_cert.sh. The traffic is encrypted, but clients don't trust a self-signed cert by default and will refuse to connect until told to trust it. For the mcp-remote bridge that means pointing Node at your cert:

    NODE_EXTRA_CA_CERTS=/path/to/server.crt npx mcp-remote https://<host>:8765/mcp \
      --header "Authorization: Bearer <token>"
    

When TLS is on, use https:// in every client URL. The MCP_BRIDGE_ALLOW_IPS and token gates apply exactly the same over HTTPS.

macOS permissions

  • Shell and file tools need no special permission.
  • screenshot needs Screen Recording for whatever process runs the server (Terminal / iTerm / python): System Settings -> Privacy & Security -> Screen Recording, then restart that app.
  • Future mouse/keyboard control will need Accessibility permission in the same place.

License

MIT © IamLeandrooooo


Built on the Model Context Protocol and FastMCP.

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选