Metadata-Version: 2.5
Name: mimir-memory-mcp
Version: 1.0.0
Summary: Mimir — structured memory MCP server for AI assistants
Project-URL: Repository, https://github.com/jimmy-larsson/mimir
Author: Jimmy Larsson
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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 :: Software Development :: Libraries
Requires-Python: >=3.11
Requires-Dist: fastmcp>=3.0
Requires-Dist: pydantic>=2.0
Provides-Extra: dev
Requires-Dist: pre-commit>=4.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff<0.16,>=0.15.11; extra == 'dev'
Description-Content-Type: text/markdown

# Mimir

**Structured memory server for AI assistants.**

Mimir stores what an assistant needs to keep: work (threads, tasks, reminders) and knowledge (rules, facts) anchored to the work it is about. Multi-user, scope-based access control, tiered context loading, keyword search, a full audit trail.

The **HTTP API is the contract**. The [MCP](https://modelcontextprotocol.io/) surface is a generated adapter over the same operation registry — every operation exists on both, and neither can quietly grow one the other lacks.

Named after [Mímir](https://en.wikipedia.org/wiki/M%C3%ADmir), the Norse keeper of the Well of Wisdom.

## 1.0 is a clean break

1.0 does not read a 0.x database. New schema, new API, new database file; the server refuses a pre-1.0 file at boot and names the way across:

```bash
mimir-mcp migrate --from ./old-mimir.db --to ./mimir.db
```

The migration is a one-time move into a *new* file — dry-runnable, with judgement queues for what does not map cleanly. The 0.x tool names and session lifecycle (`start_session`, `end_session`, `set_context`, …) are gone: nothing opens, closes or resumes — every call carries its own authority, and re-reading replaces remembering.

## Quick Start

### pip

```bash
pip install mimir-memory-mcp
# write seed.sql — your principal, scope, membership (see Provisioning below)
MIMIR_DB_PATH=./mimir.db MIMIR_SEED_FILE=./seed.sql MIMIR_PORT=8100 mimir-mcp
```

### Docker

```bash
cp seed.sql.example data/seed.sql   # edit: your principal and scope
docker compose up -d --build        # compose provides MIMIR_DB_PATH and MIMIR_SEED_FILE
```

`scripts/setup.sh` walks the same steps with a health check.

### From Source

```bash
git clone https://github.com/jimmy-larsson/mimir.git
cd mimir
pip install -e ".[dev]"
cp seed.sql.example seed.sql        # edit: your principal and scope
MIMIR_DB_PATH=./mimir.db MIMIR_SEED_FILE=./seed.sql mimir-mcp
```

## Configuration

| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| `MIMIR_DB_PATH` | `/data/mimir.db` | SQLite database file path |
| `MIMIR_PORT` | `8100` | HTTP port (both surfaces) |
| `MIMIR_SEED_FILE` | *(unset)* | SQL file auto-applied at boot while the database has no principals |

## Provisioning

Identity and credentials are separate things, provisioned separately:

**1. Principals, scopes, memberships** come from a seed file — see [`seed.sql.example`](seed.sql.example). No credentials live there: 1.0 stores token hashes, so a plaintext key in a seed file would be a recoverable credential on disk. Auto-applied at boot via `MIMIR_SEED_FILE` while the database has no principals, or loaded by hand: `mimir-mcp seed --file seed.sql`.

**2. Tokens** are minted, never seeded. In the hermes deployment, `hermes-template`'s provisioning does this. Standalone, bootstrap the first token at the domain — point `MIMIR_DB` at the same file the server runs against (the plaintext is printed once and never recoverable):

```bash
MIMIR_DB=./mimir.db python -c "
import os
from mimir_mcp.db import init_db
from mimir_mcp import tokens
db = init_db(os.environ['MIMIR_DB'])
row, plaintext = tokens.mint(db, 'your-user-id', label='console', scopes='*',
                             may_write_rules=True, privileged=True)
print(plaintext)"
```

Docker: run the same snippet inside the container against the volume — `docker compose exec mimir env MIMIR_DB=/data/mimir.db python -c "…"`.

Every further token is minted over the API (`POST /tokens` / `manage_tokens`) with that one. A token is a first-class object: a scope subset, capability limits, individually revocable, rotatable with an overlap window. Authority is always `token.scopes ∩ live membership`, resolved per request.

## The Surface

Five item types — `thread · task · reminder · rule · fact`. Type carries force (a rule binds, a fact informs), anchors carry reach (knowledge loads with the work it is anchored to).

### HTTP (the contract)

Authenticate with `x-api-key`. Every response carries `X-Mimir-API-Version`.

| Route | Operation |
|-------|-----------|
| `GET /orientation` | T0 — the always-loaded view: rules, unanchored facts, active threads, due reminders, scopes, tags |
| `GET /items/{id}/context` | T1 drill — the item in full, open children, anchored knowledge, links |
| `GET /items?ids=` | T2 detail for explicit ids |
| `GET /items` | Browse by filters (`type`, `status`, `scope`, `tag`, `parent`, `anchor`) |
| `GET /search?q=` | Keyword search with per-hit matched terms and honest totals |
| `GET /history` | Audit trail, by `item` or by `conversation` |
| `POST /items` | Create items; anchor knowledge at creation via `anchors` |
| `PATCH /items/{id}` | Update fields; explicit null clears |
| `POST /items/resolve` | Finish work: done, dropped or archived — cascade guarded |
| `DELETE /items` | Hard delete (privileged), stranded-knowledge guarded |
| `POST /relations` · `DELETE /relations` | Anchor, link, blocked_by |
| `POST /items/{id}/log` | Append a progress note |
| `GET /scopes` · `POST /scopes` · `POST\|DELETE /scopes/{id}/members` | Scopes and membership (writes privileged) |
| `POST\|GET /tokens` · `DELETE /tokens/{id}` | Mint, list, revoke tokens (privileged) |
| `GET /version` · `GET /health` | Open probes |

### MCP Tools (15)

Generated from the same registry; served at `http://host:8100/mcp`.

| Category | Tools |
|----------|-------|
| Reads | `orient`, `open`, `read_items`, `find_items`, `read_history`, `list_scopes` |
| Writes | `add_items`, `update_item`, `add_log`, `relate_items`, `resolve_items`, `delete_items` |
| Administration | `manage_scope`, `manage_tokens` |
| Probe | `version` |

## Integrating with Claude Code

See [docs/integration/claude-code.md](docs/integration/claude-code.md). Quick version — add to `.mcp.json`:

```json
{
  "mcpServers": {
    "mimir": {
      "type": "http",
      "url": "http://localhost:8100/mcp",
      "headers": {
        "x-api-key": "YOUR_TOKEN"
      }
    }
  }
}
```

## Development

```bash
pip install -e ".[dev]"
pre-commit install   # installs ruff check/format as a git hook
python -m pytest tests/ -q
```

## License

MIT
