mcpField
K
KEPTA — the memory for AI systems

KEPTA — the memory for AI systems

本地服务
github.com记忆与知识22 周前更新

关于 KEPTA — the memory for AI systems

KEPTA 是面向 AI 系统、脚本和 Python 项目的本地加密记忆层。共享知识库结合混合搜索和带时间信息的历史记录,并提供多种访问方式,无需云托管或账户。

主要功能

  1. 01本地加密知识库
  2. 02全文与向量混合搜索
  3. 03知识图谱与本地重排
  4. 04带时间信息的事实与历史
  5. 05导入 PDF、Markdown、文本和 JSON
  6. 06MCP 工具、HTTP API 和 Python 客户端

适用场景

  1. 01在多个 AI 客户端间共享持久笔记
  2. 02搜索导入的文档和聊天记录
  3. 03查看过去某个日期已知的信息

MCP 相关

提供八种 MCP 工具,用于搜索、保存、更新、删除、列出、关联、整合和遗忘记忆。服务端支持 stdio 和 Streamable HTTP。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"damiantodorovic-kepta": {
"command": "npx",
"args": [
"-y",
"kepta-mcp"
]
}
}
}
启动命令npx -y kepta-mcp

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
npmkepta-mcp3.4.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

KEPTA

v3.4.0 BUSL-1.1 tests coverage gate platform encrypted Damian Todorovic on LinkedIn

KEPTA——AI 系统的记忆

你的 AI 什么都记不住。每次聊天都从零开始。

KEPTA 就是解决方案:一份本地加密记忆,供每个 AI 读取和写入——Claude、Cursor、Gemini CLI、Cline、任何 MCP 客户端,以及通过 HTTP 运行的脚本。没有云端。无需账户。只有一个由你掌控的文件。

AI 系统学到的一切都会写入你自己电脑上的加密知识库——无论上下文增长到多长,每个 AI 都能在毫秒内回忆起来。文档、决策、客户知识、完整聊天记录:都会被记住、关联、发现矛盾并由新内容取代——绝不丢失。

此仓库包含源代码可用的核心(BUSL-1.1——每一行代码都公开,并在各版本发布四年后转为 AGPL-3.0-or-later):记忆引擎、MCP 服务、HTTP API,以及 Python 客户端;Python 客户端采用 MIT 许可证,因此任何 Python 项目都可以嵌入使用。让记忆变得智能的一切功能都在这个免费引擎中。记忆没有分级套餐——不会为了销售而扣留任何功能。

有疑问、关于安全的反馈或对基准测试的意见?→ 讨论

flowchart LR
  subgraph Apps["Your AI apps — every client, one memory"]
    direction TB
    A["Claude Desktop · Claude Code"]
    B["Cursor · Gemini CLI<br/>Cline · Codex · Zed"]
    C["Your scripts"]
  end
  subgraph KEPTA["KEPTA — this repository"]
    direction TB
    M["MCP server<br/>8 tools · stdio + Streamable HTTP"]
    G["HTTP API · 32 routes<br/>Python client · CLI"]
    E["Memory engine<br/>hybrid retrieval: FTS5 + vectors + graph<br/>RRF fusion → local rerank"]
  end
  D[("One encrypted file<br/>SQLCipher 4 · AES-256<br/>~/.kepta/kepta.db")]
  K["OS keychain<br/>the key never leaves"]
  A --> M
  B --> M
  C --> G
  G --> E
  M --> E
  E --> D
  D -.-> K

⚡ 一条命令,连接每个 AI 客户端

安装设备需要 Node 22.13 或更高版本(package.json → engines);npm 为 Node 22、24 和 26 提供预构建的 SQLite 二进制文件。

npx -y kepta-mcp demo          # six scenes in a throwaway database — nothing of yours is touched
npx -y kepta-mcp setup         # connects Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, Gemini CLI, Cline and Roo Code
npx -y kepta-mcp remember "Client Miller signs renewals in December."   # write a note from the terminal, no AI client needed
npx -y kepta-mcp recall "who signs renewals"                            # read it back: 1 match — ranked by relevance
npx -y kepta-mcp stats         # size, encryption state, top tags
npx -y kepta-mcp timeline "miller"                                     # what was true, and when
npx -y kepta-mcp import chatgpt <export-folder>   # bring your ChatGPT history with you (export → extract → import)

以下是这两行命令的实际输出——来自注册表的 kepta-mcp 3.2.0,日期为 10.10.2026,使用临时 HOME,记忆为空:

$ npx -y kepta-mcp remember "Client Miller signs renewals in December."
✓ remembered — Client Miller signs renewals in December.
  type: semantic · id: k-mv2mghs9-fdf75c17

$ npx -y kepta-mcp recall "who signs renewals"
1 match — ranked by relevance

1. Client Miller signs renewals in December. · semantic · today
  Client Miller signs renewals in December.
  #remember

