Git-Managed MCP Configuration (v2.0.0+ Generic Compiler Pipeline)#

In this configuration workflow, all Model Context Protocol (MCP) server definitions are managed via a centralized, version-controlled repository. Directly modifying target configuration files or using basic symlinks from your Obsidian vault has been deprecated.

Instead, a single generic flat list of servers is defined in a master configuration file. This is automatically compiled, adapted, and deployed to all your software clients via an automated Git post-commit pipeline.

Antigravity chat: agy –conversation=2b91f028-6933-4a8f-b76a-7b35290e35b8

Current deployment snapshot (2026-10-22): The Mac Studio and MacBook Air use the same GitHub-backed ~/.mcp-config repository. The shared config.json contains 35 MCP server definitions, including rea-agents@6.7.0. The Mac Studio’s OpenCode adapter compiled all 35 entries into ~/.config/opencode/opencode.json; the generated JSON and mode 0600 were verified. opencode mcp list reports 34 of 35 servers connected; only macos-mcp failed because Accessibility permission is not granted to its server process, /Users/marc/mcp-servers/macos-mcp/.venv/bin/python3. Grant permission to that exact process through the native macOS prompt and restart the MCP server; granting the OpenCode host app does not grant permission to the Python process. Do not add the interpreter manually in System Settings because the uv-managed binary path can change. REA 6.7.0 is connected in OpenCode 2.1.3; binary_session({}) succeeded with no analysis target open. Other harnesses and the MacBook Air still need their own connection checks after syncing.

Intel Mac support: The 2014 Intel iMac uses the same shared MCP definitions, but its Homebrew prefix is /usr/local rather than /opt/homebrew. The portable apply.py compiler resolves the local op executable automatically, so this path difference does not require a separate configuration repository. The compiler still emits the complete shared server list; a server can remain unavailable on a workstation when its local executable, Python environment, credentials, or external service is not present.

The active Proxmox MCP endpoints are:

MCP server Proxmox API endpoint
proxmox-mm https://10.1.1.10:8006
proxmox-hp1 https://10.1.1.11:8006
proxmox-hp2 https://10.1.1.12:8006
proxmox-hp3 https://10.1.1.13:8006
proxmox-hp4 https://10.1.1.14:8006
proxmox-hp5 https://10.1.1.15:8006
proxmox-hp7 (HP7Proxmox) https://10.1.1.17:8006

HP node credentials use matching HPnPROXMOX_TOKEN_ID and HPnPROXMOX_TOKEN_SECRET fields in 1Password Homelab-MCP → MCP-Secrets. The MCP-Access service-account token is stored in Homelab → Mac OS .zshrc file and is configured locally on both Macs. Secret values are never stored in this vault or in config.json.


MCP & Client Support Matrix#

MCP Server Antigravity-CLI Antigravity 2.0 Antigravity-IDE Codex-CLI Codex-App Claude Code Pi-CLI Hermes CLI OpenCode
cloudflare ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-100 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-202 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-217 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-230 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-231 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-233 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-10-1-2-4 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
docker-72-11-147-220 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
gdrive ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
git ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
github ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
home-assistant ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
macos-mcp ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
n8n-mcp ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
nut ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
pihole-primary ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
pihole-secondary ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp1 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp2 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp3 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp4 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp5 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-hp7 (HP7Proxmox) ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
proxmox-mm ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
rea ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
shell-exec ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
synology-hp1 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
truenas-hp1 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
truenas-hp2 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
truenas-hp3 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
truenas-hp6 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
truenas-hp7 ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
unifi ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
xcode-tools ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅

rea is supported by all eight registered client targets. A live binary_session({}) call has been verified in both OpenCode and Codex. OpenCode reports 34 of 35 configured servers connected; macos-mcp awaits Accessibility permission for its Python server process. The matrix records compiler support, not a live connection guarantee. ChatGPT desktop with local execution shares the Codex target; it does not need a separate server definition.

The Hermes column means the compiler emits each server definition in Hermes format. The shared configuration contains 35 entries; local overrides can disable an entry on an individual workstation. Connection tests have verified git and home-assistant. Runtime availability for each remaining server still depends on its local executable, credentials, permissions, and network access.

The OpenCode column means the compiler emits each server in OpenCode V2’s local stdio format. It indicates compiler support, not a verified live connection.

Codex-hosted entries#

The following entries are built into Codex rather than defined in the Git-managed ~/.mcp-config/config.json. They may appear in /mcp for Codex CLI and other local Codex clients even when disabled, and are not compiled by apply.py:

Entry Observed status outside the ChatGPT desktop app
codex_app disabled (0 tools)
computer-use disabled (0 tools)

The active computer-use interface is cua_repl; it is separate from the disabled built-in computer-use entry. Do not add or remove these Codex-hosted entries through the external MCP master list.


1. Workstation Setup & Replication#

1.1 New Machine Setup (From Scratch)#

Follow these steps in order when setting up MCP on a new computer for the first time.

Prerequisites for a New Mac#

Before beginning the numbered setup, confirm that the workstation has the following foundations:

  1. GitHub SSH access: Create or register an SSH key for the new Mac with GitHub. Both the ~/Scripts and ~/.mcp-config repositories use GitHub SSH remotes. Verify access with:
    ssh -T git@github.com
  2. Homebrew and 1Password: Install Homebrew, 1Password CLI, and the 1Password desktop application. The MCP service-account workflow requires the CLI; the desktop application is used for personal CLI sign-in and optional biometric integration.
  3. Docker: Install the Docker CLI and a local Docker engine if the local Docker MCP is required. Remote Docker MCPs additionally require network and SSH access to their target hosts and running Docker daemons.
  4. Node.js and npm: Install a supported Node.js LTS release. node, npm, and npx are required by the npx-launched MCP and by the Pi CLI MCP adapter.
  5. AI clients: Install the AI clients you intend to use and launch each one once so its application directory is created. The compiler can then write the generated MCP configuration files.
  6. macOS privacy permissions: Grant Accessibility, Screen Recording, and Automation permissions to the AI client or terminal process that will launch the local GUI MCPs. These permissions are only required for local GUI automation; they do not affect Proxmox or Home Assistant MCPs.

On an Intel Mac, Homebrew uses /usr/local and may build large dependencies from source. Install uv with the official standalone installer and use uv to provision Python 3.12 for MCP virtual environments when Homebrew installation is impractical. Keep Homebrew-managed Node.js and 1Password CLI separate from this Python bootstrap path.

1.1.0 Restore the Workstation Shell Foundation#

