mcpField
T
tether

tether

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

关于 tether

tether 是面向个人 Agent 的本地优先 MCP 记忆服务,使用 SQLite 保存持久笔记。它支持项目感知检索和可选的跨设备同步,并可在扩展功能不可用时退回关键词搜索。

主要功能

  1. 01记忆、检索、关联和遗忘笔记
  2. 02SQLite 存储与可选设备同步
  3. 03关键词与语义混合搜索
  4. 04基于使用图的关联检索
  5. 05项目感知的启动索引

适用场景

  1. 01在 Agent 会话间延续个人偏好
  2. 02通过 libSQL 或 Turso 跨设备共享记忆
  3. 03编码时检索相关项目笔记

MCP 相关

它向兼容 MCP 的 Agent 提供记忆操作:记忆、检索、关联和遗忘。自动加载的启动索引也会呈现简明记忆上下文。

配置

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

mcp.json · 通用配置
{
"mcpServers": {
"sidyellur-tether": {
"command": "uvx",
"args": [
"tether-memory"
],
"env": {
"TETHER_DB": "<TETHER_DB>",
"TETHER_SEMANTIC": "<TETHER_SEMANTIC>",
"TETHER_SYNC_URL": "<TETHER_SYNC_URL>",
"TETHER_SYNC_TOKEN": "<TETHER_SYNC_TOKEN>"
}
}
}
}
启动命令uvx tether-memory
需要配置的环境变量
TETHER_DBPath to the SQLite memory file. Defaults to the platform data dir (e.g. ~/.local/share/tether/memory.db).
TETHER_SEMANTICSet to 0 to force keyword-only recall. Semantic recall needs the [semantic] extra and is on by default when available.
TETHER_SYNC_URLOptional libSQL/Turso primary URL to sync memory across devices. Leave unset for local-only.
TETHER_SYNC_TOKEN密钥Auth token for TETHER_SYNC_URL.

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

安装包
pypitether-memory0.6.1

工具

4

收录的工具列表 · 更新于 2 周前

参数类型必填说明
bodystring是
tagsstring否
typestring是
linksany否
titlestring是
crystallizesany否

详细介绍

tether

一个跨设备的个人 Agent 共享记忆层。 tether 是一个由本地 SQLite 文件提供支持的 MCP 服务。任何兼容 MCP 的 Agent 都可以 remember、recall、link 和 forget 持久化笔记——关于你、你的项目和偏好的事实——让上下文伴随你,而不是随着每次会话结束而消失。

它仅在本地运行,无需任何配置。将它指向托管的 libSQL/Turso 主库后,同一个文件就会成为嵌入式副本,近乎实时地在所有设备间同步你的记忆。

为什么

不久的将来,个人 Agent 将运行在许多设备上——笔记本电脑、台式机和手机。要让它们感觉像是同一个助手,而不是几个健忘的助手,记忆就必须成为伴随你的底层基础:可从每台设备和任何 Agent 读取和写入,而不是被隔离在单个工具中。

tether 就是这样的基础。它有意设计成一个便利层——存在时能让 Agent 更有用;出现故障时也绝不会妨碍 Agent 的工作。

状态

v0.6.1。 核心功能(四种记忆操作 + 启动索引 + FTS5)已在 v0.1 发布;此后,recall 增加了语义检索功能、整合功能、关联使用图、自组织存储和可选的结晶功能——每项都是增量式功能,且都能平稳退化为纯关键词检索。以下所有功能均已实现。

设计和原理始于 docs/superpowers/specs/2026-07-03-tether-design.md; 关联核心、种子主导检索、自组织存储(Tier B1)和结晶(Tier B2)各有独立的设计文档,位于 docs/superpowers/specs/,对应的计划则位于 docs/superpowers/plans/。