笔记是记忆中保存的一条内容——手动运行 remember 可写入一条笔记,你的 AI 客户端则通过 memory_save 工具写入同类笔记。接着告诉 AI 一些值得保存的内容,再看它如何出现在记忆中。详情请见快速入门。



🖥️ 或下载桌面应用

核心本身没有窗口:它的界面就是你的 AI 客户端。 如果你想要一个窗口,可以使用免费的桌面应用——引擎相同、加密文件相同、密钥相同,可从此代码库的 releases 下载。团队和组织可通过协议使用 KEPTA Enterprise。这三句话就是完整的答案;这里的每份文档说的都是同一件事。

该应用提供记忆浏览器、带检索来源信息的混合搜索、知识图谱、时间回溯、档案,以及一个能读取记忆的聊天功能。从最新版本下载适用于 Mac 的 DMG(Apple Silicon 或 Intel),然后将它拖到 Applications 文件夹中。此构建采用临时签名,未经公证,因此 macOS 只会提示一次。有两种解决方法,在所有 macOS 版本上都适用:xattr -dr com.apple.quarantine /Applications/KEPTA.app,或前往系统设置 → 隐私与安全性 → KEPTA 提示 → 仍要打开。只需操作一次,之后就不会再提示。较早的指南建议右键点击 → 打开;Apple 已在 macOS 15 中移除此方式,因此它在当前系统上不起作用。(从此代码库运行的程序没有窗口:npm run dev 会启动 HTTP API 及其 POST /mcp——它是你机器上的服务,而不是界面。)

该应用免费,和此代码库中的所有内容一样。KEPTA Enterprise(团队和租户记忆、审计链、人工审核、指定时间点恢复)需通过协议授权——在 LinkedIn 上联系我。

🧠 一个引擎。免费。适用于所有 AI。

KEPTA 不是某个应用中的一项功能——它是一层记忆,可跨越所有模型、所有应用和所有上下文窗口。三种方式都能访问同一个加密文件:

入口使用者
MCP — 8 个工具,stdio(npm 二进制文件和容器)+ Streamable HTTP(此代码库,从源代码运行)所有 MCP 客户端:Claude、Cursor、Gemini CLI、Cline、Codex、Zed,以及你自己的 Agent
HTTP API — 32 个路由,仅限 loopback脚本、cron 作业、Agent 团队、自动化任务
Python — pip install kepta,仅使用标准库任何 Python 项目,嵌入式使用

免费就是真免费:€0,永久免费——无需账户、许可证密钥或每日限额,记忆中没有等级限制,也没有任何锁定功能留待日后出售。这是我们能打造的最佳记忆引擎,而且免费;这正是重点。这句话说的是费用,而不是容量。在一台机器上,当活跃笔记达到 KEPTA_MAX_ACTIVE(默认值为 5000,server.ts → maxActiveMemories())后,本地 API 就会停止接受新笔记:这是为了防止失控的 Agent 把记忆写满,而不是付费墙——调整该变量即可提高上限,其他一切都不会改变。免费核心中的所有功能都不会被锁定;有关此类限制的所有配置项,请参阅 SECURITY.md。

团队和组织——共享团队记忆、集中策略、MDM、组织范围的审计——可按需获取 KEPTA Enterprise。我们唯一收费的是协作协调,记忆质量永远免费。→ 在 LinkedIn 上联系我


⚡ 快速开始

连接你的 AI 应用
npx -y kepta-mcp setup

它会查找电脑上的 Claude Desktop、Claude Code、Cursor、Windsurf、VS Code、Gemini CLI、Cline 和 Roo Code,并将 KEPTA 添加到这些应用中。它会逐个询问是否连接(--yes 会连接所有应用),为每个修改过的文件保留备份,并且不会改动其他条目。Zed、Codex CLI 和 Continue 会获得可直接粘贴的代码片段(它们的配置格式变化太快,无法从外部编写)。其他任何 MCP 客户端:

{
  "mcpServers": {
    "kepta": {
      "command": "npx",
      "args": ["-y", "kepta-mcp"]
    }
  }
}

8 个工具:memory_search、memory_save、memory_update、memory_delete、memory_list、memory_graph、memory_consolidate、memory_forget。

HTTP API
git clone https://github.com/DamianTodorovic/kepta.git
cd kepta && npm install && npm run dev
# → http://127.0.0.1:3000

# save a note
curl -s localhost:3000/api/memory -H 'Content-Type: application/json' \
  -d '{"title":"Client Miller","content":"Billed quarterly.","tags":["client"]}'

# search
curl -s "localhost:3000/api/memories/search?q=how+does+miller+pay"
Docker(仅 MCP 服务)

