Contextual Memory MCP
A local-first persistent contextual-memory engine with an MCP adapter for AI models such as Qwen.
README
Contextual Memory MCP
A local-first persistent contextual-memory engine with an MCP adapter for AI models such as Qwen.
The project is being developed incrementally. The first ingestion target is a directory of reusable Markdown prompt material, but the storage and retrieval layers are general-purpose.
Architecture
Text, images, audio, and video
|
v
Modality-specific semantic distillation
|
+--> SQLite semantic capsules and sparse concepts
|
+--> packed int8 latent parameter bank
|
v
Hybrid retrieval and context assembly
|
v
Thin MCP adapter used by Qwen
The CLI performs administrative work. The MCP server exposes memory operations that are useful to the model.
Install with uv
uv venv --python 3.12
uv pip install -e .
cp .env.example .env
Python 3.12 or 3.13 is recommended for broad compatibility with the current machine-learning dependencies.
Index files and directories
The CLI accepts either one file or an entire directory. With no --name, the
content is added to the normal writable main store:
uv run contextual-memory-index scan /path/to/character.md
uv run contextual-memory-index scan /path/to/saved/prompts
Provide --name to add the target to a named database. If that database does
not exist, it is created automatically:
uv run contextual-memory-index scan /path/to/character.md --name roleplay
New named databases are immutable after indexing by default. Use --mutable
when the named database should remain writable:
uv run contextual-memory-index scan /path/to/saved/prompts --name prompt-library --mutable
A later explicit scan can update an existing named database. Locked databases
are reopened only for that update and then returned to their previous mode.
Use --replace when the entire named database should be rebuilt instead:
uv run contextual-memory-index scan /path/to/saved/prompts --name prompt-library --replace
Directory scans support exclusions, and either kind of scan can force unchanged content to be indexed again:
uv run contextual-memory-index scan /path/to/saved/prompts --exclude archive --force
Clear stored data
Interactive confirmation:
uv run contextual-memory-index clear --store main
Non-interactive confirmation:
uv run contextual-memory-index clear --store main --yes
Scanning and clearing are deliberately CLI-only maintenance operations. They are not exposed to the model through MCP.
Run the MCP server
uv run contextual-memory-mcp
The MCP server exposes model-facing recall, ingestion, lifecycle, and maintenance tools:
recall_memory
Retrieves semantically, lexically, and graph-related memory and returns clean, source-attributed Markdown that Qwen can use in its active context.
Typical model call:
recall_memory(
query="Create a gender-swapped character reference sheet while preserving identity, colors, and species traits"
)
store_memory
Automatically captures durable information directly stated by the user. The model is instructed to call it before drafting its response whenever the current message contains durable information, including during ordinary conversation. The user does not need to say “remember this,” and routine storage must not trigger a permission question or an announcement. The model supplies an integer memory type and a normalized importance score from 0.0 to 2.0. The server validates those values and assigns lifecycle state, origin, confidence, source quality, and conservative server-owned lifecycle policy.
store_memory_candidate
Stores model-generated hypotheses and interpretations as candidate inferences.
It is not a substitute for store_memory when the user directly stated the
information, whenever that statement is durable. The
model supplies semantic type and importance, while the server assigns lifecycle
state, origin, confidence, source quality, and conservative retention policy.
explore_memory
Traverses the knowledge graph around a concept and returns related concepts plus supporting memory excerpts.
The MCP does not expose scan, clear, stats, or database-deletion tools. Those are administrative concerns and remain under direct user control.
LM Studio configuration
Add the server as a stdio MCP using the repository's virtual environment. A typical configuration resembles:
{
"mcpServers": {
"contextual-memory": {
"command": "/absolute/path/to/contextual-memory-mcp/.venv/bin/contextual-memory-mcp",
"args": [],
"cwd": "/absolute/path/to/contextual-memory-mcp"
}
}
}
Alternatively, invoke it through uv:
{
"mcpServers": {
"contextual-memory": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/contextual-memory-mcp",
"contextual-memory-mcp"
]
}
}
}
Use absolute paths when LM Studio is launched outside a terminal, because GUI applications may not inherit the same shell PATH.
Storage
Persistent data is stored beneath CM_DATA_DIR, which defaults to ./data:
contextual_memory.sqlite3vectors/latent_vectors.sqlite3(compact int8 parameter bank)store_overlays.sqlite3(local ranking overlays for immutable stores)stores/<name>/manifest.jsonplus each scanned store database
The embedding model is stored in the application's own model directory and normal server/index runs load it with network access disabled. Install it once before the first scan or recall:
uv run contextual-memory-index model install
Check the local installation without contacting Hugging Face:
uv run contextual-memory-index model status
The default location is CM_DATA_DIR/models. Override it with CM_MODELS_DIR.
After installation, deleting the global Hugging Face cache does not affect this
project. A missing model produces an explicit error instead of downloading during
an MCP or indexing operation.
Current retrieval path
recall_memory currently combines:
- semantic similarity from the packed int8 parameter bank
- SQLite full-text relevance
- graph relationships
- segment importance
- per-source diversity
- a configurable context-size budget
The returned value is Markdown rather than an embedding blob or database record, so the model receives reusable source material directly.
Memory importance and lifecycle
Memory importance is persistent and evolves through an explicit maintenance pass:
new recall accesses
+
configured access gain
-
elapsed inactivity decay
|
v
updated importance
|
v
promotion / archival policy
Run run_memory_maintenance through MCP to reinforce accessed memories, decay
inactive unpinned memories, synchronize vector metadata, and then evaluate
candidate promotion or active-memory archival. Pass dry_run=true to inspect
all proposed changes without mutating storage.
All state, type, origin, lifecycle-reason, and importance-reason enums are
stored as SQLite integers and exposed in Python as IntEnum values.
Multiple memory stores
The server provides a writable main store. Scanned databases live beneath
data/stores/<name>/ and contain their own manifest.json. The filesystem is
the source of truth: there is no separate store registry, registration step,
mount operation, or startup fixture.
list_memory_stores discovers manifests directly from disk. A named store is
opened lazily when recall or another operation addresses it. Returned memory
IDs are globally qualified, for example ghidra-core:seg_abcd.
Store modes are SQLite integers exposed through StoreMode:
0 READ_WRITE
1 READ_ONLY
2 IMMUTABLE
Writes require an explicit target_store; they are never broadcast. Before a
write, clients must call list_memory_stores whenever the destination is not
already established in the current context. Store IDs must not be guessed or
discovered by intentionally causing a failed write.
Maintenance runs only against writable stores. Read-only and immutable SQLite
databases are opened with SQLite read-only URI modes and are never migrated
automatically. Their recall access counts and user-specific ranking choices are
kept in store_overlays.sqlite3 instead of changing canonical content.
Creating a scanned database is sufficient to make it discoverable:
uv run contextual-memory-index scan ./project --name project-memory
This creates:
data/stores/project-memory/
├── manifest.json
├── project-memory.sqlite3
└── vectors/
No registration or mounting command is required.
Web search providers
Automatic web acquisition can use multiple search providers in priority order. Providers that need credentials are skipped unless configured, and failures automatically fall through to the next provider.
CM_WEB_SEARCH_PROVIDERS=exa,brave,tavily,searxng,duckduckgo
CM_WEB_SEARCH_TIMEOUT=12
CM_EXA_API_KEY=
CM_BRAVE_SEARCH_API_KEY=
CM_TAVILY_API_KEY=
CM_SEARXNG_URL=http://localhost:8080
With no API keys or SearXNG URL, DuckDuckGo is used as the zero-configuration fallback. For a self-hosted setup, place searxng first and set CM_SEARXNG_URL. The configured SearXNG instance must permit JSON search responses.
Web acquisition and indexing
By default, indexed memory is authoritative over the web. recall_memory only triggers web discovery, page ingestion, and a second local recall when local retrieval returns no hits. Search providers are attempted in configured priority order; unconfigured providers are skipped and failures fall through to the next provider.
CM_MEMORY_AUTHORITY_OVER_WEB=true
CM_WEB_SEARCH_PROVIDERS=exa,brave,tavily,searxng,duckduckgo
CM_WEB_SEARCH_CACHE_DAYS=7
CM_WEB_ACQUISITION_RETRY_DAYS=7
CM_WEB_ACQUISITION_REFRESH_DAYS=90
Search results are cached in data/web_acquisition.sqlite3. Acquisition history suppresses repeated searches for unavailable topics and schedules successful topics for a later refresh.
The index CLI accepts directories, individual files, direct URLs, and search queries:
python main.py scan ./prompts
python main.py scan ./character.md --name roleplay
python main.py scan https://example.org/wiki/Character --name roleplay
python main.py scan --search "Character franchise personality dialogue" --name roleplay
When --name is omitted, content is indexed into the writable main store. Missing named stores are created automatically and are immutable after indexing unless --mutable is supplied. MediaWiki pages use their API when available, and GitHub blob URLs are fetched through their raw-content endpoint.
Visual memory
scan now discovers common image formats and sends them to an OpenAI-compatible
vision model. LM Studio's local server is the default endpoint.
contextual-memory-index scan ./reference-images \
--name visual-reference \
--vision-model qwen2.5-vl-7b-instruct
The extractor stores a searchable visual summary plus independently classified text regions. Its general-purpose taxonomy distinguishes speech and thought bubbles, captions/overlays, clothing text, text attached to physical surfaces, documents, UI/HUD text, sound effects, watermarks, and uncategorized text. Every region includes normalized bounding coordinates and separate OCR and classification confidence values. This lets retrieval distinguish, for example, a caption saying "red coat" from the words printed on the coat itself.
Configuration:
CM_VISION_MODEL: default vision model name (required when images are found)CM_VISION_BASE_URL: compatible/v1endpoint; defaults to LM Studio athttp://127.0.0.1:1234/v1CM_VISION_API_KEY: optional bearer tokenCM_VISION_TIMEOUT: request timeout in secondsCM_VISUAL_GLOBS: comma-separated image globs
Use --no-vision to skip image files during a directory scan. Scanning a single
image with --no-vision is rejected rather than silently doing nothing.
Latent multimodal memory
This branch stores learned external-memory representations rather than copies of source training material. The scanner reads a source only during ingestion, distills it into a lossy semantic capsule, embeds that capsule, quantizes the normalized embedding to signed int8, and persists the compact parameter record. Raw image, audio, and video bytes are never copied into the memory store.
Supported inputs:
- Text: works immediately through the built-in heuristic semantic provider.
Configure
CM_SEMANTIC_MODELlater for higher-quality local-LLM distillation. - Images: analyzed only when
CM_VISION_MODELis configured, including classified text regions. Otherwise directory scans skip images and report the count. - Audio: transcribed only when
CM_AUDIO_MODELis configured, then semantically distilled. Otherwise directory scans skip audio and report the count. - Video: enabled only when both vision and audio providers are configured. It is sampled with ffmpeg, frames are analyzed, audio is transcribed, and both channels become a compact temporal capsule.
Optional local services are enabled per modality:
CM_SEMANTIC_PROVIDER=auto
# CM_SEMANTIC_MODEL=your-local-instruct-model
# CM_VISION_MODEL=your-local-vision-model
# CM_AUDIO_MODEL=your-local-whisper-model
Configured endpoints use the OpenAI-compatible API and default to LM Studio's
local http://127.0.0.1:1234/v1. Unconfigured modalities do not prevent the
server or text scanner from running. Audio/video ingestion requires ffmpeg on
PATH only when those modalities are actually processed. The original wording or media cannot be reconstructed from the stored
capsules and quantized vectors; retain source files separately when exact
reproduction or citation is required.
Parameter storage
The former vector collection has been replaced by
latent_vectors.sqlite3. Each row contains only a stable memory ID, dimensions,
a scalar quantization scale, and a packed int8 vector. Retrieval uses exact
integer-vector scanning and SQLite remains authoritative for semantic capsules,
concept weights, and lifecycle state.
Hierarchical latent distillation
Large text files are distilled hierarchically rather than sent to the semantic model in one request. Source text is split into bounded input chunks, chunk capsules are merged into section capsules, and section capsules are merged into a document capsule. The stored latent document contains the compact document capsule and section capsules; original source wording and transient leaf capsules are not retained.
Configuration:
CM_SEMANTIC_MAX_TOKENS=512
CM_SEMANTIC_INPUT_CHUNK_CHARS=12000
CM_SEMANTIC_MERGE_FAN_IN=6
CM_SEMANTIC_MAX_TOKENS limits each generated capsule, not the source file.
CM_SEMANTIC_INPUT_CHUNK_CHARS is an approximate input-size guard chosen to
remain comfortable within an 8192-token model context. CM_SEMANTIC_MERGE_FAN_IN
controls how many lower-level capsules are combined per hierarchy request.
Interactive memory-store console
The MCP server starts a small localhost-only TCP console by default. It changes
which stores are searched when recall_memory omits its stores argument.
Explicit tool arguments still take precedence.
Start the MCP server normally, then connect from another terminal:
nc 127.0.0.1 8765
Available commands:
stores
use prompts
use main prompts
use all
status
help
exit
use all restores federated retrieval across every enabled store. Configure or
disable the console in .env:
CM_CONSOLE_ENABLED=true
CM_CONSOLE_HOST=127.0.0.1
CM_CONSOLE_PORT=8765
Console without a TCP port (recommended with LM Studio)
LM Studio can keep the MCP process and its stderr hidden. The separate console
command writes the active-store selection into the same CM_DATA_DIR used by
the server, and the server reloads it on every recall:
contextual-memory-console
memory> stores
memory> use prompts
memory> status
A one-shot form is also available:
contextual-memory-console use prompts
contextual-memory-console status
No nc connection or listening port is required. Both LM Studio and the
console command must use the same CM_DATA_DIR.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.