Linkwarden MCP

io.github.flumpiey由 GitHub 帳號 flumpiey 發布v0.1.6更新於 Oct 28, 2026

Read-first Linkwarden bookmarks MCP with opt-in write, delete, and collection tools.

已驗證STDIO僅桌面效率與工作流知識與記憶

概覽

AI 產生的概覽

以唯讀為優先的 Linkwarden 書籤庫 MCP 伺服器,讓助理搜尋、閱讀並整理連結、收藏集與標籤,寫入與刪除工具需明確開啟。

可以做什麼
  • 搜尋、讀取與檢視連結,包含保存的網頁正文與完整中繼資料
  • 列出收藏集與標籤及其連結數量,並提供書籤庫總覽:總數、空收藏集、未使用標籤
  • 整理與清理:找出未分類或重複連結、建議收藏集與標籤、比較收藏集重疊、檢查結構問題
  • 開啟寫入範圍後,可儲存、搬移、重新標記連結,排入封存,並建立收藏集
  • 僅在設定對應刪除範圍時,才能刪除連結、標籤、收藏集或合併標籤
適用情境
適合把書籤存放在 Linkwarden 執行個體,並希望助理回答書籤相關問題或協助清理未整理收件匣的人。預設為唯讀,也適合先只做查詢、之後再決定是否開啟寫入的謹慎使用者。
執行需求
本機需有 Python 執行環境與 uv/uvx(Python 3.10 以上),以及可連線的 Linkwarden 執行個體。需設定 LINKWARDEN_API_URL 為執行個體基礎網址,LINKWARDEN_API_KEY 為在 Linkwarden 設定中建立的存取權杖。選用的 LINKWARDEN_MCP_WRITE_SCOPES 與 LINKWARDEN_MCP_DELETE_SCOPES 決定註冊哪些寫入/刪除工具。僅支援 stdio 傳輸。
安裝前請注意
LINKWARDEN_API_KEY 是可存取書籤庫的 Bearer 權杖,不要寫進會提交的設定檔,正式環境建議使用密鑰管理工具。開啟寫入或刪除範圍會暴露修改或刪除資料的工具,包括具破壞性的標籤合併與收藏集刪除;批次操作預設 dry_run=true,確認方案後再設為 false。刪除範圍不會由寫入範圍自動推導。一個程序只對應一個執行個體網址。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Linkwarden MCP,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[Linkwarden]

linkwarden-mcp

MCP server for self-hosted Linkwarden: ask your AI about bookmarks, collections, and tags.

[License: MIT] [Python] [MCP] [CI] [PyPI]

What is Linkwarden?

Linkwarden is a self-hosted, open-source bookmark manager. You collect, organize, annotate, and preserve webpages in one place, with full-page archives so content stays readable after the original page disappears. It also supports collaboration and public sharing.

This project wires the Linkwarden HTTP API into the Model Context Protocol so Cursor, Claude, VS Code Copilot, and other MCP hosts can query your live library in natural language.

Useful Linkwarden links:

What this server does

Default is read-only. You get:

  • 18 read tools - discovery (list_resources), six core reads (search, get, preserved content, collections, tags, overview), and eleven triage/hygiene workflows
  • Task tools (opt-in) - intent-shaped writes such as save_link, smart_save_link, organise_links, create_collection, apply_triage_plan (register when matching write scopes are set)
  • Delete tools (opt-in) - delete_links, delete_tags, merge_tags, delete_collection (register only under delete scopes; never implied by write)
  • Hard denylist - tokens, session, auth, user admin (except GET /api/v1/users/me), migration, and whole-instance preservation stay blocked even when writes are on

Transport is stdio. No HTTP server. No global install required if you use uv / uvx.

Branding / icons