请从干净克隆的仓库中,在运行任何 npm install 之前构建镜像——如果构建上下文中包含为 macOS 构建的 node_modules,就会导致 Linux 构建失败(ERR_DLOPEN_FAILED)。根据 2026.10.12 的测量结果(docs/belege/r1/kontext-groesse-2128.log.txt):同一个文件夹会带来 180 MB 的构建上下文,其中 169 MB 是 node_modules,而已跟踪文件本身只有 4 MB。(.dockerignore 现在会将 node_modules 和构建产物排除在上下文之外;在这些更改到达你的检出目录之前,使用干净克隆是稳妥的做法。)

git clone https://github.com/DamianTodorovic/kepta.git && cd kepta
docker build -t kepta-mcp .

# A container has no keychain, so the database key is not optional here: it has
# to come from the environment. Generate it ONCE and keep it — it is the only way
# back into the volume.
KEPTA_DB_KEY=$(openssl rand -hex 32)

docker run --rm -i -e KEPTA_DB_KEY="$KEPTA_DB_KEY" -v kepta-data:/data kepta-mcp

没有密钥,就没有文件。请传入真实值:64 个十六进制字符,可用 openssl rand -hex 32 生成一次,并存放在你保存机密信息的地方。容器无法回退到密钥链,因此如果没有 KEPTA_DB_KEY,就不会创建新的知识库——KEPTA 会以非零退出码停止,并说明该怎么做。之后每次启动都必须使用同一个值:第二次重新运行 openssl rand -hex 32,就会得到一个与卷不匹配的密钥,程序同样会停止,且不会更改任何内容。只有明确声明的开关 KEPTA_ENCRYPTION=off 才能创建明文数据库。

给使用旧版构建的读者补充一句过渡说明:这条规则加入代码之前,无效值(从指南中复制的占位符、长度不足或不是十六进制的值)不会导致失败——KEPTA 会打印一行信息,以明文创建数据库,然后以 0 退出。如果你的 kepta.db 以字节 SQLite format 3 开头,就是这种情况;任何能读取该文件的人都能读取其中内容。请检查版本,然后重新设置密钥或替换卷。完整规则见 SECURITY.md。

CI、服务器以及所有其他无头启动场景

CI 运行器也没有密钥链,因此密钥必须作为机密传入——只生成一次,而不是每个作业都生成一次,否则每次运行都会从全新的空白状态开始:

# GitHub Actions, one step. The secret holds the 64 hex characters from `openssl rand -hex 32`.
- run: KEPTA_DB_KEY="${{ secrets.KEPTA_DB_KEY }}" npx -y kepta-mcp stats

根据此仓库的实际测量结果,有三个陷阱:

  • 空值不等于“没有密钥”。KEPTA_DB_KEY="" 会被忽略,程序随后仍会尝试查找密钥链——在你自己的机器上,这意味着它会读取你本不打算使用的密钥链条目。请在启动前检查变量是否非空,并避免模板错误将其变成 ""。
  • **占位符也是一个值。**从任何指南中复制类似 <64-hex> 的字符串,和传入空值的情况一样。
  • **出现在已记录命令行中的密钥,就等于已泄露的密钥。**请通过环境文件或运行器的机密机制传递密钥,不要通过 CI 会打印出来的 shell 历史记录传递。

如果运行过程完全无法获取密钥,正确结果就是上文所述:不创建数据库、以非零退出码停止,并提示 KEPTA_DB_KEY。构建出明文知识库的 CI 即使显示为绿色,也正是这条规则要杜绝的问题。完整变量列表及其默认值和读取位置见:docs/ENVIRONMENT.md。


✨ 包含内容

🔍 混合搜索BM25 全文搜索 + 向量相似度(Ollama)+ 知识图谱,通过 RRF 融合,并进行本地重排。这三条检索路径并非势均力敌——本仓库测得的数据见下方图表
🔐 静态加密SQLCipher 4:AES-256,并对每个页面进行 HMAC-SHA512 校验(包括 WAL);密钥存储在操作系统密钥链中(macOS Keychain、Windows DPAPI、Linux Secret Service)
🕐 时间回溯有效期窗口(valid_from / valid_to)和 asOf 查询——“3 月 3 日时我知道什么?”
♻️ 被取代,而非被推翻新事实会取代旧事实(superseded_by);历史记录仍会保留
🔗 MCP 优先8 个工具,API 和 MCP 共用一条代码路径——Agent 获得的质量与任何客户端相同
📄 文件导入PDF(pdf.js,支持字符映射)、带有 [[wiki links]] 的 Markdown、文本、JSON
📊 评估在固定语料上运行 npm run eval,包含 58 条笔记 / 45 个查询:Hit@1、Recall@5(封顶)、MRR——仅词法检索、离线且确定性。这里特意称为 召回率:脚本用 min(5, relevant) 除以前五条中的命中数(scripts/eval.ts 的 evaluate() 中:hitsIn5 / Math.min(5, Math.max(1, relevant.length))),衡量的是答案集合中有多少内容被找回,而不是前五条结果有多准确。npx tsx scripts/ablation.ts 使用来自本地 Ollama 的嵌入,在同一语料上比较各检索路径;其 P@5 使用固定分母 5(scripts/ablation.ts:46)——笔记相同,指标不同,数据不可互换
查询如何找到答案
flowchart TD
  Q(["Your query"]) --> A["FTS5 · BM25<br/>lexical search"]
  Q --> B["Vector KNN<br/>local embeddings (Ollama)"]
  Q --> C["Entity match<br/>knowledge graph"]
  A --> R["Reciprocal Rank Fusion<br/>k = 60"]
  B --> R
  C --> R
  R --> BO["Recency + confidence boost"]
  BO --> T{"Temporal state?"}
  T -->|expired| X5["score × 0.5"]
  T -->|superseded| X4["score × 0.4"]
  T -->|valid| K1["unchanged"]
  X5 & X4 & K1 --> R2["Local reranker<br/>term coverage · phrases · title · tags<br/>max boost +0.25 — no network"]
  R2 --> OUT(["Top-k, ranked by relevance"])