设计概览

  • 四种记忆操作:remember · recall · link · forget。(启用结晶功能会增加一个反思控制工具 dismiss_cluster——它不属于记忆操作。)
  • 写入时执行 upsert,避免存储中逐渐充斥近似重复项。
  • 丰富的检索结果(id、type、title、body、tags、updated_at,以及说明每条结果为何出现的 via 凭据),让 Agent 能判断信息是否过时,并引用要更新的内容。body 是以查询为中心的摘录,而非完整记忆——参见摘录。
  • 自动加载的启动索引——每条记忆占一行的精简列表,会在每次会话中呈现给 Agent,因此即使 Agent 没想到要搜索,记忆也能发挥作用。
  • 本地优先,同步可选——未配置后端时,本地路径不受影响;功能退化时绝不抛出异常。
  • 混合搜索,叠加关联能力——融合 FTS5 关键词结果和本地静态嵌入,再由使用图(显式链接、学习到的共同检索关系、语义邻居)补充相关记忆。每一层都是增量式的,且都能退化为纯关键词检索。
  • 安全支持并行工具调用——Agent 同时发起多个 remember/recall 调用时,结果仍然原子且报告准确;参见性能与持久性。

安装

需要在 Linux、macOS 或 Windows 上使用 Python ≥3.10。

使用 uv 将其注册到 Claude Code:

claude mcp add tether -- uvx tether-memory

……也可以先安装:

pip install tether-memory
claude mcp add tether -- tether-memory

(该软件包在 PyPI 上的名称是 tether-memory——tether 作为常见品牌名称已被占用。claude mcp add tether -- ... 中的 tether 只是 Claude Code 用来指代此服务的标签,无需与已安装的命令匹配。)

也可以将其添加为 Claude Code 插件(此仓库同时也是一个仅含一个插件的市场;该插件会运行 uvx --from 'tether-memory[semantic]',因此也会附带语义回忆功能):

/plugin marketplace add sidyellur/tether
/plugin install tether@tether

它也已在 MCP 注册表中列出,mcp-name 为 io.github.sidyellur/tether。

默认情况下,记忆存储在本地 SQLite 文件中:~/.local/share/tether/memory.db;在 Windows 上为 %LOCALAPPDATA%\tether\memory.db(可通过 TETHER_DB 覆盖任一路径,或设置 XDG_DATA_HOME,该变量在所有平台上均有效)。无需账户,无需联网——这就是一款供单台机器使用的完整工具。

项目感知

tether 知道自己正在为哪个项目提供服务:Claude Code 会在每个 MCP 服务的环境中设置 CLAUDE_PROJECT_DIR,tether 会将该目录的名称作为项目名称(可通过 TETHER_PROJECT 覆盖或禁用)。这会自动实现以下三项功能,无需配置:

  • 启动索引优先显示当前项目。 自动加载的索引会先显示 # This project (<name>) 部分,然后是 # Everything else,因此 Agent 开始会话时就能看到当前所在仓库的决策和注意事项,而不是你最近在任何地方处理的内容。
  • 工作记忆会自动添加标签。 project、feedback 和 reference 记忆会获得 proj:<name> 标签,除非 Agent 自行传入 proj: 标签。user 记忆与你本人有关,而非工作内容,因此保持全局可用。该标签是普通标签:recall(tags="proj:<name>") 可确定性地列出某个项目的记忆。
  • 相近结果中优先显示当前项目的内容。 带有当前项目标签的匹配项,会比同等质量的其他项目匹配项靠前几位;但绝不会超过明显更好的匹配项,而且未加标签的记忆既不会加分,也不会扣分。
变量默认值作用
TETHER_PROJECTCLAUDE_PROJECT_DIR 的基本名称显式指定项目名称;off 可禁用项目感知

不会回退到工作目录:在 Claude Code 之外(或设置 TETHER_PROJECT=off 时),tether 的行为与之前完全相同。

跨设备同步(可选)

将 tether 指向一个 Turso / libSQL 数据库,本地 文件就会成为嵌入式副本——读取速度如同本地,写入会传播到你的其他设备。安装额外依赖并设置两个环境变量:

pip install 'tether-memory[sync]'
export TETHER_SYNC_URL='libsql://<your-db>.turso.io'
export TETHER_SYNC_TOKEN='<your-auth-token>'

