Composite Memory MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Composite Memory MCP ServerRemember that the server IP is 10.0.0.1"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Composite Memory MCP Server (CMMS)
Independent MCP memory service for AI agents. Agent-independent.
Dev Setup
# Clone and enter
git clone git@github.com:fedosis/Composite-memory-MCP-server.git
cd memory-server
# Create venv and install
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
# Run tests
pytest tests/ -x -q
# Lint
ruff check src/
# CLI
memory-server --help
memory-server pingRelated MCP server: agent-memory-hub
Docs
ADR — Architecture Decision Records (10 ADRs)
Agent Spec — Implementation specification
Technical Design — Tech stack + roadmap
Architecture — Mermaid architecture diagram
Usage — Full usage reference
Metrics & Benchmarking — Metrics and benchmark framework
Comparative Analysis — Comparative analysis with ChromaDB/SQLite
Drift Matrix — Contract audit
Contracts — JSON Schema 2020-12 tool contracts
API Reference
The server exposes nine MCP tools:
ping
Health check — verifies the server is running and responsive.
Arguments: None
Response:
{"status": "ok"}search
Search for stored facts by query text, subject, predicate, or object.
Arguments:
Parameter | Type | Required | Description |
| string | yes | Text to search across all fact fields |
| string | no | Filter by subject |
| string | no | Filter by predicate |
| string | no | Filter by object |
| string | no | Filter by source |
| int | no | Max results (default: 10) |
Response:
{
"total": 2,
"results": [
{"id": "uuid", "subject": "Docker", "predicate": "runs_on", "object": "OMV8", "confidence": 1.0, "source": "test", "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-01-01T00:00:00Z"}
],
"query": "Docker"
}remember
Store a new fact in the memory server.
Arguments:
Parameter | Type | Required | Description |
| string | yes | Subject entity |
| string | yes | Relation/predicate |
| string | yes | Object entity |
| float | no | Confidence score 0.0–1.0 (default: 0.5) |
| string | no | Source identifier (default: "manual") |
| list | no | Optional tags |
Response:
{
"receipt": {
"id": "uuid",
"memory_type": "fact",
"confidence": 1.0,
"source": "test",
"verification_status": "candidate",
"timestamp": "2025-01-01T00:00:00Z"
},
"fact": {
"id": "uuid",
"subject": "Docker",
"predicate": "runs_on",
"object": "OMV8",
"confidence": 1.0,
"source": "test",
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-01T00:00:00Z"
}
}get_context
Retrieve relevant context facts for a given task or subject.
Arguments:
Parameter | Type | Required | Description |
| string | yes | Task description or subject to find context for |
| string | no | Optional subject filter |
| int | no | Max results (default: 10) |
Response:
{
"total": 2,
"facts": [
{"id": "uuid", "subject": "Caddy", "predicate": "uses", "object": "Port 443", "confidence": 1.0, "source": "test", "created_at": "2025-01-01T00:00:00Z", "updated_at": "2025-01-01T00:00:00Z"}
],
"task": "Caddy"
}semantic_search
Semantic search — embed a query, find similar facts via vector similarity, and return ranked results with similarity scores.
Per ADR-005, routing rules (keyword-based exact matches) are evaluated before the embedding search. If a rule matches, the result indicates which route should handle the query (e.g., "route": "sql"). Otherwise, semantically ranked results are returned.
Arguments:
Parameter | Type | Required | Default | Description |
| string | yes | — | Natural language query text |
| int | no | 10 | Maximum number of results |
| float | no | 0.0 | Minimum similarity score 0.0–1.0 |
Response (rule match):
{
"rule_match": {
"route": "sql",
"rule_name": "ip_address_query",
"matched_keyword": "ip of"
}
}Response (semantic results):
{
"semantic_results": [
{
"id": "uuid",
"score": 0.92,
"payload": {
"subject": "Docker",
"predicate": "runs_on",
"object": "OMV8",
"content": "Docker runs on OMV8"
}
}
],
"total": 1
}learn
Extract and store facts, decisions, and skills from natural language text. Runs all three extractors (FactExtractor, DecisionExtractor, SkillExtractor) on the input text, stores extracted items in the memory database, and returns structured results with receipts per item type.
Arguments:
Parameter | Type | Required | Default | Description |
| string | yes | — | Natural language text to extract knowledge from |
| string | no | "user" | Source identifier for provenance tracking |
Response:
{
"facts": [
{
"receipt": {"id": "uuid", "memory_type": "fact", "source": "user", "confidence": 0.5, "verification_status": "candidate"},
"item": {"id": "uuid", "subject": "Docker", "predicate": "is", "object": "container", "confidence": 0.5, "source": "user"}
}
],
"decisions": [
{
"receipt": {"id": "uuid", "memory_type": "decision", "source": "user", "confidence": 0.5, "verification_status": "candidate"},
"item": {"id": "uuid", "context": "", "choice": "use Caddy", "reason": "it is simpler", "source": "user"}
}
],
"skills": [
{
"receipt": {"id": "uuid", "memory_type": "skill", "source": "user", "confidence": 0.5, "verification_status": "candidate"},
"item": {"id": "uuid", "purpose": "deploy docker", "steps": ["pull image", "run container"], "success_rate": 0.5}
}
],
"receipts": [
{"id": "uuid", "memory_type": "fact", "source": "user", "verification_status": "candidate"},
{"id": "uuid", "memory_type": "decision", "source": "user", "verification_status": "candidate"}
]
}graph_search
Search the knowledge graph for entities, relations, and paths between entities.
Supports three search modes depending on which parameters are provided:
Mode 1 — Query (entity lookup): Pass a query string. The server extracts entity references from
the query and returns matching entities plus their neighbors and the relations between them.
Mode 2 — Direct node lookup: Pass an entity_id to look up a specific graph node by its ID
and get its neighbors and edges.
Mode 3 — Pathfinding: Pass source_id and target_id to find paths between two entities
in the graph (max depth 4).
Arguments:
Parameter | Type | Required | Description |
| string | no | Text to extract entity references from |
| string | no | Direct node ID lookup |
| string | no | Source entity for pathfinding |
| string | no | Target entity for pathfinding |
Response:
{
"nodes": [
{"id": "docker", "name": "Docker", "type": "entity", "attributes": {}},
{"id": "omv8", "name": "OMV8", "type": "entity", "attributes": {}}
],
"edges": [
{"source_id": "docker", "target_id": "omv8", "relation": "runs_on", "attributes": {}}
],
"paths": []
}Pathfinding response:
{
"nodes": [],
"edges": [],
"paths": [
[
{"id": "serveralpha", "name": "ServerAlpha", "type": "entity"},
{"id": "webapp", "name": "WebApp", "type": "entity"},
{"id": "postgresql", "name": "PostgreSQL", "type": "entity"}
]
]
}route
Route a query through the 4-stage hybrid router (rules → embeddings → graph → LLM fallback).
Per ADR-005, each stage is evaluated in priority order:
Rules: Keyword-based exact match rules.
Semantic: Embedding similarity search via Qdrant.
Graph: Entity relation lookup in the knowledge graph.
LLM fallback: Placeholder for future LLM-based routing.
Returns the result from the highest-priority stage that produces meaningful output.
Arguments:
Parameter | Type | Required | Default | Description |
| string | yes | — | Natural language query text |
| int | no | 10 | Maximum semantic search results |
| float | no | 0.0 | Minimum similarity score 0.0–1.0 |
Response (rule match — stage 1):
{
"stage": 1,
"route": "rules",
"rule_match": {
"route": "sql",
"rule_name": "ip_address_query",
"matched_keyword": "ip of"
}
}Response (semantic — stage 2):
{
"stage": 2,
"route": "semantic",
"semantic_results": [
{"id": "uuid", "score": 0.92, "payload": {"subject": "Docker", "predicate": "runs_on", "object": "OMV8"}}
],
"total": 1
}Response (graph — stage 3):
{
"stage": 3,
"route": "graph",
"graph_result": {
"entities": [{"id": "docker", "name": "Docker", "type": "entity"}],
"relations": [{"source_id": "docker", "target_id": "omv8", "relation": "runs_on"}],
"paths": []
}
}Response (LLM fallback — stage 4):
{
"stage": 4,
"route": "llm_fallback",
"message": "LLM fallback not configured"
}audit
Run a structured memory audit covering consistency, orphan detection, confidence analysis, lifecycle validation, and index drift detection.
Supports focused sub-audits via the audit_type parameter, or a comprehensive "full" report.
Arguments:
Parameter | Type | Required | Default | Description |
| string | no | "full" | One of |
Audit checks (full mode):
# | Check | Description |
1 | Orphan records | Items in the validator store with no corresponding |
2 | Missing receipts | Validator entries referencing receipts that don't exist |
3 | Lifecycle violations | Items in an invalid lifecycle state or that skipped a required transition |
4 | Confidence issues | Confidence scores that conflict with current lifecycle state |
5 | SQL/vector drift | Consistency gaps between SQLite fact storage and Qdrant vector index |
6 | SQL/graph drift | Consistency gaps between SQLite fact storage and the knowledge graph |
When audit_type is set to a specific sub-audit ("consistency", "orphans", or "confidence"), only the corresponding analysis is returned:
consistency — Checks for deprecated facts with active receipts, zero-confidence facts not marked stale/archived/forgotten, and stale facts with full confidence.
orphans — Scans the graph for nodes with no incoming edges (unlinked facts).
confidence — Analyzes the confidence score distribution, bucket counts, and lists low-confidence items (< 0.3).
Response:
{
"audit_type": "full",
"warnings": [],
"errors": [
"Found 2 items without MemoryReceipt: fact_001, fact_002"
],
"stats": {
"confidence": {
"total": 150,
"buckets": {"0.0-0.3": 5, "0.3-0.5": 20, "0.5-0.7": 45, "0.7-0.85": 50, "0.85-1.0": 30},
"low_confidence": ["fact_001", "fact_002"]
},
"sql_vector_drift": {"drift_pct": 0.0, "sql_count": 150, "vector_count": 150},
"sql_graph_drift": {"drift_pct": 2.0, "sql_count": 150, "graph_count": 147}
}
}metrics
Return a Prometheus-formatted snapshot of all observability metrics. Compatible with any Prometheus scraper or curl | grep workflows.
Arguments: None
Response: Plaintext Prometheus exposition format:
# HELP tool_calls_total Total MCP tool calls
# TYPE tool_calls_total counter
tool_calls_total{tool="search",status="success"} 42.0
tool_calls_total{tool="remember",status="success"} 17.0
# HELP search_latency_ms Search latency in ms
# TYPE search_latency_ms histogram
search_latency_ms_bucket{le="1.0"} 0.0
search_latency_ms_bucket{le="5.0"} 5.0
...Stack
Python 3.12+, MCP SDK, Pydantic, SQLAlchemy, Qdrant, Neo4j, GitPython, Prometheus Client, OpenTelemetry
Storage
The server uses a multi-tier storage architecture with SQLite as the primary durable store, backed by vector (Qdrant) and graph (Neo4j / SimpleGraph) indexes.
SQLite with WAL Mode
The primary fact store uses SQLite in WAL (Write-Ahead Logging) mode for concurrent read performance during background indexing operations:
PRAGMA journal_mode=WAL;WAL mode allows simultaneous reads while a single writer is active, which is critical for the outbox pattern and background indexing without blocking the MCP tool handler.
Alembic Migrations
Database schema migrations are managed via Alembic. To apply pending migrations:
alembic upgrade headMigrations live in migrations/ and are automatically tested in CI (upgrade then downgrade -1).
FTS5 Full-Text Search
The facts_fts virtual table provides fast keyword search across fact content:
CREATE VIRTUAL TABLE facts_fts USING fts5(
subject, predicate, object, content='facts', content_rowid='id'
);FTS5 enables the search tool's full-text capabilities with ranking, prefix queries, and snippet generation.
Outbox Pattern for Reliable Indexing
Facts are written to the SQLite store first, then queued through an outbox pattern for background indexing to Qdrant (vector embeddings) and Neo4j (graph relations):
Fact is inserted into SQLite (single write transaction)
An outbox record is created in a dedicated table or queue
A background worker picks up outbox entries and indexes them to Qdrant and Neo4j
On success, the outbox record is marked as processed
On failure, the outbox record is retried — the fact is never lost
This ensures that even if vector or graph indexing fails, the fact data is durably stored and can be re-indexed on the next retry.
Lifecycle
Every fact and extracted memory item passes through a 6-stage lifecycle. The lifecycle determines how a fact moves from raw ingestion to trusted knowledge and eventual retirement.
Lifecycle States (v0.6)
State | Description |
| Initial state after ingestion via |
| Confidence >= 0.7 — fact has passed an internal quality check. |
| Confidence >= 0.85 AND corroboration >= 2 sources. High-reliability knowledge. |
| Confidence has decayed below threshold — fact may be outdated. |
| Stale fact moved to cold storage. Retained for audit but excluded from active queries. |
| Permanently removed from indexes. Only receipt/provenance metadata preserved. |
Lifecycle Flow
candidate → validated → active → stale → archived → forgottenTransitions are forward-only — once promoted, an item can only move forward through the lifecycle. Backward compatibility maps the v0.5 states "trusted" → "active" and "deprecated" → "stale".
Confidence Scoring
Confidence scores (0.0–1.0) are computed heuristically from:
Source reliability:
verified(0.9),admin(0.85),inferred(0.7),extracted(0.6),unknown(0.3)Age decay: Exponential decay over TTL (default 90 days), minimum 0.3
Corroboration boost: +0.05 for 2 sources, +0.10 for 3+
Conflict penalty: -0.10 for 1 conflict, -0.20 for 2+
Decay Engine
The DecayEngine applies time-based decay to all stored facts:
TTL-based confidence reduction (default 90 days)
Archive threshold: facts below 0.3 confidence are flagged for archiving
Runs on-demand at audit time, not as a background process
Auto-Indexing
When a fact is stored via remember() or learn(), the server automatically:
Embeds the fact text using SentenceTransformer (
all-MiniLM-L6-v2)Upserts the embedding into Qdrant for semantic search
Syncs to the knowledge graph (creates entity nodes + relation edges)
This is best-effort — failures during auto-indexing never crash the caller.
Observability
The server exposes structured observability through Prometheus metrics and OpenTelemetry instrumentation.
Prometheus Metrics
A dedicated /metrics tool returns Prometheus-formatted output on demand. The MetricsCollector singleton tracks key performance indicators across all tool operations.
Key metrics:
Metric | Type | Labels | Description |
| Counter |
| Total MCP tool calls by name and success/error status |
| Counter |
| Total errors per tool |
| Histogram | — | Search latency buckets (1–500 ms) |
| Histogram | — | Semantic search latency buckets (10–1000 ms) |
| Histogram | — | Remember latency buckets (5–500 ms) |
| Gauge | — | SQL/vector index drift count (updated on each audit) |
| Counter | — | Reindex repairs triggered |
| Counter | — | SQLite WAL busy events |
OpenTelemetry Hooks
Every tool call is wrapped with OpenTelemetry tracing:
tracer = trace.get_tracer(__name__)Spans are created per tool invocation, capturing duration and status. The tool_call() context manager on MetricsCollector automatically records:
Start time and duration
Success/error status
Exception propagation for error counting
Development
Makefile Targets
Target | Description |
| Install package with dev dependencies ( |
| Run unit tests ( |
| Run Ruff linter ( |
| Run lint + test sequentially |
| Apply Alembic migrations ( |
| Build Python package ( |
CI/CD
GitHub Actions (.github/workflows/ci.yml) runs on push/PR to main:
Job | What it runs |
lint |
|
unit-tests |
|
integration-tests |
|
contract-tests | JSON Schema validation + |
migration-tests |
|
Roadmap
Phase | Milestone |
v0.1a | MCP API + SQLite provider + get_context/search/remember |
v0.2 | Qdrant + embeddings + semantic router |
v0.3 | LLM extractors + learn() |
v0.4 | Graph DB + entity relations |
v0.5 | Confidence engine + validation + decay + auditor + auto-indexing |
v0.6 | 6-state lifecycle, audit tool, metrics/observability, outbox indexing, storage docs, CI/CD |
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/fedosis/Composite-memory-MCP-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server