关于 bookmarks-lifecycle
bookmarks-lifecycle 是用于整理浏览器书签的本地 MCP 服务,为希望逐步处理收藏内容的用户设置限时决策队列。它不会删除书签,所有状态变更均可撤销。
主要功能
- 01按 24 小时和 30 天期限管理决策
- 02书签按每日配额逐步进入待处理队列
- 03支持保留、观察、放弃与恢复
- 04记录状态历史并支持撤销
- 05从浏览器扫描并汇总书签
适用场景
- 01逐批清理长期积累的浏览器书签
- 02将书签标为观察或永久保留
- 03找回超时或已放弃的书签
- 04查看各状态数量和当日待办
MCP 相关
作为本地 MCP 服务,它通过工具和提示词让 MCP 客户端扫描、分类及管理书签。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
7收录的工具列表 · 更新于 3 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| source | string | 否 | 按浏览器("chrome"、"safari"、"firefox" 等)或 bookmarks-mcp 的 list_sources 中的来源 ID 进行筛选。省略则表示全部。 |
详细介绍
bookmarks-lifecycle
为已保存的书签设定生命周期。
保存很容易。你保存的内容几乎从未经过处理——只是不断累积。这是一个本地 MCP 服务,为每个书签设定一个时限:24 小时内做出决定,或者再观察 30 天,或者永久保留。内容永远不会被删除——超时后仍未做出决定的书签,只会离开你的注意力范围,不会从磁盘上消失;任何更改(包括 AI 做出的更改)都可以撤销。
Aggregates via bookmarks-mcp. Writes only its own local state file, atomically. No accounts, no cloud, no network calls.
模型
共有五种状态:
| 状态 | 含义 | 是否倒计时? |
|---|---|---|
inbox | 已汇总,尚未进入待决状态 | 否 |
pending | 24 小时层——今天实际要处理的清单 | 是 |
watching | 30 天层——“再给它一点时间” | 是 |
kept | 已决定:永久保留 | 否 |
lapsed | 已超时或放弃——完全可恢复,永不删除 | 否 |
aggregate → inbox
│ drip (up to N/day, oldest first)
▼
pending ──you decide──→ watching / kept / lapsed
│
└──24h, no decision────────────→ lapsed
▲
watching ──30d, no decision───────────┘
└──you decide──→ kept
lapsed ──restore──→ pending (clock resets)
any state ──undo (by history event)──→ whatever it was right before that event
在 pending 状态下,你可以选择三个结果中的任意一个。在 watching 状态下,唯一可做出的决定是 keep——这与上述模型相符;若要撤销 watch 或 drop 操作,请使用 undo,而不是重新决定一个已经进入下一状态的书签。
汇总书签时,它们不会全部立刻进入 pending——否则,一次性导入 3,000 个旧书签会让它们在同一天全部超时,这套机制也就毫无意义了。它们会按每日配额逐步进入(默认每天 15 个,最早的优先;如果来源提供了真实保存日期,则按该日期排序)。每次调用工具时都会惰性计算,不使用后台计时器,而且离开期间的配额不会累积:无论你离开了多少天,一次调用最多只会推进一天的配额。每天访问一次,要清理 3,000 个书签的积压,现实中需要数月——这是“没有提醒,除非你主动调用,否则什么都不会运行”的坦诚取舍,并不意味着它能取代帮助你养成习惯的应用。
安装
无需账户、API 密钥或配置——安装后即可使用。
Claude Code:
claude mcp add -s user bookmarks-lifecycle -- npx -y bookmarks-lifecycle
Claude Desktop / Cursor / 任意 MCP 客户端(mcpServers JSON):
{
"mcpServers": {
"bookmarks-lifecycle": {
"command": "npx",
"args": ["-y", "bookmarks-lifecycle"]
}
}
}
若要改为从源代码运行(用于开发),请将 parse-bookmarks、bookmarks-mcp 和本仓库克隆到同级目录,在 bookmarks-mcp 中运行 npm install,然后在 bookmarks-lifecycle 中运行,再将客户端指向 node /absolute/path/to/bookmarks-lifecycle/src/index.js。
请使用 -s user。 如果不使用该参数,范围默认是 local,这会使服务仅注册到你运行命令所在的目录——你必须进入该目录,助手才能看到它。你的书签与你当前所在的代码项目无关,因此应将它注册一次,供整个账户使用。
配置文件位置(适用于上述 JSON 配置):
- Claude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.json(macOS) - Cursor:
~/.cursor/mcp.json(或项目级.cursor/mcp.json)
验证是否已连接:让助手调用 stats 工具,或查看客户端的 MCP/服务日志——如果 initialize 握手成功,且 tools/list 中包含 intake, today, decide, list_layer, restore, undo, stats,则说明服务已启动。
更改下方任何环境变量后,请彻底重启客户端与此服务的连接(退出并重新打开 Claude Desktop,或重启 Cursor MCP 进程)——客户端只会在启动时读取这些变量。
首次运行
如果你使用 macOS,并希望纳入 Safari 书签,则托管此服务的应用(Claude Desktop、你的终端、Cursor)需要完全磁盘访问权限(系统设置 → 隐私与安全性 → 完全磁盘访问权限)——~/Library/Safari 受到保护。没有该权限,intake 的响应会显示 "sourceStatus": "permission_denied",并在 warnings 条目中准确说明原因;它绝不会悄悄返回空结果。Chromium 浏览器和 Firefox 不需要额外权限。
先调用 intake——在此之前,today 不会显示任何内容。然后,today
会给你当天的实际队列。如果 intake 和 today 的返回结果都完全为空,且 sourceStatus 显示为 "ok",那就说明“你在扫描的来源中没有书签”——在认定出了问题之前,请先检查 sourceStatus:
sourceStatus | 含义 |
|---|---|
no_sources | 这台设备上甚至没有检测到受支持的浏览器 |
permission_denied | 至少有一个来源读取失败(常见情况:Safari 未获得完全磁盘访问权限) |
empty | 所有来源都已成功扫描,且确实有 0 个书签 |
ok | 扫描成功并发现了内容 |
明明能在浏览器中看到书签,却显示 no_sources? 此功能只会在各操作系统的标准安装位置检测 Chromium 浏览器(Chrome、Edge、Brave、Arc、Vivaldi、Chromium)。如果你的浏览器使用自定义配置文件或数据目录(单独的工作配置文件、便携式安装、重命名过的用户数据文件夹等),系统不会自动找到它:
- 在该浏览器中打开
chrome://version(edge://version、brave://version等——所有 Chromium 浏览器都有相同的页面),然后复制 Profile Path 旁边的值。 - 在 MCP 客户端中此服务的配置里,添加环境变量
CHROMIUM_BOOKMARKS_PATH,将其设为该路径并在末尾追加/Bookmarks,例如"/Users/you/Library/Application Support/BraveSoftware/Brave-Browser/Custom/Bookmarks"。 如果要包含多个配置文件,请用逗号分隔多个路径。 - 完全重启 MCP 客户端与此服务的连接(请参阅下方的配置)。
此说明不适用于 Safari——请参阅上文关于完全磁盘访问权限的说明。
如何使用
你无需亲自调用这些工具——由你的助手来调用。你只需交谈。如果希望有人引导你操作,可以运行一次 clean_up_my_bookmarks 提示词(在 Claude Code 中:/mcp;在 Claude Desktop 中:提示词菜单),它会帮你完成设置并带你操作一轮。
除此之外,直接用自然语言提出请求即可:
| 可以这样说 | 会发生什么 |
|---|---|
| “导入我的浏览器书签” | intake——扫描你的浏览器,并将新网址添加到收件箱 |
| “我今天该看些什么?” | today——当天的队列,按从旧到新的顺序排列,最多达到每日配额 |
| “保留第一个,删除最后两个” | decide——等你确认后再执行 |
| “等等,撤销刚才的操作” | undo——撤销任何决定,包括“保留” |
| “我放弃了哪些?” | 对 lapsed 执行 list_layer——内容仍全部保留 |
| “把那个还给我” | restore——将其放回队列并重新计时 |
| “还剩多少?” | stats——显示每个层级的数量,以及收件箱中仍在等待处理的内容 |
第一天有两点值得了解:
- 不会有任何提醒。 没有后台进程,也不会发送通知。只有你提出请求,队列才会变化——这也意味着它绝不会让你措手不及。
- 空结果会说明原因。 每条响应都包含
nextStep,告知你的助手应该建议什么,所以“0 项”不会让人摸不着头脑:它会说明你是否还没扫描、今天的批次是否已完成,或者是否有来源读取失败。
工具
| 工具 | 功能 |
|---|---|
intake | 扫描书签来源,将新书签合并到 inbox,并核对已移动或消失的书签 |
today | 查看当前 pending 层中的项目,按时间从早到晚排列——这是你的每日入口 |
decide | 判断一个或多个项目:keep / watch / drop |
list_layer | 分页查看任意单个层(默认每页 50 条),包括 lapsed(“我放弃了什么”) |
restore | 将 lapsed 项目移回 pending,并重置计时 |
undo | 将某个项目恢复到其自身某条历史事件发生前的状态——对 kept / watching 也有效,不限于 lapsed |
stats | 按层统计数量、今天的决定数,以及 inbox 中有多少项在等待处理 |
每个读取工具(today / list_layer / stats)都可能在调用时写入磁盘:
过期和滴入是延迟计算的,因此即使只是“看看”,也可能作为副作用使项目
在层之间移动。只有实际发生变更时才会写入——如果没有到期项,也没有
要滴入的项目,则调用不会改动任何内容。
此外还有两个提示词:
| 提示词 | 使用时机 |
|---|---|
clean_up_my_bookmarks | 第一次使用时。说明决定计时机制,运行 intake,并与你一起进行一轮简短分类。 |
daily_triage | 此后每天使用。运行 today → 为每个项目提供建议 → 等待你确认 → 应用建议。 |
intake 和 today 还会返回一个 nextStep 对象(code + why),
让你的助手知道接下来该建议什么,而不是根据空列表进行推断。这只是
操作指引,绝不会提升项目。
关于授权的坦诚说明
此服务无法验证标记为 "user" 的工具调用是否确实来自你的确认。
它收到的每个参数——包括 actorClaim: "user"——都来自 AI,且通过与
其他所有内容相同的通道传入。代码没有可供检查的独立可信通道。本 README
的早期版本曾声称“未经你同意,AI 无法操作”是服务端强制执行的保证;经测试
后已证明这不属实——AI 只要省略该字段或声称自己是 "user",就能不受阻拦地
通过。我们不会再重复这一说法。
实际情况如下:
- AI 是否必须先等你点击确认,才能调用会修改数据的工具,取决于你的 MCP 客户端自身的工具审批设置——Claude Desktop 和 Cursor 都提供按工具或按 会话的审批提示。这才是真正的把关机制,它由你的客户端负责,而非此服务。
- 除非你明确设置
BOOKMARKS_LIFECYCLE_AUTO_DECIDE=true,否则会拒绝actorClaim: "ai";但调用方可以直接省略该字段(记录为"mcp-client"), 或改为声称自己是"user",因此也不要将此机制视为安全边界。 - 此服务实际保证的是可撤销性。 每项变更——包括在
autoDecide下作出的 变更,包括过期和滴入——都可以撤销。restore会逆转lapsed → pending。undo可按历史事件逆转任何状态变更,包括kept和watching,并提供preview模式供你事先检查。如果 AI 做了你不想要的事,解决办法是undo, 而不是相信它不可能发生。 - 每次变更都会由
history记录by: "user" | "ai" | "mcp-client" | "drip" | "expiry" | "system"。前两项是声明,未经身份验证——请将其视为供你审查的线索,而非证据。
配置
所有配置都通过 MCP 客户端配置中的环境变量完成,无需修改此软件包的代码。更改这些配置后,请重启 MCP 客户端的连接。
| 变量 | 默认值 | 说明 |
|---|---|---|
BOOKMARKS_LIFECYCLE_PENDING_HOURS | 24 | 项目在 pending 层中停留的小时数;超过后,尚未决定的项目会失效 |
BOOKMARKS_LIFECYCLE_WATCHING_DAYS | 30 | 项目在 watching 层中停留的天数;超过后,尚未决定的项目会失效 |
BOOKMARKS_LIFECYCLE_DRIP_PER_DAY | 15 | 每天最多从 inbox 晋升到 pending 的项目数(间隔期间不会累积) |
BOOKMARKS_LIFECYCLE_AUTO_DECIDE | false | 是否允许声称 actorClaim: "ai" 的 decide/restore/undo 调用通过(参见关于授权的说明——这并非安全保证) |
BOOKMARKS_LIFECYCLE_STATE_DIR | ~/.bookmarks-lifecycle | state.json(及其锁定/备份文件)的存放位置 |
存储内容
一个文件:~/.bookmarks-lifecycle/state.json。采用普通 JSON 格式,可供人阅读。
写入是原子性的(临时文件 → fsync → 重命名,不会在崩溃时留下写入了一部分的文件),并且每次覆盖前都会将上一版本保存为 state.json.bak。
每条书签记录包含:id、url、title、已知的浏览器来源(同一 URL 在两个浏览器中保存时会保留两处来源)、浏览器记录的实际添加时间(addedAt,用于按时间从早到晚排序——若来源未提供则为 null,绝不会伪造)、当前生命周期状态、进入该状态的时间、每次状态变更的完整历史记录(每条记录都包含稳定的 eventId、时间、执行者/操作以及可选备注),以及 sourceGone 标记,用于标记在成功重新扫描的所有来源中都已找不到的书签(其记录仍会保留——此处绝不会自动删除任何内容;仅仅读取失败的来源不算作书签已消失的证据)。
只存储标识符和你自己的判断,绝不存储页面内容本身。文件中有一个内部 version;如果此工具的未来版本写入了当前版本无法识别的数据结构,当前版本会拒绝操作该文件,而不会自行猜测。
并发访问:如果两个 MCP 客户端(例如 Claude Desktop 和 Cursor)同时使用同一个状态文件运行此服务,锁文件(state.json.lock)会串行处理它们的操作——第二个客户端会短暂等待,而不是悄悄覆盖第一个客户端的更改。
时区
stats 中的“今天”(用于 decidedToday)采用运行此服务的机器上的本地日历日。由于此服务只会在你自己的机器上运行(它会直接读取本地浏览器文件——没有远程/托管部署),所以使用的正是你所在时区的时钟。这是有意如此,并非需要修复的错误。24h/30d 的层级时长采用严格的经过时间窗口,而非按日历日计数——夏令时切换会改变墙上时钟的时间,但不会改变实际经过的 24 小时长度。
保证
- **绝不操作浏览器书签文件。**读取工作完全交由
bookmarks-mcp处理,而它本身是只读的。此软件包写入的文件仅有自己的state.json、state.json.bak和临时锁文件。 - 绝不删除生命周期记录,并且每次状态变更都可撤销——具体有哪些保护、哪些不受保护,请参见关于授权的说明。
- 不进行网络调用、不收集遥测信息,也不需要账户。
设计边界
- 没有后台进程、没有 cron、没有推送通知。 这里的一切都在你调用工具的那一刻按需计算——这正是「无需守护进程」得以实现的原因。坦诚地说,代价是:如果你不主动来查看,队列就会悄悄过期。没人会提醒你。
- 没有界面。 它始终是 MCP 工具,而不是应用。
- 自带 AI。 此服务不执行推理,也不收费——用来评判你书签的 AI,就是你已经连接的那个。这个项目提供的是状态机和提示词,而不是模型。
谁在打造它
由 Burn 451 背后的团队打造——这里的 24 小时 / 30 天机制以 Burn 为蓝本。不同之处在于:此工具只会在你主动调用时运行,而且就在你正在工作的地方。如果你希望以同样的理念自动运行、每天提醒你,并且能通过手机访问,那就是 Burn 的用途——无论如何,这个项目本身也依然实用。
许可证
MIT
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。