Contextual Memory MCP

Contextual Memory MCP

A local-first persistent contextual-memory engine with an MCP adapter for AI models such as Qwen.

Category
Visit Server

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.sqlite3
  • vectors/latent_vectors.sqlite3(compact int8 parameter bank)
  • store_overlays.sqlite3 (local ranking overlays for immutable stores)
  • stores/<name>/manifest.json plus 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 /v1 endpoint; defaults to LM Studio at http://127.0.0.1:1234/v1
  • CM_VISION_API_KEY: optional bearer token
  • CM_VISION_TIMEOUT: request timeout in seconds
  • CM_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_MODEL later for higher-quality local-LLM distillation.
  • Images: analyzed only when CM_VISION_MODEL is configured, including classified text regions. Otherwise directory scans skip images and report the count.
  • Audio: transcribed only when CM_AUDIO_MODEL is 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

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.

Official
Featured
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured