mcpField
R
raindrop-api

raindrop-api

github.com/intellectronica生产力298504 次安装27 周前更新
代码仓库

关于 raindrop-api

raindrop-api 是面向 Raindrop.io 用户的技能,通过 REST API 管理书签、集合、标签和高亮,并要求破坏性操作先确认。

主要功能

  1. 01读写书签与批量管理
  2. 02管理集合和标签
  3. 03读取与管理高亮
  4. 04搜索、筛选及导出数据
  5. 05执行破坏性操作前确认

适用场景

  1. 01按集合检索或导出书签
  2. 02创建书签并添加标签
  3. 03查看书签高亮和过滤统计

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/intellectronica/agent-skills --skill raindrop-api

安装后在 Claude Code 中输入/raindrop-api确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
collections-sharing.md
highlights.md
search-operators.md

详细介绍

Raindrop.io API 技能

此技能可通过 REST API 与 Raindrop.io 书签服务交互。使用 curl 和 jq 直接调用 REST API。

官方 API 文档:https://developer.raindrop.io/

身份验证

令牌解析

按以下顺序解析 API 令牌:

  1. 检查环境变量 RAINDROP_TOKEN
  2. 检查用户是否已在对话上下文中提供令牌
  3. 如果两者都不可用,则使用 AskUserQuestion 向用户索取令牌

验证环境中是否存在令牌:

[ -n "$RAINDROP_TOKEN" ] && echo "Token available" || echo "Token not set"

快速设置:个人使用或开发时,可在 https://app.raindrop.io/settings/integrations 生成测试令牌——打开应用并复制“Test token”。测试令牌不会过期。

完整的 OAuth2 流程详情请参阅下方的身份验证部分。

发起经过身份验证的请求

所有请求都需要在 Authorization 标头中携带 Bearer 令牌:

curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/ENDPOINT"

对于带有 JSON 请求体的 POST/PUT 请求:

curl -s -X POST \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"key": "value"}' \
  "https://api.raindrop.io/rest/v1/ENDPOINT"
验证身份验证

通过获取当前用户来测试令牌:

curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/user" | jq '.user.fullName'

基础 URL 和约定

  • 基础 URL:https://api.raindrop.io/rest/v1/
  • 数据格式:所有请求/响应体均为 JSON
  • 时间戳:ISO 8601 格式
  • 速率限制:每位经过身份验证的用户每分钟 120 个请求
  • CORS:支持基于浏览器的应用

确认要求

执行任何破坏性操作(DELETE、批量更新、移至回收站)之前,务必使用 AskUserQuestion 征求用户确认。 对于一组逻辑上相关的操作,只需确认一次。

破坏性操作包括:

  • 删除 raindrop、集合或标签
  • 批量更新或移动 raindrop
  • 合并或移除标签
  • 从共享集合中移除协作者
  • 清空回收站

只读操作(GET 请求)无需确认。

端点参考

Raindrop(书签)

文档:https://developer.raindrop.io/v1/raindrops

单个 Raindrop 操作
操作方法端点
获取 raindropGET/raindrop/{id}
创建 raindropPOST/raindrop
更新 raindropPUT/raindrop/{id}
移除 raindropDELETE/raindrop/{id}
上传文件PUT/raindrop/file
上传封面PUT/raindrop/{id}/cover
获取永久副本GET/raindrop/{id}/cache
建议(新 URL)POST/raindrop/suggest
建议(现有项目)GET/raindrop/{id}/suggest

文档:https://developer.raindrop.io/v1/raindrops/single

Raindrop 创建/更新字段:

  • link(字符串,创建时必填)- 书签 URL
  • title(字符串)- 书签标题
  • excerpt(字符串)- 简短描述
  • note(字符串)- 用户备注(支持 Markdown)
  • tags(字符串数组)- 标签名称
  • collection(对象)- {"$id": collectionId}
  • type(字符串)- link、article、image、video、document、audio
  • important(布尔值)- 标记为收藏
  • order(数字)- 排序顺序(升序)
  • media(数组)- 媒体/缩略图信息
  • highlights(数组)- 文本高亮
  • cover(字符串)- 封面图片 URL,或使用 <screenshot> 自动截取
  • pleaseParse(对象)- 使用 {} 触发后台元数据解析
  • created(字符串)- ISO 8601 创建日期
  • lastUpdate(字符串)- ISO 8601 最后更新日期
  • reminder(对象)- 提醒设置

删除行为:移除 raindrop 会将其移至回收站(集合 ID -99)。从回收站移除则会永久删除。

多个 Raindrop 操作
操作方法端点
获取 RaindropGET/raindrops/{collectionId}
创建多个POST/raindrops
更新多个PUT/raindrops/{collectionId}
移除多个DELETE/raindrops/{collectionId}
导出GET/raindrops/{collectionId}/export.{format}

文档:https://developer.raindrop.io/v1/raindrops/multiple

collectionId 值:

  • 0 - 所有 Raindrop
  • -1 - 未分类
  • -99 - 回收站
  • 任意正整数 - 指定集合

