Engrava MCP
The Model Context Protocol server for Engrava — expose an agent memory database to any MCP client (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, …) over stdio.
engrava-mcp is a standalone, runnable package that consumes Engrava's public
API. It is the one way to run Engrava as a memory server; the engrava library
itself ships no MCP code.
uv tool install engrava-mcp # recommended for daily use: a persistent install
engrava-mcp # spawned by your MCP client over stdio
uvx engrava-mcp runs it without an install step, and pip install engrava-mcp
works too. uvx keeps its environment in a cache. When that cache is cold, the
first start waits for the download; see Optional providers
for the [local] extra, where the download is largest.
Installing engrava-mcp pulls in engrava transitively, so you also get the
import engrava library in the same environment.
Compatibility
engrava-mcp follows Engrava's version: engrava-mcp X.Y.z targets engrava X.Y
and requires engrava >=X.Y,<X.(Y+1). This is a one-way version mirror for legibility —
not a lockstep: Engrava releases on its own cadence, and engrava-mcp patch releases
are independent.
| engrava-mcp | Works with engrava |
|---|---|
0.5.x |
>=0.5,<0.6 |
0.6.x |
>=0.6,<0.7 |
0.7.x |
>=0.7,<0.8 |
The dependency range is the source of truth. Normal installs resolve a compatible
engrava automatically; if you pin engrava yourself, keep it within that range. If no
matching engrava-mcp exists yet for an engrava newer than the table's last row, that
pairing is not yet verified/supported — not broken; stay on a supported pair until a
matching engrava-mcp ships.
Which package do I want?
| Goal | Install |
|---|---|
| Build on the Engrava Python API (memory DB in your own code) | pip install engrava |
| Run Engrava as a memory server for an MCP client | uvx engrava-mcp (or pip install engrava-mcp) |
There is no third option.
Migrating from engrava[mcp]
The server used to ship inside Engrava as the engrava[mcp] extra and an
in-engrava engrava-mcp command. As of Engrava 0.5.0 it lives here instead.
| Before | After |
|---|---|
pip install "engrava[mcp]" |
pip install engrava-mcp (or uvx engrava-mcp) |
engrava-mcp (installed by engrava) |
engrava-mcp (installed by this package) |
client mcp.json: "command": "engrava-mcp" |
client mcp.json: "command": "uvx", "args": ["engrava-mcp"] |
- Watch out:
pip install "engrava[mcp]"against Engrava 0.5 does not fail — pip ignores the now-unknown extra and quietly installs bareengrava, so it can look like the server installed when it did not. Installengrava-mcpinstead. - Update any pinned requirement strings (
engrava[mcp]>=...) to depend onengrava-mcp, not just reinstall. - Your store configuration is unchanged — the same
engrava.yaml/ env vars work exactly as before (see Configuration).
Configuration
The server resolves its store from environment variables, in priority order:
| Variable | Meaning |
|---|---|
ENGRAVA_MCP_CONFIG |
Path to an engrava.yaml. Built with the full configuration — embedding provider, vector backend, journal, TTL. The thought/edge journal is configured here: set journal: enabled: true to turn it on. Recommended. |
ENGRAVA_DB_PATH |
Path to a bare SQLite database file. Use an absolute path: a relative one resolves against the server's working directory, which the client chooses. Zero-config quick-start; no embedding provider is configured, so semantic (vector) search is inert — full-text search, the graph, and MindQL still work. This route builds the store with no journal; use ENGRAVA_MCP_CONFIG for that. "Zero-config" means Engrava's default search policy, so search_memory's recency_now is honoured on this route too — recency is scored against the timestamp you supply, under Engrava's default search weights. |
ENGRAVA_MCP_READ_ONLY |
When set to 1 / true / yes, the write tools are not registered and no read makes a write of its own — including a deferred access-count update a store with access tracking on would otherwise buffer and flush on close. Every tool's readOnlyHint annotation is therefore accurate under this mode, on every configuration route. Read-only mode governs the tools, not how the database is opened. At startup the server still opens the file read-write, creates it if it is missing, and upgrades its schema to the one its Engrava version uses, so a database file the server cannot write cannot be served in this mode either. |
Recommended: give the MCP server the same engrava.yaml your application
uses. The yaml is the only place to declare an embedding provider (and its
model / key), which the server needs to embed a new query at search time for
semantic search. With only ENGRAVA_DB_PATH set, the server emits a startup
warning that semantic search is inert and points you at ENGRAVA_MCP_CONFIG.
At search time, the server embeds the query with the provider this yaml
declares. Whether this server's writes embed anything is decided by the same
yaml's embeddings.auto_embed, which Engrava leaves off by default. With it
off, a thought created through store_thought gets no embedding, so
search_memory's vector ranking cannot match it — its keyword ranking still
can — and an update_thought leaves whatever embedding the thought already had
as it was, not refreshed. With it on, creating a thought, or changing its
essence or content, also calls the provider.
Store-hook extensions need the config path
Engrava extensions that hook the store — anything wired through an
engrava.yaml's hooks: section — are attached only on the
ENGRAVA_MCP_CONFIG launch. ENGRAVA_DB_PATH opens a bare database and carries
no configuration, so it runs with Engrava's default hooks and cannot attach a
store-hook extension. That is deliberate: it is an intentionally minimal
read/write facade.
Installing such an extension and starting with ENGRAVA_DB_PATH therefore
leaves its store hooks unattached in this server. When an installed package
advertises any extension, the server emits a startup warning naming it — it
reports what is advertised, not what each one does, since it never loads them
itself — so you can tell the difference between "nothing advertised" and
"advertised but nothing wired it here". If reading the installed-package
metadata raises an ordinary error, the server attempts to log that instead and
carries on starting. Both go through Python's logging, so whether and where
they surface is up to your logging configuration. To wire a store hook, launch
with ENGRAVA_MCP_CONFIG pointing at an engrava.yaml with a hooks:
section:
hooks:
class: "my_package.hooks.MyHooks"
Example engrava.yaml
database:
path: /absolute/path/to/memory.db
embeddings:
provider: openai-compatible # or: ollama, sentence-transformer, huggingface
model: text-embedding-3-small
api_key: ${OPENAI_API_KEY}
A relative database.path resolves against the server process's working directory,
which the MCP client chooses, not against the yaml's folder.
Client setup
Point your MCP client at the server over stdio. For example, a typical
mcp.json entry:
{
"mcpServers": {
"engrava": {
"command": "engrava-mcp",
"env": {
"ENGRAVA_MCP_CONFIG": "/absolute/path/to/engrava.yaml"
}
}
}
}
A ${VAR} value in the engrava.yaml, such as ${OPENAI_API_KEY}, is read from the
server's own environment, so add that variable to the same env block, unless the
client is known to pass its own environment through.
This assumes uv tool install engrava-mcp. If your client cannot find the
command, give its absolute path; uv tool dir --bin prints the directory.
Without an install, use "command": "uvx", "args": ["engrava-mcp"].
Use ENGRAVA_DB_PATH instead of ENGRAVA_MCP_CONFIG for the zero-config
quick-start, and add "ENGRAVA_MCP_READ_ONLY": "1" for an app-writes /
agent-reads deployment.
Running without uvx
engrava-mcp # console script
python -m engrava_mcp # module run
python -m engrava_mcp.server # module run (server module directly)
Optional providers
For an MCP deployment, prefer an embedding provider that runs outside the
server process: Ollama (provider: ollama) or an OpenAI-compatible endpoint
(provider: openai-compatible). The default install already covers both, and
the server then loads no embedding model itself.
The default install supports the vector backend and HTTP-based embedding
providers (OpenAI / Ollama) once configured in the yaml. Heavier providers are
opt-in extras that mirror Engrava's own extras:
uvx --from "engrava-mcp[local]" engrava-mcp # sentence-transformers (local model)
uvx --from "engrava-mcp[hf]" engrava-mcp # HuggingFace Inference API
uvx --from "engrava-mcp[openai]" engrava-mcp # OpenAI-compatible embeddings deps
uvx --from "engrava-mcp[ollama]" engrava-mcp # Ollama embeddings deps
[local] runs the model inside the server process and installs PyTorch, which
can add several gigabytes. A first start on a cold uvx cache waits for that
download; later starts reuse the cache. uv tool install "engrava-mcp[local]"
pays the download once, at install time. A model that is not already in the
local model cache is downloaded when it is first loaded.
The surface
- Tools (13):
get_thought,search_memory,search_keywords,list_memory,query_memory,memory_stats,get_edges,list_edges(read);store_thought,update_thought,link_thoughts,delete_thought,delete_edge(write, gated byENGRAVA_MCP_READ_ONLY). - Resources (3):
engrava://thought/{thought_id},engrava://stats,engrava://recent. - Prompts (3):
summarize_recent_memory,find_related,reflect_on_topic.
query_memory accepts only MindQL FIND queries; raw SQL and every other
command are rejected. It returns at most 5000 rows. A limit argument replaces
the query's own LIMIT; without one, a LIMIT outside 1–5000 is refused.
get_edges traverses a thought's edges by direction (IN / OUT / BOTH);
with limit, at most that many edges, the highest-weight ones first, and
without it, every edge. list_edges browses edges filtered by type, source,
or metadata.
link_thoughts accepts optional edge metadata (JSON fields that list_edges
can filter on). search_memory accepts an optional recency_now (ISO-8601
timestamp) giving the moment to measure age against (transaction time); recency
takes part in the ranking only when you pass it.
Development
pip install -e ".[dev]"
ruff check src/ tests/
ruff format --check src/ tests/
mypy --strict src/
pytest --cov --cov-fail-under=90
License
MIT
Metadata
Release files for engrava-mcp 0.7.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| engrava_mcp-0.7.0.tar.gz | 200.0 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| engrava_mcp-0.7.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 267.4 kB
Release files / engrava_mcp-0.7.0.tar.gz
| Download URL | engrava_mcp-0.7.0.tar.gz |
|---|---|
| Size | 200.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
93821e7f9b8adca18d954c029281feb01986e72571978ebb9d8868a6fe197905
|
|
BLAKE2b-256 checksum How to use checksums |
033254fcf94a540268f489cebe7b1a55e2eb7e1baeac548483d09d4f29348bbd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency logRelease files / engrava_mcp-0.7.0-py3-none-any.whl
| Download URL | engrava_mcp-0.7.0-py3-none-any.whl |
|---|---|
| Size | 67.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
df5b505d6f7e3839ee181ba564e7d1f1b836a6e51bcb64eb3c3982baf9648fec
|
|
BLAKE2b-256 checksum How to use checksums |
373e50344f94ea1ee4e746b69aacfdf9dce87099bce260fefb139a9341acb36f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 2, 2026.
Transparency log