Skip to main content
Glama
Vince-Yi

Sentinel-Memory MCP

by Vince-Yi
README.md
# Sentinel-Memory MCP

A lightweight MCP server that records and reuses **Prompt Gaps** — essential context missing from initial instructions — so your AI assistant learns from every session.

No vector databases. No ML models. Just a plain JSONL file tracked by Git.

---

## How It Works

Every time your AI assistant works on a task, it encounters information that was never in the original instructions but turned out to be critical. Sentinel-Memory captures those gaps and surfaces them automatically at the start of the next related task.

```
[Before task]  search_memory()        →  past lessons + questions to ask
[After task]   log_memory()           →  what was missing, what to remember
[When full]    compact_memory()       →  group logs by topic for Claude to summarize
               compact_memory_delete() →  remove originals after principle is saved
```

Memory is stored in `.context/memory_log.jsonl` inside your project — a plain text file you can read, diff, and commit like any other source file.

---

## Features

- **Zero ML dependencies** — no embeddings, no model downloads
- **Git-native storage** — plain JSONL, human-readable, fully diffable
- **Claude judges relevance** — returns all records; Claude picks what matters
- **Topic normalization** — similar topics merged during compaction
- **Atomic writes** — temp file + rename, safe against crashes
- **Cross-platform file locking** — directory-based lock, works on Windows and Linux
- **Sensitive data filtering** — API keys and tokens redacted before storage
- **npx-ready** — no installation required once published to npm

---

## Requirements

- Node.js 18+
- An MCP-compatible client (Cursor, Claude Code, etc.)

---

## Installation

### Option A — npx (after npm publish, no installation needed)

Copy `.cursor/mcp.json.example` to `.cursor/mcp.json` in your project:

```json
{
    "mcpServers": {
        "sentinel-memory": {
            "command": "npx",
            "args": ["-y", "@vncy/sentinel-memory-mcp"]
        }
    }
}
```

Cursor automatically sets the working directory to the workspace root when launching MCP servers, so no `cwd` is needed. `.context/memory_log.jsonl` is created in the project root on first use.

### Option B — local build

```bash
git clone https://github.com/your-org/dug-sentinel-memory-mcp.git
cd dug-sentinel-memory-mcp
npm install
npm run build
```

Then reference the built file directly in `.cursor/mcp.json`:

```json
{
    "mcpServers": {
        "sentinel-memory": {
            "command": "node",
            "args": ["/absolute/path/to/dug-sentinel-memory-mcp/dist/server.js"]
        }
    }
}
```

> `.cursor/mcp.json` is listed in `.gitignore`. Copy `.cursor/mcp.json.example` and edit locally — no need to commit your personal paths.

---

## Project path per developer

Each developer keeps their own `.cursor/mcp.json` (git-ignored). Cursor sets the working directory to the workspace root automatically, so every developer gets their own `.context/` without any path configuration.

```
Developer A  opens ProjectA  →  MCP CWD = ProjectA/  →  ProjectA/.context/memory_log.jsonl
Developer B  opens ProjectB  →  MCP CWD = ProjectB/  →  ProjectB/.context/memory_log.jsonl
```

---

## Tools

### `search_memory(query, topic?)`

Call this **before starting any task**. Returns all past records (filtered by topic if specified). Claude reads the output and selects relevant lessons.

| Parameter | Type | Description |
|-----------|------|-------------|
| `query` | string | Task description or keywords |
| `topic` | string (optional) | Exact-match topic filter |

### `log_memory(topic, missing_context, lesson, ask_next_time?, type?, compact_threshold?)`

Call this **after completing any task**. Records what was missing and what to remember.

| Parameter | Type | Description |
|-----------|------|-------------|
| `topic` | string | Module/feature tag (e.g. `auth`, `payment`) |
| `missing_context` | string | Info absent from original instructions but critical |
| `lesson` | string | Rule to apply in future tasks |
| `ask_next_time` | string (optional) | Question to ask the user next time |
| `type` | string (optional) | `"log"` (default) or `"principle"` (compacted) |
| `compact_threshold` | int (optional) | Compaction trigger count (default: 50) |

### `compact_memory(target_topic?, compact_threshold?)`

Call this **when record count exceeds the threshold**. Returns grouped records for Claude to summarize into principles.

### `compact_memory_delete(ids)`

Call this **only after** `log_memory(type="principle")` succeeds. Deletes the original log records by id.

---

## Workflow (.cursorrules)

The `.cursorrules` file enforces the 3-step loop for every task:

