---
name: gbrain-vault-mcp
description: Operate GBrain (garrytan/gbrain) as a semantic retrieval layer over the Syncthing-mirrored Obsidian vault on the VPS — install, MCP wiring into Hermes gateway, freshness cron, and the PGLite single-writer constraint.
---

# GBrain vault MCP on the VPS

## What this is

GBrain v0.42.73.2 (Bun/TypeScript, PGLite embedded Postgres) indexes `/root/.hermes/vault` (56 pages, 116 chunks, embedded via OpenAI text-embedding-3-large, 1536 dims) and exposes 106 MCP tools over stdio. Hermes gateway spawns it as `mcp_servers.gbrain` in config.yaml.

**Division of labor:** Obsidian = static markdown storage. GBrain = semantic compute/retrieval on top. Built-in Hermes memory = facts + gotchas + skill pointers. GBrain does NOT replace built-in memory; it answers "what's in the vault" when pinned memory doesn't have it.

## Install (already done — reference only)

- Bun 1.3.14 at `/root/.hermes/bun/` (BUN_INSTALL override — /root is read-only)
- `bun install -g github:garrytan/gbrain` (NOT npm — npm `gbrain` is a squatter)
- State at `/root/.hermes/gbrain-home/` (GBRAIN_HOME honored)
- Brain DB at `/root/.hermes/gbrain-home/brain/` (PGLite, schema v125)
- Search mode: `conservative` (NOT the default `tokenmax` — 25x cost difference)

## Critical constraints

1. **PGLite single-writer**: only ONE process can open the brain DB. The gateway's `gbrain serve` holds it 24/7. Any CLI command (`gbrain import`, `gbrain query`, `gbrain stats`) fails with "database is already open" while the gateway runs.
2. **Read-only /root**: Bun and GBrain state must live under `/root/.hermes/`. `GBRAIN_HOME=/root/.hermes/gbrain-home` is honored; without it, `gbrain init` fails with EROFS on `/root/.gbrain`.
3. **mcp==1.0.0 SDK incompatibility**: the venv pins mcp 1.0.0 whose `stdio_client()` has no `errlog` kwarg. Hermes 0.19.0 passes it unconditionally. Fix: the PGLITE-SHIM patch in `tools/mcp_tool.py` line ~2308 checks `inspect.signature(stdio_client)` before passing `errlog`. **This patch is wiped by `pip install --force-reinstall`** — reapply after any venv rebuild.
4. **MCP surface is read-only**: the 106 tools include `query`, `search`, `get_page`, `put_page`, `traverse_graph` etc. but NO `import` or `embed` tools. Freshness must go through the CLI, which requires the gateway to be stopped.

## Freshness cron

`/root/.hermes/scripts/gbrain-refresh.sh` runs every 30 min via root crontab:
1. `systemctl stop hermes-gateway`
2. `gbrain import /root/.hermes/vault/`
3. `gbrain embed --stale`
4. `systemctl start hermes-gateway`

Log: `/root/.hermes/logs/gbrain-refresh.log`. Typical run: <1s import (all pages cached), <1s embed, ~5s total downtime.

## MCP wrapper

`/root/.hermes/bin/gbrain-mcp` — bash wrapper that sets `PATH`, `GBRAIN_HOME`, `GBRAIN_NO_ONBOARD_NUDGE=1`, then execs `gbrain "$@"`. Referenced in config.yaml as the MCP server command.

## Config entry (config.yaml)

```yaml
mcp_servers:
  gbrain:
    command: /root/.hermes/bin/gbrain-mcp
    args: ["serve"]
```

The `args` MUST be a YAML list, not a quoted string. If `hermes config set` writes it as `'["serve"]'` (string), fix by hand in nano/vim or sed.

## Testing the wiring

Ask a question whose answer is in the vault but NOT in pinned memory (e.g., "What did the Stripe JD say about comp bands?"). If the agent calls gbrain `query` and returns sourced results, routing works. If it answers from memory, the session's tool list was built before gbrain registered — start a fresh session.

## Useful commands (gateway must be stopped)

```bash
systemctl stop hermes-gateway
/root/.hermes/bin/gbrain-mcp query "your question"
/root/.hermes/bin/gbrain-mcp stats
/root/.hermes/bin/gbrain-mcp doctor --json
systemctl start hermes-gateway
```

## Upgrade path

`gbrain upgrade` handles self-update + schema migrations. After upgrading Bun or the venv, verify:
1. `/root/.hermes/bun/bin/bun --version` works
2. `/root/.hermes/bin/gbrain-mcp --version` works
3. PGLITE-SHIM patch still present in mcp_tool.py
4. Gateway restarts cleanly with gbrain MCP connected