GET /raindrops/{collectionId} 的查询参数:

  • sort - 排序顺序:-created(默认)、created、score、-sort、title、-title、domain、-domain
  • perpage - 每页结果数(最多 50)
  • page - 页码(从 0 开始)
  • search - 搜索查询(参见 references/search-operators.md)
  • nested - 布尔值,是否包含子集合中的书签

批量更新字段(使用 ids 数组或 search 查询执行 PUT):

  • important(布尔值)
  • tags(数组)- 追加标签;空数组会清除所有标签
  • media(数组)- 追加媒体;空数组会清除所有媒体
  • cover(字符串)- URL 或 <screenshot>
  • collection(对象)- 使用 {"$id": collectionId} 移动

导出格式:csv、html、zip

集合

文档:https://developer.raindrop.io/v1/collections

操作方法端点
列出根集合GET/collections
列出子集合GET/collections/childrens
获取集合GET/collection/{id}
创建集合POST/collection
更新集合PUT/collection/{id}
上传封面PUT/collection/{id}/cover
删除集合DELETE/collection/{id}
删除多个集合DELETE/collections
重新排序/全部展开PUT/collections
合并集合PUT/collections/merge
移除空集合PUT/collections/clean
清空回收站DELETE/collection/-99
系统集合计数GET/user/stats
搜索封面/图标GET/collections/covers/{text}
精选封面GET/collections/covers

文档:https://developer.raindrop.io/v1/collections/methods

集合字段:

  • title(字符串)- 集合名称
  • view(字符串)- 显示样式:list、simple、grid、masonry
  • public(布尔值)- 是否可公开访问
  • parent(对象)- 使用 {"$id": parentCollectionId} 设置嵌套
  • sort(数字)- 排序位置
  • cover(数组)- 封面图片 URL
  • expanded(布尔值)- 是否展开子集合
  • color(字符串)- 集合颜色

系统集合(不可移除):

  • ID -1 - “未分类”
  • ID -99 - “回收站”

访问级别(access.level):

  • 1 - 只读
  • 2 - 协作者(可写)
  • 3 - 协作者(可写 + 管理)
  • 4 - 所有者

有关共享/协作者的信息,请参见 references/collections-sharing.md。

标签

文档:https://developer.raindrop.io/v1/tags

操作方法端点
获取标签GET/tags/{collectionId}
重命名标签PUT/tags/{collectionId}
合并标签PUT/tags/{collectionId}
移除标签DELETE/tags/{collectionId}

collectionId:省略或使用 0 获取所有集合中的标签。

获取标签的响应:

{
  "result": true,
  "items": [{"_id": "tagname", "count": 42}]
}

重命名标签:

curl -s -X PUT \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"replace": "new-name", "tags": ["old-name"]}' \
  "https://api.raindrop.io/rest/v1/tags/0"

合并标签(同一端点,数组中包含多个标签):

curl -s -X PUT \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"replace": "merged-name", "tags": ["tag1", "tag2", "tag3"]}' \
  "https://api.raindrop.io/rest/v1/tags/0"

移除标签:

curl -s -X DELETE \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tags": ["tag-to-remove"]}' \
  "https://api.raindrop.io/rest/v1/tags/0"
高亮

文档:https://developer.raindrop.io/v1/highlights

操作方法端点
获取所有高亮GET/highlights
获取集合高亮GET/highlights/{collectionId}
获取 Raindrop 高亮GET/raindrop/{id}
添加高亮PUT/raindrop/{id}
更新高亮PUT/raindrop/{id}
删除高亮PUT/raindrop/{id}

详情请参见 references/highlights.md。

筛选器

文档:https://developer.raindrop.io/v1/filters

curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/filters/{collectionId}" | jq '.'

使用 0 表示所有收藏集。返回失效链接、重复项、收藏项、未添加标签的项目、标签和内容类型的汇总计数。

查询参数:

  • tagsSort - -count(默认)或 _id(按字母顺序)
  • search - 其他搜索筛选条件
用户

文档:https://developer.raindrop.io/v1/user

操作方法端点
获取当前用户GET/user
更新用户PUT/user
导入

文档:https://developer.raindrop.io/v1/import

操作方法端点
解析 URLGET/import/url/parse?url={url}
检查 URL 是否存在POST/import/url/exists
解析 HTML 书签文件POST/import/file
备份

文档:https://developer.raindrop.io/v1/backups

操作方法端点
列出备份GET/backups
下载备份GET/backup/{id}.{format}
生成新备份GET/backup

格式:html 或 csv

身份验证:OAuth2 流程

文档:https://developer.raindrop.io/v1/authentication/token

对于访问其他用户数据的应用(非个人用途),请使用完整的 OAuth2 流程:

步骤 1:授权

将用户引导至:

https://raindrop.io/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&response_type=code
步骤 2:用授权码交换令牌
curl -s -X POST "https://raindrop.io/oauth/access_token" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "AUTH_CODE",
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "redirect_uri": "YOUR_REDIRECT_URI",
    "grant_type": "authorization_code"
  }' | jq '.'