各条检索路径单独发挥的作用——在当前状态下运行 npx tsx scripts/ablation.ts,使用 58 条笔记 / 45 个查询和本地 Ollama,于 12.10.2026 进行三次相同的运行测得(docs/belege/r1/ablation-2326.log.txt):Hit@1 中,仅全文搜索为 71 %,全文搜索 + 图谱为 71 %(+ 0 个百分点),全文搜索 + 向量为 78 %,三者齐上为 76 %;仅图谱的检索路径达到 11 %。请如实解读:答案主要由全文搜索提供,向量检索路径带来了额外的七个百分点,也是唯一需要模型的路径;而在这个语料上,图谱检索路径并未提升排序——叠加在前两者之上反而使结果降低了两个百分点。它的作用是处理实体并支持 GET /api/graph,而非提升胜率。声称三者势均力敌,只会拿出被本仓库自身脚本所否定的数据。


🖥️ HTTP API(32 个路由路径)

共有 32 个不同的路径;如果将每个 HTTP 动词单独计数,则有 35 个端点,因为 /api/memories、/api/settings 和 /mcp 这样的路径会响应两个动词。这两个数字均来自 server.ts 本身,而 tests/doku-zahlen.test.ts 统计的是路径数——因此,在现有路径上新增一个动词只会改变第二个数字,新增一个路径则会同时改变两个数字。

区域路由
记忆GET/POST /api/memories、POST /api/memory、DELETE /api/memories/:id、POST /api/memories/:id/restore、POST /api/memories/bulk-delete、POST /api/memories/bulk-restore、POST /api/memories/reclassify、POST /api/memories/import
搜索与图谱GET /api/memories/search、POST /api/search、GET /api/graph、GET /api/graph/bild
导入 / 导出POST /api/import/markdown、POST /api/export/markdown
收件箱GET /api/inbox/status、POST /api/inbox/scan
设备同步POST /api/sync/export、POST /api/sync/import、GET /api/sync/journal
加密与修复GET /api/health(包括 encryption 状态)、POST /api/repair/imports
MCPPOST /mcp、GET /mcp、GET /api/mcp/tools、POST /api/mcp/search、POST /api/mcp/save、POST /api/mcp/consolidate、POST /api/mcp/forget、GET /api/tools、POST /api/embed
系统GET /api/settings、PUT /api/settings、GET /api/storage-info、GET /api/activity

每个路由都只监听 127.0.0.1,并启用速率限制、Helmet 和输入验证。

此 API 是从本仓库运行的服务(npm run dev,或 npm run build && npm start)。已发布的 npm 二进制文件和 Docker 容器仅通过 stdio 提供 MCP 服务——POST /mcp 在此处响应,而不是通过 npx kepta-mcp 响应。

回环地址是默认设置,不是承诺:设置 KEPTA_HOST 会让同一个未经身份验证的 API 绑定到该地址,届时网络上的任何设备都能读取和删除你的记忆。关于不应这样做以及替代方案,请参阅 SECURITY.md。

API 在销毁任何内容前会要求什么

