关于 Purl
Purl 是面向希望集中整理和分享有用网址的链接管理服务。它可识别网页、PDF、YouTube 视频和音频,并通过应用、REST API 与 MCP 服务提供已保存链接。
主要功能
- 01按内容类型识别并保存网址
- 02获取标题和预览元数据
- 03按相对日期分组链接
- 04在文件夹中整理链接
- 05跨设备同步列表变更
适用场景
- 01集中保存文章、PDF、视频和音频链接
- 02通过应用或 API 查找已保存的链接
- 03通过 MCP 客户端访问保存的链接
MCP 相关
Purl 提供 MCP 服务,可用于保存、列出、获取和移动链接,以及管理文件夹。MCP 访问支持 API 密钥或 OAuth 身份验证。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://purl.live/api/mcpclaude mcp add --transport http nublson-purl https://purl.live/api/mcp{"mcpServers":{"nublson-purl":{"type":"http","url":"https://purl.live/api/mcp"}}}在 Cursor 中打开{"servers":{"nublson-purl":{"type":"http","url":"https://purl.live/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"nublson-purl":{"type":"http","url":"https://purl.live/api/mcp"}}}{"mcpServers":{"nublson-purl":{"serverUrl":"https://purl.live/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
https://purl.live/api/mcp需要授权工具
详细介绍
Purl
保存值得珍藏的链接。分享值得传递的链接。
在线预览: https://purl.live
Purl 是一个宁静的空间,让你保存和分享找到的链接——也是你的“珍珠”的归属之处。粘贴 URL 即可保存:网页、PDF、YouTube 视频和音频。Purl 会解析每项内容的元数据(标题、网站图标、描述、缩略图),并将所有内容集中保存,让你可以通过应用、REST API 和 MCP 服务访问。
Purl 免费使用,但有一项限制:每个账户最多可保存 1,000 个链接(src/lib/limits.ts 中的 MAX_SAVED_LINKS)。
产品目标:为你关心的链接提供一个集中存放的地方,并让值得传递的链接易于分享。
当前已实现
- 营销网站 — 着陆页(包含实时预览的主视觉区域)、REST API 和 MCP 服务文档、隐私政策和服务条款。
- 身份验证 — 通过 Better Auth 在着陆页使用 Google 和 GitHub 登录(设置相应环境变量后也可使用 Apple)。每个账户都会获得唯一的用户名,可在设置中编辑;你也可以在此连接或断开登录方式。头像来自 OAuth 提供方的个人资料照片。
- 保存和整理
- 通过 URL 添加内容,并自动检测内容类型(网页、PDF、YouTube、音频)。
- 链接按相对时间分组(例如:今天、本周、上个月)。
- 预览元数据(标题、描述、网站图标,以及可用时的缩略图)。
- 强化的出站请求安全 — 服务端
safeFetch,支持可选的代理/DNS 控制(参见AGENTS.md)。可通过SAFE_OUTBOUND_HTTP_PROXY配置出站代理。 - 实时列表同步 — 使用 Supabase Realtime,让保存和更新快速同步到其他标签页/设备。
- 链接操作 — 打开原始链接、复制 URL、编辑元数据、删除。
- REST API 和 MCP —
/api/v1(链接和文件夹)以及 MCP 服务(save_link、list_saved_items、get_link、move_link、list_folders、create_folder、update_folder、delete_folder),支持 API 密钥或 OAuth 身份验证。 - 运维补充功能 — 可选的 Upstash API 速率限制,以及针对关键路径的 Vitest 覆盖率测试。
- PWA(可安装应用) — Web App Manifest 以及一个 Serwist 服务工作线程(
src/app/sw.ts),构建后生成public/sw.js(运行pnpm build时生成,并被 git 忽略)。在平台支持的 Chrome/Edge 等浏览器中启用安装功能,并通过 Serwist 的 Next.js 默认设置实现运行时缓存,同时提供位于/~offline的静态离线页面。在pnpm dev中会禁用 Serwist,以避免开发期间出现意外的服务工作线程缓存问题——请使用pnpm build && pnpm start(或生产环境 URL)测试安装功能和服务工作线程。
保存流程
保存链接完全采用同步方式——不会进行后台处理。
- 输入 — 使用 URL 调用
POST /api/links(也可使用/api/v1/links和 MCP 的save_link工具)。 - 分类和补充信息 — 服务端使用
detectContentType(安全防范 SSRF 的HEAD请求/内容嗅探)和scrapeLinkMetadata(Open Graph HTML、PDF 的Content-Disposition/大小、YouTube oEmbed)。再次保存已有 URL 时,会刷新其元数据并将其移至列表顶部。 - 持久化 — 创建包含标题、网站图标、缩略图、域名和
contentType(WEB、PDF、YOUTUBE或AUDIO)的Link行。 - 同步 —
broadcastLinksChanged通过 Supabase Realtime 通知其他标签页/设备。
尚未实现
由于该仓库即将公开,以下事项被明确列出:
- 设置范围 — 设置涵盖用户名、登录方式和账户删除;更广泛的账户偏好设置(通知设置等)尚未实现。
营销内容与产品功能: 落地页文案提到了合集和每周摘要等构想。当前架构或应用中尚未实现这些功能——应将其视为路线图内容,而非已发布功能。
技术栈
- Web: Next.js(App Router)、React、TypeScript
- UI: Tailwind CSS、shadcn/ui
- 身份验证: Better Auth
- 数据库: PostgreSQL + Prisma
- 电子邮件(开发环境中可选): 使用 Resend 发送反馈邮件
- 实时功能: Supabase 客户端(匿名密钥 + 服务端服务角色)
- PWA: Serwist(
@serwist/next)、Web 清单 + 预缓存 / 离线回退
CI / GitHub Actions
自动化流程位于 .github/workflows/ 下。每个 PR 和手动发布都必须通过这些流水线。
PR 检查 — pr-checks.yml
在针对 develop 和 main 的 pull_request 上运行:设置与验证 → Prisma(生成客户端 + 类型修复)→ Lint 和 类型检查(并行)→ 测试 和 生产构建(并行,在 Lint 和类型检查通过后运行)。并发按 PR 隔离,因此新的推送会取消过时的运行。
发布 — release.yml
在 workflow_dispatch(手动触发)时运行:将 develop 合并到 main,然后进行构建验证,确保仅在构建通过后才将版本推广到生产环境。
安全
Purl 围绕不可信输入(任意 URL)构建。生产环境中有几个重要的安全层:
- 考虑 SSRF 的出站请求 — 用户提供的 URL 不会直接传给原始
fetch。OG/缩略图探测、PDF 获取、内容类型嗅探等路径都会通过safeFetch:仅允许 HTTP(S),屏蔽私有、链路本地和保留地址目标,处理重定向时逐跳检查主机,并在连接前固定 DNS 解析结果(缓解针对预检查的经典 DNS 重绑定攻击);还可选用响应大小上限(例如 PDF 代理)。可选的出站代理和自定义 DNS 服务器见AGENTS.md。 - 身份验证与路由限制 — 使用 Better Auth 会话;Next.js
proxy会将未通过身份验证的用户重定向出私有路由。登录仅支持 OAuth(Google/GitHub,以及配置后可用的 Apple);不提供密码登录。 - API 授权 — 敏感路由(
/api/links、/api/v1/*、MCP 等)会在服务端解析会话,并将操作限制在已登录用户的范围内。 - 速率限制 — 设置
UPSTASH_REDIS_REST_URL和UPSTASH_REDIS_REST_TOKEN后,代理会对/api/auth/*、POST /api/links和POST /api/feedback实施按 IP 限制(见proxy-rate-limit.ts)。未配置 Upstash 时,限制将停用——本地开发没有问题,但不适合生产环境。 - 密钥与客户端暴露 —
SUPABASE_SECRET_KEY(或旧版SUPABASE_SERVICE_ROLE_KEY)等值仅供服务端使用。浏览器仅使用 Supabase anon 密钥进行实时功能;.env会被 Git 忽略。 - 响应大小限制 — PDF 代理流式传输设有大小上限(见
safe-outbound-fetch)。
报告漏洞: 请通过此仓库的 GitHub Security Advisories 提交报告,以便在修复前对详情保密。
设置(本地开发)
先决条件
- **Node.js:**近期 LTS 版本
- 包管理器:
pnpm(此仓库包含pnpm-lock.yaml) - **Postgres:**本地或托管实例(Supabase 是不错的选择)
1) 安装依赖
pnpm install
2) 配置环境变量
在仓库根目录创建 .env 文件。完整列表请参阅 .env.example;核心功能所需的最少配置如下:
DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/DBNAME"
# Supabase Realtime — cross-device instant link list sync (same project as Postgres)
SUPABASE_URL="https://YOUR_PROJECT.supabase.co"
SUPABASE_ANON_KEY="eyJ..."
SUPABASE_SECRET_KEY="sb_secret_..."
# Sign-in (OAuth apps with callback {BETTER_AUTH_URL}/api/auth/callback/{google,github})
GOOGLE_CLIENT_ID="..."
GOOGLE_CLIENT_SECRET="..."
GITHUB_CLIENT_ID="..."
GITHUB_CLIENT_SECRET="..."
# Optional (used to send in-app feedback emails)
RESEND_API_KEY="re_..."
RESEND_FROM="Purl <[email protected]>"
说明:
DATABASE_URL是必需的(Prisma + Better Auth)。- 实时同步链接列表需要 Supabase 环境变量。请在 Supabase 控制台中打开 Project Settings → API。服务角色密钥必须仅用于服务器端。
- 生产环境需要 Google/GitHub OAuth 凭据;本地环境中,缺少变量的提供方会直接隐藏。本地开发时,请使用回调 URL
http://localhost:3000/api/auth/callback/{google,github}。Apple 是可选项,只有设置了全部四个APPLE_*变量时才会启用(请参阅.env.example)。 - 本地开发时 Resend 是可选的:未设置
RESEND_API_KEY时,无法发送应用内反馈。 - Better Auth 密钥和 URL 列于
.env.example中——复制这些键即可完成可用的身份验证配置。
3) 运行数据库迁移
pnpm prisma migrate dev
4) 生成 Prisma 客户端(如有需要)
pnpm prisma generate
5) 启动开发服务器
pnpm dev
打开 http://localhost:3000。
可选:使用 portless 设置命名 HTTPS URL。 全局安装 portless(npm install -g portless,Node.js 24+)后,运行 portless run,而不是 pnpm dev。它会通过本地代理在 https://purl.localhost 上运行 dev 脚本。在 .env.local 中将身份验证 URL 指向该地址,否则登录时会因来源不符而被拒绝:
BETTER_AUTH_URL="https://purl.localhost"
BASE_URL="https://purl.localhost"
在 git worktree 中,portless 会为分支名称添加前缀(例如 https://my-branch.purl.localhost);请在其中将两个变量都设为该 URL。
**PWA / 安装:**使用 pnpm dev 时,服务工作线程不会启用。生产构建完成后,public/sw.js 会在本地生成;运行 pnpm start 并在 Chromium 中打开应用,即可使用 Install,或测试离线访问 /~offline。
测试
测试使用 Vitest,重点验证关键逻辑(格式化程序、链接分组、身份验证路由、API 行为、元数据抓取)。测试有意避免仅针对浅层 UI 封装的内容。
pnpm test # run once
pnpm test:watch # watch mode
常用命令
pnpm lint
pnpm build
pnpm start
pnpm test
更多贡献者说明(Prisma、出站代理环境变量):请参阅 AGENTS.md。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。