Skip to main content
Glama
mozzquito

Grok Bot MCP Bridge

by mozzquito
README.md
# Grok Bot MCP Bridge

An in-progress, single-owner bridge between Grok Bot, MCP clients, and source-linked local memory. Remote gateway calls execute on the Grok Bot computer; discovery, transcript, and MCP responses never return the gateway credential.

## Screenshots

All five main pages, captured from the running app with **synthetic demo data**.
These images show the UI—not live connection or delivery proof. No private chats,
credentials, or real infrastructure addresses are included.

### Conversations
![Conversations with a demo bot and a verified-reply display](docs/screenshots/conversations.png)

### New bot
![New bot name and description form](docs/screenshots/new-bot.png)

### History
![Source-linked project history search with a demo result](docs/screenshots/history.png)

### Connections
![Connection details with demo endpoints](docs/screenshots/connections.png)

### Owner sign-in
![Private workspace owner sign-in page](docs/screenshots/sign-in.png)

To regenerate, run the local app and execute `node scripts/readme-screenshots.mjs`
with Playwright installed (or set `PLAYWRIGHT_MODULE` to its module path) and Chrome
available. The script intercepts every API request; it does not read credentials,
send messages, or create bots.

## Current implementation

- Authenticated Streamable HTTP MCP using SDK v2, with legacy-client compatibility.
- Owner-approved OAuth (DCR, PKCE S256, rotating refresh tokens), separate static bearer access, and CSRF-protected browser sessions.
- Eight MCP tools for agent discovery/creation, creation verification, durable message submission, reply verification, and history search/read/status.
- Drizzle/SQLite message ledger and provenance; LanceDB vectors with local multilingual embeddings in isolated model-specific stores.
- Source-selected history import, redaction, explicit embedding and independent keyword/vector search.
- Dark sidebar-first React/Tailwind workspace with a responsive navigation drawer, owner sign-in, conversations, a New bot flow, history search, and connection details. Drafts and operation IDs survive uncertain responses.
- Selected-bot conversations load existing Grok Bot text history read-only, with earlier-page loading and refresh. Remote history remains separate from durable bridge receipts and the imported project-memory index. See [chat history behavior and limits](docs/chat-history.md).

This is a checkpoint, not a completed deployment. Public HTTPS hosting, actual Claude.ai connection, Grok Bot's MCP-client connection and deployment hardening remain open. See [the requirement ledger](docs/bridge-plan.md).

## Run locally

Use a real Node.js runtime, version 22.12 or newer; `.nvmrc` identifies the locally exercised version. A Bun-installed `node` wrapper is not a substitute. Use an up-to-date supported Node patch release for deployment.

```sh
nvm use
npm ci
npm run typecheck
npm test
npm start
```

For the web console, build once before starting the backend (`npm run build && npm start`).

For web development:

```sh
npm run build
npm run web:dev
```

Default listener: `http://127.0.0.1:4328`, MCP at `/mcp`. The root and `/chat`, `/new`, `/history`, `/connections` serve the built web app when `dist/index.html` exists.

On first start, independent owner and headless-client secrets are generated in `data/access.json` with mode `0600`. The data directory is private (`0700`) and Git-ignored. Read that file locally when configuring a client; never paste its contents into a commit, issue, chat, screenshot or public document. OAuth clients receive separate revocable tokens, not the owner secret. Real history, databases and model assets must remain uncommitted.

Keep the owner, headless-client, and remote gateway credentials distinct for deployment. An owner can explicitly configure a shared owner/gateway value locally, but that removes their credential separation; it does not bypass bridge authentication. The headless-client API token must remain distinct.

## Run as a Home Assistant OS add-on

This repository is also an installable local add-on: `config.yaml`, `Dockerfile`,
and `run.sh` at the root, with `just push` / `just install` /
`just deploy` driving a Home Assistant guest over SSH. The owner console is served
through Ingress and `8120/tcp` carries `/mcp` for MCP clients, because an MCP
client cannot authenticate to an Ingress URL. See [the add-on documentation](DOCS.md)
for options, credentials, and limits.