脚本必须了解以下五种行为。它们都是后来添加的,因为旧的默认行为很容易因一个笔误导致数据丢失:

  • **POST /api/memories/import 使用 mode:"replace" 时需要 confirm:"replace"。**没有该参数时,调用会返回 400,不会执行任何操作——以前只需一行调用,整个知识库就会永久消失。清除数据前,核心会将加密快照写入 <data folder>/backup/kepta-pre-replace-<timestamp>.db,并在响应中以 backupPath 指明其路径。dryRun: true 会先显示 affected: { active, trashed },但不会更改任何内容。没有可用笔记的载荷(空数组,或不含内容的笔记)会被拒绝,并返回 400——之前就是这种情况导致了全部数据被擦除。要恢复数据:将 .db 放入空数据文件夹,命名为 kepta.db,然后使用相同的密钥启动。每次确认替换都会留下一份快照;清理 backup/ 由你负责,不是核心负责。
  • **DELETE /api/memories/:id?permanent= 的参数校验很严格。**只接受 1、0、true、false,或不传该参数(即移入回收站)。其他值,包括 True,都会返回 400,且不会删除任何内容;?permanent=1&permanent=0 同样会返回 400。
  • **GET /api/settings 不再显示密钥。**以 key、api_key、token、secret、password、passwort、passphrase、schluessel 结尾的键,以及 ai_settings 数据块,都会以 { gesetzt: true, ende: "…last four characters…" } 的形式返回;少于 8 个字符时不包含 ende,已删除的条目不会出现在响应中。仍通过 PUT 写入;完整值仍保存在加密数据库中。任何界面都应显示 gesetzt + ende,绝不能显示实际值。
  • **错误响应均为 JSON。**不会包含堆栈跟踪、绝对路径,也不会回显你发送的请求正文。413 会指出限制和实际接收大小(limitBytes、receivedBytes);格式错误的请求正文会返回 400,且不会重复回显正文;从 500 开始,真实原因会写入服务器日志,而不是响应。
  • **POST /api/repair/imports 接受 16 kb。**此前虽然声明了限制,却从未实际生效(900 KB 也能通过);现在,超过限制的请求都会返回 413。此路由的其他部分没有变化。

还有两个较小的改动,各用一句话说明:~/.kepta/inbox/ 中的符号链接不会被导入——它会留在原处,而 POST /api/inbox/scan 会在 skipped: [{ file, reason }] 中报告它(一个链接就足以将你任何可读取的文件引入 Agent 可见的记忆中)。此外,GET /api/graph 有数量上限:最多 500 个实体和 2000 个关系(src/core/store.ts、getGraph()),且两个上限前都没有 ORDER BY——返回哪些内容取决于行顺序,而不是重要程度,因此大型存储中的核心术语可能会缺失。这些边不会提供的一点是:响应中的关系带有 validFrom 和 validTo,但核心自身的写入路径会将两者留空(调用 addRelation 时未传入时间范围,因此默认值 null 会保留)。绘制此图的客户端无法判断某条声明是已过期还是仍然有效,因此不得假装能够判断。

GET /api/graph/bild — 会说明裁掉了哪些内容的那个接口

GET /api/graph 保持原样,因为外部 Agent 会依赖它的结构编写代码。图片路由是它诚实的同级接口:它按 graf-2 契约返回 sicht、entitaet、tiefe、knoten、kanten、layout,并且有意不返回 width/height。位置以世界单位表示,而 welt.groesse 是这张图片的边长——下限为 1000,随库存增长,由力学定律计算,并在每次响应中报告(src/core/graf-vertrag.ts)。welt.nullpunkt 是该世界的左下角:自布局版本 5 起,位置在每个轴上都处于 nullpunkt + [0, welt.groesse] 范围内,但不保证从 0 开始,因为新增的笔记可能会让范围超出上一张图片的下限,而每个逐位精确锚定的节点仍会保持原位——为了让零点看起来漂亮而平移图片,会移动所有节点。因此,客户端应计算 (x - welt.nullpunkt.x) / welt.groesse,再按 min(width, height) 缩放,窗口大小绝不会参与布局计算。渲染器绝不能做的一件事,就是除以硬编码的 1000——或假设下限为 0:当有 3 000 条笔记时,世界宽约为 2 500 个单位,图片就会变成空画布中五分之一大小的一团。计算结果与呈现结果并不相同,而响应会通过 kuerzung 明确说明:它遵守的上限、剩余内容(uebrig)、截断原因(grund:knoten、kanten、paarBudget、tiefe、privat、papierkorb)、筛除的私有和已删除载体数量——只给数字,不给名称——哪些节点和边是孤立的,以及一个 vollständig 标志。如果客户端需要知道图片是否涵盖整个存储区,应读取这个字段;GET /api/graph 不会告诉你。

