mcpField
K
Keepfor.me

Keepfor.me

远程服务
keepfor.me生产力02 天前更新

关于 Keepfor.me

Keepfor.me 是面向需要保存和整理网页及笔记,并向 AI Agent 开放内容的稍后阅读型个人图书馆。它结合持久网页快照与关键词、语义混合搜索。

主要功能

  1. 01保存网页、笔记和片段
  2. 02关键词与语义混合搜索
  3. 03保存原始及清理后的快照
  4. 04管理标签、高亮和集合
  5. 05从回收站恢复条目

适用场景

  1. 01保存文章以便稍后阅读
  2. 02按主题搜索个人图书馆
  3. 03让 Agent 阅读和整理已保存内容
  4. 04恢复误删的图书馆条目

MCP 相关

在 `/api/mcp` 提供远程、无状态的 Streamable HTTP MCP 服务,并通过 Bearer Personal Access Token 验证。其工具支持保存、搜索、阅读、标记和管理图书馆条目。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://app.keepfor.me/api/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

全部服务地址
Streamable HTTPhttps://app.keepfor.me/api/mcp需要授权

工具

详细介绍

Keepfor.me

Release Tests Security Runtime FastAPI Protocol License 支持此项目

一款轻量、快速的稍后阅读和个人资料库应用,完全运行于 Cloudflare Python Workers、使用 FTS5 的 D1 SQLite、Vectorize、R2 和 Model Context Protocol(MCP)。


功能

  • 四项核心任务:与 AI Agent 一起捕获、存储、搜索和分享。
  • Python 边缘运行时:由 Cloudflare Python Workers(Pyodide)上的 FastAPI 提供支持。
  • 可安装的 PWA 和原生分享:可在 Android 和 iOS 上添加到主屏幕。在 Android 上,原生 Web Share Target 可直接集成到系统分享面板中。在 iOS 上,只需轻点 1 次,Apple Shortcuts 即可使用你的 Safari 会话集成到系统分享面板中,并配合 PWA 中的智能剪贴板检测。
  • 无干扰阅读器:可自定义主题(浅色、复古纸张色、深色)、字体(无衬线、衬线、等宽)和字号。
  • 混合搜索:通过倒数排名融合(RRF),结合 D1 FTS5 BM25 关键词匹配和 Vectorize 语义嵌入(bge-base-en-v1.5)。FTS 和嵌入调用并发运行,且向量检索路径设有时间限制,因此 AI 绑定运行缓慢时会降级为仅关键词搜索,而不会一直卡住。
  • 可靠的内容提取:使用 trafilatura 自动解析正文,并在失败时回退到 OpenGraph 元数据,确保书签不会丢失。与浏览器一致的请求标头,以及可选的阅读器代理回退(通过 READER_PROXY_BASE 配置,默认关闭),可访问许多设有机器人防护墙的来源(HTTP 403)。
  • 清晰可见的提取状态:每个条目都会显示 Extracting…、内容或失败原因(例如 HTTP 403),而不是悄无声息地卡住。批量导入会通过队列分发,不会阻塞请求。
  • R2 中的双快照:原始 HTML 快照(raw.html)和经过净化的阅读器 HTML(clean.html)。
  • 移至回收站,而非丢失数据:从界面或 Agent 删除条目时,会将其移至回收站,而非彻底销毁。条目行、快照和向量都会保留,因此可立即恢复;在回收站视图中选择永久删除是唯一的永久删除方式,定时清理任务会在 30 天后清空回收站。
  • 零配置单租户锁定:首次注册会自动获得管理员所有权,并禁止外部用户注册。
  • Model Context Protocol(MCP):位于 /api/mcp 的远程 Streamable HTTP 服务(无状态,使用 Bearer PAT 进行身份验证),可供 opencode、Claude Desktop 和 Cursor 使用,无需本地安装。
  • 即时浏览器捕获:可拖放的 JavaScript 书签工具,以及未打包的 Manifest V3 扩展。
  • 导入与导出:导入 Pocket、Instapaper、Omnivore 和浏览器书签导出文件(Netscape HTML 和 CSV)。保留 Chrome 文件夹名称作为标签。可从 Google Keep Takeout 压缩包、Evernote .enex 文件和Markdown/文本文件压缩包(Obsidian vault、通过 Exporter 导出的 Apple Notes、Simplenote)导入笔记:保留标签和原始日期,笔记中的链接会作为普通保存项处理,附件会列出但不会存储,重复导入不会产生重复项(压缩包和 .enex 的上限为 50 MB,HTML/CSV 的上限为 10 MB;压缩包内每个文件上限为 2 MB,总计上限为 200 MB、最多 20,000 个文件,因此会拒绝解压缩炸弹)。每次笔记上传都会保留一条状态记录,记录进度和最终计数(导入的笔记数、跳过的重复项、排队的链接、未导入的附件、解析错误、因计划限制跳过的项目),并保存数量受限的错误消息列表,因此刷新后仍可查看结果。
  • 移动设备优先的界面:手机上提供底部标签栏和标签条,触控目标 ≥32px,在宽度低至 360px 时也不会出现水平溢出。