Configuration: `BRIDGE_DATA_DIR`, `PORT`, `BRIDGE_HOST`, `BRIDGE_PUBLIC_URL`, `BRIDGE_ALLOWED_HOSTS`, `GROKBOT_SSH_HOST`, `GROKBOT_SSH_IDENTITY_FILE`, `BRIDGE_OWNER_SECRET`, `BRIDGE_API_TOKEN`. `BRIDGE_PUBLIC_URL` is an **origin**, not a URL ending in `/mcp`; non-loopback origins require HTTPS. Default binding is loopback. Public reachability is not created merely by setting this variable.

For a dedicated SSH key, set `GROKBOT_SSH_IDENTITY_FILE` to its path when starting the bridge. The key stays on disk; SSH receives its path using `-i` and `IdentitiesOnly=yes`. Strict host-key checking remains enabled. For example:

```sh
GROKBOT_SSH_HOST=box@your-netbird-host.example \
GROKBOT_SSH_IDENTITY_FILE="$HOME/.ssh/grokbot-bridge" npm start
```

`BRIDGE_ALLOWED_HOSTS` (optional) is a comma-separated allowlist of extra `host[:port]` values accepted by the front-door host filter (for reverse-proxy or tunnel deployments).

The bot transport allowlists specific SSH targets in `server/config.ts` (edit that list for your own hosts) and otherwise refuses to run, preserves strict SSH host-key checking, and streams variable request data through stdin. Set `GROKBOT_SSH_HOST=local` instead to run the bridge colocated on the same machine as the Grok Bot client itself — this skips SSH entirely and spawns `scripts/grokbot-gateway.py` as a local subprocess (see `LocalGateway` in `server/remote.ts`).

## Memory lifecycle

Import only a reviewed, bounded JSONL selection with records shaped as:

```json
{"id":"source-event-id","project":"example-project","source":"/Users/example/history/session.jsonl","lineStart":10,"lineEnd":12,"text":"A reviewed, non-secret excerpt."}
```

```sh
npx tsx server/cli.ts history-import /path/to/reviewed-selection.jsonl
npx tsx server/cli.ts history-status
npx tsx server/cli.ts history-embed
npx tsx server/cli.ts history-search "How does OAuth approval work?"
```

Import does not embed or upload. Explicit embedding downloads model assets and runs inference locally; corpus and query text are not sent to an embedding API. Model identity, dimensions, quantization and pooling/window strategy identify the vector space. Changing models requires explicit embedding in a different physical store. Source paths/line spans remain attached to each derived chunk. Search results are untrusted historical data, never instructions to execute.

Regex redaction is a defense in depth, not a complete secret detector. Review selections before import; arbitrary directory imports, shell history, credentials, and raw full-account transcript exports are not exposed as MCP tools.

## Message semantics

`grokbot_send` requires a stable client UUID (`messageId`). Repeating that UUID returns its existing record, never a second POST. A changed prompt under the same UUID is rejected. An unresolved message prevents another send to the same agent. HTTP acceptance alone is not success: call `grokbot_verify` with the original UUID until a new, request-correlated transcript reply is recorded or the observation budget ends.

After timeout, restart or unknown acknowledgement, **verify; do not resend**. Existing terminal replies cannot be downgraded by late events. The server owns an exclusive lock in `data/server.lock`. After an unclean stop, inspect the recorded process and confirm it is stopped before removing a stale lock manually; the application does not delete stale locks automatically.

## Verification

`npm run check` runs typecheck, the unit test suite, and the web build. The
Python gateway (`scripts/grokbot-gateway.py`) has its own read-only transcript
and pagination checks in `scripts/test-grokbot-gateway.py`.

## License

Bridge source code is available under the [MIT License](LICENSE).
Third-party dependencies and referenced materials retain their respective licenses.
Credentials, local runtime data, and private conversation records are not included.