核心现在会将各个圆盘彼此分开布局(LAYOUT_VERSION 5)。布局会确保在绘制任何内容之前,节点圆盘彼此不重叠;在 27 个概念下,对 400 / 1 500 / 3 000 个节点进行测量,结果为:按核心自身未设上限的规则 r = 6 + 2,4·√grad 和表层规则 min(18, 4 + log2(1+grad)·2,2) 计算,相交节点对均为 0(tests/graf-ruhe.test.ts;在此状态之前,同一字段通过第 4 版布局的源代码运行——git show 6ae32d3:src/core/graf-kraft.ts——按核心规则有 37 / 935 / 7 134 对重叠,按表层规则有 15 / 443 / 5 236 对重叠,世界边框上的位置分别为 36 / 221 / 818 个;运行记录保存在 docs/belege/nacht-12-10/vorher-gleich-12-10.log.txt 中,该文件随项目文档一起提供,不包含在已发布的软件包内;通过该提交对同一字段进行布局,即可复现其中的数据)。为避免通过增加空白区域来换取这一结果,测试还会按每种规模类别验证两个数值——测量时间为 2026-10-12 14:44,所用机器经安静度探测认定状态平稳:

  • **顺序:**真实边的中位数为 283 / 385 / 571 个世界单位,随机配对的中位数为 427 / 572 / 817 → 比率为 0,662 / 0,674 / 0,699,低于本仓库已用于可读性的 0,8 标准(tests/ui/graph.test.ts;运行记录:docs/belege/nacht-12-10/ruhe-mit-anteil-1444.log.txt)。
  • **比例:**最小绘制圆盘覆盖图片世界边长的 0,769 % / 0,572 % / 0,368 %(注意半径为 10,16 WE,世界边长为 1 321 / 1 775 / 2 759 WE),且必须保持在 0,3 % 或以上——这个标准根据我们自己的画布测得;目前发布的最密集场景绘制比例为 0,414 %(世界边长见 kepta-app/src/lib/graphLayout.ts:521,半径见 src/components/KnowledgeGraph.tsx:1418)。比率本身无法识别整体均匀放大的世界:一个被否决的变体在世界边长为 19 684 时,配对数达到 0,比率为 0,721——低于标准——但圆盘仅占 0,052 %(运行记录 docs/belege/nacht-12-10/kleinste-scheibe-2007.log.txt,按其自身标题所述,于 18:07:18 UTC 启动——一次运行测量半径和边长,并将边长与 bild-guete.json[28] 核对),经过客户端常规归一化后,这只是尘埃,而非一张图片。

🐍 Python 客户端

前提是这台机器上正在运行 KEPTA:可以是桌面应用,也可以是在本仓库中运行 npm run dev。pip install kepta 安装的是客户端,不是服务——请注意,npx kepta-mcp(AI 客户端启动的 stdio 服务)完全不会打开 HTTP 端口,因此它不是此客户端的通信对象。

pip install kepta
from kepta import KeptaClient
kepta = KeptaClient()
kepta.save("Carbonara", "Guanciale, pecorino, egg yolk. No cream.", tags=["cooking"])
for hit in kepta.search("carbonara without cream"):
    print(f"{hit.score:.2f}  {hit.memory.title}")

无依赖项——仅使用 Python 标准库。

上面的示例经过实际测量,并非装饰:search("carbonara without cream") 会将该笔记排在首位,在默认模型(nomic-embed-text)下的向量相似度为 0.75。同一个模型无法做到的是,找出与笔记没有任何共同用词的改述:search("what do I cook with pasta") 得到的食谱相似度为 0.51,低于 0.58 的向量下限(src/core/engine.ts 中的 VECTOR_FLOOR);而一条仅仅包含“Pasta”一词的笔记则以 0.59 胜出。这种情况下,由全文检索补上另一条腿——它能匹配问题和笔记共有的那个词。python/README.md 说明了这一限制,以及突破它需要什么。


🏗️ 架构

src/core/           memory engine (store, search, encryption, MCP protocol)
server.ts           HTTP API (Express, 32 routes)
src/mcp-server.ts   MCP stdio server (npx kepta-mcp) and the CLI (npx kepta-mcp)
src/ui/graph.ts     the graph builder behind the CLI and the demo — `GET /api/graph` reads `store.getGraph` directly instead. No UI: the core has no window of its own, the interface is your AI client, and for a window there is the free desktop app in this repository's releases
npm/                source of the npm package (kepta-mcp)
Dockerfile          container for the MCP server
python/             Python client (PyPI: kepta)
scripts/            eval, benchmark, repair
tools/              benchmark harnesses (LongMemEval, latency)
docs/               environment variables and the words the API uses
tests/              Vitest suite with CI-enforced coverage thresholds

一条代码路径同时用于 HTTP API 和 MCP 服务——Agent 获得的结果与直接 API 调用相同。



🔧 设置项

KEPTA 从环境中读取的每个变量——包括默认值、它会改变什么,以及修改后可能导致什么问题——都列在一个表中:docs/ENVIRONMENT.md。最重要的三项简要说明如下:

KEPTA_MAX_ACTIVE本地 API 接受的活跃笔记数量上限(默认 5000),超过后会返回 429。这不是许可证限制,而是为了防止 Agent 失控的刹车。调高它不会改变其他任何东西。
KEPTA_HOST绑定地址,默认为 127.0.0.1。在这里设置网络地址,会向该网络开放未经身份验证的 API,并不再保证仅限环回访问;请改用带有自身身份验证机制的反向代理。
KEPTA_ENCRYPTIONoff 会直接以明文写入数据库,不会再次确认。这是为需要直接访问 SQLite 的脚本提供的工具——绝不是解决密钥问题的方法。

API 和这些文档中使用的术语——笔记、记忆、范围、dry-run、替代,以及 key 和 restore 的两种含义——均在 docs/WORDS.md 中统一说明。

🔐 加密

