内容
# Raindrop.io MCP 服务器
Raindrop.io 的模型上下文协议(MCP)服务器。它通过 Streamable HTTP 与 OAuth 或直接令牌身份验证向 MCP 客户端公开书签、收藏、标签和亮点。
## 功能
- 收藏:列表、管理、合并、清理、重新排序、封面上传
- 书签:搜索、创建/更新/删除、批量创建/删除、文件/封面上传
- 标签:列表、重命名、合并、删除
- 亮点:列表、创建、更新、删除
- OAuth 2.0 + PKCE 或直接令牌身份验证
- Cloudflare Workers 部署,带有 Workers KV 支持的 OAuth 存储
## 要求
- Bun 1.0+
- 具有启用 Workers 的 Cloudflare 账户
- Raindrop.io 账户
- 一种身份验证方法:
- Raindrop OAuth 应用 + Workers KV,或
- Raindrop API 令牌
## 设置
安装依赖项:
```bash
bun install
```
## 环境变量
OAuth(推荐用于生产):
- `OAUTH_CLIENT_ID`
- `OAUTH_CLIENT_SECRET`
- `OAUTH_REDIRECT_URI`(例如 `https://raindrop-mcp.anuragd.me/auth/callback`)
- `OAUTH_ALLOWED_REDIRECT_URIS`(逗号分隔)
- `TOKEN_ENCRYPTION_KEY`(64 个十六进制字符)
- `JWT_SIGNING_KEY`
- `RAINDROP_AUTH_KV` Workers KV 绑定,在 `wrangler.jsonc` 中配置
直接令牌回退(单用户):
- `RAINDROP_ACCESS_TOKEN`
- `ALLOW_ENV_TOKEN_AUTH=true`
不建议在生产环境中使用部署范围内的 `RAINDROP_ACCESS_TOKEN` 回退。只有当显式设置为 `true` 时,它才有效;对于生产使用,请首选 OAuth 或每个请求的 `X-Raindrop-Token` 身份验证。
## 部署(Cloudflare Workers)
```bash
bunx wrangler login
bun run cf:kv:create
# 将打印的 KV ID 复制到 wrangler.jsonc,然后使用 wrangler 设置密钥
bun run deploy:cloudflare
```
参见 [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) 以获取完整的 Cloudflare 设置和烟雾测试。
### 主机服务器
使用生产 MCP 端点:
```text
https://raindrop-mcp.anuragd.me/mcp
```
OAuth 感知 MCP 客户端将:
1. 发现 `/.well-known/oauth-protected-resource`。
2. 发现 `/.well-known/oauth-authorization-server`。
3. 使用 `/register` 注册。
4. 使用 PKCE 打开 `/authorize`。
5. 当没有 Raindrop 会话时,通过 Raindrop OAuth 发送您。
6. 在 `/token` 处交换授权代码。
7. 使用颁发的承载令牌调用 `/mcp`。
## MCP 客户端配置
```json
{
"mcpServers": {
"raindrop": {
"url": "https://raindrop-mcp.anuragd.me/mcp",
"transport": "streamable-http"
}
}
}
```
如果使用直接令牌身份验证:
```json
{
"mcpServers": {
"raindrop": {
"url": "https://raindrop-mcp.anuragd.me/mcp",
"transport": "streamable-http",
"headers": {
"X-Raindrop-Token": "your_token"
}
}
}
}
```
## 端点
| 端点 | 目的 |
| --- | --- |
| `GET /` | 公共登陆页面 |
| `GET /docs/` | 静态设置/参考文档 |
| `GET /info` | 公共 JSON 功能摘要 |
| `POST /mcp` | MCP Streamable HTTP 端点 |
| `GET /.well-known/oauth-protected-resource` | 受保护资源元数据 |
| `GET /.well-known/oauth-authorization-server` | 授权服务器元数据 |
| `POST /register` | 动态客户端注册 |
| `GET /authorize` | MCP OAuth 授权入口 |
| `POST /authorize` | 同意批准/拒绝 |
| `POST /token` | 授权代码和刷新令牌交换 |
| `GET /auth/init` | 内部 Raindrop OAuth 启动 |
| `GET /auth/callback` | 内部 Raindrop OAuth 回调 |
## 工具
收藏:
- `collection_list`
- `collection_children_list`
- `collection_manage`
- `collection_bulk_delete`
- `collection_reorder`
- `collection_expand`
- `collection_merge`
- `collection_clean`
- `collection_empty_trash`
- `collection_cover_upload`
- `user_stats`
书签:
- `bookmark_search`
- `bookmark_manage`
- `bookmark_cache`
- `bookmark_suggest_existing`
- `bookmark_bulk_create`
- `bookmark_bulk_delete`
- `bookmark_file_upload`
- `bookmark_cover_upload`
- `bulk_edit_bookmarks`
- `bookmark_statistics`
标签:
- `tag_list`
- `tag_manage`
亮点:
- `highlight_manage`
## 架构
```mermaid
graph TB
subgraph "客户端层"
Browser[Web 浏览器]
MCPClient[MCP 客户端 SDK]
end
subgraph "传输层"
Worker["Cloudflare Worker\nsrc/worker.ts"]
end
subgraph "身份验证层"
OAuth["OAuth 服务\nPKCE 流"]
TokenStorage["令牌存储\nAES-256 加密"]
WorkersKV["Workers KV\nRAINDROP_AUTH_KV"]
OAuth --> TokenStorage
TokenStorage --> WorkersKV
end
subgraph "MCP 协议层"
MCPService["MCP 服务器\nMCP SDK 网络传输"]
end
subgraph "服务层"
RaindropService["RaindropService\nAPI 客户端\nopenapi-fetch"]
end
subgraph "外部服务"
RaindropAPI[Raindrop.io API]
end
MCPClient -->|HTTP| Worker
Browser -->|HTTPS| Worker
Worker -->|MCP 身份验证包装器| OAuth
OAuth -->|验证令牌| MCPService
MCPService -->|每个用户令牌| RaindropService
RaindropService -->|HTTP 请求| RaindropAPI
```
## OAuth 流
```mermaid
sequenceDiagram
participant User
participant Client as 客户端应用
participant Worker as Cloudflare Worker
participant OAuth as OAuth 服务
participant KV as Workers KV
participant Raindrop as Raindrop.io
User->>Client: 添加 MCP 端点
Client->>Worker: GET /.well-known/oauth-protected-resource
Worker->>Client: 受保护资源元数据
Client->>Worker: GET /.well-known/oauth-authorization-server
Worker->>Client: 授权元数据
Client->>Worker: POST /register
Worker->>KV: 存储 OAuth 客户端
Client->>Worker: GET /authorize with PKCE + 资源
Worker->>Client: 重定向到 /auth/init(当没有 Raindrop 会话时)
Client->>Worker: GET /auth/init
Worker->>Raindrop: 授权请求
Raindrop->>User: 同意
User->>Raindrop: 批准访问
Raindrop->>Worker: GET /auth/callback?code=XXX&state=YYY
Worker->>KV: 存储加密的 Raindrop 令牌
Worker->>Client: 继续 /authorize 同意
User->>Worker: 批准 MCP 客户端
Worker->>KV: 存储授权代码
Worker->>Client: 重定向代码
Client->>Worker: POST /token
Worker->>Client: JWT 访问令牌
Client->>Worker: POST /mcp (Bearer JWT)
Worker->>KV: 获取加密的 Raindrop 令牌
Worker->>Raindrop: 使用 Raindrop 令牌的 MCP 操作
Raindrop->>Worker: 响应
Worker->>Client: MCP 结果
```
## 多租户模型
```mermaid
graph LR
subgraph "共享服务器实例"
Endpoint["MCP 端点\n/mcp"]
Auth[身份验证层]
subgraph "请求作用域服务"
Service1["RaindropService\n用户 1 令牌"]
Service2["RaindropService\n用户 2 令牌"]
Service3["RaindropService\n用户 3 令牌"]
end
end
subgraph "用户"
User1[用户 1]
User2[用户 2]
User3[用户 3]
end
subgraph "存储"
KV["Workers KV"]
end
User1 -->|Bearer JWT| Endpoint
User2 -->|X-Raindrop-Token| Endpoint
User3 -->|Bearer JWT| Endpoint
Endpoint --> Auth
Auth --> KV
Auth -->|令牌 A| Service1
Auth -->|令牌 B| Service2
Auth -->|令牌 C| Service3
Service1 --> API[Raindrop.io API]
Service2 --> API
Service3 --> API
```
## 开发
```bash
bun run dev
bun run type-check
bun test
```
## 故障排除
- 401:缺少身份验证(OAuth 流未完成或没有 X-Raindrop-Token)
- 406:客户端必须发送 `Accept: application/json, text/event-stream`
- 500:检查日志和令牌有效性
## 许可证
MIT