An MCP server that preserves agent context across conversation compressions. Solves the problem of losing valuable context when Claude's conversation window gets compacted.
When Claude compresses conversations to save tokens, you lose:
- Implementation decisions - "Why we chose approach X over Y"
- Edge cases discovered - "NPI validation fails silently if business_id is null"
- Failed attempts - "Tried approach A, it broke because of Z"
- Agent handoff context - What code-reviewer learned before test-master took over
- Recurring bugs - "We've fixed this before, here's how"
This MCP server stores context in ~/.context-memory/ that persists across sessions. Before compression, agents can dump important context. After compression, they can read it back.
Add to your project's .mcp.json:
{
"mcpServers": {
"context-memory": {
"command": "npx",
"args": ["-y", "github:Dithilli/context-memory-mcp"]
}
}
}Then restart Claude Code CLI.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"context-memory": {
"command": "npx",
"args": ["-y", "github:Dithilli/context-memory-mcp"]
}
}
}Then fully restart Claude Desktop.
The server supports three storage modes:
Location: ~/.context-memory/
Use case: Share context across all projects (problem/solution cache, cross-project patterns)
Configuration:
{
"mcpServers": {
"context-memory": {
"command": "npx",
"args": ["-y", "github:Dithilli/context-memory-mcp"]
}
}
}Location: ./.context-memory/ (in project root)
Use case: Project-specific context that shouldn't leak to other projects
Configuration:
{
"mcpServers": {
"context-memory": {
"command": "npx",
"args": [
"-y",
"github:Dithilli/context-memory-mcp",
"--storage-dir",
".context-memory"
]
}
}
}Add to .gitignore:
# Context memory (if using per-project storage)
.context-memory/Or commit it for team-wide context sharing.
Location: Any absolute or relative path
Configuration:
{
"mcpServers": {
"context-memory": {
"command": "npx",
"args": [
"-y",
"github:Dithilli/context-memory-mcp",
"--storage-dir",
"/path/to/custom/storage"
]
}
}
}All storage modes create four JSONL files:
notes.jsonl- Context notes from agentsfile_decisions.jsonl- File-specific decision historyhandoffs.jsonl- Agent-to-agent handoff contextproblems.jsonl- Problem/solution cache
// Get statistics
"context://stats"
// Recent context notes (last 50)
"context://notes/recent"
// Recent agent handoffs (last 20)
"context://handoffs/recent"
// All problem/solution pairs
"context://solutions/cache"
// Dynamic URIs
"context://session/{session_id}/notes"
"context://file/{file_path}/history"Store context with tags and metadata.
{
"type": "decision" | "problem" | "handoff" | "edge-case" | "workaround",
"summary": "Brief one-line summary",
"details": "Detailed explanation",
"tags": ["tag1", "tag2"],
"session_id": "optional-session-id",
"project": "optional-project-name",
"file_path": "optional/file/path.ts",
"related_files": ["file1.ts", "file2.ts"],
"tried_and_failed": ["approach A", "approach B"],
"why_it_matters": "Why this context is important"
}Log why you made a specific decision about a file.
{
"file_path": "app/api/providers/route.ts",
"decision": "Used query builder pattern instead of raw SQL",
"why": "Better type safety and prevents SQL injection",
"alternatives": ["raw SQL", "ORM"],
"tags": ["security", "database"]
}Store context when handing off between agents.
{
"from_agent": "code-reviewer",
"to_agent": "test-master",
"what_was_done": "Fixed authentication bugs in provider API",
"what_needs_doing": "Write tests for the auth fixes",
"important_context": [
"Auth uses RLS policies, not manual checks",
"Provider isolation is critical for HIPAA"
],
"files_modified": ["app/api/providers/route.ts"]
}Save a problem/solution pair for future reference.
{
"problem": "Supabase RLS returns empty array instead of 401",
"solution": "Add explicit auth check before query",
"tags": ["supabase", "rls", "auth"],
"project": "bip_ui"
}Search all context with filters.
{
"query": "authentication",
"tags": ["security", "rls"],
"type": "decision",
"session_id": "session-123",
"project": "bip_ui",
"limit": 10
}Find cached solution for a problem.
{
"problem": "Supabase RLS returns empty array"
}Get latest handoff context for an agent.
{
"agent_type": "test-master",
"session_id": "session-123"
}Clear all context for a session.
{
"session_id": "session-123"
}// Store implementation decision
await tools.add_note({
type: "decision",
summary: "Used RLS for multi-tenancy instead of manual checks",
details: "Tried manual business_id checks in every query, but RLS is more secure and less error-prone. All tables have RLS policies.",
tags: ["security", "database", "multi-tenancy"],
project: "bip_ui",
related_files: ["app/api/providers/route.ts", "supabase/migrations/*.sql"],
tried_and_failed: ["Manual business_id filtering", "Middleware-based isolation"],
why_it_matters: "Critical for HIPAA compliance - provider data must be isolated"
});
// Store edge case
await tools.add_note({
type: "edge-case",
summary: "NPI validation fails silently when business_id is null",
details: "If business_id is null, the RLS policy returns empty array instead of error",
tags: ["validation", "edge-case"],
file_path: "app/api/providers/route.ts"
});// Read recent notes for this session
const notes = await resources.read("context://notes/recent");
// Search for specific context
const authNotes = await tools.search_context({
tags: ["security", "auth"],
limit: 10
});
// Find solution to a problem we've seen before
const solution = await tools.find_solution({
problem: "Supabase RLS returns empty array"
});// code-reviewer agent finishes, hands off to test-master
await tools.handoff_to_agent({
from_agent: "code-reviewer",
to_agent: "test-master",
what_was_done: "Fixed 3 security issues: path traversal, missing RLS checks, SQL injection risk",
what_needs_doing: "Write security tests for the fixes",
important_context: [
"Path traversal fix uses path.normalize()",
"RLS checks added to all provider endpoints",
"Using parameterized queries throughout"
],
files_modified: [
"app/api/providers/route.ts",
"app/api/documents/route.ts"
]
});
// test-master agent starts, reads handoff
const handoff = await tools.get_handoff_context({
agent_type: "test-master",
session_id: "current-session-id"
});Scenario: Debugging a multi-tenancy bug across multiple sessions.
Session 1 (Discovery):
await tools.add_note({
type: "problem",
summary: "Users seeing other businesses' providers",
details: "RLS policy missing on provider_licenses table",
tags: ["security", "bug", "multi-tenancy"],
project: "bip_ui"
});
await tools.cache_solution({
problem: "Users seeing other businesses' providers",
solution: "Add RLS policy: CREATE POLICY ON provider_licenses USING (business_id = current_business_id())",
tags: ["security", "rls"],
project: "bip_ui"
});Session 2 (weeks later, similar bug):
// Find cached solution
const solution = await tools.find_solution({
problem: "Users seeing other businesses' providers"
});
// Returns:
// "Add RLS policy: CREATE POLICY ON provider_licenses USING (business_id = current_business_id())"All notes include:
id- Unique identifiertimestamp- ISO 8601 timestampsession_id- Session identifier (auto-generated if not provided)type- Note type (decision, problem, edge-case, etc.)tags- Array of tags for categorizationcontent- Structured content with summary, details, etc.
Global Storage (~/.context-memory/)
- ✅ Problem/solution cache that applies to all projects
- ✅ Generic programming patterns and gotchas
- ✅ Cross-project debugging insights
- ✅ Personal knowledge base
Per-Project Storage (./.context-memory/)
- ✅ Project-specific architecture decisions
- ✅ "Why we did X" for this codebase
- ✅ Edge cases unique to this project
- ✅ Team-wide context (commit to git)
Mixed Approach (Run both simultaneously)
{
"mcpServers": {
"context-memory-global": {
"command": "npx",
"args": ["-y", "github:Dithilli/context-memory-mcp"]
},
"context-memory-local": {
"command": "npx",
"args": [
"-y",
"github:Dithilli/context-memory-mcp",
"--storage-dir",
".context-memory"
]
}
}
}Then specify which one to use based on context type.
Use consistent tags for easy searching:
By Domain:
security,performance,bug,featuredatabase,api,frontend,backend
By Language/Framework:
typescript,react,nextjs,supabasepython,rust,go
By Severity:
critical,important,nice-to-know
By Status:
todo,in-progress,resolved,blocked
✅ Store These:
- "We tried X, it failed because Y" - saves future debugging time
- Edge cases that aren't obvious from the code
- Why a weird workaround exists (setTimeout, specific order of operations)
- Security decisions and threat model considerations
- Performance optimizations and why they matter
- Agent handoff context when switching between specialized agents
❌ Don't Store These:
- Generic code explanations (that's what comments are for)
- Implementation details visible in git history
- Secrets or sensitive data
- Verbose debug logs (use regular logging instead)
Before Compression:
// Dump important context that would be lost
await add_note({
type: "decision",
summary: "Why we use RLS instead of manual auth checks",
details: "...",
tags: ["security", "architecture"],
why_it_matters: "Critical for HIPAA compliance"
});After Compression:
// Retrieve context to resume work
const context = await search_context({
tags: ["security", "architecture"],
limit: 10
});End of Session:
// Optional: Clear session-specific notes
await clear_session({ session_id: "current-session-id" });Commit per-project storage to git:
# Add to git
git add .context-memory/
git commit -m "Add context notes for RLS implementation"Team members get context automatically:
- Pull repo →
.context-memory/files included - Claude reads context from local storage
- Everyone has the same "why we did this" knowledge
Use for:
- Onboarding new team members
- Explaining non-obvious architectural decisions
- Documenting failed approaches (so others don't repeat them)
- Storage: Append-only JSONL files (fast writes)
- Search: In-memory filtering (fast reads)
- Size: Negligible (text only, no binaries)
- Cleanup: Manual via
clear_sessiontool - Scalability: Tested with 10,000+ notes (still fast)
All notes include:
id- Unique identifiertimestamp- ISO 8601 timestampsession_id- Session identifier (auto-generated if not provided)type- Note type (decision, problem, edge-case, etc.)tags- Array of tags for categorizationcontent- Structured content with summary, details, etc.
MCP server not loading:
# Check that the server is in .mcp.json
cat .mcp.json | grep context-memory
# Restart Claude Code CLI
exit
claudeCan't find stored context:
# Check storage directory
ls ~/.context-memory/ # Global storage
ls .context-memory/ # Per-project storage
# Verify files exist
cat ~/.context-memory/notes.jsonl | wc -lStorage location unclear:
- Server logs storage directory on startup to stderr
- Check Claude Code CLI output when it launches
MIT
This is a personal tool, but PRs welcome if you find it useful.
- Added configurable storage directory (
--storage-diroption) - Support for per-project storage
- Storage location logging on startup
- Initial release
- Global storage in
~/.context-memory/ - MCP resources and tools for context management