```
You are the Memory Manager for this project.
All tasks are grounded in .context/memory_log.jsonl.

IMPORTANT: Do NOT write any code or edit any file before completing Step 1.

[Before every task — REQUIRED]
1. Call search_memory with a description of the current task.
2. Read the returned records and identify lessons relevant to this task.
3. If relevant records exist:
   - Apply the lessons directly to your approach.
   - Ask the user the questions listed in ask_next_time before proceeding.
4. If no relevant records exist:
   - Do not guess constraints. Ask the user about key requirements first.

[After every task — REQUIRED]
5. Call log_memory with:
   - missing_context  ←  info absent from the initial instructions but turned out critical
   - lesson           ←  rule to apply in future tasks of this type
   - ask_next_time    ←  question to ask the user before starting similar tasks

[Topic naming rules]
- Use module- or feature-level granularity (language/framework agnostic).
- Good examples : auth, payment, api-gateway, ui-form, db-migration
- Too narrow (forbidden) : login_bug_fix_2026, verify_token_v2
- Too broad  (forbidden) : code, backend, fix
- Check existing topics first. Reuse a close match instead of creating a new one.
  e.g. if "auth-login" exists, use it instead of creating "authentication"

[Compaction — REQUIRED when record count exceeds 50]
6.  Call compact_memory to receive records grouped by topic.
7.  Merge similar topics (e.g. "auth", "auth-login" → "auth").
8.  Summarize each topic's lessons into one concise sentence.
9.  Merge each topic's ask_next_time values; keep under 512 bytes total.
10. Call log_memory(type="principle", ...) to store the summary.
11. After confirming the principle is saved, call compact_memory_delete(ids=[...]) to remove originals.

Skipping any step in this sequence is not allowed.
```

---

## Data format

Records are stored one JSON object per line in `.context/memory_log.jsonl`.

**Log record:**
```json
{
    "id": "a1b2c3d4e5f6a7b8",
    "type": "log",
    "topic": "payment",
    "missing_context": "VAT rates differ by country — not mentioned in the brief",
    "lesson": "Always check the country-specific tax rate file before modifying payment logic",
    "ask_next_time": "Which countries does this change apply to?",
    "meta": { "created": "2026-02-27T10:30:00.000Z" }
}
```

**Principle record (after compaction):**
```json
{
    "id": "b2c3d4e5f6a7b8c9",
    "type": "principle",
    "topic": "payment",
    "missing_context": "",
    "lesson": "Payment module: verify country tax rates, keep refund API separate, PG timeout is 10s",
    "ask_next_time": "Which countries apply? Which payment gateway?",
    "meta": {
        "created": "2026-03-15T09:00:00.000Z",
        "compacted_at": "2026-03-15T09:00:00.000Z",
        "source_count": 7
    }
}
```

| Field | Limit | On exceed |
|-------|-------|-----------|
| `topic` | 64 bytes (UTF-8) | Error |
| `missing_context` | 1,024 bytes (UTF-8) | Error |
| `lesson` | 1,024 bytes (UTF-8) | Error |
| `ask_next_time` | 512 bytes (UTF-8) | Error |

---

## File structure

```
your-project/
├── .cursor/
│   ├── mcp.json              ← git-ignored, copy from mcp.json.example
│   └── mcp.json.example      ← committed template
└── .context/
    └── memory_log.jsonl      ← auto-created, commit this file

dug-sentinel-memory-mcp/      ← this repository
├── src/
│   ├── server.ts             ← MCP tools (4 tools)
│   ├── store.ts              ← JSONL CRUD + file lock + atomic write
│   └── sanitizer.ts          ← sensitive data filter
├── dist/                     ← compiled output (generated by npm run build)
├── .cursor/
│   └── mcp.json.example      ← configuration template
├── docs/
│   ├── Design.md
│   └── Design_KR.md
├── package.json
├── tsconfig.json
├── .cursorrules
└── .gitignore
```

---

## Security notes

- `missing_context` and `lesson` fields are scanned for API keys, tokens, and secrets before storage. Detected patterns are replaced with `[REDACTED]`.
- `.context/memory_log.jsonl` is plain text. Review `git diff .context/` before pushing to a shared repository.
- For sensitive projects, add `.context/` to `.gitignore`.

---

## License

MIT

TDQS

A4.2/5.0

Scored across 1 tool

Disambiguation5/5

Only one tool exists, so there is no risk of confusion between tools.

Naming Consistency5/5

The single tool uses a consistent snake_case naming convention with a verb_noun pattern.

Tool Count1/5

With only one tool, the server is severely under-scoped for its apparent purpose, which involves a multi-step workflow (compact_memory, principle save, then delete).

Completeness1/5

The server lacks prerequisite tools like compact_memory and principle save, making this tool unusable on its own and the surface severely incomplete.

Maintenance

ActivityInactive
ResponsivenessNo issues