架构概览

flowchart LR
    Browser["Web UI / PWA / Share Sheet"] -->|FastAPI| Worker["Cloudflare Python Worker"]
    Claude["Claude Desktop / MCP Agents"] -->|Streamable HTTP + Bearer PAT| Worker

    Worker -->|Queries & FTS5| D1[("D1 Database")]
    Worker -->|Enqueue job| Queue["Cloudflare Queue"]
    Queue -->|Process batch| Worker
    Worker -->|Raw & Clean HTML| R2[("R2 Storage")]
    Worker -->|Embeddings| WAI["Workers AI"]
    Worker -->|Upsert vectors| Vec[("Vectorize")]
提取生命周期

保存 URL 会插入一条 status='queued' 的记录并将任务加入队列;队列消费者会获取内容、提取内容、存储快照,并将状态更新为 ok 或 failed,同时记录失败原因。失败状态始终会显示在 UI 和阅读器中。

两项经过深思熟虑的设计选择:

  • 未绑定队列 → 内联提取。 本地开发和测试环境没有队列消费者,因此 save_item 会同步提取,而不会让条目永远卡在 queued 状态。
  • 批量导入绝不内联执行。 导入 900 个书签会在一次请求中产生数千次 D1 写入;因此,系统会将任务拆分为每批 25 个书签的队列消息,或者在未绑定队列时使用后台任务。

如果消息丢失,可以通过 Settings → Re-queue stuck items 为卡在 queued 状态的记录重新发送任务(跳过刚加入的记录,以免重复发送仍在处理的消息)。

回收站与恢复

删除不会销毁数据。MCP delete_item 和 DELETE /api/items/{id} 会设置 items.deleted_at,仅此而已:记录、R2 快照和向量嵌入都会保留,因此 Agent 无法销毁知识库数据。已移至回收站的条目在恢复之前不会显示在任何地方(知识库、搜索、MCP 读取、计数、导出)。

回收站视图(/trash)会列出这些条目,并提供两个操作:Restore 可将条目恢复到知识库,Delete forever 是唯一的永久删除方式。主机也可以自行运行定期清理任务:

from keepfor.models.items import purge_trash

# Hard-deletes trashed items older than 30 days (row, snapshots, vectors).
await purge_trash(db, env, user_id=None, older_than_days=30)

# A multi-tenant host passes the tenant scope: it carries the R2 prefix
# and the Vectorize namespace of the tenant. An unscoped call is refused.
await purge_trash(db, env, user_id=None, older_than_days=30, scope=scope)

不会在用户不知情的情况下删除任何内容:如果没有调度器,回收站只会不断增长。

阅读器代理回退(READER_PROXY_BASE)

默认情况下,Keepfor.me 不会将获取失败的请求转发给任何第三方服务。当源站拒绝直接获取(HTTP 403、429、530)时,该条目会记录为失败。

如需启用阅读器代理回退(例如使用 Jina Reader 或可自托管的 readability 代理):

  • 在 wrangler.jsonc 中配置 READER_PROXY_BASE(vars.READER_PROXY_BASE = "https://r.jina.ai/"),或在 .dev.vars 中配置。
  • 隐私声明:启用后,被拦截文章的 URL 会传输到配置的代理服务。根据 SSRF 出站策略,严格禁止访问私有 IP 范围(例如 127.0.0.1、10.0.0.0/8、192.168.0.0/16)和本地域名,这些地址永远不会转发给任何阅读器代理。

有关私有部署、离线部署和出站策略的完整指南,请参阅 docs/self-hosting.md。


部署