响应:

{
  "access_token": "...",
  "refresh_token": "...",
  "expires_in": 1209599,
  "token_type": "Bearer"
}
步骤 3:刷新令牌

访问令牌在两周后过期。使用以下方式刷新:

curl -s -X POST "https://raindrop.io/oauth/access_token" \
  -H "Content-Type: application/json" \
  -d '{
    "client_id": "YOUR_CLIENT_ID",
    "client_secret": "YOUR_CLIENT_SECRET",
    "refresh_token": "YOUR_REFRESH_TOKEN",
    "grant_type": "refresh_token"
  }' | jq '.'

错误处理

检查 HTTP 状态码:

  • 200 - 成功
  • 204 - 成功,无内容
  • 400 - 请求错误
  • 401 - 身份验证失败(检查令牌)
  • 403 - 禁止访问(权限不足)
  • 404 - 未找到资源
  • 429 - 超出速率限制(超过 120 次请求/分钟)
  • 5xx - 服务端错误
错误处理示例
response=$(curl -s -w "\n%{http_code}" \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/0")

http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')

if [ "$http_code" -ge 200 ] && [ "$http_code" -lt 300 ]; then
  echo "$body" | jq '.'
else
  echo "Error: HTTP $http_code"
  echo "$body"
fi

常见模式

列出收藏集中的所有书签
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/COLLECTION_ID?perpage=50" | jq '.items[] | {title, link}'
创建书签
curl -s -X POST \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "link": "https://example.com",
    "title": "Example Site",
    "tags": ["reference", "example"],
    "collection": {"$id": COLLECTION_ID},
    "pleaseParse": {}
  }' \
  "https://api.raindrop.io/rest/v1/raindrop" | jq '.'
搜索书签
# Search across all collections
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/0?search=YOUR_QUERY" | jq '.items[] | {title, link}'

# Search with tag filter
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/0?search=%23tagname" | jq '.items[] | {title, link}'

完整的搜索查询语法请参阅 references/search-operators.md。

将书签移至收藏集
curl -s -X PUT \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"collection": {"$id": TARGET_COLLECTION_ID}}' \
  "https://api.raindrop.io/rest/v1/raindrop/RAINDROP_ID" | jq '.'
获取所有标签
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/tags/0" | jq '.items[] | {tag: ._id, count}'
创建收藏集
curl -s -X POST \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title": "My Collection", "view": "list"}' \
  "https://api.raindrop.io/rest/v1/collection" | jq '.'
列出所有收藏集(根级 + 子级)
# Root collections
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/collections" | jq '.items[] | {id: ._id, title}'

# Child collections
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/collections/childrens" | jq '.items[] | {id: ._id, title, parent: .parent."$id"}'
分页遍历所有书签
page=0
while true; do
  response=$(curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
    "https://api.raindrop.io/rest/v1/raindrops/0?perpage=50&page=$page")

  count=$(echo "$response" | jq '.items | length')
  echo "$response" | jq '.items[] | {title, link}'

  if [ "$count" -lt 50 ]; then
    break
  fi
  page=$((page + 1))
done
导出书签
# Export all bookmarks as CSV
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/0/export.csv" -o bookmarks.csv

# Export as HTML
curl -s -H "Authorization: Bearer $RAINDROP_TOKEN" \
  "https://api.raindrop.io/rest/v1/raindrops/0/export.html" -o bookmarks.html
检查 URL 是否已保存
curl -s -X POST \
  -H "Authorization: Bearer $RAINDROP_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://example.com"]}' \
  "https://api.raindrop.io/rest/v1/import/url/exists" | jq '.'

分页

Raindrop 使用基于页码的分页(而非基于游标的分页):

  • page - 页码(从 0 开始)
  • perpage - 每页项目数(最多 50;高亮内容默认 25)

当返回的项目数少于 perpage 时,表示已到最后一页。

嵌套收藏集结构

收藏集按层级组织。要重建完整的侧边栏,需要:

  1. GET /user - 返回包含收藏集排序信息的 groups 数组
  2. GET /collections - 根级收藏集
  3. GET /collections/childrens - 嵌套收藏集

根级收藏集的排序会保存在用户的 groups[].collections 数组中。子收藏集的排序保存在收藏集的 sort 字段中。

其他参考资料

有关具体主题的详细文档,请参阅:

  • references/search-operators.md - 搜索查询语法和运算符
  • references/collections-sharing.md - 收藏集共享和协作者
  • references/highlights.md - 高亮内容管理

工作流摘要

  1. 解析令牌 - 从环境、上下文中获取,或询问用户
  2. 验证身份验证 - 使用 GET /user 进行测试
  3. 读取操作 - 无需确认,直接执行
  4. 写入操作 - 执行前先征求确认
  5. 处理分页 - 按页码循环,直到项目数少于 perpage
  6. 解析响应 - 使用 jq 提取并格式化数据

评论

支持 Markdown