知识库是一个 SQLCipher 4 数据库:采用 AES-256 加密,对每个页面(包括 WAL)进行 HMAC-SHA512 校验。密钥是 256 位随机数,存放在操作系统的密钥链中:macOS Keychain、Windows DPAPI 或 Linux Secret Service。在没有密钥链的服务器和容器上,将 KEPTA_DB_KEY 设为 64 个十六进制字符——用 openssl rand -hex 32 生成一次并妥善保管。

字节层面的实际情况如何?我们进行了测量,而非仅仅断言:2026-10-10,从注册表获取的 kepta-mcp 3.2.0 在临时 HOME 中写入一条笔记后,留下的 ~/.kepta/kepta.db 文件的前 16 个字节为 85 95 55 36 a3 ab f4 02 4c 6c f0 5c 0f 0b 4c 69——并非 SQLite format 3——文件中也找不到任何笔记文本的痕迹。在任何存储库上,包括你自己的存储库,运行 head -c 16 ~/.kepta/kepta.db 就能完成整个测试。

规则:没有密钥,就没有文件。 当 KEPTA 即将创建知识库,却无法将密钥安全存放——没有密钥链、审批被拒,或 CI 环境变量为空——它就不会创建文件。它会以非零状态码退出,并指出解决办法(KEPTA_DB_KEY,或者如果你确实需要明文,则使用 KEPTA_ENCRYPTION=off)。过去的行为是悄悄退回到未加密数据库;这条规则就是为了杜绝这种情况。打开现有文件的行为没有变化:如果密钥缺失或错误,原本就会停止,且不会做出任何更改。当前说明:该决定于 2026-10-10 作出,目前正在落实到代码中——早于此决定的构建版本仍会写入明文,并在密钥不可用时以 0 状态码退出。因此,如果你使用的是旧版本,请实际测试,不要轻信这句话。

因此,只有一条通往明文的路,而且必须由你主动打开:KEPTA_ENCRYPTION=off。它适用于必须读取原始 SQLite 数据的工具,例如检查器和一次性迁移脚本;它不是性能开关,也无法解决密钥问题(对加密文件使用它会导致文件无法读取错误)。不要为了启动容器而使用它;这种情况应该使用 KEPTA_DB_KEY。关于加密的保护范围、不覆盖的内容,以及如何保存密钥副本,请参阅:SECURITY.md。


🧪 质量

使用 Vitest 和 v8 coverage 运行 1045 项测试(85 个文件,测量于 2026-10-13)——这是某次运行收集并能够执行的测试用例数:源代码中写成 it.skip 的用例不计入数量;运行期间被安静性探针拒绝的用例仍计入数量,因为无论如何都是同一运行器上的同一棵代码树(scripts/test-bericht.mjs 解释了原因:在这台机器上,三个计时用例在一个提交中被拒绝,在下一个提交中则运行了;随环境波动的数字算不上数字)。npm test 会写入本次运行的 JSON 报告,随后 node scripts/doku-check.mjs 会要求两份 README 中的数字都与该数字完全一致。tests/doku-zahlen.test.ts 会读取同一份报告;如果报告无法信任——缺失、早于测试套件,或由部分运行写入——它就会拒绝进行比较,而不是从抽屉里随便拿个数字来检查。覆盖率阈值是 CI 门禁:提交只要低于其中任意一项,CI 就会变红。此外还有检索评估(Hit@1、截顶的 Recall@5、MRR)、针对每个检索环节的消融测试、加密评估,以及针对核心架构的边界测试。

覆盖率阈值(由 CI 强制执行)
区域行函数分支语句
合计,在覆盖率范围内 — 由 CI 固定≥ 70 %≥ 72 %≥ 56 %≥ 66 %
src/core — 由 CI 固定≥ 87 %≥ 89 %≥ 74 %≥ 85 %

