# OpenDB

> AI-native local database for files, search, and long-term agent memory.

- **Type:** MCP server
- **Install:** `agentstack add mcp-opendb-ai-opendb`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [opendb-ai](https://agentstack.voostack.com/s/opendb-ai)
- **Installs:** 0
- **Category:** [Databases](https://agentstack.voostack.com/c/databases)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [opendb-ai](https://github.com/opendb-ai)
- **Source:** https://github.com/opendb-ai/openDB
- **Website:** https://opendb-ai.com/

## Install

```sh
agentstack add mcp-opendb-ai-opendb
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

3 lines to give your AI agent an AI-native database and long-term memory.
  Read any file. Search any workspace. Remember everything.

  
  
  
  

  Purpose-built long-term memory for coding agents.
  96.3% on CodeMemEval (coding-agent memory) · 100% R@5 retrieval · 0.8 ms recall · 93.6% on LongMemEval.
  Remember architecture decisions, conventions, APIs, and bug fixes across sessions —
  and read the actual code. Zero embedding APIs. Zero vector databases. Just SQLite FTS5 and good engineering.

---

```bash
pip install open-db[cli]
opendb index ./my_workspace
opendb serve-mcp
```

That's it. Your agent now has 12 MCP tools — read any file format, search across documents and code, store/recall persistent memories, and switch between multiple workspaces on the fly. Works with every major agent framework out of the box.

## Agent Usage Protocol

If you are wiring OpenDB into an AI agent, start with [AGENTS.md](AGENTS.md).
It tells agents to check local files and memories before external search, write
memories carefully, and keep OpenDB's runtime simple. For the fuller workflow,
see [docs/agent-protocol.md](docs/agent-protocol.md).

## CodeMemEval — Coding-Agent Memory (the vertical)

Conversational memory benchmarks (LongMemEval) test personal facts and life events.
Coding agents need something different: remembering **architecture decisions,
coding conventions, API signatures, past bug fixes, and where things live** across
many sessions — and knowing which of those are still *current* after the codebase
evolves. **CodeMemEval** is OpenDB's purpose-built benchmark for exactly that.

| | Result |
|---|---|
| **E2E accuracy** | **92.6%** with a cheap reader (gpt-5.4-mini) · **96.3%** with gpt-5.5 |
| **Retrieval R@5** | **100%** — right evidence in top-5 for every question |
| **Median recall** | **0.8 ms** |
| **Anti-hallucination (abstention)** | **100%** — never invents facts not in memory |

Perfect (100%) on architecture, conventions, API signatures, bug-fixes, code
locations, and knowledge-updates (with gpt-5.5). Coding memory is dominated by *exact identifiers* (`CreateInvoice`,
`:9090`, `pkg/gateway/middleware/auth.go`, `RFC 7807`) — precisely where lexical
FTS beats embedding similarity, and where OpenDB pairs memory with real code
reading that conversation-only layers (Mem0, Zep, Letta) don't have.

```bash
# Reproduce (uses the same harness as LongMemEval)
python benchmark/gen_codemem.py --model gpt-5.5
python benchmark/longmemeval_e2e_bench.py --data benchmark/codemem_dataset.json \
    --model gpt-5.4-mini --judge-model gpt-5.4-mini
```

Full methodology: [benchmark/REPORT.md → Part 8](benchmark/REPORT.md). The dataset
generator is hand-authored ground truth (LLM only renders transcripts), so it's
extensible — add facts to grow coverage.

## LongMemEval Benchmark — 93.6%

OpenDB achieves **93.6% E2E accuracy** on [LongMemEval](https://github.com/xiaowu0162/LongMemEval) (ICLR 2025), the standard benchmark for AI agent long-term memory. 500 questions, 6 categories, LLM-as-judge evaluation. Memory **retrieval recall is a reproduced 100% R@5** (470/470, 0 misses) after the rank-aware recall fix described in the report.

| System | LongMemEval E2E | Gen Model | Retrieval Infrastructure |
|--------|:-:|-----------|--------------------------|
| OMEGA | 95.4% | GPT-4.1 | Embedding model + vector DB |
| Mastra | 94.9% | GPT-5-mini | LLM + embedding model |
| **OpenDB** | **93.6%** | **qwen3.6-plus** | **SQLite only, zero API** |
| MemMachine | 93.0% | — | LLM + vector DB |
| Vectorize Hindsight | 91.4% | — | Embedding model |
| Emergence AI | 86.0% | — | LLM + graph DB + vector DB |
| Supermemory | 81.6% | GPT-4o | Embedding model |
| Zep/Graphiti | 71.2% | — | Graph DB + LLM |

> OpenDB uses **qwen3.6-plus** — a significantly cheaper model than GPT-4.1 or GPT-5-mini. On the same system, Mastra showed a 10-point gap between GPT-4o (84%) and GPT-5-mini (95%), suggesting OpenDB with a frontier model would score even higher.

### Per-Category Results

| Category | OpenDB | OMEGA | Supermemory | Zep |
|----------|:------:|:-----:|:-----------:|:---:|
| single-session-assistant | **100%** | — | 96.4% | 80.4% |
| knowledge-update | **97.4%** | 96% | 88.5% | 83.3% |
| single-session-user | 97.1% | — | 97.1% | 92.9% |
| temporal-reasoning | **95.5%** | 94% | 76.7% | 62.4% |
| multi-session | **89.5%** | 83% | 71.4% | 57.9% |
| abstention | 86.7% | — | — | — |
| single-session-preference | 73.3% | — | 70.0% | 56.7% |

OpenDB **beats every competitor** on temporal-reasoning (95.5% vs OMEGA's 94%), knowledge-update (97.4% vs 96%), and multi-session (89.5% vs 83%) — without embeddings, without vector databases, without graph databases.

### Retrieval — 100% Recall

| | OpenDB (FTS5) | MemPalace (ChromaDB) |
|---|:---:|:---:|
| **R@5** | **100%** (470/470) | 96.6% |
| Embedding model | None | all-MiniLM-L6-v2 |
| API calls | 0 | 0 |
| Median recall latency | **1.1 ms** | — |

### How?

No embeddings. No vector search. No graph databases. Three things:

1. **SQLite FTS5** — BM25 keyword search with time-decay re-ranking. 1ms recall at 10K memories.
2. **Smart conflict detection** — Automatically supersedes outdated facts while preserving episodic event history.
3. **Temporal-aware prompting** — Memories sorted chronologically with real session dates, giving the LLM the context it needs for temporal reasoning.

Full methodology and per-question results: [benchmark/REPORT.md](benchmark/REPORT.md)

## Works with Every Agent Framework

OpenDB speaks [MCP](https://modelcontextprotocol.io/) — the universal standard supported by all major frameworks. Pick yours:

Claude Code / Cursor / Windsurf

Add to your MCP config (`.mcp.json`, `mcp_servers` in settings, etc.):

```json
{
  "mcpServers": {
    "opendb": {
      "command": "opendb",
      "args": ["serve-mcp", "--workspace", "/path/to/workspace"]
    }
  }
}
```

Claude Agent SDK (Anthropic)

```python
from claude_agent_sdk import query, ClaudeAgentOptions
from claude_agent_sdk.mcp import MCPServerStdio

async with MCPServerStdio("opendb", ["serve-mcp", "--workspace", "./docs"]) as opendb:
    options = ClaudeAgentOptions(
        model="claude-sonnet-4-6",
        mcp_servers={"opendb": opendb},
        allowed_tools=["mcp__opendb__*"],
    )
    async for msg in query(prompt="Summarize the Q4 report", options=options):
        print(msg.content)
```

OpenAI Agents SDK

```python
from agents import Agent, Runner
from agents.mcp import MCPServerStdio

async with MCPServerStdio(name="opendb", params={
    "command": "opendb", "args": ["serve-mcp", "--workspace", "./docs"]
}) as opendb:
    agent = Agent(name="Analyst", model="gpt-4.1", mcp_servers=[opendb])
    result = await Runner.run(agent, "Find all revenue mentions in the PDF reports")
    print(result.final_output)
```

LangChain / LangGraph

```python
from langchain_mcp_adapters.client import MultiServerMCPClient
from langgraph.prebuilt import create_react_agent

async with MultiServerMCPClient({
    "opendb": {"command": "opendb", "args": ["serve-mcp", "--workspace", "./docs"], "transport": "stdio"}
}) as client:
    agent = create_react_agent("anthropic:claude-sonnet-4-6", await client.get_tools())
    result = await agent.ainvoke({"messages": [("user", "What changed in the latest spec?")]})
```

CrewAI

```python
from crewai import Agent, Task, Crew
from crewai.tools import MCPServerStdio

opendb = MCPServerStdio(command="opendb", args=["serve-mcp", "--workspace", "./docs"])

analyst = Agent(role="Document Analyst", goal="Analyze workspace files", mcps=[opendb])
task = Task(description="Summarize all PDF reports in the workspace", agent=analyst)
Crew(agents=[analyst], tasks=[task]).kickoff()
```

AutoGen (Microsoft)

```python
from autogen_ext.tools.mcp import mcp_server_tools, StdioServerParams
from autogen_agentchat.agents import AssistantAgent

tools = await mcp_server_tools(StdioServerParams(command="opendb", args=["serve-mcp", "--workspace", "./docs"]))
agent = AssistantAgent(name="analyst", model_client=client, tools=tools)
await agent.run("Search for deployment-related memories")
```

Google ADK

```python
from google.adk.agents import LlmAgent
from google.adk.tools.mcp_tool import McpToolset
from google.adk.tools.mcp_tool.mcp_session_manager import StdioConnectionParams

agent = LlmAgent(
    model="gemini-2.5-flash",
    name="analyst",
    tools=[McpToolset(connection_params=StdioConnectionParams(command="opendb", args=["serve-mcp", "--workspace", "./docs"]))],
)
```

Mastra (TypeScript)

```typescript
import { MCPClient } from "@mastra/mcp";
import { Agent } from "@mastra/core/agent";

const mcp = new MCPClient({
  servers: { opendb: { command: "opendb", args: ["serve-mcp", "--workspace", "./docs"] } },
});

const agent = new Agent({
  name: "Analyst",
  model: "openai/gpt-4.1",
  tools: await mcp.listTools(),
});
```

Python (direct, no framework)

```python
from opendb import OpenDB

db = OpenDB.open("./my_workspace")
await db.init()
await db.index()

text    = await db.read("report.pdf", pages="1-3")
results = await db.search("quarterly revenue")
await db.memory_store("User prefers concise answers")
memories = await db.memory_recall("user preferences")

await db.close()
```

## Build Your Own Agent (No Framework Needed)

You don't need a framework. A while loop, an LLM, and OpenDB — that's a complete agent:

```python
import json, asyncio
from anthropic import Anthropic
from opendb import OpenDB

client = Anthropic()
db = OpenDB.open("./workspace")

TOOLS = [
    {"name": "read",   "description": "Read a file",           "input_schema": {"type": "object", "properties": {"filename": {"type": "string"}}, "required": ["filename"]}},
    {"name": "search", "description": "Search across all files","input_schema": {"type": "object", "properties": {"query": {"type": "string"}},    "required": ["query"]}},
    {"name": "memory", "description": "Store a memory",         "input_schema": {"type": "object", "properties": {"content": {"type": "string"}},  "required": ["content"]}},
    {"name": "recall", "description": "Recall memories",        "input_schema": {"type": "object", "properties": {"query": {"type": "string"}},    "required": ["query"]}},
]

async def run(task: str):
    await db.init()
    await db.index()
    messages = [{"role": "user", "content": task}]

    while True:
        resp = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=4096,
            system="You have tools to read files, search, and remember things.",
            tools=TOOLS, messages=messages,
        )

        # Extract text and tool calls
        for block in resp.content:
            if block.type == "text":
                print(block.text)

        if resp.stop_reason == "end_turn":
            break

        # Execute tool calls and feed results back
        tool_results = []
        for block in resp.content:
            if block.type == "tool_use":
                match block.name:
                    case "read":   result = await db.read(block.input["filename"])
                    case "search": result = await db.search(block.input["query"])
                    case "memory": result = await db.memory_store(block.input["content"])
                    case "recall": result = await db.memory_recall(block.input["query"])
                tool_results.append({"type": "tool_result", "tool_use_id": block.id,
                                     "content": json.dumps(result) if isinstance(result, dict) else str(result)})

        messages.append({"role": "assistant", "content": resp.content})
        messages.append({"role": "user", "content": tool_results})

    await db.close()

asyncio.run(run("Summarize the Q4 report and remember the key metrics"))
```

That's it. ~40 lines, zero abstractions, full agent capabilities. Swap `Anthropic()` for any LLM client — the pattern is the same.

## Why OpenDB?

Without OpenDB, agents write inline parsing code for every document:

```python
# Agent writes this every time — 500+ tokens, often fails
run_command("""python -c "
import PyMuPDF; doc = PyMuPDF.open('report.pdf')
for page in doc: print(page.get_text())
" """)
```

With OpenDB:

```python
read_file("report.pdf")  # 50 tokens, always works
```

**Benchmarked across 4 LLMs on 24 document tasks:**

| Metric | Without OpenDB | With OpenDB |
|--------|:-:|:-:|
| Tokens used | 100% | **27-45%** (55-73% saved) |
| Task speed | 100% | **36-58%** faster |
| Answer quality | 2.4-3.2 / 5 | **3.4-3.9 / 5** |
| Success rate | 79% | **100%** |

**FTS vs RAG vector retrieval (25-325 documents):**

| Scale | FTS Tokens Saved | FTS Quality | RAG Quality |
|-------|:-:|:-:|:-:|
| 25 docs | **47%** | 3.9/5 | 4.2/5 |
| 125 docs | **44%** | **4.7/5** | 4.0/5 |
| 325 docs | **45%** | **4.6/5** | 3.5/5 |

FTS quality **improves with scale** while RAG degrades from distractor noise. See [benchmark/REPORT.md](benchmark/REPORT.md) for methodology.

## MCP Tools

12 tools, auto-discovered by any MCP-compatible agent:

### `opendb_info` — Workspace overview

```
opendb_info()
-> Workspace: 47 files (ready: 45, processing: 1, failed: 1)
  By type:  Python (.py) 20 | PDF 12 | Excel (.xlsx) 5 | ...
  Recently updated:  config.yaml (2 min ago) | main.py (1 hr ago)
```

### `opendb_read` — Read any file

Code with line numbers, documents as plain text, spreadsheets as structured JSON.

```
opendb_read(filename="main.py")                            # Code with line numbers
opendb_read(filename="report.pdf", pages="1-3")            # PDF pages
opendb_read(filename="report.pdf", grep="revenue+growth")  # Search within file
opendb_read(filename="budget.xlsx", format="json")          # Structured spreadsheet
opendb_read(filename="app.py", offset=50, limit=31)         # Lines 50-80
```

### `opendb_search` — Search across code and documents

Regex grep for code, full-text search for documents. Auto-detects mode.

```
opendb_search(query="def main", path="/workspace", glob="*.py")   # Grep code
opendb_search(query="quarterly revenue")                           # FTS documents
opendb_search(query="TODO", path="/src", case_insensitive=True)    # Case insensitive
```

### `opendb_glob` — Find files

```
opendb_glob(pattern="**/*.py", path="/workspace")
opendb_glob(pattern="src/**/*.{ts,tsx}", path="/workspace")
```

### `opendb_memory_store` — Store a memory

```
opendb_memory_store(content="User prefers dark mode", memory_type="semantic")
opendb_memory_store(content="Deployed v2.1, rollback required", memory_type="episodic", tags=["deploy"])
opendb_memory_store(content="Always run tests before merging", memory_type="procedural")
opendb_memory_store(content="User is a senior engineer at Acme", pinned=true)
opendb_memory_store(
  content="The auth spec requires key rotation every 90 days",
  memory_type="procedural",
  source="tool_extraction",
  metadata={"evidence": {"file": "docs/auth.md", "lines": "42-58", "tool": "opendb_read"}}
)
```

Three memory types: **semantic** (facts/knowledge), **episodic** (events/outcomes), **procedural** (workflows/rules).

Write memories as durable, context-free atoms. Skip one-off commands and small talk; use `metadata.evidence` when a memory comes from a file or tool result so agents can drill back to the source.

Set `pinned=true` for critical facts — they get 10x ranking boost and can be retrieved instantly with `pinned_only=true`.

### `opendb_memory_recall` — Search memories

Results ranked by **relevance x recency**. Multi-term queries filter weak tail matches that only hit one broad token, so recall stays compact. Recall output includes source, confidence, supersession, tags, and evidence metadata when available. Pinned memories always surface first.

```
opendb_memory_recall(query="user preferences")
opendb_memory_recall(query="deploy", memory_type="episodic")
opendb_memory_recall(pinned_only=true)   # Instant — no search needed, ideal for agent startup
```

For a white-box Markdown summa

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [opendb-ai](https://github.com/opendb-ai)
- **Source:** [opendb-ai/openDB](https://github.com/opendb-ai/openDB)
- **License:** MIT
- **Homepage:** https://opendb-ai.com/

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-opendb-ai-opendb
- Seller: https://agentstack.voostack.com/s/opendb-ai
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
