Metadata-Version: 2.4
Name: cairn-agent-mcp
Version: 0.1.0
Summary: MCP server for Cairn reminders — lets an AI agent create, list, complete and delete reminders on a Cairn backend over a signed agent API
Author-email: Evgeny Bereza <evgeny@birch.co.il>
License: MIT
Keywords: mcp,model-context-protocol,cairn,reminders,agent,llm,assistant
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Utilities
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: mcp>=1.0
Requires-Dist: httpx>=0.27
Requires-Dist: cryptography>=42
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: mypy>=1.11; extra == "dev"
Dynamic: license-file

# cairn-agent-mcp

An [MCP](https://modelcontextprotocol.io) server that lets an AI agent (Claude Code, Claude Desktop,
Cursor, …) create, list, complete and delete reminders on a **Cairn** backend. The reminders converge to
the owner's phone and Mac. Every request is signed with an Ed25519 key, so an agent can only reach a Cairn
server it has been given a key for.

Tools exposed: `add_reminder`, `list_reminders`, `complete_reminder`, `delete_reminder`.

---

## How the pieces fit

```
   your machine (the agent)                     your server
 ┌──────────────────────────┐             ┌───────────────────────────┐
 │ Claude / Cursor / …       │  signed     │ cairn-server (the binary  │
 │   └─ cairn-agent-mcp ─────┼──HTTPS────► │   you installed)          │
 │        uses your KEY FILE │  request    │   checks authorized_keys  │
 └──────────────────────────┘             └───────────────────────────┘
```

You run **two** things: the `cairn-server` binary on your server, and this MCP on the machine where your
agent runs. This guide connects them. It is a one-time setup per agent machine.

You will: **(1)** create a key on the server, **(2)** add its public half to the server's allow-list,
**(3)** copy the private half to your agent machine, **(4)** point the MCP at the server with three
settings. That's the whole connection.

---

## Setup

### Step 1 — On the server: create a key

`cairn-server` ships with a `cairn-keygen` tool. On the server, run it once, choosing any id for this
agent (e.g. your name or the machine's):

```sh
cairn-keygen -id myagent
```

It prints two things:

```
private key (base64 seed, KEEP SECRET):
K5s1p...oQ==                              ← goes to your agent machine (Step 3)

authorized_keys line:
myagent AAAAC3NzaC1lZDI1...               ← goes into the server allow-list (Step 2)
```

If your server runs as a container, run the same tool inside it, e.g.
`docker exec <container> cairn-keygen -id myagent`.

### Step 2 — On the server: allow this key

`cairn-server` reads an allow-list file (the path is in its `CAIRN_AUTHORIZED_KEYS` setting; the server
refuses to start without it). Append the **`authorized_keys line`** from Step 1 to that file — one key per
line:

```
myagent AAAAC3NzaC1lZDI1...
```

The server re-reads this file automatically when it changes — **no restart needed**. To revoke this agent
later, delete its line.

### Step 3 — On your agent machine: save the private key

Take the **`private key (base64 seed)`** from Step 1 to the machine where your agent runs, and save it to
a file. Keep it readable only by you:

```sh
mkdir -p ~/.cairn
printf '%s\n' 'K5s1p...oQ==' > ~/.cairn/myagent.key
chmod 600 ~/.cairn/myagent.key
```

This file is the secret. It never leaves your machine — the MCP signs with it locally, and only signatures
travel to the server.

### Step 4 — On your agent machine: point the MCP at the server

Register the MCP with three settings. `uvx` fetches and runs it — nothing to install by hand
(install `uv` once: `curl -LsSf https://astral.sh/uv/install.sh | sh`).

| Setting | Value |
|---|---|
| `CAIRN_API_URL` | your server's HTTPS URL, e.g. `https://cairn.example.com` |
| `CAIRN_KEY_ID` | the id you chose in Step 1 (`myagent`) — must match the allow-list line |
| `CAIRN_KEY_FILE` | the path from Step 3 (`~/.cairn/myagent.key`) |

**Claude Code:**

```sh
claude mcp add cairn \
  -e CAIRN_API_URL=https://cairn.example.com \
  -e CAIRN_KEY_ID=myagent \
  -e CAIRN_KEY_FILE=/Users/you/.cairn/myagent.key \
  -- uvx cairn-agent-mcp
```

**Claude Desktop / Cursor / any MCP client** — add to the `mcpServers` block of its config
(`claude_desktop_config.json` for Desktop):

```json
{
  "mcpServers": {
    "cairn": {
      "command": "uvx",
      "args": ["cairn-agent-mcp"],
      "env": {
        "CAIRN_API_URL": "https://cairn.example.com",
        "CAIRN_KEY_ID": "myagent",
        "CAIRN_KEY_FILE": "/Users/you/.cairn/myagent.key"
      }
    }
  }
}
```

### Step 5 — Verify

In Claude Code: `claude mcp list` should show `cairn … ✔ Connected`. Then ask your agent to "add a reminder
to test cairn" — it should appear on your phone and Mac. If a call fails, the tool returns the server's
reason (e.g. `unknown key id` → the allow-list line is missing or the id doesn't match; `timestamp outside
window` → the two machines' clocks differ by more than 5 minutes).

---

## Notes

- **`CAIRN_API_URL` must be `https`** (except `localhost` for local testing). A signature guarantees the
  request wasn't tampered with, not that it's private — over plain `http` the reminder text would travel in
  cleartext, so the MCP refuses it.
- **The key id ties the three together:** the id in Step 1, the first word of the allow-list line in Step 2,
  and `CAIRN_KEY_ID` in Step 4 must all be the same string.
- **One key per agent machine** is the clean model — issue a separate id for each, so you can revoke one
  without touching the others.

## Run from source (contributors)

```sh
python3 -m venv .venv && .venv/bin/pip install -e '.[dev]'
.venv/bin/pytest
```

The test suite includes a cross-language golden vector that pins byte-for-byte signing compatibility with
the Cairn server (Go) and app (Swift) — the same key format works across all three.

## License

MIT — see [LICENSE](LICENSE).