1. 前置条件
  • Node.js 20 或更高版本以及 npm
  • uv 0.12.3 或更高版本
  • 已启用 Workers、D1、R2、Vectorize 和 Queues 的 Cloudflare 账户
  • 自定义域名:keepfor.me(或标准的 *.workers.dev 子域名)
2. 配置 Cloudflare 资源

运行以下命令一次,以创建 D1 数据库、R2 存储桶、Vectorize 索引和队列:

# 1. Create D1 Database
npx wrangler d1 create keepfor-me-db
# Copy the returned database_id into wrangler.jsonc

# 2. Create R2 Bucket
npx wrangler r2 bucket create keepfor-me-bucket

# 3. Create Vectorize Index (768 dimensions for bge-base-en-v1.5)
npx wrangler vectorize create keepfor-me-index --dimensions=768 --metric=cosine

# 4. Create Queue
npx wrangler queues create keepfor-me-queue
3. 应用数据库迁移

应用初始架构(表、FTS5 虚拟表、索引):

npx wrangler d1 migrations apply keepfor-me-db --remote

本地测试时:

npx wrangler d1 migrations apply keepfor-me-db --local
4. 部署

部署需手动进行:自托管用户通过 pywrangler deploy 或 GitHub Actions workflow_dispatch(输入 confirm: "deploy")部署到自己的 Cloudflare 账户。推送到 main 不会自动部署。

警告

D1、R2 和 Vectorize 绑定在 wrangler.jsonc 中设置了 "remote": true。切勿使用 wrangler.jsonc 运行本地开发,因为它会直接与远程资源交互。若要进行本地模拟,请将 wrangler.local.example.jsonc 复制为 wrangler.local.jsonc,然后运行 uvx --from workers-py pywrangler dev --config wrangler.local.jsonc。

PyWrangler 会打包 pyproject.toml 中声明的 Python 依赖。

# Always dry-run first and check the "Total (N modules)" row: the deploy
# hard-fails if the bundle exceeds 64 MiB.
uvx --from workers-py pywrangler deploy --dry-run

uvx --from workers-py pywrangler deploy

健康的打包文件大约为 52,000 KiB / ~4,500 个模块。如果模块表中出现 .venv-workers/ 路径,说明构建虚拟环境正在被打包,部署距离失败只差一次依赖升级。

