
Purl
io.github.nublson由 GitHub 帳號 nublson 發布v0.5.1更新於 Nov 7, 2026
Save, organize and share your Purl links from any MCP client.
概覽
Purl 是託管書籤服務,其 MCP 伺服器讓助理儲存、列出、讀取、移動和刪除收藏連結,並以資料夾整理。
- 可以做什麼
- 將網址存為連結,自動辨識網頁、PDF、YouTube 影片和音訊,並解析標題、描述、圖示和縮圖。
- 列出已儲存項目並查看單一連結的詳細資料。
- 在資料夾之間移動連結。
- 列出、建立、更新和刪除資料夾。
- 重複儲存同一網址會更新其中繼資料並把它移到清單最上方。
- 適用情境
- 適合想讓助理幫忙維護一份值得回看的連結收藏,或在對話中把收藏歸檔、整理進資料夾而不必開啟 Purl 應用程式的情況。
- 執行需求
- 遠端 MCP 端點 purl.live,需要網路連線。必須驗證:OAuth,或在 Authorization 標頭中帶上於「設定 → 整合」建立的 Purl API 金鑰。需要 Purl 帳號,每個帳號最多可儲存 1,000 個連結。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 Purl,將其新增到工作區。
- 連接 所需的 憑證。它們會被私密儲存,絕不會在公開頁面上展示。
- 為需要使用其工具的對話啟用該服務。
Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。
交給代理程式安裝
把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。
閱讀 https://sourceweft.com/mcp/io.github.nublson%2Fpurl/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。其他 MCP 客戶端
把它新增到你客戶端的 mcpServers 設定中。 客戶端會在首次連接時完成 OAuth 登入。
{
"mcpServers": {
"purl": {
"type": "http",
"url": "https://purl.live/api/mcp"
}
}
}README
[Purl — Save Anything. Keep what matters. A home for your links, PDFs, video, and audio.]
Purl
Save the links worth keeping. Share the ones worth passing on.
Live preview: https://purl.live
Purl is a calm place to save and share the links you find — a home for your "pearls". You paste URLs: web pages, PDFs, YouTube videos, and audio. Purl resolves each item's metadata (title, favicon, description, thumbnail) and keeps everything in one place, available from the app, a REST API, and an MCP server.
Purl is free, with one limit: each account can save up to 1,000 links (MAX_SAVED_LINKS in src/lib/limits.ts).
The product goal: one place to keep the links you care about, and an easy way to share the ones worth passing on.
Implemented today
- Marketing site — Landing page (hero with a live preview), docs for the REST API and MCP server, privacy and terms.
- Authentication — Google and GitHub sign-in on the landing page via Better Auth (Apple too when its env vars are set). Every account gets a unique username, editable in Settings, where you can also connect or disconnect sign-in methods; avatars come from the OAuth provider's profile photo.
- Save & organize
- Add items by URL with automatic content-type detection (web, PDF, YouTube, audio).
- Links grouped by relative time (e.g. Today, This week, Last month).
- Preview metadata (title, description, favicon, thumbnail where available).
- Hardened outbound fetch — Server-side
safeFetchwith optional proxy/DNS controls (seeAGENTS.md). An egress proxy can be configured viaSAFE_OUTBOUND_HTTP_PROXY. - Realtime list sync — Supabase Realtime so saves and updates propagate across tabs/devices quickly.
- Link actions — Open original, copy URL, edit metadata, delete.
- REST API & MCP —
/api/v1(links and folders) and an MCP server (save_link,list_saved_items,get_link,move_link,list_folders,create_folder,update_folder,delete_folder) with API-key or OAuth auth. - Operational extras — Optional Upstash-backed API rate limiting, Vitest coverage for critical paths.
- PWA (installable app) — Web App Manifest plus a Serwist service worker (
src/app/sw.ts) that builds topublic/sw.js(generated onpnpm build, gitignored). Enables Install in Chrome/Edge and similar where the platform supports it, with runtime caching via Serwist's Next.js defaults and a static offline shell at/~offline. Serwist is disabled inpnpm devto avoid service-worker cache surprises during development — usepnpm build && pnpm start(or your production URL) to exercise installability and the SW.
Save flow
Saving a link is fully synchronous — there is no background processing.
- Input —
POST /api/linkswith a URL (also/api/v1/linksand the MCPsave_linktool). - Classify & decorate — Server-side
detectContentType(SSRF-safeHEAD/ sniff) plusscrapeLinkMetadata(Open Graph HTML, PDFContent-Disposition/ size, YouTube oEmbed). Saving an existing URL again refreshes its metadata and moves it to the top. - Persist — A
Linkrow with title, favicon, thumbnail, domain, andcontentType(WEB,PDF,YOUTUBE, orAUDIO). - Sync —
broadcastLinksChangednotifies other tabs/devices via Supabase Realtime.
Not implemented yet
These are called out explicitly because the repo is going public:
- Settings breadth — Settings cover username, sign-in methods, and account deletion; broader account preferences (notification settings, etc.) are not implemented yet.
Marketing vs. product: The landing page copy mentions ideas such as collections and a weekly digest. Those are not built in the current schema or app — treat them as roadmap, not shipped features.
Tech stack
- Web: Next.js (App Router), React, TypeScript
- UI: Tailwind CSS, shadcn/ui
- Auth: Better Auth
- Database: PostgreSQL + Prisma
- Email (optional in dev): Resend for feedback emails
- Realtime: Supabase client (anon + service role on server)
- PWA: Serwist (
@serwist/next), web manifest + precache / offline fallback
CI / GitHub Actions
Automation lives under .github/workflows/. Every PR and manual release is gated by these pipelines.
PR checks — pr-checks.yml
Runs on pull_request to develop and main: Setup & validation → Prisma (generate client + type fixes) → Lint and type check (in parallel) → Tests and production build (in parallel, after lint and type check pass). Concurrency is per-PR so new pushes cancel stale runs.
[GitHub Actions graph for pr-checks.yml: Setup, Prisma, Lint & Type Check, Test & Build]
Release — release.yml
Runs on workflow_dispatch (manual): Merge develop into main, then build validation so production is only promoted after a green build.
[GitHub Actions graph for release.yml: merge develop into main, then build validation]
Security
Purl is built around untrusted input (arbitrary URLs). A few layers matter in production:
- SSRF-aware outbound fetches — User-supplied URLs are not passed to raw
fetch. OG/thumbnail probes, PDF fetch, content-type sniffing, and similar paths go throughsafeFetch: HTTP(S) only, blocked private/link-local/reserved targets, redirect handling with per-hop host checks, DNS resolution pinned before connect (mitigates classic DNS rebinding against the pre-check), optional response size caps (e.g. PDF proxy). Optional egress proxy and custom DNS servers are documented inAGENTS.md. - Authentication & route gating — Better Auth sessions; Next.js
proxyredirects unauthenticated users away from private routes. Sign-in is OAuth-only (Google/GitHub, plus Apple when configured); there are no passwords. - API authorization — Sensitive routes (
/api/links,/api/v1/*, MCP, etc.) resolve the session server-side and scope work to the signed-in user. - Rate limiting — When
UPSTASH_REDIS_REST_URLandUPSTASH_REDIS_REST_TOKENare set, the proxy applies per-IP limits to/api/auth/*,POST /api/links, andPOST /api/feedback(seeproxy-rate-limit.ts). Without Upstash, limits are disabled — fine locally, not ideal for production. - Secrets & client exposure —
SUPABASE_SECRET_KEY(or the legacySUPABASE_SERVICE_ROLE_KEY) and similar values are server-only. The browser uses the Supabase anon key for Realtime only;.envstays gitignored. - Response bounds — PDF proxy streaming is size-capped (see
safe-outbound-fetch).
Reporting a vulnerability: use GitHub Security Advisories for this repository so details stay private until patched.
Setup (local development)
Prerequisites
- Node.js: recent LTS
- Package manager:
pnpm(this repo includespnpm-lock.yaml) - Postgres: local or hosted (Supabase works well)
1) Install dependencies
2) Configure environment variables
Create a .env file in the repo root. See .env.example for the full list; minimum for core behavior:
Notes:
DATABASE_URLis required (Prisma + Better Auth).- Supabase env vars are required for realtime link list sync. Use Project Settings → API in the Supabase dashboard. The service role key must stay server-only.
- Google/GitHub OAuth credentials are required in production; locally, a provider whose vars are missing is simply hidden. For local dev, use callback URLs
http://localhost:3000/api/auth/callback/{google,github}. Apple is optional and enabled only when all fourAPPLE_*vars are set (see.env.example). - Resend is optional for local dev: without
RESEND_API_KEY, in-app feedback can't be sent. - Better Auth secrets and URLs are in
.env.example— copy those keys for a working auth setup.
3) Run database migrations
4) Generate Prisma client (if needed)
5) Start the dev server
Open http://localhost:3000.
Optional: a named HTTPS URL with portless. With portless installed globally (npm install -g portless, Node.js 24+), run portless run instead of pnpm dev. It runs the dev script behind a local proxy at https://purl.localhost. Point auth at that URL in .env.local, or sign-in rejects the origin:
In a git worktree, portless prefixes the branch name (for example https://my-branch.purl.localhost); set both variables to that URL there.
PWA / install: With pnpm dev, the service worker is not active. After a production build, public/sw.js exists locally; run pnpm start and open the app in Chromium to use Install or to test offline navigation to /~offline.
Testing
Tests use Vitest and focus on critical logic (formatters, link grouping, auth routing, API behavior, metadata scraping). They intentionally avoid shallow UI-only wrappers.
Useful commands
More contributor notes (Prisma, outbound proxy env): see AGENTS.md.
來源:README.md,提交 a140440
工具
0版本歷史
16- v0.5.1最新Nov 7, 2026
- v0.3.0Oct 29, 2026
- v0.2.0Oct 21, 2026
- v0.1.16Oct 15, 2026
- v0.1.15Oct 11, 2026
- v0.1.14Oct 10, 2026
- v0.1.13Oct 9, 2026
- v0.1.12Oct 8, 2026
- v0.1.11Oct 4, 2026
- v0.1.10Oct 3, 2026
- v0.1.9Oct 2, 2026
- v0.1.8Oct 2, 2026
- v0.1.6Oct 1, 2026
- v0.1.4Sep 25, 2026
- v0.1.3Sep 24, 2026
- v0.1.1Sep 16, 2026
評分
已滿足適用檢查項的 75%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通必需25 分
- 已宣告認證方式必需10 分
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分
請在儲存庫或註冊中心條目中宣告授權條款。