enhanced-mcp-memory
by cbuntingde
README.md
# Enhanced MCP Memory
> An enterprise-grade Model Context Protocol server for AI agents: long-term memory, task management, sequential reasoning, project-convention learning, and intelligent auto-processing — with at-rest encryption, an audit log, Prometheus metrics, and structured logging baked in.
[](https://pypi.org/project/enhanced-mcp-memory/)




> Optimised for Claude Sonnet 4 and other long-context reasoning models. Works equally well as a local memory layer for any MCP-capable client.
---
## Table of contents
1. [Why this exists](#why-this-exists)
2. [Features at a glance](#features-at-a-glance)
3. [Quick start](#quick-start)
4. [MCP client configuration](#mcp-client-configuration)
5. [Available tools](#available-tools)
6. [Configuration reference](#configuration-reference)
7. [Enterprise hardening (v2.6.0)](#enterprise-hardening-v260)
8. [Project convention learning](#project-convention-learning)
9. [Database & storage](#database--storage)
10. [Logging](#logging)
11. [Project structure](#project-structure)
12. [Testing](#testing)
13. [Building & publishing](#building--publishing)
14. [Troubleshooting](#troubleshooting)
15. [License](#license)
---
## Why this exists
Memory and task state for an AI agent shouldn't be lost when the conversation ends. Most MCP servers treat memory as a sidecar feature — a few JSON blobs, no audit trail, no encryption, no retry semantics. **Enhanced MCP Memory** treats memory as production infrastructure:
- **Reliable** — bare `except Exception: pass` is gone. Every silent failure logs at WARNING with full context. SIGTERM and SIGINT trigger a graceful shutdown that flushes the audit log.
- **Observable** — Prometheus metrics for every tool call, structured JSON logs ready for log shippers, and a tamper-evident `audit_log` table recording who did what and when.
- **Secure by default** — opt-in at-rest encryption with Fernet (AES-128-CBC + HMAC-SHA256) for memories, tasks, thinking chains, and project content.
- **Defensive under load** — circuit breaker, sampling, and a per-call cap on the auto-processing middleware so a chatty agent can't melt the server.
- **Typed knowledge graph** — `depends_on`, `relates_to`, `conflicts_with`, `implements`, `references`, `similar_content`, with `strength` clamped to `[0, 1]` and direction-aware queries.
---
## Features at a glance
| Area | What you get |
|---|---|
| Memory | Semantic search via sentence-transformers, automatic classification + importance scoring, content-hash deduplication, file-path associations, LRU cap with importance-aware eviction. |
| Sequential thinking | Five-stage reasoning chains (analysis -> planning -> execution -> validation -> reflection), real-time token estimation, 30-70% context compression, key-point / decision / action auto-extraction. |
| Tasks | Auto-extraction from conversation and code, status tracking (pending / in_progress / completed / cancelled), task-memory relationships, project scoping, no-false-positive `decompose_task`. |
| Project conventions | Auto-detect OS / shell / toolchain / build commands, learn npm scripts and Makefile targets, suggest correct commands, persist as high-importance memories. |
| Enterprise | At-rest encryption, audit log, structured JSON logging, Prometheus `/metrics` endpoint, circuit-breakered middleware, typed KG, graceful shutdown. |
| Operations | `health_check()`, `get_performance_stats()`, `cleanup_old_data()`, `optimize_memories()`, `get_database_stats()`, multi-editor safe with WAL + 5s busy-timeout. |
| Deployment | Single entry point (`enhanced-mcp-memory`) — works under `uvx`, `uv tool install`, and `pip install`. No nested venv built on top of uvx's cache. |
---
## Quick start
The launcher (`run_in_venv.main`) is wired into `[project.scripts]`, so **every install path funnels through it**. The launcher detects how it was invoked and picks the right strategy:
| Invocation | What the launcher does |
|---|---|
| `uvx enhanced-mcp-memory` | Detects uvx's cache venv (`sys.prefix != sys.base_prefix`) and runs the server in place — no nested venv. |
| `uv tool install enhanced-mcp-memory` then `enhanced-mcp-memory` | Same as uvx: detects the tool venv, runs in place. |
| `pip install enhanced-mcp-memory` then `enhanced-mcp-memory` | Same: runs in the install's venv in place. |
| `python run_in_venv.py` (from a checkout) | Builds (or reuses) a private `~/enhanced-mcp-memory/.venv`, editable-installs the package, re-execs the server inside. |
### Option 1 — `uvx` (recommended for end users)
```bash
uvx enhanced-mcp-memory
```
First launch is slow (it builds uvx's cache venv and downloads dependencies); subsequent launches are a near-zero-overhead passthrough.
### Option 2 — run from a checkout (recommended for development)
```bash
git clone https://github.com/cbunting99/enhanced-mcp-memory.git
cd enhanced-mcp-memory
python run_in_venv.py
```
Use this when you want to hack on the server — the editable install means source edits take effect after a re-launch.
### Option 3 — system Python, no venv
```bash
git clone https://github.com/cbunting99/enhanced-mcp-memory.git
cd enhanced-mcp-memory
pip install -r requirements.txt
python mcp_server_enhanced.py
```
### Add the enterprise extras (encryption + metrics)
The base wheel ships the memory, task, and thinking modules. To get **at-rest encryption**, the **Prometheus metrics endpoint**, and the **audit log**, install the optional `enterprise` extra — pipe it through whichever launcher you use:
| Launcher | Command |
|---|---|
| `uvx` (one-off) | `uvx --from "enhanced-mcp-memory[enterprise]" enhanced-mcp-memory` |
| `uv tool` (persistent) | `uv tool install enhanced-mcp-memory[enterprise]` |
| `pip` | `pip install "enhanced-mcp-memory[enterprise]"` |
If you skip the extras, the server still works — `crypto.status()` reports `enabled=False`, `ENCRYPTION_KEY` is silently ignored, and `METRICS_PORT` does nothing.
### Useful launcher flags
```bash
python run_in_venv.py # bootstrap (or reuse) + run
python run_in_venv.py --venv-path # print the resolved venv path
python run_in_venv.py --data-dir # print the resolved data dir path
python run_in_venv.py --upgrade # force reinstall into the venv
python run_in_venv.py --uninstall # remove venv + database + logs
python run_in_venv.py --uninstall --yes # same, skip the confirmation prompt
```
Override locations with environment variables if needed:
```bash
export ENHANCED_MCP_MEMORY_VENV=/some/other/path/.venv
export ENHANCED_MCP_MEMORY_DATA=/some/other/data/dir
```
---
## MCP client configuration
The MCP server is launched via the same `enhanced-mcp-memory` entry point regardless of install method — point your client at whichever form fits.
### `uvx` (recommended for end users)
```json
{
"mcpServers": {
"memory-manager": {
"command": "uvx",
"args": ["--from", "enhanced-mcp-memory[enterprise]", "enhanced-mcp-memory"],
"env": {
"LOG_LEVEL": "INFO",
"MAX_MEMORY_ITEMS": "1000",
"ENABLE_AUTO_CLEANUP": "true",
"STRUCTURED_LOGS": "true",
"METRICS_PORT": "9090",
"AUDIT_ACTOR": "$USER@$(hostname)"
}
}
}
}
```
### Local checkout (developer / hacking)
```json
{
"mcpServers": {
"memory-manager": {
"command": "python",
"args": ["run_in_venv.py"],
"cwd": "/path/to/enhanced-mcp-memory",
"env": {
"LOG_LEVEL": "INFO",
"MAX_MEMORY_ITEMS": "1000",
"ENABLE_AUTO_CLEANUP": "true",
"STRUCTURED_LOGS": "true",
"METRICS_PORT": "9090",
"AUDIT_ENABLED": "true"
}
}
}
}
```
> If you use multiple editors (Cursor, Claude Desktop, VS Code, etc.), make sure they all use the same `DATA_DIR` — otherwise each editor writes to its own private database and memories will appear to "vanish" when you switch editors. See [Canonical data directory](#canonical-data-directory) below.
---
## Available tools
### Core memory tools
| Tool | Purpose |
|---|---|
| `get_memory_context(query)` | Fetch relevant memories and project context for the current prompt. |
| `list_memories(memory_type, project_id, limit)` | List stored memories with optional filters. |
| `create_task(title, description, priority, category)` | Create a new task in the active project. |
| `get_tasks(status, limit)` | Retrieve tasks, optionally filtered by status. |
| `get_project_summary()` | Get a comprehensive overview of the active project. |
### Sequential thinking tools
| Tool | Purpose |
|---|---|
| `start_thinking_chain(objective)` | Begin a structured reasoning process. |
| `add_thinking_step(chain_id, stage, title, content, reasoning)` | Append one reasoning step. |
| `get_thinking_chain(chain_id)` | Retrieve the complete chain. |
| `list_thinking_chains(limit)` | List recent chains. |
### Context management tools
| Tool | Purpose |
|---|---|
| `create_context_summary(content, key_points, decisions, actions)` | Compress context for token optimisation. |
| `start_new_chat_session(title, objective, continue_from)` | Begin a new conversation with optional continuation. |
| `consolidate_current_session()` | Compress the current session for handoff. |
| `get_optimized_context(max_tokens)` | Get token-optimised context within a budget. |
| `estimate_token_usage(text)` | Real-time token count for planning. |
### Enterprise auto-processing tools
| Tool | Purpose |
|---|---|
| `auto_process_conversation(content, interaction_type)` | Extract memories and tasks automatically; threshold + per-call cap enforced. |
| `decompose_task(prompt)` | Break a complex task into subtasks — no false positives on trivial or conversational prompts. |
### Project convention tools
| Tool | Purpose |
|---|---|
| `auto_learn_project_conventions(project_path)` | Automatically detect and learn project patterns. |
| `get_project_conventions_summary()` | Get a formatted summary of learned conventions. |
| `suggest_correct_command(user_command)` | Suggest project-appropriate command corrections. |
| `remember_project_pattern(pattern_type, pattern, description)` | Manually store a project pattern. |
| `update_memory_context()` | Refresh memory context with the latest project conventions. |
### System management tools
| Tool | Purpose |
|---|---|
| `health_check()` | Run health checks and connectivity diagnostics. |
| `get_performance_stats()` | Get detailed performance metrics. |
| `cleanup_old_data(days_old)` | Clean up old memories and tasks. |
| `optimize_memories()` | Remove duplicates and optimize storage. |
| `get_database_stats()` | Get comprehensive database statistics. |
---
## Configuration reference
All settings are environment variables — no config files required.
### Core
| Variable | Default | Description |
|---|---|---|
| `DATA_DIR` | `~/enhanced-mcp-memory` | Where to store data and logs. Important: keep this consistent across every editor's MCP config — see [Canonical data directory](#canonical-data-directory). |
| `LOG_LEVEL` | `INFO` | Logging level: `DEBUG`, `INFO`, `WARNING`, `ERROR`. |
| `MAX_MEMORY_ITEMS` | `1000` | Maximum memories per project; LRU-evicts lowest-importance items when over. |
| `MAX_CONTEXT_TOKENS` | `8000` | Token threshold at which context auto-compression kicks in. |
| `CLEANUP_INTERVAL_HOURS` | `24` | How often the background cleanup pass runs. |
| `ENABLE_AUTO_CLEANUP` | `true` | Toggle the background cleanup pass. |
| `MAX_CONCURRENT_REQUESTS` | `5` | Max concurrent MCP tool calls. |
| `REQUEST_TIMEOUT` | `30` | Per-request timeout in seconds. |
### Enterprise (require `[enterprise]` extras)
| Variable | Default | Description |
|---|---|---|
| `ENCRYPTION_KEY` | _unset_ | Fernet key (base64-url, 32 bytes). When set, memory, task, thinking-chain, and project content columns are encrypted at rest with AES-128-CBC + HMAC. Generate with `python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"`. Existing plaintext databases remain readable when the key is unset. |
| `METRICS_PORT` | _unset_ | When set, exposes Prometheus metrics on `http://127.0.0.1:PORT/metrics` (where `PORT` is the value of this variable). |
| `METRICS_HOST` | `127.0.0.1` | Bind address for the metrics endpoint. |
| `STRUCTURED_LOGS` | `false` | When `true`, logs are emitted as one JSON object per line (log-shipper friendly). |
| `LOG_FILE` | _unset_ | When set, also writes JSON-formatted logs to this file path (parallel to the console log). |
| `AUDIT_ENABLED` | `true` | Master switch for the `audit_log` writes. Set to `false` for read-only or audit-bypass deployments. |
| `AUDIT_ACTOR` | `$USER` | Identity recorded in each `audit_log` row. Override per environment so multi-tenant deployments can attribute actions correctly. |
### Middleware (auto-processing gate)
| Variable | Default | Description |
|---|---|---|
| `MIDDLEWARE_ENABLED` | `true` | Master switch for the conversation auto-processing middleware. |
| `MIDDLEWARE_SAMPLE_RATE` | `1.0` | Probability (0.0-1.0) that a conversation triggers extraction. Lower = less work. |
| `MIDDLEWARE_MIN_CONTENT_LEN` | `200` | Skip extraction when content is shorter than this many characters. |
| `MIDDLEWARE_CIRCUIT_FAILURES` | `5` | Consecutive failures that trip the middleware circuit breaker. |
| `MIDDLEWARE_CIRCUIT_COOLDOWN` | `60` | Seconds the middleware stays disabled after tripping. |
| `AUTO_PROCESS_THRESHOLD` | `0.5` | Importance threshold above which extracted items become memories. |
| `AUTO_PROCESS_MAX_PER_CALL` | `5` | Hard cap on memories / tasks created per `auto_process_conversation` call. |
---
## Enterprise hardening (v2.6.0)
### Cold-start behaviour
Each MCP server process pays for one-shot work at import time. Cold start on
this machine measures ~1.31 s end-to-end on Python 3.14; **`fastmcp`'s deep
imports dominate (~1.28 s)** and cannot be deferred — `@mcp.tool()` decorators
need the FastMCP instance to exist at module load.
The four service singletons (`db_manager`, `convention_learner`,
`memory_manager`, `thinking_engine`) are bound at module scope behind
`_LazyProxy` placeholders. The DB and `DatabaseManager` are only constructed
on first attribute access, so:
- A process that only imports the module (a probe, `--help`, a unit test that
doesn't touch the DB) never opens the SQLite file.
- A burst of 30-40 parallel editor launches (e.g. Kimi Code CLI) each pay
import cost but defer per-service construction until the first tool call.
- `mcp_server_enhanced.reset_services_for_tests()` clears the cache for the
test harness.
The realistic wall-clock saving on a no-tool-call path is ~50 ms per process
(plus the avoidance of opening a SQLite WAL file). For end-to-end user
latency the gain is modest; the architectural benefit is that probe / test
paths no longer touch the data directory. See `tests/test_lazy_init.py`
and `measure_lazy.py` for measurements.
### At-rest encryption
Set `ENCRYPTION_KEY` and the server transparently encrypts all sensitive columns — memory `title` / `content`, task descriptions, thinking-chain content, and project conventions — using **Fernet** (AES-128-CBC + HMAC-SHA256). Each row is independently keyed with a fresh IV; ciphertexts are prefixed with `fernet:v1:` so a future format change can be detected at read time.
The encryption layer is **fail-soft**: a transient decryption error logs at WARNING and returns the ciphertext unchanged rather than crashing the request. The format version prefix means you can rotate `ENCRYPTION_KEY` and run an offline re-encryption migration without touching call sites.
### Audit log
Every mutating tool writes one row to `audit_log`:
| Column | Meaning |
|---|---|
| `timestamp` | ISO-8601 UTC at write time. |
| `actor` | `$AUDIT_ACTOR` (defaults to `$USER` / `$USERNAME`, falls back to `system`). |
| `action` | Tool name / operation. |
| `resource_type` | e.g. `memory`, `task`, `project`. |
| `resource_id` | UUID of the affected row, when applicable. |
| `success` | `1` on success, `0` on failure. |
| `error` | Error string on failure. |
| `metadata` | Free-form JSON (request args, prior value, etc.). |
| `host`, `pid` | Process attribution. |
Audit writes are best-effort: if the table is unreachable the tool call still succeeds. Set `AUDIT_ENABLED=false` to skip writes entirely (e.g. for read-only mirrors).
### Structured (JSON) logging
Set `STRUCTURED_LOGS=true` and every log line becomes a single JSON object:
```json
{"ts": "2026-07-09T03:26:49.714Z", "level": "INFO", "logger": "audit",
"message": "memory mutated", "pid": 15268, "tid": 26564}
```
Set `LOG_FILE=/var/log/enhanced-mcp-memory.jsonl` to tee the same JSON into a file for downstream shippers (Loki, Vector, Fluent Bit). The console stays human-readable.
### Prometheus metrics
Set `METRICS_PORT=9090` (or any free port) and the server exposes `/metrics`. Counters: tool calls, tool errors, audit writes. Histograms: tool latency. Gauges: database size, memory count, circuit-breaker state.
```bash
$ curl -s http://127.0.0.1:9090/metrics | head
# HELP enhanced_mcp_tool_calls_total Total MCP tool invocations.
# TYPE enhanced_mcp_tool_calls_total counter
enhanced_mcp_tool_calls_total{tool="get_memory_context",status="success"} 42
```
### Reliability primitives
Every silent-failure path now flows through `safe_call(logger, op, fn, *args, default=None, **kwargs)`. The helper runs `fn(*args, **kwargs)`, catches `Exception`, logs at WARNING with the operation name and exception class, and returns `default`. Bare `except Exception: pass` is gone — enforced in CI by a banned-pattern grep.
A SIGTERM and SIGINT handler is installed at startup (and registered with `atexit`) so the server flushes pending audit writes and closes the database cleanly before exit. CI catches the SIGTERM that pytest sends at teardown.
### Middleware hardening
The conversation auto-processing path is gated by:
- a **circuit breaker** (`MIDDLEWARE_CIRCUIT_FAILURES` / `MIDDLEWARE_CIRCUIT_COOLDOWN`) — consecutive failures trip the breaker and disable the path until cooldown elapses,
- **sampling** (`MIDDLEWARE_SAMPLE_RATE`) — only a fraction of conversations trigger extraction,
- a **minimum-content gate** (`MIDDLEWARE_MIN_CONTENT_LEN`) — short conversations are skipped without overhead.
Each skip / trip event is itself recorded in `audit_log` and in the Prometheus counters so you can see why extraction didn't run.
### Typed knowledge graph
`add_relationship(from_type, from_id, to_type, to_id, relationship_type, strength=1.0)` now validates the typed catalog and clamps `strength` to `[0, 1]`:
```python
allowed = {"depends_on", "relates_to", "conflicts_with",
"implements", "references", "similar_content"}
db.add_relationship("memory", "m1", "task", "t1", "relates_to", strength=2.5)
# ^ ValueError: unknown relationship_type; valid set: depends_on, ...
# strength clamped to 1.0 before insert
```
`get_related_items(item_type, item_id, relationship_type=None, min_strength=0.0, limit=50)` honours both filters and returns both `outgoing` and `incoming` edges with a `direction` field.
---
## Project convention learning
The server automatically detects and remembers project-specific conventions so AI assistants stop suggesting the wrong commands. Across detection:
- **Operating system & shell** — Windows vs Unix, `cmd.exe` / PowerShell / Bash / Zsh.
- **Project type** — Node.js, Python (FastAPI / Django / pytest / poetry), Rust, Go, Java, MCP servers.
- **Build & test commands** — `npm run *`, `cargo test`, `pytest`, `go test`, Makefile targets, project-specific scripts.
- **Tooling** — IDEs, linters (flake8 / eslint), formatters (black / prettier), CI/CD files (GitHub Actions / GitLab CI).
- **Package management** — npm / yarn / pnpm, pip / poetry / uv, cargo, go modules.
- **Smart suggestions** — given `"node server.js"` in a project with `"dev": "node server.js"` in `package.json`, the suggestion engine responds with the correct invocation.
All learned conventions persist as **high-importance memories** so they appear in AI context for every interaction, across session and project boundaries.
Windows-specific quirks (path separators, `dir` vs `ls`, `where` vs `which`, `cmd.exe` quoting) are detected and respected automatically.
---
## Database & storage
- **SQLite** for reliable, file-based storage — no separate DB process to manage.
- **WAL journal mode + 5s busy-timeout** — safe concurrent access from multiple editors.
- **Automatic schema migrations** — every migration recorded in `schema_migrations` and run exactly once; older DBs upgrade transparently on first connect.
- **`audit_log` table** — every mutating tool writes a row (see [Audit log](#audit-log)).
- **Comprehensive indexing** — most queries return in single-digit milliseconds even at 100k rows.
- **Built-in backup & repair tools** — `optimize_memories()` deduplicates on content hash; `get_database_stats()` reports size + integrity.
Default location: `~/enhanced-mcp-memory/data/mcp_memory.db` (or `$DATA_DIR/data/mcp_memory.db` when set).
### Canonical data directory
When you point several MCP clients at this server, **every client must use the same `DATA_DIR`** — or, easier, leave `DATA_DIR` unset everywhere and let each client fall back to the default `~/enhanced-mcp-memory`. Otherwise each editor writes to its own private database and memories appear to "vanish" when you switch editors.
Symptoms of a misconfigured setup:
- Memory counts differ between editors.
- Multiple `mcp_memory.db` files exist at `~/.enhanced_mcp_memory/`, `~/ClaudeMemory/`, etc.
- The server logs `data dir SOME_PATH is inside cwd SOME_PATH` at startup — that warning means the project root was used as the data dir, which produces a brand-new DB per project.
If you already have scattered DBs, consolidate them into the canonical target:
```bash
# Dry-run first; shows how many rows would merge and how many dedup by content_hash.
python scripts/merge_databases.py \
"$HOME/.enhanced_mcp_memory/data/mcp_memory.db" \
"$HOME/ClaudeMemory/data/mcp_memory.db"
# When the dry-run looks right, apply (each source is auto-backed up to
# <source>.bak-TIMESTAMP).
python scripts/merge_databases.py --apply \
"$HOME/.enhanced_mcp_memory/data/mcp_memory.db" \
"$HOME/ClaudeMemory/data/mcp_memory.db"
# Add more sources later by re-running; idempotent by primary key plus
# content_hash dedup for memories.
```
Run `scripts/merge_databases.py --help` for the full flag list (`--no-backup`, `--target` / `-d`, etc.).
---
## Logging
- **Daily rotation** in `./logs/` (or `$DATA_DIR/logs/`).
- **Human-readable console** by default; set `STRUCTURED_LOGS=true` for one-JSON-object-per-line.
- **Optional file sink** via `LOG_FILE=/path/to/file.jsonl` — useful for Loki / Vector / Fluent Bit ingestion.
- **Performance tracking** integrated — every tool call emits a structured event with latency and success.
- **Error tracking** with full stack traces at WARNING and above.
The structured-logging helpers (`structured_logging.install_once(level, log_file)`) are safe to call multiple times — only the first call wires a new handler; subsequent calls are no-ops. This lets MCP tool decorators request a logger without worrying about double-handler noise.
---
## Project structure
```text
enhanced-mcp-memory/
mcp_server_enhanced.py # Main MCP server, FastMCP integration
memory_manager.py # Core memory / task logic + project detection
sequential_thinking.py # Five-stage reasoning chains + context optimisation
database.py # SQLite layer, typed KG, audit schema install
project_conventions.py # OS / shell / toolchain / command learner
enhanced_automation_middleware.py # Auto-processing with circuit breaker + sampling
audit.py # Audit-log writer (audit_log table)
crypto.py # Fernet at-rest encryption [enterprise]
metrics.py # Prometheus counters / histograms / gauges [enterprise]
structured_logging.py # JSON formatter + install_once()
run_in_venv.py # Cross-platform venv launcher (console_script)
version.py # Single-source __version__
pyproject.toml # Build metadata + [enterprise] / [dev] extras
tests/ # Pytest suite: 45 tests, all passing
conftest.py
test_audit.py
test_concurrency.py
test_database_schema.py
test_decompose_task.py
test_encryption.py
test_knowledge_graph.py
test_memory_manager.py
test_metrics.py
test_middleware_circuit_breaker.py
test_structured_logging.py
test_sweep_bare_except.py
data/ # SQLite database storage
logs/ # Application logs
.github/workflows/ci.yml # Pytest matrix + flake8 + banned-pattern grep
```
---
## Testing
The repo ships with a 45-test pytest suite under `tests/`. Run it locally:
```bash
pip install -e ".[enterprise,dev]"
pytest tests/
```
CI (`.github/workflows/ci.yml`) runs the suite across Python 3.9-3.12, plus `flake8` and a banned-pattern sweep that fails the build if any `except Exception: pass` or bare `except:` slips back into production:
```yaml
- ! grep -rnE 'except\s+Exception\s*:\s*pass' --include='*.py' .
- ! grep -rnE '^\s*except\s*:\s*$' --include='*.py' .
```
Targeted runs are common while iterating:
```bash
pytest tests/test_encryption.py -v # only the crypto round-trip
pytest tests/test_audit.py -v # only the audit-log path
pytest tests/test_sweep_bare_except.py -v # only the banned-pattern lint
pytest tests/ -k "decompose" -v # any test whose name matches "decompose"
```
---
## Building & publishing
The wheel is built with `python -m build` and validated with `twine check`. Both tools are pure-Python and install-on-demand.
```bash
# 1. Make sure the dev extras + the enterprise extras are present.
pip install -e ".[enterprise,dev]"
# 2. Build sdist + wheel into ./dist.
python -m build
# 3. Validate metadata and long-description rendering.
python -m twine check dist/*
# 4. Upload to TestPyPI first, smoke-test, then promote to PyPI.
python -m twine upload --repository testpypi dist/*
python -m twine upload dist/*
```
A successful `python -m build` produces:
```text
dist/
enhanced_mcp_memory-2.6.1-py3-none-any.whl
enhanced_mcp_memory-2.6.1.tar.gz
```
After upload, verify the published version is installable from a fresh venv:
```bash
python -m venv /tmp/verify
/tmp/verify/Scripts/python -m pip install "enhanced-mcp-memory[enterprise]"
/tmp/verify/Scripts/python -c \
"import mcp_server_enhanced, audit, crypto, metrics, structured_logging; print('OK')"
```
### Manual release checklist
1. Bump `version.py` (`2.6.1` -> `2.6.2`, etc.).
2. `pytest tests/ -v` — must be 45 / 45.
3. `python -m build` then `python -m twine check dist/*` — must PASS.
4. Confirm CI green on the release branch.
5. Tag the release with `git tag -s v2.6.1 -m 'v2.6.1'`.
6. `python -m twine upload dist/*`.
---
## Troubleshooting
### The server starts but memories appear missing in editor X
Almost always a `DATA_DIR` mismatch — editor X is reading a different SQLite file than editor Y. See [Canonical data directory](#canonical-data-directory). Fix: pick one `DATA_DIR` and set it everywhere (or unset it everywhere and let every client default to `~/enhanced-mcp-memory`).
### `crypto.status()` reports `enabled=False` even though I set `ENCRYPTION_KEY`
You installed the base wheel without the `enterprise` extras. Reinstall as `pip install "enhanced-mcp-memory[enterprise]"` (or the equivalent `uvx --from` / `uv tool` form) so `cryptography` is on the Python path.
### `uvx enhanced-mcp-memory` hangs on first launch
First launch is slow: uvx builds a cache venv and downloads the sentence-transformers model (~90 MB). Subsequent launches are near-instant. Watch the first-launch output for `pip install` progress bars.
### The audit log keeps growing
Expected — every mutating tool writes a row. For long-running deployments, prune via `cleanup_old_data()` or a periodic SQL `DELETE FROM audit_log WHERE timestamp < datetime('now', '-90 days')`. Pairs naturally with `audit_log` being created with a covering index on `timestamp`.
### The auto-processing middleware stopped extracting
Check the circuit-breaker counters via `/metrics` (look for `enhanced_mcp_middleware_circuit_state`) or query `audit_log` for `action='middleware_skip'` entries to see why. Likely candidates: too many consecutive failures tripped the breaker, sample rate is `0.0`, or content length is below `MIDDLEWARE_MIN_CONTENT_LEN`.
---
## License
MIT — see [LICENSE](LICENSE).
## Support
- Issues: [cbunting99/enhanced-mcp-memory/issues](https://github.com/cbunting99/enhanced-mcp-memory/issues)
- Documentation: [README on GitHub](https://github.com/cbunting99/enhanced-mcp-memory#readme)
- Discussions: [cbunting99/enhanced-mcp-memory/discussions](https://github.com/cbunting99/enhanced-mcp-memory/discussions)
## Version history
- **v2.6.1** — README rewrite as pure GitHub Flavored Markdown; no HTML wrappers, properly-aligned tables, working ToC anchors.
- **v2.6.0** — Enterprise hardening release: at-rest encryption, audit log, structured logging, Prometheus metrics, circuit-breakered middleware, typed knowledge graph, full pytest + CI suite.
- **v2.0.3** — Lazy init via `_LazyProxy` placeholders; services only built on first attribute access. Probe / test paths no longer open the DB.
- **v2.0.2** — Build configuration + license compatibility fixes.
- **v2.0.1** — Sequential thinking + project conventions.
- **v1.2.0** — Performance monitoring + health checks.
- **v1.1.0** — Semantic search + knowledge graph.
- **v1.0.0** — Initial release.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing