README.md•7.54 kB
# Fieldnote MCP
Local‑first memory and a symmetrical knowledge graph you can clone, start, and use in minutes.
This repo gives any agent or app three superpowers:
* **Auto‑store memory** — drop text in, it’s embedded and saved locally.
* **Auto‑recall & inject** — retrieve relevant memories and assemble a ready‑to‑paste context block.
* **Symmetrical Knowledge Graph** — every memory can mirror into Neo4j with inverse edges for clean traversal.
It’s portable, version‑pinned, works on macOS/Linux/WSL/Windows, and never asks for root.
---
## What’s inside
* **Qdrant** (vector DB) + **Neo4j** (graph) via Docker Compose
* **Cross‑platform shims** so the same commands work everywhere:
* `memory-store`, `memory-search`, `context-inject`, `mcp-health`, `qdrant-run`
* **Hybrid retrieval** (dense + optional sparse)
* Dense: MiniLM (pinned)
* Sparse (optional): BGE‑M3 if available, with hashing fallback so demos never block
* **Health gate** to verify services before use
* **.env overrides** to configure without touching code
---
## Requirements
* **Docker Desktop** (macOS/Windows) or Docker Engine (Linux)
* **Python 3.11+** (for local CLI tools)
* \~2GB free disk space for local data
> No sudo needed. Everything lives in `~/dev/mcp` by default.
---
## Quickstart (copy/paste)
### macOS / Linux / WSL
```bash
# 0) place the repo at the expected path
mkdir -p ~/dev && cd ~/dev
# if you downloaded an archive, extract it to ~/dev/mcp; if using git:
# git clone <your-repo-url> mcp
cd ~/dev/mcp
# 1) bootstrap local env & command shims (idempotent)
./mcp-init.sh
# 2) env config (optional; overrides defaults)
cp .env.example .env
# edit .env as needed
# 3) start services
docker compose up -d
# 4) verify
make health
# 5) try the demo
make demo
```
### Windows (PowerShell)
```powershell
cd $HOME\dev\mcp
.\mcp-init.ps1
Copy-Item .env.example .env
# Edit .env if you want to change ports/creds
docker compose up -d
make health
make demo
```
Expected demo output:
* `memory-store` responds with `{ "status": "ok", "id": "…" }`
* `memory-search` prints top hits (hybrid if enabled)
* `context-inject` prints a compact block of the highest‑scoring memories (ready to paste into an agent prompt)
---
## Everyday commands
* `make compose-up` / `make compose-down` / `make compose-logs` – manage services
* `make health` – confirm Qdrant + Neo4j are reachable (and collection exists)
* `make demo` – store → search → inject in one go
* `make clean-data` – wipe Qdrant storage; `make clean-compose` also wipes Neo4j
* `qdrant-run` – portable runner if you’re not using Compose (Linux/Docker fallback)
CLI shims installed to `~/dev/mcp/bin`:
* `memory-store` — embed + upsert to Qdrant, then mirror to KG
* `memory-search` — dense (and sparse if enabled) retrieval with optional KG symmetry expansion
* `context-inject` — assembles a ready‑to‑paste context block from top memories
* `mcp-health` — sanity check for Qdrant/Neo4j
Registered in `plugins.json` so orchestrators can discover them.
---
## Configure
All defaults live in `config/memory.config.json`. Anything in **.env** overrides it at runtime.
**.env keys** (see `.env.example`):
| Key | Meaning | Default |
| --------------------------- | ----------------------------- | ---------------------------------------- |
| `QDRANT_URL` | Qdrant HTTP endpoint | `http://127.0.0.1:6333` |
| `QDRANT_COLLECTION` | Collection name | `fieldnote_memory` |
| `DENSE_MODEL` | SentenceTransformer model | `sentence-transformers/all-MiniLM-L6-v2` |
| `TOP_K` | Search results to return | `8` |
| `NEO4J_URI` | Bolt URI | `bolt://127.0.0.1:7687` |
| `NEO4J_USER` / `NEO4J_PASS` | Neo4j credentials | `neo4j` / `password` |
| `INJ_MAX_TOKENS` | Max tokens to inject | `2000` |
| `INJ_SCORE_THRESHOLD` | Minimum similarity to include | `0.75` (recommended) |
| `SPARSE_ENABLED` | Enable sparse lane | `true` |
| `SPARSE_MODEL` | Sparse model | `bge-m3` |
| `SPARSE_HASH_DIM` | Hashing fallback dim | `32768` |
> Tip: If you enable sparse on an existing collection created without it, start fresh (rename the collection or run `make clean-compose`).
---
## How it works
```
Store text ──▶ memory-store ──▶ Qdrant (dense [+ sparse])
│
└─▶ GraphSync hook ──▶ Neo4j (symmetrical edges)
Query ──▶ memory-search ──▶ Qdrant hybrid search
│
└─▶ optional KG symmetry expansion
Assemble ──▶ context-inject ──▶ compact, thresholded context block
```
* **Symmetry**: When a relation has a defined inverse (e.g., `depends_on ↔ supports`), both directions are stored so traversals stay consistent.
* **Hybrid**: If `SPARSE_ENABLED=true`, sparse vectors are stored alongside dense. If BGE‑M3 isn’t installed, a hashing fallback keeps hybrid functional.
Open Neo4j Browser at `http://localhost:7474` to explore the graph. Qdrant Console is available via the API (`:6333`).
---
## Data & paths
* Qdrant data: `qdrant/storage/`
* Neo4j data: `neo4j/data/`
* Local venvs: `venv/` (Linux/macOS/WSL), `win-venv/` (Windows)
* PATH shims: `~/dev/mcp/bin`
All are git‑ignored by default.
---
## Troubleshooting
**"connection refused" on health check**
* Ensure Docker is running and `docker compose up -d` completed.
**Ports already in use**
* Change ports in `.env` / `docker-compose.yml` or stop the conflicting service.
**Windows symlink errors**
* Enable Developer Mode, or replace symlinks with tiny `.cmd` wrappers that call `python`.
**KG looks empty**
* Run the demo (`make demo`) or start storing memories. Graph is populated by the post‑store hook.
**Sparse/hybrid isn’t kicking in**
* Confirm `SPARSE_ENABLED=true`. If BGE‑M3 isn’t available, the hashing fallback still enables hybrid queries.
---
## Extend
* **Typed relations**: Enrich `hooks/graphsync_post_store.py` with light keyword rules or your own IE pipeline.
* **Keep models hot**: Wrap store/search in a small FastAPI service (you already have `uvicorn` + `fastapi`).
* **Provenance**: Add `source_id`, `confidence` to edges for auditing.
---
## Security
* Don’t commit real credentials. `.env` is git‑ignored.
* Everything runs locally by default; expose ports only if you know why.
---
## License
Project Navi - Dual License
This software is dual-licensed:
Option A: GNU Affero General Public License v3.0 (AGPL-3.0)
- For open source use
- See https://www.gnu.org/licenses/agpl-3.0.html
Option B: Commercial License (PNEUL-D v2.2)
- For proprietary/closed-source use
- Contact legal@projectnavi.ai for licensing
Full license terms: /docs/legal/
---
## Support
If something feels off, run:
```bash
make health
```
Then check `docker compose logs` for `qdrant` and `neo4j`. Open an issue or ping your team with the logs.