Complete this subsection before setting up ~/.mcp-config. The MCP shortcuts are loaded from ~/Scripts, and the compiler needs the service-account token in the shell when it generates the Codex configuration.

  1. Restore ~/Scripts: Clone the scripts repository, or pull it if it already exists:
    git clone git@github.com:marcoue/Scripts.git ~/Scripts
    # Existing clone: cd ~/Scripts && git pull origin main
  2. Confirm the tracked aliases file exists:
    test -f ~/Scripts/MacOS/Aliases/MacOS-Aliases.zsh
  3. Create or update the local ~/.zshrc: Copy the private values from 1Password Homelab → Mac OS .zshrc file into the local file, and ensure the file sources ~/Scripts/MacOS/Aliases/MacOS-Aliases.zsh. Keep credentials local; never put their values in the vault notes or Git repositories.
  4. Reload the shell:
    source ~/.zshrc
  5. Verify the shell foundation before continuing:
    whence -w mcp pushmcp pullmcp
    op whoami
    op whoami should report User Type: SERVICE_ACCOUNT. The mcp, pushmcp, and pullmcp commands should be available.

On macOS, personal 1Password CLI sign-in can use the desktop app integration: open 1Password → Settings → Developer → Integrate with 1Password CLI. After it is enabled, op signin or another op command may display an authentication prompt from the desktop app. This is separate from the OP_SERVICE_ACCOUNT_TOKEN used by the MCP compiler and op run servers.

The aliases restore utility has been removed. Create or update ~/.zshrc manually using the local 1Password entry Homelab → Mac OS .zshrc file, and keep credential values out of Git repositories and vault notes.

1.1.1 Clone the MCP Master Repository#

git clone git@github.com:marcoue/MCP-Config-MacOS.git ~/.mcp-config

1.1.2 Set Up Git Hooks#

The .git/hooks/ directory is never tracked by GitHub (Git intentionally excludes it for security). You must create these hook scripts manually on every new machine.

Create and populate both hook files:

nano ~/.mcp-config/.git/hooks/post-commit
nano ~/.mcp-config/.git/hooks/post-merge

Add the following content to both files:

#!/bin/bash
/Users/marc/.mcp-config/apply.py

Make them executable:

chmod +x ~/.mcp-config/.git/hooks/post-commit ~/.mcp-config/.git/hooks/post-merge

1.1.3 Verify Target Software Clients & Folders#

Before running the compiler, ensure your AI software clients are installed. The compiler (apply.py) will deploy settings to the following expected folders and files:

  • Antigravity CLI: ~/.gemini/config/mcp_config.json
  • Antigravity 2.0: ~/.gemini/antigravity/mcp_config.json
  • Antigravity IDE: ~/.gemini/config/mcp_config.json
  • Pi-CLI: ~/.pi/agent/mcp.json
  • Claude Code: ~/.claude.json (lives directly in user home folder)
  • Codex (CLI / App): ~/.codex/config.toml
  • Hermes Agent (CLI / Desktop): ~/.hermes/config.yaml (mcp_servers section)
  • OpenCode: ~/.config/opencode/opencode.json (mcp.servers section)

Launch each installed AI client at least once on a new machine so its application data folder (e.g. ~/.gemini, ~/.pi/agent, ~/.codex, ~/.hermes) is created automatically before running mcp.

1.1.4 Install Python MCP Servers#

Intel runtime bootstrap: When Homebrew’s Python or uv build is excessively slow on Intel, use the standalone uv installer and its managed Python instead:

curl -LsSf https://astral.sh/uv/install.sh | sh
~/.local/bin/uv python install 3.12

Use the resulting Python 3.12 interpreter to create the virtual environments below. The 2014 Intel iMac was provisioned this way because brew install uv attempted a multi-hour source build.

# Proxmox (public repository + Python virtual environment)
mkdir -p ~/mcp-servers
git clone https://github.com/bsahane/mcp-proxmox.git ~/mcp-servers/mcp-proxmox
cd ~/mcp-servers/mcp-proxmox
python3 -m venv .venv
./.venv/bin/python3 -m pip install -r requirements.txt
./.venv/bin/python3 -m pip install -e .

# TrueNAS (custom local server.py — copy source before compiling)
mkdir -p ~/mcp-servers/mcp-truenas
python3 -m venv ~/mcp-servers/mcp-truenas/.venv
~/mcp-servers/mcp-truenas/.venv/bin/pip install "mcp[cli]"

# NUT UPS Monitor (custom local server.py — copy source before compiling)
mkdir -p ~/mcp-servers/mcp-nut
python3 -m venv ~/mcp-servers/mcp-nut/.venv
~/mcp-servers/mcp-nut/.venv/bin/pip install "mcp[cli]"

# macOS MCP (pip package)
mkdir -p ~/mcp-servers/macos-mcp
python3 -m venv ~/mcp-servers/macos-mcp/.venv
~/mcp-servers/macos-mcp/.venv/bin/pip install macos-mcp

# Synology DSM HP1 (public repository + Python virtual environment)
# The server currently uses the MCP 1.x FastMCP API; install the SDK constraint
# before the editable package so pip does not select MCP 2.x.
mkdir -p ~/mcp-servers
git clone https://github.com/rafalr100/synology-mcp.git ~/mcp-servers/synology-mcp
cd ~/mcp-servers/synology-mcp
python3 -m venv .venv
./.venv/bin/python -m pip install "mcp[cli]>=1.0.0,<2.0.0"
./.venv/bin/python -m pip install -e .
Synology HP1 master configuration#

Add this server to ~/.mcp-config/config.json. Do not create a .env file or place credential values in the repository. The op:// references resolve from the Homelab-MCP vault item MCP-Secrets:

"synology-hp1": {
  "command": "/opt/homebrew/bin/op",
  "args": [
    "run",
    "--",
    "/Users/marc/mcp-servers/synology-mcp/.venv/bin/python",
    "-m",
    "synology_mcp"
  ],
  "env": {
    "SYNOLOGY_URL": "https://10.1.2.221:5001",
    "SYNOLOGY_USER": "op://Homelab-MCP/MCP-Secrets/HP1SYNOLOGYDSM_USER_ID",
    "SYNOLOGY_PASS": "op://Homelab-MCP/MCP-Secrets/HP1SYNOLOGYDSM_PASSWORD",
    "SYNOLOGY_VERIFY_SSL": "false",
    "SYNOLOGY_ENABLE_POWER_CONTROL": "false",
    "SYNOLOGY_TIMEOUT": "30",
    "SYNOLOGY_SESSION_NAME": "HP1SynologyMCP",
    "SYNOLOGY_DEVICE_NAME": "HP1-AI-Agent"
  }
}

The DSM account is restricted to the trusted 10.1.2.0/24 source subnet through DSM Application Privileges. 2FA is not currently enabled. After committing config.json, the post-commit hook runs apply.py and deploys the server to all registered clients. Fully restart each client before checking /mcp.

Read-only smoke test (the op run wrapper resolves the two secret references without printing their values):

cd ~/mcp-servers/synology-mcp
SYNOLOGY_URL='https://10.1.2.221:5001' \
SYNOLOGY_USER='op://Homelab-MCP/MCP-Secrets/HP1SYNOLOGYDSM_USER_ID' \
SYNOLOGY_PASS='op://Homelab-MCP/MCP-Secrets/HP1SYNOLOGYDSM_PASSWORD' \
SYNOLOGY_VERIFY_SSL='false' \
SYNOLOGY_TIMEOUT='30' \
/opt/homebrew/bin/op run -- .venv/bin/python smoke_test.py

