A temporal knowledge graph memory system for AI applications. SerialMemory provides persistent "second brain" capabilities with semantic search, entity extraction, and relationship trackingβenabling AI agents to maintain context and learn from past interactions.
- Semantic Search: Find memories by meaning, not keywords, using vector embeddings (1536-dim)
- Entity Extraction: Automatically identify people, organizations, locations, skills, and projects
- Knowledge Graph: Build and traverse relationships between entities for multi-hop reasoning
- Temporal Tracking: Full event sourcing with confidence decay and audit trails
- Multi-Tenant: Complete data isolation with row-level security
- MCP Integration: Claude Desktop (Anthropic) and OpenAI compatibility via Model Context Protocol
- REST API: Full-featured HTTP API for custom integrations
- Self-Hosted: Deploy on your own infrastructure with security hardening
ββββββββββββββββββββββββββββββββββββββββββββββ
β Client Applications β
β (Claude/Anthropic, OpenAI, Custom Apps) β
ββββββββββββββββββ¬ββββββββββββββββββββββββββ
β
βββββββββ΄βββββββββ¬βββββββββββββββ
βΌ βΌ βΌ
βββββββββββ ββββββββββββββββ ββββββββββ
β MCP β β REST API β β Admin β
β Server β β (HTTP) β β API β
β Anthropicβ β β β β
β OpenAI β β β β β
ββββββ¬βββββ ββββββββ¬ββββββββ βββββ¬βββββ
β β β
βββββββββββββββββΌβββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββ
β Core Services β
β βββββββββββββββββββββββββββ β
β β Knowledge Graph Engine β β
β β β’ Memory ingestion β β
β β β’ Entity extraction β β
β β β’ Semantic search β β
β β β’ Graph traversal β β
β βββββββββββββββββββββββββββ β
βββββββββββββββββ¬ββββββββββββββββ
β
ββββββββββββββββββΌβββββββββββββββββ
βΌ βΌ βΌ
ββββββββββββ βββββββββββββ βββββββββββ
βPostgreSQLβ β Ollama β β Redis β
β+pgvector β β(Embeddings)β β(Cache) β
ββββββββββββ βββββββββββββ βββββββββββ
SerialMemory goes beyond simple keyword search. It's a semantic memory system that understands meaning and context, tracks how information relates over time, and provides intelligent context retrieval for AI applications.
A memory is any piece of information you store in SerialMemory:
- Natural Language: "John works at Acme Corp in San Francisco on Python projects"
- Structured Data: Notes, facts, observations, conversations, summaries
- Metadata: When it was created, what project it's for, confidence level
Each memory has:
Memory {
id: "uuid",
content: "John works at Acme Corp in San Francisco on Python projects",
embedding: [0.123, -0.456, 0.789, ...], // 1536-dimensional vector (OpenAI text-embedding-3-small)
confidence: 0.95, // Starts high, decays with time
layer: L1_CONTEXT, // See layers section below
entities: [
{ type: "PERSON", text: "John" },
{ type: "ORG", text: "Acme Corp" },
{ type: "GPE", text: "San Francisco" },
{ type: "SKILL", text: "Python" }
],
createdAt: "2026-02-11T10:00:00Z",
lastAccessedAt: "2026-02-11T14:30:00Z"
}
Instead of keyword matching, memories are found by semantic similarity:
// This query...
"Who works at the tech company in San Francisco?"
// ...finds memories about "John works at Acme Corp in San Francisco"
// Even though keywords don't match exactly!
How it works:
- Your query is converted to an embedding (1536-dimensional vector)
- The system finds memories with similar embeddings
- Results are ranked by meaning, not keywords
This is powered by PostgreSQL's pgvector extension, which uses vector similarity search (KNN) for fast retrieval.
Memories are classified into layers based on how processed/refined they are:
| Layer | What It Is | Typical Retention | Use Case |
|---|---|---|---|
| L0_RAW | Raw input, minimal processing | 30 days | Recently captured notes, conversations |
| L1_CONTEXT | Contextual understanding, entities extracted | 90 days | Processed notes with relationships identified |
| L2_SUMMARY | Summarized information, themes extracted | 180 days | Synthesis of similar concepts |
| L3_KNOWLEDGE | Extracted knowledge, proven patterns | 365 days | Reliable facts, validated learnings |
| L4_HEURISTIC | Learned patterns, general principles | Indefinite | Core knowledge, fundamental truths |
Example Flow:
Raw: "John, Sarah, and Mike met yesterday to discuss the backend API design"
β (Processing)
L1: Entities extracted - PERSON(John), PERSON(Sarah), PERSON(Mike),
Relationships identified - John knows Sarah, John knows Mike
β (Summarization)
L2: "Key discussion participants coordinated on technical architecture"
β (Pattern recognition)
L3: "Backend API design is a priority for team coordination"
β (Generalization)
L4: "The team uses synchronous discussion for architectural decisions"
SerialMemory models human memory: information becomes less reliable over time unless reinforced.
The decay formula:
confidence = initial_confidence Γ 0.5^(days / half_life)
Default half-life: 90 days
Example:
Day 0: Confidence = 1.0 (100%)
Day 90: Confidence = 0.5 (50%) - Half as confident
Day 180: Confidence = 0.25 (25%) - Quarter as confident
Day 270: Confidence = 0.125 (12.5%)
Why this matters:
- New information is fresh and high-confidence
- Old information without reinforcement becomes less trusted
- Memories below 0.1 (10%) confidence are candidates for archival
- Accessing a memory reinforces it (increases confidence)
- An explicit "reinforce" action can boost confidence
This allows the system to automatically forget unimportant details while keeping validated knowledge intact.
SerialMemory automatically identifies key entities (named things) in memories:
| Type | Examples | Used For |
|---|---|---|
| PERSON | John, Sarah, Alice | Finding people-related memories |
| ORG | Acme Corp, Google, MIT | Finding organization memories |
| GPE | New York, France, Silicon Valley | Finding location-related context |
| DATE | 2026-02, Next Tuesday, Q1 | Finding time-relevant memories |
| SKILL | Python, React, Leadership | Finding capability-related memories |
| PROJECT | Project Omega, Dashboard v2 | Finding project-specific context |
How it works:
- When a memory is stored, entities are automatically extracted
- Relationships between entities are identified
- A knowledge graph is built and maintained
SerialMemory doesn't just store memories separatelyβit builds a knowledge graph of relationships:
John βββββworks_atβββββ Acme Corp βββββlocated_inβββββ San Francisco
β β
β β
βββββββknowsβββββββ Sarah βββββworks_atβββββββ Acme Corp β
β
ββββββknowsβββββββ Mike
Projects that use Python:
Dashboard v2 βββββusesβββββ Python βββββlanguage_forβββββ Backend Systems
Project Omega βββββusesβββββ Python
Relationships tracked:
works_at: Entity1 works at Entity2located_in: Entity1 is located in Entity2knows: Entity1 knows Entity2uses: Entity1 uses Entity2created: Entity1 created Entity2- (And many more, automatically discovered)
The real power emerges when traversing multiple hops:
Query: "Find technologies used in projects by people I know"
Search process:
1. Start: Find entities I know (Sarah, Mike, ...)
2. Hop 1: Find projects they work on
3. Hop 2: Find technologies used in those projects
4. Result: [Python, Rust, TypeScript, ...]
Another example:
Question: "Who works with technologies similar to what Mike uses?"
1. Find Mike
2. Find technologies Mike uses
3. Find other people who use similar technologies
4. Return those people
This reveals hidden connections and provides better context
for multi-modal AI reasoning!
Every change to a memory is captured as an immutable event:
MemoryCreated(id, content, timestamp)
MemoryUpdated(id, oldContent, newContent, timestamp)
MemoryReinforced(id, confidence, timestamp)
MemoryDecayed(id, oldConfidence, newConfidence, timestamp)
MemoryArchived(id, reason, timestamp)
Benefits:
- Complete audit trail (GDPR compliant)
- Reproduce system state at any point in time
- Detect tampering or unauthorized changes
- Replay events for debugging
Each tenant's data is completely isolated:
Tenant A Tenant B
βββ Memories (isolated) βββ Memories (isolated)
βββ Entities βββ Entities
βββ Relationships βββ Relationships
βββ Search results (A only) βββ Search results (B only)
Implemented via PostgreSQL Row-Level Security (RLS):
- Database enforces isolation at query time
- Impossible to leak tenant data via SQL
- API keys scoped per tenant
- No cross-tenant search possible
- Docker & Docker Compose
- .NET 10+ SDK (for development)
- PostgreSQL 15+ (or use Docker)
# Clone the repository
git clone https://github.com/sblanchard/SerialMemoryServer.git
cd SerialMemoryServer
# Start infrastructure (PostgreSQL, Redis, RabbitMQ)
docker compose up -d
# Bootstrap development database
./dev-bootstrap.sh # Linux/Mac
.\dev-bootstrap.ps1 # Windows
# Run the C# MCP server
dotnet run --project SerialMemory.Mcp# Start all services
docker compose up --build
# Access dashboard at http://localhost:8080Services available:
- API: http://localhost:5001
- Dashboard: http://localhost:8080
- PostgreSQL: localhost:5432 (user:
postgres) - Redis: localhost:6379
- RabbitMQ Dashboard: http://localhost:15672 (guest/guest)
Claude Desktop (Anthropic)
# Configure in Claude Desktop after starting the server
# See: ./docs/02-quickstart-claude-mcp.mdOpenAI Integration
- Use REST API at http://localhost:5001
- Build custom tools or plugins
- Leverage semantic search and knowledge graph capabilities
- Overview & Architecture - Concepts and system design
- Claude Desktop Setup - MCP integration guide
- .NET SDK Guide - C# development
- Node.js SDK Guide - JavaScript/TypeScript
- Data Lifecycle - Memory management and cleanup
- Self-Hosting Guide - VPS deployment
- Local Development - Development environment setup
-
.NET SDK - Full-featured C# client
var client = new SerialMemoryClient("http://localhost:5001", "tenant-id", "api-key"); await client.StoreMemory("My important note", "personal"); var results = await client.Search("relevant memories", 5);
-
Node.js SDK - TypeScript/JavaScript support (coming soon)
SerialMemory implements the Model Context Protocol, enabling integration with:
- Claude Desktop (Anthropic)
- OpenAI integrations
- Future compatible AI agents
- Custom MCP clients
# Store a memory
POST /api/memories
{
"content": "I learned about distributed systems",
"memoryType": "LEARNING",
"layer": "L0_RAW",
"metadata": { "subject": "backend" }
}
# Semantic search
POST /api/memories/search
{
"query": "distributed systems",
"limit": 5,
"filters": { "layer": "L0_RAW" }
}
# Get memory by ID
GET /api/memories/{id}# List entities
GET /api/entities?limit=100
# Get entity details
GET /api/entities/{entityId}
# Multi-hop graph search
POST /api/graph/search
{
"startEntity": "John",
"relationshipType": "knows",
"hops": 2
}See OpenAPI Specification for complete API documentation.
SerialMemoryServer/
βββ SerialMemory.Mcp/ # C# MCP server (recommended)
βββ SerialMemory.Api/ # REST API
βββ SerialMemory.Core/ # Domain logic
βββ SerialMemory.Infrastructure/# Data access layer
βββ SerialMemory.Sdk.DotNet/ # .NET client SDK
βββ SerialMemory.ML/ # Embeddings & NLP
βββ SerialMemory.Worker/ # Background jobs
βββ SerialMemory.Web/ # React dashboard
βββ SerialMemory-MCP/ # Standalone MCP server (submodule)
β βββ SerialMemory.Mcp/ # Alternative MCP implementation
βββ examples/ # Ready-to-run examples
βββ docs/ # Documentation
βββ docker-compose.yml # Development stack
βββ SerialMemoryServer.sln # .NET solution file
- SerialMemory-MCP - Standalone MCP server for Anthropic & OpenAI
- Included as a git submodule
- Can be built and distributed separately
- Full MCP protocol support for Claude Desktop (Anthropic)
- Compatible with OpenAI's tool-calling capabilities
- Ready for future AI agent integrations
# Clone including submodules
git clone --recurse-submodules https://github.com/sblanchard/SerialMemoryServer.git
# Or if already cloned, initialize submodules
git submodule update --init --recursiveA persistent "second brain" for Claude to store and retrieve personal notes:
cd examples/ai-second-brain
dotnet runFeatures:
- Store notes and learnings
- Semantic search for relevant context
- User persona management
- Automatic entity extraction
Per-project memory isolation for development tools:
cd examples/project-context-memory
dotnet runFeatures:
- Scoped memory per project/repository
- Metadata-based filtering
- Cross-project search capabilities
- Multi-tenant patterns
See Examples README for more details.
SerialMemory includes production-ready security features:
- Complete data isolation with PostgreSQL row-level security (RLS)
- Tenant-scoped API keys
- Secure tenant context propagation
- JWT token-based API authentication
- Role-based access control (admin, user)
- Service-to-service authentication
- All passwords and secrets in environment variables
- No default credentials in code
- CORS and CSRF protection
- SQL injection protection via parameterized queries
Use docker-compose.prod.yml for security-hardened deployment:
# Configure environment
cp .env.production.example .env
# Edit .env with strong passwords
# Start with production configuration
docker compose -f docker-compose.prod.yml up -dSee Self-Hosting Guide for detailed security setup.
- Runtime: .NET 10+
- Database: PostgreSQL 15+ with pgvector
- Search: Vector embeddings (1536-dim via OpenAI text-embedding-3-small)
- Caching: Redis
- Queue: RabbitMQ
- NLP: Pattern-based entity extraction (extensible to spaCy, BERT)
- Dashboard: React + TypeScript + Vite
- Protocol: Model Context Protocol (MCP)
- Supports millions of memories per tenant
- Sub-100ms semantic search queries (with appropriate indexing)
- Horizontal scaling via PostgreSQL connection pooling
- Async processing queue for heavy operations
Run the test suite:
# Unit tests
dotnet test SerialMemory.Tests
# MCP integration tests
dotnet test SerialMemory.Mcp.Tests
# All tests with coverage
dotnet test --collect:"XPlat Code Coverage"# Install dependencies
dotnet restore
# Build solution
dotnet build
# Run with local infrastructure
docker compose up -d
dotnet run --project SerialMemory.Mcp- SerialMemory.Core: Domain models and business logic
- SerialMemory.Infrastructure: EF Core data access patterns
- SerialMemory.Mcp: MCP server implementation
- SerialMemory.Api: REST API endpoints
- SerialMemory.Tests: Unit and integration tests
We welcome contributions! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow C# naming conventions (PascalCase for public members)
- Add tests for new features
- Update documentation for API changes
- Ensure all tests pass before submitting PR
SerialMemory is released under the MIT License. See LICENSE for details.
- GitHub Issues: Report bugs and request features
- Documentation: Full docs
- Examples: Ready-to-run examples
- Python MCP server
- GraphQL API
- Advanced reasoning with multi-hop traversal
- Temporal graph visualization
- Plug-in system for custom entity types
- Multi-language support (embeddings & entity extraction)
SerialMemory is built on these excellent open-source projects:
- PostgreSQL & pgvector
- Ollama for local embeddings
- Model Context Protocol by Anthropic
Made with β€οΈ for AI-powered applications