Four surfaces (keep them in sync when the mark changes):

  1. stdio hosts (Cursor, Claude Desktop via mcp.json): serverInfo.icons from server_icons() — embedded data URI from src/linkwarden_mcp/assets/icon.png, plus HTTPS fallback docs/icon-512.png (https://raw.githubusercontent.com/flumpiey/linkwarden-mcp/main/docs/icon-512.png). website_url is https://linkwarden.app/.
  2. Cursor plugin: .cursor-plugin/plugin.json logo → docs/linkwarden-icon.svg.
  3. Claude Desktop Extension: mcpb/icon.png (packed with npx @anthropic-ai/mcpb pack mcpb).
  4. Claude.ai remote connectors: Claude.ai ignores serverInfo.icons and uses the root-domain favicon of the connector URL. If you host a remote MCP later, serve docs/favicon.ico at the registrable domain root (e.g. https://acme.com/favicon.ico for https://mcp.acme.com/...).

server.json registry metadata also points its icons[0].src at the same raw docs/icon-512.png URL.

Requirements

  • Python ≥ 3.10 (pulled in automatically by uvx)
  • uv (provides uvx)
  • A reachable Linkwarden instance: LINKWARDEN_API_URL + LINKWARDEN_API_KEY

Access token

  1. Sign in to your Linkwarden instance (self-hosted or Cloud).
  2. Open Settings → Access Tokens (or go to /settings/access-tokens).
  3. Create a New Access Token, give it a name, and copy the value into LINKWARDEN_API_KEY.
  4. Set LINKWARDEN_API_URL to your instance base URL (usually without /api/v1; include /api/v1 only if your deployment requires it), e.g. https://links.example.com or local Docker http://127.0.0.1:3000.

linkwarden-mcp sends the token as Authorization: Bearer …. API overview: API Introduction.

Copy .env.example to .env for local runs — never commit .env. Prefer the Cursor plugin Configure UI for credentials, or a secret manager in production.

Quick start

Run the PyPI package with uvx:

bash
uvx linkwarden-mcp

Paste a client config below, set LINKWARDEN_API_URL / LINKWARDEN_API_KEY, restart the host, then ask: “Find my unread bookmarks about Python” or “What's in my Dev collection?”

From a git clone (dev): uvx --from git+https://github.com/flumpiey/linkwarden-mcp linkwarden-mcp or uv run --directory /path/to/linkwarden-mcp linkwarden-mcp.

Installation

Configs below pull linkwarden-mcp from PyPI. Leave write-scope env vars unset for read-only.

Cursor

Plugin (Configure UI for URL, key, and scopes): this repo is a Cursor plugin via .cursor-plugin/plugin.json + root mcp.json.

  1. Symlink or copy the clone to ~/.cursor/plugins/local/linkwarden-mcp (Windows: %USERPROFILE%\.cursor\plugins\local\linkwarden-mcp).
    • macOS / Linux: ln -s /path/to/linkwarden-mcp ~/.cursor/plugins/local/linkwarden-mcp
    • Windows: Cursor does not follow symlinks for local plugins. Use a junction or copy instead:
      bat
      mklink /J "%USERPROFILE%\.cursor\plugins\local\linkwarden-mcp" "E:\Development\linkwarden-mcp"
      or:
      bat
      robocopy "E:\Development\linkwarden-mcp" "%USERPROFILE%\.cursor\plugins\local\linkwarden-mcp" /E
  2. Reload the window.
  3. Open Plugins → Configure on linkwarden-mcp. Set Linkwarden API URL and Linkwarden API key. Leave Write scopes / Delete scopes empty for read-only, or paste a CSV such as links,collections.
  4. Confirm the linkwarden MCP server is enabled under Customize / MCP.

Marketplace listing is a separate submit at cursor.com/marketplace/publish.

Manual mcp.json: project .cursor/mcp.json or user-wide ~/.cursor/mcp.json. Root mcp.json is plugin wiring with ${…} placeholders only — never commit real secrets there.

From PyPI:

json
{  "mcpServers": {    "linkwarden": {      "type": "stdio",      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Local editable (dev):

json
{  "mcpServers": {    "linkwarden": {      "type": "stdio",      "command": "uv",      "args": ["run", "--directory", "/path/to/linkwarden-mcp", "linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Optional scoped writes in the env block:

json
"LINKWARDEN_MCP_WRITE_SCOPES": "links,collections","LINKWARDEN_MCP_DELETE_SCOPES": "links"

Restart Cursor after saving. Confirm linkwarden under MCP settings.

Claude Desktop

Desktop Extension (.mcpb): download mcpb.mcpb from GitHub Releases. Use v0.1.5+ (needs uv on PATH). Launch is uv tool run --python 3.12 linkwarden-mcp. Do not put the PyPI package in mcpb/pyproject.toml dependencies — Claude Desktop syncs that file at install and can fail on system Python 3.13.

  1. Open Claude Desktop → Settings → Extensions.
  2. Open Advanced settings → Install Extension…
  3. Select mcpb.mcpb. Review permissions, enter Linkwarden API URL and Linkwarden API key, then click Install.
  4. Leave Write scopes and Delete scopes empty for read-only.
  5. Restart Claude Desktop if tools do not appear.

Build your own bundle from a clone:

bash
npx @anthropic-ai/mcpb pack mcpb

On Windows, double-click often does nothing and dragging the file into chat attaches it to the conversation instead of installing it. Use Install Extension… in Settings.

Manual claude_desktop_config.json fallback: edit the Claude Desktop config, then restart the app.

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
json
{  "mcpServers": {    "linkwarden": {      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Local clone:

json
{  "mcpServers": {    "linkwarden": {      "command": "uv",      "args": ["run", "--directory", "/path/to/linkwarden-mcp", "linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}
Claude Code

Add via CLI:

bash
claude mcp add linkwarden --env LINKWARDEN_API_URL=https://links.example.com --env LINKWARDEN_API_KEY=your-token -- uvx linkwarden-mcp

Or edit ~/.claude.json / project MCP config:

json
{  "mcpServers": {    "linkwarden": {      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}
VS Code / GitHub Copilot

Create .vscode/mcp.json in the project root:

json
{  "servers": {    "linkwarden": {      "type": "stdio",      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Local editable:

json
{  "servers": {    "linkwarden": {      "type": "stdio",      "command": "uv",      "args": ["run", "--directory", "/path/to/linkwarden-mcp", "linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Reload the window. Open Copilot Chat and confirm the linkwarden tools are available.

Windsurf

Edit ~/.codeium/windsurf/mcp_config.json (macOS/Linux) or the Windsurf MCP settings UI:

json
{  "mcpServers": {    "linkwarden": {      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}

Restart Windsurf after saving.

Zed

Add under context_servers in Zed settings.json (Agent Panel → settings also works):

json
{  "context_servers": {    "linkwarden": {      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}
Cline

Edit the Cline MCP settings file (cline_mcp_settings.json via the Cline MCP UI):

json
{  "mcpServers": {    "linkwarden": {      "command": "uvx",      "args": ["linkwarden-mcp"],      "env": {        "LINKWARDEN_API_URL": "https://links.example.com",        "LINKWARDEN_API_KEY": "your-token"      }    }  }}
Continue

In .continue/config.yaml:

yaml
mcpServers:  - name: linkwarden    command: uvx    args:      - linkwarden-mcp    env:      LINKWARDEN_API_URL: https://links.example.com      LINKWARDEN_API_KEY: your-token
Generic / any stdio MCP host

Any host that can spawn a stdio MCP server:

FieldValue
Commanduvx
Argslinkwarden-mcp
EnvLINKWARDEN_API_URL, LINKWARDEN_API_KEY (+ optional write scopes)
bash
uvx linkwarden-mcp

Dev from a clone: uv run --directory /path/to/linkwarden-mcp linkwarden-mcp.

npx only runs npm packages. This is a Python package; use uvx.

Environment

VariableRequiredNotes
LINKWARDEN_API_URLyesBase URL (include /api/v1 only if required; typical: https://links.example.com)
LINKWARDEN_API_KEYyesAccess token from Settings → Access Tokens; sent as Authorization: Bearer; never logged
LINKWARDEN_MCP_WRITE_SCOPESnoComma-separated domains for create/update. Empty = no writes.
LINKWARDEN_MCP_DELETE_SCOPESnoComma-separated domains for delete only. Never implied by WRITE_SCOPES.
LINKWARDEN_MAX_BULKnoMax records per bulk op (default 25)
TEST_LINKWARDEN_API_URLintegration onlyLive sandbox URL for pytest -m integration
TEST_LINKWARDEN_API_KEYintegration onlyLive sandbox token for pytest -m integration

Valid scopes: links, collections, tags, raw. No wildcards (*, all). raw expands effective scopes to all domain scopes (escape hatch).

Recommended (covers most bookmark workflows without every mutating tool):

json
"LINKWARDEN_MCP_WRITE_SCOPES": "links,collections","LINKWARDEN_MCP_DELETE_SCOPES": "links"

Default with no scopes: 18 tools. All three domain scopes in WRITE and DELETE: 31 tools.

Legacy LINKWARDEN_MCP_ALLOW_WRITES / ALLOW_WRITES / LINKWARDEN_MCP_WRITES hard-fail if set. Use the scoped vars instead.

MCP host env (.cursor/mcp.json or Cursor plugin Configure) must match process env / .env or scope behavior drifts.

See .env.example. Never commit .env. Prefer Cursor plugin Configure UI or a secret manager in production.

Write scopes and task tools

When a scope is listed in LINKWARDEN_MCP_WRITE_SCOPES, the server registers task tools for that domain. LINKWARDEN_MCP_DELETE_SCOPES enables delete/merge tools per domain. Call list_resources to inspect read_only, scope lists, and the live boundary string.

ToolScopesPurpose
save_linkWRITE linksSave a URL into a collection (by name)
smart_save_linkWRITE linksSave with optional heuristic collection/tags
organise_linksWRITE linksMove or retag multiple links
update_linkWRITE linksUpdate link fields (read-modify-write)
queue_archiveWRITE linksQueue preservation (async; not immediate)
apply_triage_planWRITE linksApply [{link_id, collection?, tags?}]; default dry_run=true
bulk_sort_by_rulesWRITE linksMatch domain_pattern rules then organise; default dry_run=true
create_collectionWRITE collectionsCreate a collection (optional parent)
auto_tag_by_domainWRITE links + tagsApply domain→tag rules; default dry_run=true
delete_linksDELETE linksDelete multiple links
delete_tagsDELETE tagsDelete tags by id or name
merge_tagsDELETE tagsMerge tags into a new name (destructive)
delete_collectionDELETE collectionsDelete a collection after user chooses delete/move/cancel for its links (elicitation or on_links)

Example with recommended scopes only:

json
"LINKWARDEN_MCP_WRITE_SCOPES": "links,collections","LINKWARDEN_MCP_DELETE_SCOPES": "links"

Denylist (always blocked): /api/v1/tokens, /api/v1/session, /api/v1/auth, /api/v1/users/** (except GET /api/v1/users/me), migration, and whole-instance preservation worker actions.

Tools

Read tools

Always registered (18 total).

ToolPurpose
list_resourcesDiscovery; reports read_only + live write/delete scopes
search_linksSearch by query, collection, tag, or pin status
get_linkFull metadata for one link
read_link_contentPreserved plain text (textContent or archive fallback)
list_collectionsCollections with link counts
list_tagsTags with link counts
get_library_overviewTotals, empty collections, unused tags
suggest_collection_for_urlHeuristic collection suggestions for a URL
suggest_tags_for_linkSuggest existing-library tags (never invents names)
find_unsorted_linksList unsorted links (default collection: Unorganized)
triage_linksPropose collection/tags for link ids (no writes)
find_duplicate_linksGroup links with the same normalized URL
recommend_collection_for_linksConsensus collection for a batch of links
suggest_links_for_collectionFind links elsewhere that likely belong
analyze_collection_overlapCompare two collections for shared domains/tags/URLs
suggest_collection_structureHygiene: empty, near-duplicate names, overcrowded
align_tags_with_similar_linksTags used on similar-domain links
get_sorting_dashboardOne-shot triage: unsorted, duplicates, empty, largest

Write tools

Registered only when matching scopes are set (see table above). Prefer smart_save_link / triage tools over raw field edits when you are sorting an inbox.

PatternRequiresNotes
Link create/update/organise/archiveWRITE linksIncludes workflow writers with dry_run defaults
Collection createWRITE collectionsOptional parent by name
Domain auto-tagWRITE links + tagsOnly existing tag names
Deletes / tag mergematching DELETE scopeDestructive; confirm ids first

Agent Skill

Companion skill: skills/linkwarden-bookmarks/SKILL.md.

The Cursor plugin discovers this skill from skills/. Without the plugin, copy or symlink that folder into your agent skills path. It tells the model to call list_resources first, verify after writes, and which workflow tools to prefer.

Development

bash
uv sync --extra devnpm install          # installs lefthook + commitlint; registers git hooksuv run linkwarden-mcp

Offline tests only (respx). No live Linkwarden required:

bash
uv run ruff check src testsuv run pytest

Git hooks (lefthook)

Hook / commandWhat it runs
pre-commitruff check + full pytest (mocked suite)
commit-msgcommitlint Conventional Commits
npm run pre-publishensure build/twine → ruff → pytest → sdist contents → python -m build → twine check → npx @anthropic-ai/mcpb pack mcpb

Commit messages must follow Conventional Commits, e.g. feat(api): add delete_links tool.

Run the local publish gate before tagging a release:

bash
npm run pre-publish

GitHub Actions matrix: Python 3.10 and 3.12.

Caveats

  • One process ↔ one LINKWARDEN_API_URL. Multi-instance routing is out of scope.
  • Multi-user / team disambiguation on a shared instance is unverified. Do not claim multi-tenant support until validated against a live shared library.
  • Collection/tag suggestions are heuristic and library-local; they do not invent new tag names.
  • Bulk mutating workflows default to dry_run=true; set dry_run=false only after you review the plan.
  • ChatGPT Apps need a hosted HTTP MCP endpoint. This package is stdio-only.

License

MIT. See LICENSE.

來源:README.md,提交 e389df4

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.1.6最新Sep 16, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分