部署完成后,访问你的域名(例如 https://app.keepfor.me 或 https://keepfor-me.<your-subdomain>.workers.dev)。第一个注册的用户会自动成为管理员,并关闭公开注册。

5. 自定义域名

wrangler.jsonc 声明了 app.keepfor.me 的路由。创建一次 DNS 记录(Cloudflare 控制面板 → DNS → 添加记录):

类型名称内容代理
Aapp192.0.2.1已代理(橙色云朵)

Worker 路由会在访问 IP 之前匹配,因此占位地址可以正常使用。workers_dev 保持启用状态,因此 *.workers.dev URL 仍可使用。


连接 AI Agent(远程 MCP)

Keepfor.me 在 https://app.keepfor.me/api/mcp 托管了一个远程 Streamable HTTP MCP 服务,提供 42 个工具,用于捕获、查找、阅读和标记你的资料库:

  1. save_url:将任意网页保存到你的资料库。
  2. save_urls:一次调用即可将多个网页保存到你的资料库,并为每个 URL 返回状态。
  3. save_note:保存笔记、片段或提示词模板。
  4. search_library:跨文本内容和含义进行混合搜索。
  5. search_passages:搜索段落,并提供永久快照 URL。
  6. find_item:按标题或 URL 查找项目 ID(不搜索,也不使用嵌入)。
  7. get_item:按 ID、URL 或精确标题读取元数据和摘要。
  8. read_item:分页读取全文。
  9. list_items:使用排序和筛选条件分页浏览精简内容。
  10. reading_history:查看你保存和打开过的内容,并可按日期筛选。
  11. related_items:查找与指定项目或文本相似的项目。
  12. list_tags / create_tag / describe_tag / update_tag / rename_tag / merge_tags / delete_tag:完整的标签管理功能。
  13. tag_item / tag_items / set_item_tags / retag_by_query:安全地添加标签,支持批量操作(默认仅试运行)。
  14. bulk_update:更新所有符合筛选条件的项目的状态、置顶状态和标签(默认仅试运行)。
  15. suggest_tags / search_tags / tag_stats / related_tags / tag_cleanup:标签词汇工具。
  16. find_cleanup:只读的清理报告(重复 URL、失效链接、长期未打开的旧项目、未加标签的项目、近似重复的标签)。
  17. delete_item / pin_item:移除或置顶项目。
  18. library_digest:精简摘要 — 保存内容、打开内容、热门标签和未读重点。
  19. create_highlight / list_highlights / delete_highlight:引用项目中的段落,并通过字符偏移定位。
  20. create_collection / list_collections / add_to_collection / remove_from_collection / rename_collection / delete_collection:用于归纳资料库项目的命名集合。
  21. get_account:查看你的套餐、试用结束时间和剩余配额 — 此工具免费,因此即使配额用尽仍会响应。

该服务无状态(没有会话,返回普通 JSON 响应,不使用 SSE 流),并使用与 REST API 相同的个人访问令牌进行身份验证。

设置
  1. 在 Keepfor.me 界面中前往 设置与 API。
  2. 点击 生成令牌,创建个人访问令牌(kfm_live_...)。如果 Agent 只需浏览和搜索资料库,请在权限范围选择器中选择 只读。
  3. 将客户端指向该端点,并在 Bearer 标头中传入令牌:

opencode(opencode.json):

{
  "mcp": {
    "keepfor-me": {
      "type": "remote",
      "url": "https://app.keepfor.me/api/mcp",
      "headers": { "Authorization": "Bearer {env:KEEPFOR_ME_TOKEN}" }
    }
  }
}

然后在启动 opencode 前执行 export KEEPFOR_ME_TOKEN=kfm_live_...,并在更改配置后重启 opencode。

**Cursor / Claude Desktop:**添加自定义远程 MCP 服务,URL 为 https://app.keepfor.me/api/mcp,并设置标头 Authorization: Bearer kfm_live_YOUR_TOKEN_HERE。

无需任何客户端即可检查握手:

curl https://app.keepfor.me/api/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H "Authorization: Bearer kfm_live_YOUR_TOKEN_HERE" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
可用的 MCP 工具(服务端 0.2.0)

MCP 服务提供 42 个工具。可一次更改多个项目的工具带有 dry_run 标志:该标志只接受 JSON 布尔值(省略时默认为 true,即预览),其他任何值都会被拒绝,而不会执行更改。

  1. save_url — 将任意网页保存到你的资料库。可选接受 agent_summary、why_saved、source_context、saved_by,用于记录 Agent 研究来源。
  2. save_urls — 一次调用最多将 50 个网页保存到你的资料库,并为每个 URL 返回状态(queued、exists、invalid、over_limit)和总数。需要写入权限范围。URL 会按规范 URL 去重;每个新 URL 都会经过与 save_url 相同的保存检查(保存限额拒绝的 URL 会返回 over_limit);提取任务会进入队列,因此调用不会等待网页处理完成。
  3. save_note — 保存个人笔记、代码片段或提示词模板。可选接受相同的来源记录字段。
  4. search_library — 基于文本和含义进行混合搜索(返回带摘要的条目级结果)。
  5. search_passages — 在语义分块中进行段落级混合搜索,并支持 max_chars 字符数预算。返回 chunk_id、字符偏移量和永久 snapshot_url(R2 存档),即使原链接失效也可访问。
  6. read_item — 以节省令牌的方式分页读取完整内容。返回 text、next_cursor、total_chunks、outline。
  7. get_item — 通过 item_id、url 或精确的 title 获取元数据和摘录。默认将 content_text 限制为摘录,并报告 truncated 和 content_length;使用 include_content=true 可获取全文。
  8. list_items — 简洁地分页浏览条目(id、title、url、saved_at、tags——不含正文)。按 saved、opened 或 title 排序;可按 since/until、domain、pinned、type 和标签筛选。
  9. find_item — 按精确/前缀标题或精确/规范化 URL 查找条目 ID。不进行搜索,也不使用嵌入:这是从已知标题获取可读取的 item_id 的快捷方式。
  10. reading_history — 阅读历史记录,支持按日期(since/until)、事件类型(saved/opened)筛选,并可选按查询词/标签筛选。
  11. related_items — 根据 item_id 或原始 text,通过向量相似度查找最近邻条目,并附上一行原因说明。
  12. list_tags — 列出每个标签及其条目数和最后使用日期。按 count、name 或 recent 排序;可按 prefix 和 min_count 筛选。
  13. create_tag — 创建标签,可选设置 description、color 和 parent(层级结构,例如 work/research)。
  14. describe_tag — 获取标签的元数据、父级、子级和条目数。
  15. update_tag — 编辑标签的描述、颜色或父级。
  16. rename_tag — 重命名标签;所有带有该标签的条目都会更新。
  17. merge_tags — 将多个标签合并到一个目标标签中(每次调用最多 20 个源标签)。
  18. delete_tag — 从条目中移除标签。不会删除条目。默认 dry_run=true:返回受影响的数量和样例;dry_run=false 时执行操作。
  19. tag_item — 为单个条目添加或移除标签。
  20. tag_items — 为多个条目添加或移除标签。默认 dry_run=true。每次调用最多处理 100 个条目;结果会报告 total_matched 和 truncated。
  21. retag_by_query — 为符合标题/URL 查询条件(以及标签筛选条件)的条目添加标签。默认 dry_run=true。每次调用最多处理 100 个条目;结果会报告 total_matched 和 truncated。
  22. bulk_update — 更新符合筛选条件(状态组、保存日期范围、域名、置顶状态、类型、标签)的所有条目的状态、置顶状态和标签。默认 dry_run=true:仅报告 total_matched、affected 和 truncated,不会写入任何更改。每次调用最多更新 200 个条目;空筛选条件或空更改会被拒绝。所有更新都在一个事务中执行,标签名称遵循 create_tag 规则(由 2–64 个 a-z、0-9、空格、_ 或 - 字符组成)。
  23. set_item_tags — 替换单个条目的全部标签。
  24. suggest_tags — 为条目或自由文本推荐标签,并优先从你现有的词汇表中选取。
  25. search_tags — 模糊搜索标签名称和描述(machinelearning 可找到 machine-learning)。
  26. tag_stats — 资料库的标签使用统计信息。
  27. related_tags — 查找与某标签同时出现在相同条目中的标签。
  28. tag_cleanup — 查找值得检查的近似重复标签、未使用标签和未加标签的条目。
  29. find_cleanup — 只读清理报告:重复条目(规范化 URL 相同)、失效链接(记录的提取失败——不发送网络请求)、从未打开的旧条目、未加标签的条目和近似重复标签。接受 categories、older_than_days 和每个类别的 limit(最大值为 100);每个类别都会报告候选项、数量和 truncated 标志。条目类别会为每个条目列出一个 ID 和原因;分组类别会为每个分组列出一项——duplicates 会给出该组的 ID(最多 10 个)、组内数量以及 ID 列表是否被截断,near_duplicate_tags 会给出该组的标签名称。因此,limit 限制的是分组数量,即使同一个 URL 保存了 300 次,响应也依然简洁。
  30. delete_item — 将条目移至回收站。条目会离开资料库,但不会被销毁:30 天内仍可恢复,且只有用户能在回收站视图中将其永久删除。
  31. pin_item — 将条目置顶或取消置顶。
  32. library_digest — 只读回顾一段时间内的资料库情况:保存数、打开数、热门标签和未读精选内容。可选接受 since、until 和 tag;响应中的每个列表都有数量上限。
  33. create_highlight — 引用条目中的一段内容,并用该段在 content_text 中覆盖的字符偏移量进行定位。start_offset 默认为 0,end_offset 默认为 start_offset + len(text);如果结束偏移量超出条目内容末尾,则会被拒绝。
  34. list_highlights — 列出单个条目的所有高亮内容,按其在文本中的位置排序,并附上引用文本、偏移量、可选备注和颜色。
  35. delete_highlight — 移除一个高亮内容。其所属条目不会被删除。
  36. create_collection — 创建一个命名集合,用于收纳资料库条目,并可选添加描述。若名称已存在,则原样返回该集合。
  37. list_collections — 列出你的集合及其条目数和条目 ID(每个集合最多列出 20 个条目;条目更多时会显示 items_truncated)。
  38. add_to_collection — 将条目加入集合,可通过名称或 ID 指定集合。每次调用最多处理 100 个条目;结果会报告 added、skipped 和 truncated。
  39. remove_from_collection — 将条目从集合中移除。条目本身不会被删除。
  40. rename_collection — 重命名集合。若新名称已被占用,则会拒绝操作,不会合并集合。
  41. delete_collection — 删除集合及其关联关系。集合中的条目不会被删除;请使用 remove_from_collection 清空集合。
  42. get_account — 只读查看你的账户信息:套餐、trial_ends_at 以及每种计量操作的配额(limit、used、remaining、resets_at)。此调用免费,不消耗配额单位,因此即使配额耗尽也能返回结果。 所有工具都声明了 MCP 注解(readOnlyHint、destructiveHint、idempotentHint)。这些是提供给客户端的提示,服务端会用它们来强制执行令牌的作用域(见下文)。令牌不会因缺少作用域信息而被拒绝:没有作用域信息意味着拥有完整访问权限。每个工具的说明都会指出何时应使用该工具,而不是它的同类工具。列表类型的响应包含 limit、offset/cursor 和 fields 投影;默认的 list_items 页面大小保持在 4 KB 以内。

标签筛选器(tags_all、tags_any、tags_none、untagged)适用于 list_items、search_library、search_passages、find_item、reading_history 和 bulk_update,并会统计子标签:筛选 work 也会匹配 work/research。

MCP 资源和提示词

该服务还支持 MCP 规范中的资源和提示词部分,身份验证和租户范围与工具相同。

资源 — 以只读方式查看你自己的知识库:

URI内容
keepfor://item/{item_id}一篇已保存的文章或笔记:元数据、标签和存储的文本(最多 20,000 个字符;若内容被截断,truncated 会说明)。
keepfor://tag/{name}你的一个标签及带有该标签的项目(最多 50 个;若还有更多,items_truncated 会说明)。

resources/list 会返回你最近的项目和最常用的标签,resources/templates/list 会返回两个 URI 模板,resources/read 会以 JSON 格式返回内容。

提示词 — 可重复使用、用于读取你自己的数据的模板:

提示词参数功能
research_brieftopic(必需)、max_items向助手简要介绍你已保存的相关主题内容,让研究会话从你的知识库开始。
weekly_reviewdays、tag回顾你过去几天保存的内容,并请助手总结以及推荐接下来阅读的内容。
令牌作用域(只读令牌)

个人访问令牌可以限制为只读。在设置与 API 中创建令牌时,使用令牌名称旁边的作用域选择器(默认值为完整访问权限):

  • *(全部) — 默认值。所有工具均可使用,与之前完全相同。
  • read — 通过 MCP,该令牌在 tools/list 中只能看到读取工具;任何写入或破坏性工具(save_url、save_note、tag_item、create_tag、update_tag、rename_tag、merge_tags、delete_tag、tag_items、retag_by_query、bulk_update、set_item_tags、delete_item、pin_item、create_highlight、delete_highlight、create_collection、add_to_collection、remove_from_collection、rename_collection、delete_collection)都会被拒绝,并返回 JSON-RPC 错误(error.data.type = insufficient_scope),且拒绝发生在执行之前——不会写入任何内容。

作用域功能推出前创建的令牌仍保留完整访问权限:其存储的作用域为 NULL,表示“全部”。无论令牌用于何处,都会强制执行作用域:通过 MCP 使用时,每个工具都需要其注解声明的作用域;通过 REST 使用时,只读令牌在每个写入路由上都会收到 403。例外是只读 POST 路由 /api/search 和 /search:搜索属于读取操作,因此只读令牌可以使用这些路由。/api/mcp 会按工具强制执行作用域。PAT 完全不能用于 /settings/*,因此令牌永远无法创建权限更广的令牌。

自托管用户:作用域列来自迁移文件 0012_pat_scopes.sql,因此请在部署前应用迁移(上文第 3 步)。


浏览器与移动设备捕获

1. Android(PWA + 系统分享面板)
  1. 在 Chrome 中打开你的域名,然后点按添加到主屏幕(或安装应用)。
  2. 如需在任何应用中保存内容,点按分享 → Keepfor.me — 原生 Web Share Target 会打开预填好的保存面板;向后滑动即可无缝返回你的应用。
2. iPhone 和 iPad(Apple 快捷指令与智能剪贴板)

iOS WebKit 会将 PWA 与系统分享菜单隔离。Keepfor.me 为 iOS 提供两种无需繁琐操作的保存方式:

  1. 一键 Apple 快捷指令(分享菜单):前往 设置与 API → iPhone 和 iPad 快速分享,然后点按 安装 Keepfor.me 快捷指令。这会在 iOS 分享菜单中添加一个原生操作,使用你现有的 Safari 登录会话直接将 URL 发送到 Keepfor.me(无需 API 令牌或技术配置)。
  2. PWA 智能剪贴板:在 Safari 中将应用添加到主屏幕(分享 → 添加到主屏幕)。在任意应用中复制链接,然后切换到 Keepfor.me PWA 时,浮动提示会检测剪贴板中的 URL,让你轻点一下即可保存。
3. 拖放书签小程序(桌面端)

前往 设置,将 Keepfor.me 按钮拖到浏览器的书签栏。点击它即可在任意页面打开快速保存对话框。

书签小程序始终显示通用地球图标。若要使用应用图标:为你的域名下任意页面添加书签,编辑该书签,将复制的代码(设置 → 复制代码)粘贴为其 URL,并将名称设为 Keepfor.me。

4. 浏览器扩展(Manifest V3)
  1. 打开 Chrome/Brave/Edge,并前往 chrome://extensions/。
  2. 启用 开发者模式(右上角)。
  3. 点击 加载已解压的扩展程序,然后选择 keepfor.me/browser-extension 文件夹。
  4. 点击扩展图标,在设置中(⚙️)输入一次 Worker URL 和 PAT 令牌,然后按 Alt+S 保存任意标签页。

本地开发与测试

安装项目及其测试依赖,然后运行 pytest 测试套件:

python3 -m pip install -e . pytest pytest-asyncio pytest-cov httpx
python3 -m pytest tests/ -q

请从仓库根目录运行 pytest——只有当根目录位于 sys.path 中时,keepfor 才能作为命名空间包解析。

按照 CI 的确切方式进行 lint 和格式化(单独运行 ruff check . 会使用不同的规则,并且会通过 CI 会拒绝的内容):

ruff check keepfor/ tests/ --select=E,W,F,I,N
ruff format --check keepfor/ tests/

使用其 Python 依赖项运行本地 Worker 预览:

uvx --from workers-py pywrangler dev

本地开发环境没有队列消费者,因此保存的链接会直接提取内容,并立即显示。

性能说明

冷启动是影响 Python Workers 感知延迟的主要因素:页面在预热时加载约需 250ms,但隔离实例启动时可能超过 1.5s。

  • 导入依赖图维护:大型文章解析器(trafilatura、bs4、lxml)会在提取代码中按需导入。回归测试会确保它们不会进入请求导入路径。
  • 并发搜索与 I/O:混合搜索会并发运行 D1 FTS 和 Workers AI 嵌入向量查询(asyncio.gather),并受 5s 超时限制。
  • D1 查询优化:复合索引((user_id, created_at DESC) 和 (user_id, status, created_at DESC))可消除 SQLite 内存临时 B-tree 排序文件(USE TEMP B-TREE FOR ORDER BY)。状态计数、信息流条目和标签聚合通过 asyncio.gather 并行执行;多语句标签和删除变更则通过 execute_batch 批量处理,以尽量减少 RPC 往返。

支持本项目

如果你觉得 Keepfor 很有用,可以支持其开发:

支持本项目

在 Stripe 上捐款支持 Keepfor(预设金额为 $5,也可自行选择金额)。


参与贡献

欢迎贡献!请阅读 CONTRIBUTING.md,了解开发工作流、测试和拉取请求流程的详情。

所有贡献者都必须签署我们的 贡献者许可协议(CLA)。你仍保留作品的版权所有权;该协议授予我们运营托管服务和提供商业许可证所需的许可。


许可证

Keepfor.me 采用 GNU Affero General Public License v3.0(AGPL-3.0-only)授权。

  • 自托管:你可以不受限制地将其自托管,用于个人或组织用途。
  • 网络服务:如果你修改 Keepfor.me 并通过网络将其作为服务提供,则必须根据 AGPL-3.0 发布修改后的源代码。
  • 商业授权:可应要求提供商业许可证和其他许可协议,以支持专有、企业或闭源部署。详情请参阅 LICENSING.md。
  • 此前的版本:许可证变更之前发布的版本仍采用 MIT License,已取得这些版本的用户可继续使用。
  • 商标:项目名称和标志受 TRADEMARK.md 约束。

评论

支持 Markdown

第一次接触 MCP?

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

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