Expected results include a successful login, DSM version, temperature, and the shared-folder list. If the client reports an MCP startup failure, confirm the virtual environment has MCP 1.x installed (.venv/bin/python -m pip show mcp) rather than MCP 2.x.

1.1.5 Install Pi CLI and MCP Adapter#

npm install -g --ignore-scripts @earendil-works/pi-coding-agent
pi install npm:pi-mcp-adapter

1.1.6 Google Drive Credentials#

Why do we copy this file? The Google Drive MCP server (gdrive) authenticates using a local OAuth token file (~/.gdrive-server-credentials.json). Copying this file from your primary Mac avoids having to re-authenticate through Google Cloud in a web browser on every new machine.

Run this command from your primary Mac to copy the existing credentials to your new machine:

scp ~/.gdrive-server-credentials.json marc@<new-machine-ip>:~/.gdrive-server-credentials.json
Option B: Create manually (If primary Mac is unavailable)#

If copying via SSH is not possible, create the file ~/.gdrive-server-credentials.json on the new machine using this format:

{
  "access_token": "[ACCESS_TOKEN]",
  "refresh_token": "[REFRESH_TOKEN]",
  "scope": "https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/spreadsheets",
  "token_type": "Bearer",
  "expiry_date": [EXPIRY_TIMESTAMP]
}

1.1.7 Configure the 1Password Service Account Token#

See #2. 1Password Service Account Token Management for full instructions.

Quick setup: Copy your token from 1Password (Vault: Homelab → Item: Mac OS .zshrc file → Field: OP_SERVICE_ACCOUNT_TOKEN), then add it to ~/.zshrc:

nano ~/.zshrc   # Add: export OP_SERVICE_ACCOUNT_TOKEN="ops_..."
source ~/.zshrc

1.1.8 Compile and Verify#

mcp

Verify all 8 client targets report Successfully applied configuration for ... with no Warning: OP_SERVICE_ACCOUNT_TOKEN not found.

Hermes writes the complete server list to ~/.hermes/config.yaml while preserving the other Hermes settings. During compilation, the compiler copies OP_SERVICE_ACCOUNT_TOKEN into the env block of each op run server. This lets Hermes Desktop authenticate when opened from its app icon. The generated local config is mode 0600 and is not part of the MCP Git repository. Load the token before compiling:

source ~/.zshrc
mcp hermes

Then verify the registered servers and test a connection:

hermes mcp list
hermes mcp test home-assistant

For OpenCode, restart the client after compilation and check its connection state with:

opencode mcp list

Treat entries as connected only when OpenCode reports connected; a generated definition alone is not a live connection test.

Compilation, configuration status, and connection health are separate. The mcp alias runs the compiler (and may commit/push changed MCP configuration); it does not launch or refresh an AI client, nor does it give an already-running GUI app the shell’s environment. hermes mcp list shows configured/enabled servers, not whether they can connect. Use hermes mcp test <server> or make a real tool call to verify a server.

1.1.9 Launch Clients with the Required Environment#

On this workstation, OP_SERVICE_ACCOUNT_TOKEN is loaded by ~/.zshrc. An MCP launched by a client can use it only if the client process passes the variable through, or the compiler/client explicitly supplies it. Launching an app from Finder or the Dock usually does not load ~/.zshrc; this is why a GUI client can fail while the same MCP works from a terminal.

There are two separate credential steps:

  1. Client-to-op authentication: OP_SERVICE_ACCOUNT_TOKEN lets op run authenticate as the 1Password service account. The client process must pass this variable to the MCP subprocess, unless the client compiler explicitly supplies it.
  2. op-to-server credentials: op run reads the individual MCP secrets from the permitted 1Password vault and passes them to that server. MCPs that do not use op run need their own configured environment, credential file, or sign-in flow.
Client / harness How the op run token is supplied Required action
Antigravity CLI Parent-shell environment when started from Terminal Run source ~/.zshrc, then start Antigravity CLI from that Terminal.
Antigravity 2.0 and Antigravity IDE The app process environment; a Finder/Dock launch may omit shell variables For a reliable launch, start the app from Terminal after source ~/.zshrc, or configure its supported environment source.
Pi CLI Parent-shell environment when started from Terminal Run source ~/.zshrc, then start Pi from that Terminal.
Claude Code CLI Parent-shell environment when started from Terminal Run source ~/.zshrc, then start Claude Code from that Terminal.
Codex CLI / App The compiler writes the token into each op run server’s local Codex environment block because Codex isolates MCP subprocess environments After token rotation, run source ~/.zshrc and recompile the Codex target. The generated local Codex config contains the runtime credential; keep it private and out of Git.
Hermes CLI / TUI / Desktop mcp hermes copies the token into the local generated config’s env blocks for op run servers After adding or rotating the token, run source ~/.zshrc && mcp hermes. Then launch or restart Hermes normally, including from its Desktop icon. The config is mode 0600; it contains the token locally and must not be copied to Git.
OpenCode The compiler writes the token into each op run server’s environment block in ~/.config/opencode/opencode.json Run source ~/.zshrc before compiling OpenCode. The generated config is mode 0600, contains the runtime credential, and must stay local. Restart OpenCode after recompiling.

The same rule applies to every other harness and local MCP tool: determine whether the compiler writes credentials into that client’s local MCP config or whether the running client must inherit them. mcp compiles configuration; it does not refresh a running client. Keep tokens out of shared config.json, notes, and Git history. The Codex target also receives an explicit local env entry; other clients that rely on parent-shell inheritance must be launched from a shell where the token is loaded.

1.1.10 REA — Install, Configure, and Run Across Harnesses#

REA (Reverse Engineer Anything) provides local MCP tools for inspecting applications and binaries. Use the same master configuration and compiler as the other MCPs. The shared entry is pinned to rea-agents@6.7.0 and is compiled for all registered harnesses.

Deployment status (2026-10-18): REA 6.7.0 was downloaded and version-checked on the Mac Studio, added to the shared master config, compiled into all seven registered client targets, and pushed to GitHub. A live binary_session({}) call succeeded in Codex. Verify the other harnesses and each additional Mac after syncing.

Step 1 — Prepare each workstation and choose one package version#

REA requires Node.js 22.x at least 22.19, 24.x at least 24.11, or 26+, with npm. Check the runtime on every Mac:

node --version
npm --version
command -v npx

The shared configuration currently pins REA 6.7.0. On a future update, check the published release and deliberately change the single version pin:

npm view rea-agents dist-tags.latest

For the current installation, check the pinned version on each workstation before restarting clients:

npx -y rea-agents@6.7.0 --version

This uses npm’s local package cache; a global installation is optional. Initial download requires registry access. The persistent MCP entry will remain pinned to the chosen release. REA’s basic local MCP registration does not require an op run wrapper or new 1Password credentials.