如果无法连接后端,tether 会记录 sync offline,并继续使用本地文件工作。 同步采用单主设计:每次写入都会发送到托管主库,副本只负责拉取,因此曾离线的设备会在下次拉取时追上进度(包括 forget 产生的墓碑),且永远不会让其他设备已忘记的记忆复活。唯一的缺口是:降级期间的写入只会进入该设备的本地文件,之后不会合并回去(#99 正在跟进协调机制)。

写入会立即推送。读取也会拉取数据,但经过防抖处理,最多每隔 TETHER_SYNC_READ_INTERVAL 秒一次(默认值为 30)——因此,即使设备只是查询内容,也能看到其他设备写入的内容,而不会一直停留在启动时的状态,直到它恰好进行写入。读取路径的拉取限制比写入路径严格得多:如果后端速度较慢,检索会返回本地数据,拉取结果留待下次读取,而不会让你等待。

变量默认值作用
TETHER_SYNC_READ_INTERVAL30读取路径拉取之间的秒数;0 = 仅在写入时同步
TETHER_DEVICE_ID主机名记录在每条记忆上的设备 ID(也是默认的 TETHER_AUTHOR)

关于副本,有一点需要了解:libSQL 会将每次写入转发到托管主库;启用关联图(默认开启)时,recall 也会写入——它会记录哪些内容是在一起检索的,让记忆随时间建立关联。在副本上,这会让每次检索除了本地搜索外,还多出几次网络往返。如果你认为学到的关联不如其他因素重要,可以设置 TETHER_ASSOC=0,让 recall 恢复为只读。

关键词搜索

关键词分支使用 SQLite FTS5 对标题、正文和标签进行全文搜索,并按 bm25 排序。可以用自然语言提问:只要记忆中包含查询词的一部分,就会命中;包含的查询词越多,排名就越高。因此,“我们如何运行集成测试?”可以找到写着“pytest 运行测试”的笔记(常见功能词会被忽略)。索引会对英文单词进行词干提取,因此 tests 能匹配 test,deciding 能匹配 decided。词干提取仅适用于英语;对于其他语言的存储,可将其关闭,tether 会在下次启动时重建索引。

变量默认值作用
TETHER_FTS_STEMMING开启设置为 0/false/off,按原样索引单词

在 LoCoMo 长对话基准测试中进行的测量(每个对话轮次对应一条记忆,共 1,536 个问题,评估“检索是否在前 10 条结果中返回了回答问题的轮次”)显示,单独使用关键词分支可为 61% 的问题找到证据,而对相同文本使用教科书式 BM25 的结果为 54%。该测试工具随仓库一同提供——请参阅基准测试。

语义搜索(可选)

默认情况下,recall 使用混合模式:关键词(FTS5)结果与语义(向量)结果融合,因此即使查询词与记忆中的确切用词不同,也能找到相关记忆(例如,搜索“automobile”会检索到一条关于你的“car”的笔记)。语义检索会在本地运行一个小型静态嵌入模型——不联网、不需要 API 密钥,也没有需要连接的服务。安装额外依赖:

pip install 'tether-memory[semantic]'

如果没有安装额外依赖(或设置了 TETHER_SEMANTIC=0),tether 会仅运行关键词 FTS5——语义搜索纯属附加功能,并非必需。首次运行时会为现有记忆生成一次嵌入(一次性回填);之后则采用增量方式。

环境变量:

变量默认值作用
TETHER_SEMANTIC开启设置为 0/false/off,强制仅使用关键词检索
TETHER_EMBEDDING_MODELminishlab/potion-base-8M指定本地静态模型

整合(可选)

tether 会保留被取代的事实,而不是直接覆盖:当一条记忆被替换时,旧记忆会标记为不再有效(保留以供追溯),并从 recall 和启动索引中排除。Recall 也会适度优先显示较新的事实。两种可选行为可进一步增强这一机制:

变量默认值效果
TETHER_CONSOLIDATE关闭开启(1/true)后,写入时会合并近似重复项——取代旧事实,而不是让存储变得零散(需要 [semantic] 附加项)
TETHER_DEDUP_THRESHOLD0.92将两条事实视为重复项所需的余弦相似度
TETHER_DECAY_HALF_LIFE_DAYS关闭设为正数后,在 recall 中按指数规律降低较旧事实的排名
TETHER_AUTHOR设备 ID记录在每条记忆上的归属信息

整合不会删除记忆——forget 会软删除(参见工具),只有管理员 CLI 的 purge 会永久删除。若没有 semantic 附加项,所有这些功能都会退化为纯关键词 recall。

关联式 recall(可选)

recall 不只会返回关键词/语义匹配结果,还会沿着使用图找到相关记忆,因此询问某件事时也会显示与之关联的上下文。图中的边来自三个本地、确定性的来源——不需要 LLM,也不需要网络:

  • 语义 — 根据嵌入向量查找最近邻(需要 [semantic] 附加项),
  • 显式 — 使用 link() 动词,
  • 赫布式 — 随着时间推移,一起 recall 的记忆会相互连接。

每条命中结果都附带一份 via 凭据,说明它为何会出现(直接匹配,或是通过哪条边找到),此外还有两个可选的 recall 参数可调整行为:

参数/变量默认值效果
budget(每次调用)TETHER_RECALL_BUDGET关联查找的范围;0 = 仅直接匹配
session(每次调用)按时间分桶将相关的 recall 分组,使它们能相互激活
TETHER_ASSOC开启设为 0/false/off,以使用纯关键词+语义 recall
TETHER_RECALL_BUDGET8默认关联范围
TETHER_PROTECT_HEAD8在关联结果之前锁定的顶级直接命中数量
TETHER_SEED_FLOOR0.35语义命中作为关联遍历起点所需的最低余弦相似度;低于此值的记忆只能通过边访问。设为 0 可禁用此下限

关联式 recall 以种子为主:顶级直接匹配会被锁定,关联结果只会填入其下方的空位——因此,开启关联功能绝不会降低关键词/语义搜索已排在前面的命中结果。

使用 TETHER_ASSOC=0(或 budget=0,或图为空)时,recall 的行为与之前完全相同——关联式 recall 只会增加能力,绝不会破坏查找。

自组织存储(可选)

随着存储不断增长,tether 会利用同一张使用图让内容保持清晰易读:

  • 由枢纽精选的启动索引。 自动加载的记忆索引超过 TETHER_BOOT_INDEX_CAP(默认值为 50)后会受到限制——该上限始终生效,因此大型存储不会产生无界索引。存在图时,超过上限后会显示两个带标签的部分——承载性记忆(行为度最高:explicit 链接 + 学到的共同回忆,而非单纯相似性)和最新的记忆——这样索引既小巧,又能展示真正重要的内容。没有图时(TETHER_ASSOC=0),则改为普通的最新 N 条列表,而不再按枢纽/近期内容拆分。低于上限时,无论哪种情况都会显示完整的最新优先列表。
  • 断连式遗忘(选择启用,TETHER_FORGET)。每写入 TETHER_FORGET_INTERVAL 次后,会执行一次有界扫描,并对同时满足时间久远(TETHER_FORGET_AGE_DAYS,默认值为 90)且行为上孤立(没有 explicit/hebbian 边——语义相似性不计入)的记忆进行软归档。归档后的记忆会从回忆结果和启动索引中移除,但仍会保留且可恢复(复用与整合相同的标记为无效机制;不会删除任何内容)。安全限制:没有实时行为图时、记忆数量低于 2 × CAP 时,或单次扫描归档数量超过 TETHER_FORGET_MAX_PER_SWEEP(默认值为 10)时,均不会运行。
变量默认值作用
TETHER_BOOT_INDEX_CAP50超过此大小后精选启动索引
TETHER_FORGET关闭启用遗忘扫描
TETHER_FORGET_AGE_DAYS90符合淡出条件的最小存续天数
TETHER_FORGET_INTERVAL20两次扫描之间的写入次数
TETHER_FORGET_MAX_PER_SWEEP10单次扫描最多归档数量

关闭 TETHER_FORGET(默认值)且存储规模正常时,回忆功能和启动索引的行为与之前完全相同。

结晶化(可选,默认关闭)

启用 TETHER_CRYSTALLIZE=1 后,tether 会进行反思:检测相关记忆的密集集群,并提供给你命名。在反思过程中读取 tether://crystallization(它只支持主动拉取,不会自动加载)即可获取候选集群;使用 remember(..., crystallizes=[source_ids]) 为真正的原则命名——这会写入该原则并将其链接到源记忆——或使用 dismiss_cluster(id_a, id_b) 舍弃候选项。集群由显式链接 + 使用情况播种(语义相似性用于补全成员),因此找到的是*"这些内容属于一组"*这样的结构,而不只是主题相似性。tether 找出结构;你的 Agent 负责措辞。

结晶化的原则会成为启动索引的枢纽,并可在回忆时从其源记忆访问。注意:这会使「已命名」成为与「已使用」和「已链接」并列的第三种重要性信号——这是刻意设计的,因为 Agent 认为某条内容值得成为原则,本身就是一个强烈信号。

工具

工具功能
remember(type, title, body, tags?, links?, crystallizes?)保存一条记忆;按 type+title 执行插入或更新,让事实不断完善而非重复。crystallizes=[ids] 会将其写成基于这些来源的原则(需要 TETHER_CRYSTALLIZE)
recall(query?, type?, limit?, budget?, session?, tags?, id?, full?)先进行关键词与语义混合搜索,再沿使用关系图查找相关记忆;返回 id/type/title/body/tags/updated_at 以及 via 凭据。body 是以查询为中心的摘录——参见摘录——使用 id=N 可获取一条完整记忆。tags 是精确匹配筛选条件(记忆必须包含列出的所有标签);可与 query 组合使用,也可省略 query,以确保完整查找符合标签的记忆
link(id_a, id_b)在两条记忆之间建立双向链接
forget(id)软删除一条记忆:通过与整合相同的可逆 valid_to 机制,将其标记为不再有效(不纳入回忆或启动索引),而不是删除该行。有关真正永久删除,请参见导出和永久删除
dismiss_cluster(id_a, id_b)反思控制(结晶):丢弃由峰值边 (id_a, id_b) 形成的候选集群,使其不再重新出现。这不是记忆操作;仅在启用 TETHER_CRYSTALLIZE 时相关

此外还有三个资源:自动加载的 tether://memory-index(每次会话中显示的紧凑索引,每条记忆占一行)、仅供读取的 tether://status(运行时配置:语义/同步状态、记忆和边的数量、数据库路径——用于调试当前实际启用的内容),以及启用 TETHER_CRYSTALLIZE 时仅供读取的 tether://crystallization(用于反思流程的候选集群)。

摘录

recall 返回每条记忆正文中以相关性为中心的摘录,而非全文——窗口以出现的第一个查询词为中心,因此你能看到记忆为何匹配,而不只是开头几行。被截断的命中还会附带 truncated: true 和 body_chars(正文的实际长度);你可以用 recall(id=N) 获取需要查看的那条完整记忆。

这就是搜索引擎的结果形式:结果列表是指针索引,包含足以判断相关性的文本,而不是文档载荷。这一点很重要,因为记忆可能很大——一条 44KB 的日志记忆,会让无关查询每次调用耗费约 57–67KB,而检索本身耗时不到一毫秒。臃肿的是响应,不是引擎:

查询完整正文摘录
seed dominance57.0KB1.4KB
hebbian edges66.9KB2.0KB
cold start latency66.9KB2.0KB

短于摘录宽度的记忆会像以前一样完整返回,且不标记为截断。

变量/参数默认值作用
TETHER_EXCERPT_CHARS500摘录宽度;设为 0 时返回完整正文
id(每次调用)—仅获取这条记忆的全文
full(每次调用)false返回每条命中的完整正文——会产生完整载荷的开销;优先使用 id=

性能与持久性

tether 旨在 Agent 的循环中隐形运行,因此我们会测量关键路径的性能,并确保其开销不会随存储规模增长而明显增加。以下数据来自启用了语义层和关联层的本地 SQLite 存储,运行在单进程中:

记忆数量rememberrecall(罕见词项)recall(出现在大多数记忆中的词项)
5001.6 ms1.8 ms3.7 ms
2,0001.8 ms2.5 ms7.7 ms
8,0003.4 ms1.0 ms19 ms

以下几点有助于实现这一效果:

  • 写入开销不会随存储规模增长。 用于语义搜索和邻居连接的嵌入矩阵保存在内存中,每次写入时逐行更新,而不是从 SQLite 重新读取。只有在向量整体发生变化(例如更换模型、回填数据),或有其他进程写入文件时(例如执行 CLI purge、启动第二个服务、同步拉取数据),才会重建矩阵;SQLite 的 data_version 计数器会检测这些变化。
  • 并行工具调用会被串行处理。 MCP 会在各自的线程中运行每个工具调用,而 Agent 会并行发起调用。所有 Store 操作都使用同一把锁,因此同时到达的 recall 和 remember 各自都是原子的:事务不会交错,不会出现只提交了一半的写入,而且 action 始终准确。
  • 提交时不会执行 fsync。 本地连接使用 WAL 和 synchronous=NORMAL:仍可防止数据损坏,但如果机器在检查点之前断电,最后几笔事务可能会丢失(应用程序崩溃不会丢失任何数据)。每次 remember 都会提交;启用图时,每次 recall 也会提交,因此每次调用都能省下一次磁盘同步。
  • 搜索开销很低。 向量搜索是对内存矩阵执行一次 numpy 矩阵乘法;即使有数千条记忆,也远低于 1 毫秒,因此无需安装向量索引扩展。关键词搜索的开销取决于 FTS5,与匹配查询的记忆数量成正比。

首次启动的开销:安装 [semantic] 附加组件后首次启动(或更换模型后),系统会为每条现有记忆生成嵌入并连接其邻居,每几千条记忆需要一两秒。启动索引和仅按标签查找都会在每次调用时扫描存储;在常见规模下,两者都很快(2,000 条记忆时低于 10 ms),也是接下来要缓存的项目。

基准测试

bench/ 中有两个测试工具,都无需 API 密钥即可运行:

  • python -m bench.locomo — 在 LoCoMo 上进行仅评估检索的测试。该数据集包含十段较长的多会话对话,每段约有 1,500 个问题,并标注了回答问题所需的对话轮次。每个对话轮次都会成为一条记忆;评分依据是 recall(question) 是否返回这些轮次(recall@k、MRR),并分别评估仅关键词、关键词 + 语义、完整关联路径三种条件,同时与教科书式 BM25 基线比较。不涉及 LLM,因此该分数衡量的是记忆层能够控制的一件事——它是否向 Agent 提供了正确的事实——不能与记忆服务商在同一数据集上发布的、由 LLM 评判的“准确率”数据相提并论。首次使用时会下载数据(约 1.5 MB)。安装 [semantic] 附加组件,即可使用真实模型测试语义和关联条件。
  • python -m bench.run — tether 自带的关联式回忆评估:使用一组受控任务语料,其中的任务成员会被一起使用;在模拟使用后,测量使用图相较于关键词 + 语义搜索带来的增益。需要 [semantic] 附加组件。

导出和永久删除

forget 永远不会删除数据,而是像整合一样进行软删除。两项管理操作被刻意排除在 MCP 工具之外,防止 Agent 触发它们;它们仅在一个小型命令行工具中提供:

tether export                    # dump all current memories to JSON (stdout)
tether export -o backup.json     # ...or to a file
tether import backup.json        # merge an export back into the store
tether restore <id>              # un-forget a soft-deleted memory
tether purge <id> --yes          # permanently delete a memory (bypasses forget)

import 会通过常规写入路径重放记录,因此会像 remember 一样按 type+title 执行插入或更新——导入到非空存储时会合并,而不是重复创建。不会保留 ID(文件中的 ID 在此处可能映射为其他 ID);链接会相应重新映射,指向文件之外的链接则会被丢弃,而不是指向错误的记忆。报告会告知处理结果:{"created", "updated", "skipped", "linked", "dropped_links"}。

restore 会清除 valid_to,撤销 forget(或整合、遗忘清理)的操作。如果更新的记忆后来已占用相同的 type+title,它会拒绝恢复,并指出冲突项,而不是含糊地失败。

没有 --yes 时,purge 会拒绝运行。所有命令都使用与服务相同的 TETHER_DB/TETHER_SYNC_* 环境变量。

许可证

MIT

评论

支持 Markdown

第一次接触 MCP?

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

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