openrhyme-mcp
Official# openrhyme-mcp
A thin [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the timeline captured by the [OpenRhyme engine](https://github.com/OpenRhyme/OpenRhyme) to any agent — Claude, local models, your own scripts — over stdio.
> **Status:** MVP implemented on this branch — a stdio MCP server exposing the engine's raw event timeline and app-allowlist controls, tested against a fixture store and a fake engine binary. The engine it depends on ([OpenRhyme/OpenRhyme](https://github.com/OpenRhyme/OpenRhyme)) has its Part 1 (capture) complete. Pending: dogfooding against a live engine capture; richer retrieval (sessions, search, embeddings) is future work.
## What it is, and is not
OpenRhyme is a local-first, open-source "Computer History" for macOS: a Swift daemon reads your activity through the accessibility API, stores it in tiered SQLite, and compacts it without any bundled model. This repository is the **agent-facing door** to that data. It:
- speaks MCP over **stdio**, so any agent host (Claude Desktop, Claude Code, …) can spawn it;
- reads the engine's SQLite tiers **read-only**;
- shells out to the `openrhyme` CLI (`openrhyme <cmd> --json`) for control commands;
- contains **no capture logic**, holds **no macOS permissions**, and makes **no network calls**.
Everything stays on your machine. The agent host that spawns this server is the trust boundary — it sees exactly what the tools return, nothing more.
## How the pieces fit
```
openrhyme daemon (Swift, launchd) ──writes──▶ ~/Library/Application Support/OpenRhyme/*.sqlite
│
read-only │ `openrhyme … --json`
▼ │
agent host ──stdio──▶ openrhyme-mcp (this repo) ─────┘
```
The full process topology, the CLI/JSON contract, and the store layout are specified in the engine repo: [`docs/engine-interface.md`](https://github.com/OpenRhyme/OpenRhyme/blob/main/docs/engine-interface.md). That document is the contract this server implements; it is not duplicated here.
## Tools & resources
| MCP tool | Returns |
|---|---|
| `events(since, until, kinds, app, limit, max_value_chars)` | raw events in a time window: `{"events": [...], "count": n}` |
| `status()` | engine trust/daemon/store status, plus this server's schema and db info |
| `apps()` | the capture allowlist and currently running apps |
| `allow_app(bundle_id)` / `deny_app(bundle_id)` | add/remove an app from the capture allowlist, by bundle identifier |
| MCP resource | Contents |
|---|---|
| `openrhyme://events/recent` | the last 15 minutes of raw events, as JSON Lines |
Richer retrieval (sessions, full-text search, embeddings) is future work, not yet built.
## Development
Requires Python 3.12+ and [uv](https://docs.astral.sh/uv/).
```sh
make sync # uv sync --all-groups
make check # ruff + mypy (strict) + pytest
uv run openrhyme-mcp # serve on stdio (Ctrl-C to stop)
```
Tests run in-process against a fixture database and a fake `openrhyme` script; they never need the real engine or a macOS permission. CI runs on Ubuntu and macOS 26.
## Using it with an agent
With the engine built (`../OpenRhyme`, `make build`) and on `PATH` — or pointed to via `OPENRHYME_BIN`:
```sh
claude mcp add openrhyme -- uv run --directory /path/to/openrhyme-mcp openrhyme-mcp
```
Then ask: *"What was I doing between 2 and 3 pm?"* — the model calls `events(since="…", until="…")`. Tools: `events`, `status`, `apps`, `allow_app`, `deny_app`; resource: `openrhyme://events/recent`. Environment: `OPENRHYME_DATA_DIR` (engine data dir), `OPENRHYME_BIN` (engine binary).
## License
MIT — see [LICENSE](LICENSE).
TDQS
Scored across 5 tools
Each tool has a clearly distinct role: events queries captured activity data, status reports engine/server state, apps lists the allowlist and running apps, and allow_app/deny_app make targeted allowlist changes. There is no functional overlap between any of these tools.
The read-only tools use noun-style names (events, status, apps) while the mutations use verb_noun style (allow_app, deny_app). This is fairly predictable and readable, though not as uniform as a single verb_noun convention throughout.
Five tools is well-scoped for this server's purpose: querying activity events, checking engine status, listing apps, and managing the allowlist. Each tool earns its place without the surface feeling bloated or thin.
The core workflows are fully covered: retrieve activity data, inspect engine health, view the allowlist, and add or remove apps from it. Since events are an append-only raw log, update/delete operations are not expected here, so there are no obvious gaps.