Step 2 — Add REA to the master configuration once#

In /Users/marc/.mcp-config/config.json, insert this entry alongside the existing server definitions, preserving the file’s existing outer structure and JSON commas:

"rea": {
  "command": "npx",
  "args": ["-y", "rea-agents@6.7.0", "mcp"]
}

Use the master file for this registration. REA’s general setup wizard can write client configuration files directly, so using it to register these compiler-managed clients would introduce a second configuration owner. A separate REA setup run is not required on each harness.

The existing compiler targets translate this standard command/args entry into their client formats. On the Mac Studio, compilation succeeded for all seven targets and Codex launched REA. Verify that GUI launches on each workstation can resolve both npx and node. If a workstation’s GUI environment cannot find them, resolve the local runtime paths through the compiler or a tracked launcher, as with other portable server commands; avoid separate hard-coded Apple Silicon and Intel master configurations.

The current compiler emits the basic REA command and arguments in the Codex target:

[mcp_servers.rea]
command = "npx"
args = ["-y", "rea-agents@6.7.0", "mcp"]

Keep configuration changes in the master/compiler rather than editing generated files manually. The current compiler does not emit REA-specific startup or tool timeout fields. The live Codex tool call succeeded with the current settings; if a long-running provider later times out, add and verify timeout support in the compiler before relying on those settings.

Step 3 — Compile, distribute, and restart the harnesses#

On the Mac Studio, the following command compiled the targets and automatically committed and pushed the changed master config to GitHub:

source ~/.zshrc && python3 $HOME/.mcp-config/apply.py

On each other Mac, run pullmcp to sync the shared repository, then compile locally if its post-merge hook did not run:

source ~/.zshrc && python3 $HOME/.mcp-config/apply.py

The compiler still needs its normal environment for the other 1Password-backed servers; follow #1.1.8 Compile and Verify and #1.1.9 Launch Clients with the Required Environment. Compilation does not restart clients. Fully quit and reopen each harness after compiling, then verify REA with a live tool call.

Harness Configuration supplied by the existing pipeline How REA starts
ChatGPT desktop with local execution, Codex CLI/App, Codex IDE extension /Users/marc/.codex/config.toml through the codex target The local client launches the configured stdio command; view /mcp after restart.
Pi CLI /Users/marc/.pi/agent/mcp.json through pi Pi’s configured MCP loader/adapter launches REA; inspect /mcp.
Claude Code /Users/marc/.claude.json through claude-code Claude Code launches REA; inspect /mcp.
Antigravity CLI / IDE /Users/marc/.gemini/config/mcp_config.json through the existing targets Restart the client and inspect its MCP status.
Antigravity 2.0 /Users/marc/.gemini/antigravity/mcp_config.json Restart the client and inspect its MCP status.
Hermes CLI / TUI / Desktop /Users/marc/.hermes/config.yaml through hermes Restart Hermes; use hermes mcp list and hermes mcp test rea.
OpenCode /Users/marc/.config/opencode/opencode.json through opencode Restart OpenCode, inspect its MCP status, and make a live REA tool call.

ChatGPT desktop uses the existing Codex configuration on the same host. Local stdio support means this route needs no additional ChatGPT target, hosted REA service, or tunnel. A standalone hosted ChatGPT web chat does not read these local files. See OpenAI’s MCP configuration documentation. A harness not registered in apply.py needs its own supported target adapter before the shared definition can reach it; for example, Claude Desktop is distinct from the existing Claude Code target.

Do not start npx ... mcp manually and leave it running in Terminal. In this configuration, each client starts its own REA process and maintains its own analysis state. For direct terminal use, invoke an ordinary CLI command instead:

npx -y rea-agents@6.7.0 --help
Step 4 — Verify a live connection in each harness#

Check that rea is connected in the harness’s MCP status, then ask the agent:

Use REA’s binary_session tool with an empty object to report the available analysis capabilities. Do not open or run a target application.

This confirms a real tool call without requiring a native analysis engine. Record successful clients per workstation. A configured entry or a passing CLI version check alone does not establish a working MCP connection. Missing optional providers can leave some operations unavailable while the MCP itself works. If tools remain absent after compilation, restart/reconnect the client and check runtime paths, startup errors, timeouts, and project overrides.

Optional — Analysis engines and workflow instructions#

Static JavaScript/Electron and .NET inspection can work without Hopper, Ghidra, or IDA. Deep native analysis requires an installed provider, configured on each workstation that needs it. Other target types have their own dependencies. Follow the REA installation guide for the chosen provider instead of installing every optional engine on every Mac.

REA also supplies a reverse-engineer-anything workflow skill. Its documented skill-only installation is:

npx skills add morluto/rea --skill reverse-engineer-anything

Install the instructions into the intended harness locations using that installer’s selection flow. This command installs instructions and references, not the MCP registration or analysis engines. Keep the instructions compatible with the pinned server’s actual tool schemas; repository instructions may be newer than the published package. MCP tools can be verified before this optional skill is installed.

Updates across computers#

Choose and check the new package version, update the single version pin in the master rea entry, distribute through pushmcp / pullmcp, download that same version on each workstation, compile, and restart clients. Refresh any installed workflow instructions as needed. This keeps package selection in the shared repository while runtimes and optional providers remain workstation dependencies.

References: REA manual registration and package runners, REA client-specific configuration and timeouts.


1.2 Existing Machine Sync (Token Rotation or Config Update)#

When a 1Password token is rotated or MCP master configuration changes are pushed from your primary machine:

  1. Update shell token (~/.zshrc) (only if token changed): Copy the token from 1Password (Vault: Homelab → Item: Mac OS .zshrc file):

    nano ~/.zshrc   # Update OP_SERVICE_ACCOUNT_TOKEN
    source ~/.zshrc
  2. Pull latest config from GitHub and recompile:

    cd ~/.mcp-config
    git pull

(The post-merge hook fires apply.py automatically. The pullmcp convenience alias performs this same pull from either workstation.)


2. 1Password Service Account Token Management#

All MCP servers that use op run require an OP_SERVICE_ACCOUNT_TOKEN. On this workstation the token is stored in local ~/.zshrc. The compiler copies it into the local Hermes and Codex MCP environment blocks; clients that rely on parent-shell inheritance must be launched from a shell where the token is loaded. See §1.1.9 for the per-harness behavior. The mcp alias compiles configuration but does not launch or refresh a client.

The Service Account (MCP-Access) has read access only to the Homelab-MCP vault. This is intentional — MCP secrets live in Homelab-MCP, not Homelab, Private, or any other vault.

Setting OP_SERVICE_ACCOUNT_TOKEN in .zshrc completely disables biometric Touch ID authentication for all op commands in that shell. The two modes are mutually exclusive.

The generated token is displayed only once. Save it to 1Password immediately before doing anything else.

2.1 Initial Token Creation#

