jade-memory
by jjjona
README.md
# jade-memory
Persistent knowledge base and journal for AI agents. Two MCP servers backed by a shared multilingual embedding sidecar, deployed as Docker containers.
**Knowledge base** stores facts, decisions, procedures, and troubleshooting notes with semantic search. Agents call `store` to save knowledge and `recall` to retrieve it. Entries are typed, tagged, and searchable across languages.
**Journal** is a free-form, append-only cognitive tool. Agents write thoughts, reflections, and session notes. Value is in the writing process (structuring thinking), not just retrieval. No categories or sections — semantics live in the content itself.
Both use vector embeddings (768-dim, gte-multilingual-base) for semantic search via sqlite-vec. Both are accessible remotely via MCP Streamable HTTP transport with bearer token auth. API keys are created through the web admin UI — no env vars needed.
## Architecture
```
┌─────────────────────────────────────────────────────┐
│ Docker network (internal bridge) │
│ │
│ jade-embeddings (Python, port 3102, internal only) │
│ Alibaba-NLP/gte-multilingual-base │
│ 768 dims, 100+ languages, ~1.2GB RAM │
│ │
│ jade-knowledge (Bun, port 3100) │
│ MCP Streamable HTTP at /mcp │
│ Bearer token auth │
│ │
│ jade-journal (Bun, port 3101) │
│ MCP Streamable HTTP at /mcp │
│ Bearer token auth (separate key) │
└─────────────────────────────────────────────────────┘
```
The embedding sidecar is internal-only — not exposed outside the Docker network. Both MCP servers call it to generate embeddings on store/write and on search/recall.
## Tools
### Knowledge base (jade-knowledge)
| Tool | Description | Parameters |
|------|-------------|------------|
| `recall` | Search knowledge base | `query` (string), `type?` (enum), `limit?` (int, default 10) |
| `store` | Add knowledge with auto-embedding | `content` (string), `type?` (enum, default "general"), `tags?` (string[]) |
| `forget` | Delete knowledge entry | `id` (int) |
Knowledge types: `fact`, `preference`, `decision`, `procedure`, `troubleshooting`, `general`
### Journal (jade-journal)
| Tool | Description | Parameters |
|------|-------------|------------|
| `write` | Record journal entry | `content` (string) |
| `search` | Semantic search journal | `query` (string), `limit?` (int, default 10) |
| `recent` | List recent entries | `limit?` (int, default 10) |
The journal is append-only. No delete, no edit.
### Context footprint
Both MCPs add approximately **~480 tokens** total to the agent's context window:
- jade-knowledge: ~300 tokens (3 tools)
- jade-journal: ~180 tokens (3 tools)
For comparison, the Playwright MCP adds ~13,700 tokens.
## Installation
### Prerequisites
- Docker and Docker Compose
- Ports 3100 and 3101 available on the host
### 1. Clone and configure
```bash
git clone <repo-url> jade-memory
cd jade-memory
cp .env.example .env
# Edit .env if you need to change ports or DB paths (no API keys needed)
```
### 2. Build and start
```bash
docker compose up -d --build
```
First build downloads the embedding model (~1.2GB) and bakes it into the image. This takes a few minutes. Subsequent builds use the cached layer.
The embedding sidecar has a health check with a 120-second start period to allow for model loading. The knowledge and journal containers wait for it to be healthy before starting.
### 3. Create admin account
Visit `http://<host>:3100` (knowledge) or `http://<host>:3101` (journal) in your browser. On first visit you'll be prompted to create an admin account.
### 4. Create API keys
Log in to the web UI, go to `/admin`, and create API keys. These are used by MCP clients (Claude Code, OpenCode, etc.) to authenticate. Copy the key immediately — it's only shown once.
### 5. Verify
```bash
# Health checks (no auth required)
curl http://localhost:3100/health
curl http://localhost:3101/health
# Test MCP auth with your API key
curl -X POST http://localhost:3100/mcp \
-H "Authorization: Bearer <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'
```
### 6. (Optional) Reverse proxy
If you want to expose the MCPs over HTTPS via traefik or another reverse proxy:
```bash
cp docker-compose.override.yml.example docker-compose.override.yml
# Edit docker-compose.override.yml with your domain names and TLS config
docker compose up -d
```
## Connecting to agents
API keys are created through the web admin UI at `/admin` after logging in. Replace `<API_KEY>` below with a key you created there.
### Claude Code
#### Option A: CLI (recommended)
```bash
claude mcp add --transport http jade-knowledge http://<host>:3100/mcp \
--header "Authorization: Bearer <API_KEY>"
claude mcp add --transport http jade-journal http://<host>:3101/mcp \
--header "Authorization: Bearer <API_KEY>"
```
Use `--scope user` to make them available across all projects, or `--scope local` (default) for the current project only.
#### Option B: JSON config
Add to `~/.claude.json` (or project-level `.claude/settings.json`) under `mcpServers`:
```json
{
"mcpServers": {
"jade-knowledge": {
"type": "http",
"url": "http://<host>:3100/mcp",
"headers": {
"Authorization": "Bearer <API_KEY>"
}
},
"jade-journal": {
"type": "http",
"url": "http://<host>:3101/mcp",
"headers": {
"Authorization": "Bearer <API_KEY>"
}
}
}
}
```
### OpenCode
Add to `opencode.json` in your project root:
```json
{
"mcp": {
"jade-knowledge": {
"type": "remote",
"url": "http://<host>:3100/mcp",
"headers": {
"Authorization": "Bearer <API_KEY>"
}
},
"jade-journal": {
"type": "remote",
"url": "http://<host>:3101/mcp",
"headers": {
"Authorization": "Bearer <API_KEY>"
}
}
}
}
```
You can use `{env:KNOWLEDGE_API_KEY}` instead of a literal key to reference environment variables.
### Other MCP clients
Any client that supports MCP Streamable HTTP transport can connect. The servers accept:
- `POST /mcp` — MCP JSON-RPC messages (requires `Accept: application/json, text/event-stream`)
- `GET /mcp` — SSE stream for server-initiated messages
- `DELETE /mcp` — Session cleanup
- `GET /health` — Health check (no auth required)
### Prompting the agent
For best results, instruct the agent to use the knowledge base proactively. Add something like this to your system prompt or CLAUDE.md:
```
You have access to a persistent knowledge base (jade-knowledge) and journal (jade-journal).
**Knowledge base**: Use `recall` when starting a task to check for relevant prior knowledge.
Use `store` when you learn something reusable — facts, decisions, troubleshooting solutions,
procedures. Tag entries with project names for cross-project retrieval.
**Journal**: Use `write` when you want to think through a problem, reflect on your approach,
or note something for your own reference. The value is in the writing process itself.
```
## Development
### Project structure
```
jade-memory/
├── packages/
│ ├── shared/ # Auth, embed client, DB helpers, types
│ ├── knowledge/ # Knowledge base MCP server
│ └── journal/ # Journal MCP server
├── embeddings/ # Python embedding sidecar
├── docker-compose.yml
└── .env.example
```
### Running tests
```bash
# All tests (from repo root)
bun test
# Specific package
bun test --filter knowledge
bun test --filter journal
bun test --filter shared
```
Tests mock the embedding sidecar and use in-memory SQLite databases. No Docker required.
### Running locally (without Docker)
```bash
# Terminal 1: Start embedding sidecar
cd embeddings
pip install -r requirements.txt
uvicorn main:app --port 3102
# Terminal 2: Start knowledge MCP
cd packages/knowledge
EMBEDDINGS_URL=http://localhost:3102 bun run src/index.ts
# Terminal 3: Start journal MCP
cd packages/journal
EMBEDDINGS_URL=http://localhost:3102 bun run src/index.ts
```
No API keys needed at startup. Visit `http://localhost:3100` to create an admin account, then go to `/admin` to create API keys for MCP clients.
## Resource usage
| Container | RAM | CPU | Disk |
|-----------|-----|-----|------|
| jade-embeddings | ~1.2 GB | Low (idle), moderate (encoding) | ~2 GB (model) |
| jade-knowledge | ~50 MB | Minimal | Grows with entries |
| jade-journal | ~50 MB | Minimal | Grows with entries |
The embedding model (gte-multilingual-base) is the main resource cost. It supports 100+ languages including English, Spanish, French, German, and Dutch. Cross-language search works — you can store in one language and recall in another.
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues