Skip to main content
Glama
README.md
# void-bridge — Void ↔ Hermes control surface

A per-machine bridge that exposes your Void Editor workspace (and its git
remotes) to Hermes / any MCP client as a clean, path-confined tool surface.
It lets the agent **search, read, write, reset, and git-push/pull** your host
files and remote repos without shelling into your machine ad hoc.

## Layout

- `bridge.py` — dependency-free stdlib HTTP server (Bearer-token auth).
  Every path is confined to `VOID_BRIDGE_ROOT`.
- `mcp_server.py` — FastMCP wrapper reusing the *same* functional API, so the
  MCP tools and the HTTP endpoints behave identically.
- `run.sh` — venv bootstrap + launcher.
- `void_bridge.service` — systemd user unit.

## Run (HTTP)

```bash
cd ~/Projects/void-bridge
VOID_BRIDGE_TOKEN=$(openssl rand -hex 24) VOID_BRIDGE_ROOT=$HOME/Projects ./run.sh
```

Health check: `curl -H "Authorization: Bearer $TOKEN" localhost:8787/health`

## Run (MCP for Void / MCP clients)

```bash
. .venv/bin/activate
pip install mcp
python3 mcp_server.py        # stdio transport
```

Point your MCP client (Void extension host, etc.) at this script. Tools:
`read_file, search, tree, write_file, reset, git_status, git_commit,
git_push, git_pull, remotes`.

## HTTP API

All calls: `Authorization: Bearer <VOID_BRIDGE_TOKEN>`, JSON in/out.

| Method | Path            | Body / Query                         | Effect                          |
|--------|-----------------|--------------------------------------|---------------------------------|
| GET    | `/health`       | —                                    | `{ok, root}`                    |
| GET    | `/tree`         | `?path=&depth=`                      | workspace tree                  |
| GET    | `/read`         | `?path=`                             | file content (≤5MB)             |
| GET    | `/remotes`      | —                                    | repos + remotes + ahead count   |
| POST   | `/search`       | `{pattern, path, glob, limit}`       | regex search (ripgrep)          |
| POST   | `/write`        | `{path, content}`                    | write/create file               |
| POST   | `/reset`        | `{path, mode}`                       | `backup`→.voidbak / `git`→HEAD   |
| POST   | `/git/status`   | `{repo}`                             | `git status -b --porcelain`     |
| POST   | `/git/commit`   | `{repo, message, all}`               | commit                          |
| POST   | `/git/push`     | `{repo}`                             | push to origin                  |
| POST   | `/git/pull`     | `{repo}`                             | ff-only pull from origin        |

## Security notes

- All paths are resolved and confined to `VOID_BRIDGE_ROOT`; symlink/escape
  attempts are rejected.
- Bind to `127.0.0.1` only. Do **not** expose the port to the network without
  a reverse proxy + TLS.
- `reset` with `mode:"git"` runs `git checkout -- .` (local restore). To pull
  remote state over local, call `/git/pull`.
- The token is the only auth — keep it out of git (`.env` is gitignored).