If re-creating after revoking an old token, first run: unset OP_SERVICE_ACCOUNT_TOKEN Otherwise op will try to authenticate as the deleted service account and fail with authenticated as a service account.

env -u OP_SERVICE_ACCOUNT_TOKEN op service-account create "MCP-Access" --vault "Homelab-MCP:read_items"

Save the generated token to:

  • Vault: Homelab
  • Item: Mac OS .zshrc file
  • Field: OP_SERVICE_ACCOUNT_TOKEN

Then update ~/.zshrc and recompile:

export OP_SERVICE_ACCOUNT_TOKEN="ops_your_generated_token_here"
source ~/.zshrc
mcp

Repeat the local ~/.zshrc update, reload, and compilation on both workstations after creating or rotating the token.


2.2 Token Rotation vs. Re-creation#

Which method should you use?

Scenario Method Why
Standard hygiene / renewal Option A: Web UI Rotation Keeps the same Service Account. Old token expires gracefully.
Token leaked / exposed / deleted Option B: CLI Re-create Immediately kills access. Must unset first or token creation fails.

Option A: Routine Rotation (Web UI)#

  1. Open https://start.1password.com/developer-tools → Service accounts → select MCP-Access.
  2. Under Tokens, click Rotate Token → set expiration → copy the new ops_... token.
  3. Save to Vault: Homelab → Item: Mac OS .zshrc file.
  4. Update ~/.zshrc and recompile:
    nano ~/.zshrc   # Replace OP_SERVICE_ACCOUNT_TOKEN
    source ~/.zshrc
    mcp

Option B: Re-create after Deletion / Exposure (CLI)#

If the old/deleted token is still in your terminal environment, op service-account create will fail: authenticated as a service account. Run unset in Step 1 first.

  1. Unset the broken token:
    unset OP_SERVICE_ACCOUNT_TOKEN
  2. Create a new Service Account Token:
    env -u OP_SERVICE_ACCOUNT_TOKEN op service-account create "MCP-Access" --vault "Homelab-MCP:read_items"
    (Copy the generated ops_... token immediately.)
  3. Save to 1Password: Vault: Homelab → Item: Mac OS .zshrc file → Field: OP_SERVICE_ACCOUNT_TOKEN.
  4. Update ~/.zshrc and recompile:
    nano ~/.zshrc   # Replace OP_SERVICE_ACCOUNT_TOKEN
    source ~/.zshrc
    mcp
  5. Verify:
    op whoami
    # Expected: User Type: SERVICE_ACCOUNT

To verify the token was injected into Codex without exposing its value:

grep -c "OP_SERVICE_ACCOUNT_TOKEN" ~/.codex/config.toml

A non-zero result confirms injection without printing the token itself.


3. The Centralized Configuration Repo (.mcp-config)#

All master settings live inside a dedicated, local Git repository located at: /Users/marc/.mcp-config

3.1. Repository Structure#

  • config.json: The single source of truth configuration file. It contains a standard, flat list of all MCP servers (completely generic and client-agnostic).
  • apply.py: A Python compiler script that loads config.json, registers your software clients, filters placeholder servers ([COMMAND_PLACEHOLDER]), resolves op through the local PATH, and writes each client’s configuration. It emits Hermes’ mcp_servers section as YAML while preserving the rest of ~/.hermes/config.yaml; for op run servers, it copies OP_SERVICE_ACCOUNT_TOKEN into local generated configs. Hermes and OpenCode refuse to replace their target config when the token is absent. The Hermes and OpenCode configs are set to mode 0600, are local-only, and contain the service-account token; never copy them to Git or shared notes. Codex also receives the token explicitly because it isolates MCP subprocess environments. OpenCode’s adapter merges its managed server definitions into mcp.servers while preserving other JSON settings and unrelated servers. It writes standard JSON and refuses to overwrite an existing non-JSON/JSONC file rather than risk losing comments; OpenCode’s first-time setup starts with no config, so compilation creates the file safely. Keep server definitions in the master config.json.
  • .git/hooks/post-commit: A Git hook script that automatically triggers apply.py whenever a commit is executed in the repository.
  • .git/hooks/post-merge: A Git hook script that automatically triggers apply.py whenever a git pull successfully merges updates from GitHub.

4. Target Client Mapping#

The apply.py script registers and compiles the configuration to the following destination files:

  • antigravity-cli: ~/.gemini/config/mcp_config.json (Prerequisite: Section 1.1.3)
  • antigravity-2.0: ~/.gemini/antigravity/mcp_config.json (Prerequisite: Section 1.1.3)
  • antigravity-ide: ~/.gemini/config/mcp_config.json (Prerequisite: Section 1.1.3)
  • pi: ~/.pi/agent/mcp.json (Prerequisite: Section 1.1.3)
  • claude-code: ~/.claude.json (Prerequisite: Section 1.1.3)
  • codex: ~/.codex/config.toml (Prerequisite: Section 1.1.3). Unlike other clients, Codex sandboxes each MCP process to only its declared env block and does not inherit the parent shell environment. apply.py therefore injects OP_SERVICE_ACCOUNT_TOKEN directly into the env block of every op run server at compile time so that op can resolve secrets without triggering GUI prompts.
  • hermes: ~/.hermes/config.yaml, under the top-level mcp_servers key. The compiler owns the marked MCP block and preserves the remaining Hermes settings, including model and provider configuration. After sourcing ~/.zshrc, mcp hermes writes the token into each op run server’s local environment block, so CLI, TUI, and Desktop can all use the same generated config. Restart Hermes after recompilation; its Desktop icon can then launch normally. mcp hermes compiles settings but does not launch or restart the app.
  • opencode: ~/.config/opencode/opencode.json, under mcp.servers. The adapter translates each generic command/args entry to OpenCode V2’s local command array and maps env to environment. Existing JSON settings and unrelated MCP servers are preserved. For each op run entry, it injects OP_SERVICE_ACCOUNT_TOKEN; the generated file is mode 0600 and compilation refuses to replace it if the token is absent. The adapter accepts standard JSON (not JSONC with comments) to avoid stripping user comments. Restart OpenCode after recompilation; the compiler does not refresh a running client.

The compiler needs a format-specific adapter for clients whose configuration format differs from the generic JSON definitions. Hermes’ YAML and OpenCode’s local-server adapters are registered in TARGETS; the master config.json remains the source of truth.

5. Active Compiled MCP Servers#