测量范围为 src/core/** 加上 server.ts(vitest.config.ts)——无头核心,也就是产品本身。tools/、scripts/、npm/ 和 python/ 有各自的测试套件,但没有覆盖率阈值,因此不计入上述百分比。

延迟——实测数据,公开可查

在一台笔记本电脑(Apple M4)上测得的搜索中位数,每次运行的结果都已提交到 tools/latenz/ergebnisse/:100,000 条记忆时,中位数为 46.6 ms(p95 为 87.6 ms,tools/latenz/ergebnisse/latenz-100k-fts-2026-10-01.json);1,000,000 条记忆时,中位数为 276.5 ms(tools/latenz/ergebnisse/latenz-1m-fts-2026-10-01.json)。记录本身还包含三个条件,这些条件应与数据一同呈现,而非置于数据之后。这些运行测试时关闭了加密,并使用确定性桩嵌入器——konfiguration.verschluesselung 和 konfiguration.embedder 中对此有明确说明。此外,两次运行的 konfiguration.vektorChunks 均为 20000:tools/latenz/bench.ts:38 将向量部分固定为 min(20_000, N),因此,百万条记忆的中位数是在与十万条记忆相同的 20,000 个块上测得的——这是有上限的向量处理量,并非该规模下完全嵌入的存储库。每条笔记都带有向量的存储库,搜索速度会比这个数字所暗示的更慢;究竟慢多少,本仓库尚未公布测量结果,而列出这些运行结果的 tools/latenz/README.md 中说明了 20,000 个块这一条件。磁盘上的文件始终经过 SQLCipher-4 加密;只是这两项中位数未计入加密成本。

基准测试记录 — LongMemEval-S,完全公开

KEPTA 发布的记忆基准测试采用逐题原始记录,而非一个醒目的总分:每次运行都会将全部 500 条问题记录提交到此仓库,存放在 tools/longmemeval/ergebnisse/ 中——每条记录都包含问题 ID、类型和技能、评审结果、检索返回的笔记数量、哪些检索到的上下文帮助得出结论,以及参考答案是否逐字出现。问题和答案的文本不在仓库中:它们来自固定版本的上游数据集,每条记录都附有该数据集的 SHA-256。数据集固定(LongMemEval-S,500 道问题,SHA 固定)、评审器固定,可在本地完全复现——详见 tools/longmemeval/README.md。

这一系列以逐题原始记录的形式提交——而且它不是当前测量结果,因此此处不引用分数。该文件夹中的每条记录都标明 kepta_version 在 2.13.2 到 2.13.22 之间(grep -h kepta_version tools/longmemeval/ergebnisse/*.json),而此仓库发布的是 3.4.0。两者必须放在同一句话里理解:这些记录对于运行它们时所用的引擎仍然有效;而没有新一轮运行,仅版本号变更并不能说明 3.4.0 的情况——它既不会让那些百分比重新生效,也不会使其失效。在针对当前发布的引擎重新运行完整流程之前,这些数字只保留在记录中,不写进论文。不会改变的是:两位评审器都在本地运行(连续性系列使用 qwen2.5:3b,后续运行使用 Q4 版 qwen2.5:14b,两者都运行在消费级 GPU 上),不使用云服务,不进行微调,而且两条流程的每一步都在同一文件夹中留有运行记录。

此指标衡量什么——在与他人的结果比较之前请先阅读。 它衡量的是上下文充分性,而非端到端答案准确率:本地评审器(qwen2.5:14b,温度 0,提示词 v1)会评估检索到的上下文是否包含参考答案。流程中没有生成式大模型,PARTIAL 结果按半分计,而且该次运行中有 29.8 % 的问题通过确定性的逐字匹配得出结论,无需调用评审器(tools/longmemeval/README.md,第 104 行)。Zep 公布的 63.8 % 是由云端大模型评审的完整生成流程的答案准确率——属于相关证据,但不是同一项指标;引用的论文明确列出了这两个数字及其差异。还有一点需要明确说明:该系列中的所有参数(topk、--temporal、--zeitsplit、HyDE、评审器规模)都是根据同一批 500 道问题选定的,因此该系列的数据是在样本内得出的,存在偏高倾向;目前尚未使用独立的留出集进行测试。发布所有这些逐题原始记录,目的就在于接受核查——包括对这里表述方式的核查。


👋 KEPTA 的开发者

KEPTA 由 Damian Todorovic 和 Emil Wagner 开发——这是一个来自德国的小团队,公开推进项目。无论是问题、想法、为团队咨询 Enterprise,还是单纯想关注项目进展:欢迎在 LinkedIn 上找到我们。

📄 许可证

BUSL 1.1 — 源码可见,但不是经 OSI 批准的开源软件:每一行代码都公开,在自己的组织内部始终允许用于生产环境;不得将其作为托管服务提供;每个版本在发布四年后转为 AGPL-3.0-or-later。npm 包 kepta-mcp 与本仓库采用相同许可证;python/ 下的 Python 客户端则继续采用 MIT 许可证,因此任何 Python 项目都可以嵌入它。面向团队和组织的 KEPTA Enterprise 根据协议授权——通过 LinkedIn 联系我。

本仓库是什么,以及它不是什么。 这个源码可见的核心就是记忆引擎:存储、检索、MCP——免费,适用于所有 AI。分叉是正当的;但把分叉版说成 KEPTA 就不行:KEPTA 名称和 KEPTA 品牌归 Damian Todorovic 所有。你可以分叉、基于它构建并发布自己的产品——但须使用不同的名称,不得将此引擎作为托管服务提供,并且你所做的每项更改都会在该版本的变更日期到来时转为 AGPL-3.0-or-later。私密笔记不会进入任何 AI 通道——private 是面向 Agent 的信息披露规则,而不是防止在你自己的机器上运行的程序访问内容的屏障(SECURITY.md)。


KEPTA — 一份本地加密记忆,供每个 AI 读取和写入。本地、加密、免费。无需订阅、无需账户、无需借口。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。