The pipeline currently compiles the following 35 shared MCP server definitions for all registered clients. Actual availability remains workstation-specific and depends on local runtimes, credentials, permissions, and network reachability:

  • cloudflare: Cloudflare DNS, Tunnels, Access policies, and edge service management.
  • docker-10-1-2-100: Remote Docker container management for host 10.1.2.100.
  • docker-10-1-2-202: Remote Docker container management for host 10.1.2.202.
  • docker-10-1-2-217: Remote Docker container management for host 10.1.2.217.
  • docker-10-1-2-230: Remote Docker container management for host 10.1.2.230.
  • docker-10-1-2-231: Remote Docker container management for host 10.1.2.231.
  • docker-10-1-2-233: Remote Docker container management for host 10.1.2.233.
  • docker-10-1-2-4: Local Docker daemon container management (unix:///var/run/docker.sock).
  • docker-72-11-147-220: Remote Docker container management for VPS (72.11.147.220).
  • gdrive: Google Drive API file operations and sheet management. (Prerequisite: Section 1.1.6)
  • git: Local repository Git operations (adds, commits, diffs, branches, worktrees).
  • github: GitHub API integration (remote repos, issues, pull requests, workflows).
  • home-assistant: Home automation controls and entities.
  • macos-mcp: macOS desktop UI automation, accessibility controls, and screen interaction. (Prerequisite: Section 1.1.4)
  • n8n-mcp: Workflow automation and node management.
  • nut: Network UPS Tools server monitoring (ups1, ups2, ups3, ups4 on 10.1.2.230:3493). (Prerequisite: Section 1.1.4)
  • pihole-primary: DNS sinkhole and ad-blocking controls for primary server.
  • pihole-secondary: DNS sinkhole and ad-blocking controls for secondary server.
  • proxmox-hp1: VM, container, cluster, and storage management for Proxmox HP1 cluster. (Prerequisite: Section 1.1.4)
  • proxmox-hp2: VM, container, cluster, and storage management for Proxmox HP2 cluster. (Prerequisite: Section 1.1.4)
  • proxmox-hp3: VM, container, cluster, and storage management for Proxmox HP3 cluster. (Prerequisite: Section 1.1.4)
  • proxmox-hp4: VM, container, cluster, and storage management for Proxmox HP4 cluster. (Prerequisite: Section 1.1.4)
  • proxmox-hp5: VM, container, cluster, and storage management for Proxmox HP5 cluster. (Prerequisite: Section 1.1.4)
  • proxmox-hp7 (HP7Proxmox): VM, container, cluster, and storage management for Proxmox HP7 node. (Prerequisite: Section 1.1.4)
  • proxmox-mm: VM, container, cluster, and storage management for Proxmox MM cluster. (Prerequisite: Section 1.1.4)
  • rea: Reverse engineering and inspection tools for local applications, binaries, and runtimes; package rea-agents@6.7.0. Optional analysis providers are workstation-specific.
  • shell-exec: Direct terminal command execution, job management, and process control.
  • synology-hp1: Synology DSM HP1 monitoring and administration through the DSM Web API. (Prerequisite: Section 1.1.4)
  • truenas-hp1: TrueNAS storage node HP1 dataset and user management. (Prerequisite: Section 1.1.4)
  • truenas-hp2: TrueNAS storage node HP2 dataset and user management. (Prerequisite: Section 1.1.4)
  • truenas-hp3: TrueNAS storage node HP3 dataset and user management. (Prerequisite: Section 1.1.4)
  • truenas-hp6: TrueNAS storage node HP6 dataset and user management. (Prerequisite: Section 1.1.4)
  • truenas-hp7: TrueNAS storage node HP7 dataset and user management. (Prerequisite: Section 1.1.4)
  • unifi: Network clients, devices, and firewall management.
  • xcode-tools: Xcode simulator controls, builds, and iOS test utilities.

The shared deployment contains 35 MCP definitions, including REA. The deployment steps and current verification scope are recorded in #1.1.10 REA — Install, Configure, and Run Across Harnesses.

5.1 Dependency & Verification Matrix#

The matrix below groups MCPs that share a dependency. It is the checklist for a blank Mac: install or restore the local dependency, provide credentials through 1Password where required, verify the external service, and only then interpret the client’s /mcp status. Homebrew-managed tools are catalogued in Mac OS - Brewfile.

For a specific server, check its command in the master ~/.mcp-config/config.json: if it starts with op run --, it requires both the service-account token to reach the client subprocess and the server-specific secrets referenced by that op run. Other servers use the credential source listed in the matrix (or their own sign-in/configuration flow); they do not automatically need OP_SERVICE_ACCOUNT_TOKEN.

MCP server(s) Local dependency / installation Credentials External requirement Verification
All op run servers op resolved through PATH (/opt/homebrew/bin/op on Apple Silicon; /usr/local/bin/op on Intel) and OP_SERVICE_ACCOUNT_TOKEN in local ~/.zshrc MCP-Access token in Homelab → Mac OS .zshrc file; service account reads Homelab-MCP 1Password service account is active source ~/.zshrc; op whoami reports SERVICE_ACCOUNT
cloudflare Node/npm package @cloudflare/mcp-server-cloudflare; binary mcp-server-cloudflare on PATH CLOUDFLARE_API_TOKEN in Homelab-MCP Internet and Cloudflare API access command -v mcp-server-cloudflare; query a read-only account or zone resource
docker-10-1-2-4, docker-10-1-2-100, docker-10-1-2-202, docker-10-1-2-217, docker-10-1-2-230, docker-10-1-2-231, docker-10-1-2-233, docker-72-11-147-220 Node/npm package mcp-server-docker; Docker CLI; local engine for 10.1.2.4; SSH/network access for remote targets DOCKER_HOST values in the compiled config Local or remote Docker daemon must be running command -v mcp-server-docker; test each Docker context/host. Offline hosts may remain connected with zero usable tools
gdrive Node/npm via npx; launched as npx -y @modelcontextprotocol/server-gdrive ~/.gdrive-server-credentials.json Google Drive API access and valid OAuth refresh token Confirm the credential file exists without printing it, then list a Drive resource
git Node/npm package @cyanheads/git-mcp-server; binary git-mcp-server on PATH Non-secret MCP logging/transport settings Local Git repositories command -v git-mcp-server; query a repository status
github Node/npm package @modelcontextprotocol/server-github; binary mcp-server-github on PATH GITHUB_PERSONAL_ACCESS_TOKEN in Homelab-MCP Internet and GitHub API access command -v mcp-server-github; query a repository or issue
home-assistant Homebrew uv; launched as uvx ha-mcp HOMEASSISTANT_URL, HOMEASSISTANT_TOKEN, HA_VERIFY_SSL Home Assistant API reachable uvx --help; then verify the server in /mcp
macos-mcp Python package macos-mcp plus ~/.mcp-config/bin/macos-mcp-wrapper; on Intel, use a uv-managed Python 3.12 virtual environment if Homebrew Python is unavailable None in MCP config Accessibility, Screen Recording, and Automation permissions belong to the server process (~/mcp-servers/macos-mcp/.venv/bin/python3), not the MCP host app. Approve the native macOS permission prompt for the running process, then restart the MCP server. Do not manually add a uv-managed interpreter in System Settings; its path can change on update. Confirm the wrapper, grant the process permission through the native prompt, restart the MCP server, and check its connection status
n8n-mcp Node/npm package n8n-mcp; binary n8n-mcp on PATH N8N_API_URL, N8N_API_KEY, MCP_MODE, LOG_LEVEL n8n API reachable command -v n8n-mcp; then list n8n tools
nut ~/mcp-servers/mcp-nut/.venv plus the custom server.py; install mcp[cli] NUT_HOSTS, NUT_PORT, PYTHONUNBUFFERED UPS services reachable on the configured hosts Confirm server.py exists, then perform a read-only UPS status query
pihole-primary, pihole-secondary Node/npm package mcp-pihole-server; binary mcp-pihole on PATH PIHOLE_URL, PIHOLE_PASSWORD Each Pi-hole endpoint reachable command -v mcp-pihole; then perform a read-only status query
proxmox-hp1, proxmox-hp2, proxmox-hp3, proxmox-hp4, proxmox-hp5, proxmox-hp7 (HP7Proxmox), proxmox-mm ~/mcp-servers/mcp-proxmox/.venv from the public mcp-proxmox repository; install requirements and editable package as in §1.1.4 Proxmox API URL, token ID, and secret references in Homelab-MCP → MCP-Secrets Target Proxmox API reachable; self-signed SSL is handled by PROXMOX_VERIFY=false command -v is not sufficient; verify each server in /mcp and expect 118 tools when available, then run a read-only node query
rea Node.js and npm; npx -y rea-agents@6.7.0 mcp pinned in the master config; optional analysis engines per workstation None for the basic local MCP registration npm registry access for initial package download; target-specific providers when needed Restart each harness, confirm rea is connected, and call binary_session with {}; see §1.1.10
shell-exec Node/npm package shell-exec-mcp; binary shell-exec-mcp on PATH None in MCP config Local shell access command -v shell-exec-mcp; run a harmless read-only command
synology-hp1 ~/mcp-servers/synology-mcp/.venv from the public rafalr100/synology-mcp repository; install mcp[cli]>=1.0.0,<2.0.0 before pip install -e . SYNOLOGY_USER and SYNOLOGY_PASS reference Homelab-MCP → MCP-Secrets; no secret values in config HP1 DSM Web API reachable at https://10.1.2.221:5001; account allowed from 10.1.2.0/24 Run the read-only smoke test through op run, then restart the client and expect synology-hp1: connected in /mcp
truenas-hp1, truenas-hp2, truenas-hp3, truenas-hp6, truenas-hp7 ~/mcp-servers/mcp-truenas/.venv plus the custom server.py and supporting files; install mcp[cli] TRUENAS_URL, TRUENAS_API_KEY, TRUENAS_VERIFY_SSL Each TrueNAS API endpoint reachable Confirm server.py exists, then perform a read-only dataset or system query
unifi Node/npm package @thelord/unifi-mcp-server; binary unifi-mcp-server on PATH UNIFI_GATEWAY_IP, UNIFI_API_KEY, UNIFI_VERIFY_SSL, LOG_CONSOLE UniFi gateway reachable command -v unifi-mcp-server; then query devices or clients
xcode-tools Node/npm package xcodebuildmcp; Xcode and Xcode Command Line Tools None in MCP config Xcode project/simulator available for build tasks command -v xcodebuildmcp; then verify the Xcode MCP tools

The mcp-truenas and mcp-nut source directories contain local custom server files and are not cloned by MCP-Config-MacOS. On a new Mac, copy or restore those source files from the working workstation before running mcp; installing only the Python SDK is not sufficient.


6. Automated Compilation Pipeline (Git Hooks)#

For instructions on creating and activating these Git hooks on a new machine, see #1.1.2 Set Up Git Hooks.

To make updates effortless, Git hooks are set up to trigger compilation automatically:

  • post-commit Hook: Located at /Users/marc/.mcp-config/.git/hooks/post-commit. Fires automatically when you execute a local commit:
    git add config.json
    git commit -m "update: configuration description"
  • post-merge Hook: Located at /Users/marc/.mcp-config/.git/hooks/post-merge. Fires automatically when you pull updates (git pull) from the remote GitHub repository:
    git pull

Both hooks execute the compiler script:

#!/bin/bash
/Users/marc/.mcp-config/apply.py

Whenever you commit changes locally or pull updates from GitHub, the compiler is automatically invoked, compiling fresh adapted target mcp_config.json files to all target paths in a single execution.

6.1 Updating Master Configurations (~/.mcp-config)#

All git commands below must be executed inside your master configuration directory:

cd ~/.mcp-config

Use this whenever you pushed configuration changes from another Mac and want to update your current machine:

cd ~/.mcp-config
git pull origin main

(Git automatically fetches updates and fires the post-merge hook to compile all AI client configs).

Method B: Forced Reset (If local files are broken or out of sync)#

Use this if git pull fails due to local file conflict errors and you want to discard local changes to align 100% with GitHub:

cd ~/.mcp-config
git fetch origin
git reset --hard origin/main
git clean -fd
./apply.py   # Required: Hard reset bypasses git hooks, so manual compile is needed

6.2 Workstation Sync Shortcuts#

The tracked aliases file provides two shortcuts for synchronizing the separate MCP repository:

  • pushmcp: Enters ~/.mcp-config, stages config.json, apply.py, and bin/macos-mcp-wrapper, commits only when those files changed, and pushes main to GitHub. The post-commit hook then runs apply.py to compile all client configurations.
  • pullmcp: Runs git pull origin main in ~/.mcp-config. The post-merge hook then runs apply.py to compile all client configurations.

These shortcuts are separate from pushscripts and pullscripts, which operate only on the ~/Scripts repository. The exact function and alias definitions are documented in Mac OS - Aliases Management.


7. Proxmox MCP Server Installation (macOS)#

This guide details the manual build process for setting up the Proxmox MCP server environment on macOS. On Intel Macs, use the uv-managed Python 3.12 described in Section 1.1.4 instead of waiting for a Homebrew Python source build.

7.1 Prerequisites#

  • Proxmox VE: Access to a Proxmox cluster or node.
  • Python 3.12: Required for the MCP server environment. Prefer uv-managed Python 3.12 on Intel Macs.
    brew install python@3.12
  • API Token: Created in Proxmox (Datacenter > Permissions > API Tokens). Ensure the token has sufficient permissions (e.g., PVEAuditor or PVEVMAdmin) and ‘Privilege Separation’ is unchecked.

7.2 Server Installation#

Run the following commands to clone the repository and set up the Python environment in a dedicated directory:

# Create and enter a dedicated directory for MCP servers
mkdir -p ~/mcp-servers
cd ~/mcp-servers

# Clone the Proxmox MCP repository
git clone https://github.com/bsahane/mcp-proxmox.git
cd mcp-proxmox

# Create a virtual environment
python3 -m venv .venv

# Activate the virtual environment
source .venv/bin/activate

# Install requirements
pip install -r requirements.txt

# Install the package in editable mode to resolve module paths
pip install -e .

7.3 Configuration Notes#

  • PROXMOX_API_URL: Do not include /api2/json at the end of the URL; the server library appends this automatically.
  • PROXMOX_TOKEN_ID: Format is typically user@realm!tokenname (e.g., root@pam!gemini).
  • PROXMOX_VERIFY: Set to "false" to allow connections to nodes using self-signed SSL certificates.

8. Troubleshooting Common Issues#

8.1. Symptom: Half of the MCP servers are missing or missing checkmarks at CLI launch#

  • Cause: 1Password Session Lock / Startup Timeout. Most servers use /opt/homebrew/bin/op run to inject secrets. When 1Password CLI is locked or cold, the initial biometric authentication call takes 10–15 seconds. Because AI clients enforce a 5-second per-server startup timeout, any server waiting for 1Password authentication times out and is skipped.
    • Fix: Pre-warm 1Password CLI before launching your AI CLI session by running:
      op run -- echo "1Password warm"
      Once authenticated, op run secret resolution drops to ~40ms, allowing all 16 servers to load cleanly.

8.2. Symptom: Server hangs indefinitely on “Initializing…”#

  • Cause: 1Password Session Lock. The 1Password CLI session timed out, and op run is silently waiting for biometric authentication in the background.
    • Fix: Run op signin in your standard terminal, complete authentication, and restart the CLI.

8.3. Symptom: Failed to reload MCP config: failed to stop mcp instance: macos-mcp: exit status 143 during /mcp hot-reload#

  • Cause: Unix SIGTERM Exit Code. When performing an in-session hot reload (/mcp), the CLI sends SIGTERM to stop running servers. Python processes default to exit code 143 when killed with SIGTERM, which some CLI watchers misidentify as a crash and abort the reload.
    • Fix: Use the wrapper script at ~/.mcp-config/bin/macos-mcp-wrapper in config.json. The wrapper traps SIGTERM, terminates macos-mcp gracefully, and exits with status 0.

8.4. Symptom: Error: invalid trailing data at the end of stream#

  • Cause: Stdout Pollution. The MCP server wrote plain-text logs or status messages to standard output instead of valid JSON-RPC format.
    • Fix: Verify you have "LOG_CONSOLE": "false" configured (for Node.js) or that the server is logging only to stderr.

8.5. Symptom: SSH-based MCP servers (e.g. Remote Docker hosts) fail to start or time out#

  • Cause: Missing SSH Keys / Empty SSH Agent. If your private SSH keys are encrypted with a passphrase and your local SSH agent has no unlocked identities, non-interactive SSH connections launched by the MCP process will silently block waiting for passphrase input until the 5-second startup timeout hits.
    • Fix: Ensure your keys are loaded into the ssh-agent before running your AI CLI session:
      ssh-add --apple-use-keychain ~/.ssh/id_ed25519
  • Cause: Untrusted SSH Host Key (known_hosts prompt). If you have never manually connected to a target remote host from the command line, SSH will attempt to prompt Are you sure you want to continue connecting (yes/no/[fingerprint])?. Because the server is launched in a headless background sub-process, it hangs indefinitely on this prompt.
    • Fix: Perform a manual connection to the target IP one time from your terminal to verify and accept the host key into ~/.ssh/known_hosts:
      ssh root@10.1.2.100 exit

8.6. Symptom: Codex triggers repeated “1Password Access Requested” GUI popups on every launch#

  • Cause: Codex MCP Environment Sandboxing. Unlike Antigravity, Claude Code, and Pi-CLI — which pass the full parent shell environment (including OP_SERVICE_ACCOUNT_TOKEN) to MCP child processes — Codex explicitly constructs an isolated environment per server using only what is declared in the [mcp_servers."name".env] block of config.toml. Since OP_SERVICE_ACCOUNT_TOKEN is only set in ~/.zshrc, the op run subprocesses spawned by Codex never see it and fall back to the 1Password desktop app GUI, producing one popup per op run server.
    • Fix: The apply.py compiler now reads OP_SERVICE_ACCOUNT_TOKEN from the shell environment at compile time and injects it into the env block of every op run server in the Codex TOML output. The token never enters config.json or git history. Re-compile after any token rotation:
      source ~/.zshrc
      cd ~/.mcp-config && ./apply.py codex
      Or simply commit any change — the post-commit hook fires apply.py for all clients automatically.

8.7. Symptom: A Proxmox MCP remains active while its host is offline#

  • Cause: The MCP process can start and advertise its tools even when the configured Proxmox API endpoint is temporarily unreachable. This status reflects the MCP process, not the power state of the target host.
  • Action: This is expected for an offline server. Do not remove the MCP definition or recreate credentials solely because the host is offline; API calls will work once the target becomes reachable again.

8.8. Symptom: Many MCP servers fail on a newly provisioned workstation#

  • Cause: The shared compiler intentionally deploys the complete server definition list to every registered client. A failed entry usually means that workstation is missing its local Node package, Python virtual environment, OAuth file, Docker/Xcode dependency, privacy permission, or access to the target service. It does not imply that the shared configuration or the other Macs are broken.
  • Action: Treat each failure according to the dependency matrix in Section 5.1. Confirm the local executable or virtual environment first, then verify credentials and network access. It is valid for optional servers such as Xcode MCP or remote Docker targets to remain offline on a workstation that does not use them.

8.9. Symptom: Hermes Desktop shows an op service-account credential error#

  • Cause: The generated Hermes config has a missing or stale OP_SERVICE_ACCOUNT_TOKEN in an op run server’s environment block.
  • Fix: Load the current token and recompile the Hermes target:
    source ~/.zshrc && mcp hermes
    Then fully quit and reopen Hermes from its Desktop icon. The compiler stores the token in ~/.hermes/config.yaml, protected by mode 0600; it does not write the token to config.json or Git. If the error persists, verify op whoami reports User Type: SERVICE_ACCOUNT, then test the server with hermes mcp test <server>.
  • Status interpretation: hermes mcp list reports configured/enabled entries; it does not test connections. In Desktop, On, unused means enabled but not yet used, not verified healthy. Use a connection test or a real tool call.

8.10. Symptom: macOS shows a “Device Control and Data Access” dialog for osascript#

  • Observed cause: Hermes logs identified its configured macos-mcp server failing because the Python process lacked Accessibility permission. The Hermes gateway itself is supervised by an osascript JavaScript wrapper. The prior log review did not prove which script initiated the specific macOS permission request, so the dialog name alone is not enough to attribute it.
  • Temporary Hermes-only fix: Add enabled: false to the macos-mcp entry under mcp_servers in ~/.hermes/config.yaml, then run hermes gateway restart. Verify the entry is disabled and no Hermes macos-mcp process starts. This was applied on the Mac Studio and MacBook Air on 2026-10-18.
  • Persistence: apply.py regenerates the compiler-managed Hermes MCP block from the shared ~/.mcp-config/config.json. Since macos-mcp remains in that master list and the current compiler does not preserve per-server enabled flags, a later full compile can re-enable it. A persistent policy requires changing the master config/compiler; do not rely on the local Hermes override after recompilation. Other harnesses have separate macos-mcp processes and are not stopped by the Hermes-only fix.