内容
# recurly-mcp
[](https://github.com/francktrouillez/recurly-mcp/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/recurly-mcp)
[](LICENSE)
[](https://nodejs.org)
一款**只读**的MCP(模型上下文协议)服务器,暴露 [Recurly v2021-02-25 API](https://recurly.com/developers/api/v2021-02-25/index.html) 给LLM客户端。与任何MCP兼容的客户端(Claude Desktop,Claude Code,Cursor,Cline,Codex CLI,Continue.dev等)一起工作。
三十个资源分组的工具涵盖了Recurly暴露的每个读取(`GET`)端点——账户、订阅、发票、交易、行项目、计划、优惠券、商品、使用情况、导出、外部产品/订阅等——以及一个通用的`recurly_request`逃生阀,用于处理未直接建模的任何内容。
**该服务器从设计上是只读的:HTTP客户端只会发出`GET`请求。没有任何代码路径可以创建、更新或删除Recurly数据——包括通过逃生阀。**
**非官方。未经Recurly官方认可或支持。**
## 安装
### Claude Code(一行命令)
```bash
claude mcp add recurly --scope user \
--env RECURLY_API_KEY=您的私有API密钥 \
-- npx -y recurly-mcp
```
重启Claude Code,`recurly_*`工具即可使用。
### 直接运行二进制文件(可选)
服务器通常由MCP客户端通过标准输入/输出启动。为了单独测试:
```bash
RECURLY_API_KEY=您的私有API密钥 npx recurly-mcp
```
它将等待标准输入上的JSON-RPC消息。仅用于安装调试。
## 配置
所有配置均通过环境变量进行。
| 变量 | 是否必需 | 默认值 | 用途 |
|---|---|---|---|
| `RECURLY_API_KEY` | 是 | — | 私有API密钥。作为HTTP基本身份验证用户名发送(空密码)。 |
| `RECURLY_REGION` | 否 | `us` | `us`或`eu` — 选择API主机。 |
| `RECURLY_HOST` | 否 | `https://v3.recurly.com` | 完全覆盖API源(本地模拟、代理)。覆盖`RECURLY_REGION`。 |
| `RECURLY_API_VERSION` | 否 | `v2021-02-25` | 在`Accept`头部发送的Recurly API版本。这里的工具路径/参数基于`v2021-02-25`建模。 |
| `RECURLY_TIMEOUT_MS` | 否 | `15000` | 每个请求的超时时间。 |
| `RECURLY_MAX_RETRIES` | 否 | `2` | 429和5xx的重试(遵守`Retry-After`,等效抖动退避)。 |
从Recurly仪表板 → 集成 → API凭证获取私有API密钥。根据需要使用限定为只读访问的密钥——此服务器从不写入,但深度防御是好的。
## MCP客户端配置
以下MCP条目对每个MCP客户端都是相同的——只有配置文件位置不同。
```json
{
"mcpServers": {
"recurly": {
"command": "npx",
"args": ["-y", "recurly-mcp"],
"env": {
"RECURLY_API_KEY": "您的私有API密钥"
}
}
}
}
```
根据客户端不同,放置位置如下:
| 客户端 | 位置 |
|---|---|
| **Claude Desktop** (macOS) | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| **Claude Code** | `~/.claude.json` — 或使用 `claude mcp add recurly --scope user --env RECURLY_API_KEY=… -- npx -y recurly-mcp` |
| **Cursor** | `.cursor/mcp.json`(每个项目)或 `~/.cursor/mcp.json`(用户范围) |
| **Cline (VS Code)** | VS Code 设置 → Cline → MCP服务器(UI),或 `cline_mcp_settings.json` |
| **Codex CLI** | `~/.codex/config.json` 下的 `mcpServers` |
| **Continue.dev** | `.continue/config.json` 下的 `experimental.modelContextProtocolServers` |
对于欧盟数据区域,在 `env` 中添加 `"RECURLY_REGION": "eu"`。
## 工具
每个操作都是只读的。每个工具接受一个 `action` 标识加上该操作的参数。
| 工具 | 操作 |
|---|---|
| `recurly_sites` | `list`, `get` |
| `recurly_accounts` | `list`, `get`, `get_balance`, `get_acquisition`, `list_acquisitions`, `list_child_accounts`, `list_notes`, `get_note`, `list_entitlements` |
| `recurly_billing_info` | `get`, `list`, `get_one` |
| `recurly_shipping_addresses` | `list`, `get` |
| `recurly_coupons` | `list`, `get`, `list_unique_coupon_codes`, `get_unique_coupon_code` |
| `recurly_coupon_redemptions` | `list_for_account`, `list_active_for_account`, `get_for_account`, `list_for_invoice`, `list_for_subscription`, `get_for_subscription` |
| `recurly_credit_payments` | `list`, `get`, `list_for_account` |
| `recurly_invoices` | `list`, `get`, `get_pdf`, `list_line_items`, `list_related`, `list_for_account` |
| `recurly_line_items` | `list`, `get`, `list_for_account` |
| `recurly_subscriptions` | `list`, `get`, `get_change`, `get_preview_renewal`, `list_invoices`, `list_line_items`, `list_for_account` |
| `recurly_transactions` | `list`, `get`, `list_for_account` |
| `recurly_custom_field_definitions` | `list`, `get` |
| `recurly_items` | `list`, `get` |
| `recurly_measured_units` | `list`, `get` |
| `recurly_plans` | `list`, `get`, `list_add_ons`, `get_add_on` |
| `recurly_add_ons` | `list`, `get` |
| `recurly_shipping_methods` | `list`, `get` |
| `recurly_usage` | `list`, `get` |
| `recurly_export` | `get_dates`, `get_files` |
| `recurly_dunning_campaigns` | `list`, `get` |
| `recurly_invoice_templates` | `list`, `get`, `list_accounts` |
| `recurly_external_products` | `list`, `get`, `list_references`, `get_reference` |
| `recurly_external_subscriptions` | `list`, `get`, `list_invoices`, `list_payment_phases`, `get_payment_phase`, `list_for_account` |
| `recurly_external_invoices` | `list`, `get`, `list_for_account` |
| `recurly_external_accounts` | `list`, `get` |
| `recurly_general_ledger_accounts` | `list`, `get` |
| `recurly_performance_obligations` | `list`, `get` |
| `recurly_price_segments` | `list`, `get` |
| `recurly_business_entities` | `list`, `get`, `list_invoices` |
| `recurly_gift_cards` | `list`, `get` |
| `recurly_request` | 逃生阀 — 对任何Recurly API路径的原始 `GET` 请求。 |
工具返回原始Recurly JSON有效载荷,不进行字段剥离。`list`操作添加一个 `_pagination` 元数据对象,以便模型可以迭代页面。
### ID和代码
大多数ID参数接受**任意**Recurly对象ID(例如 `e28zov4fw0v2`)**或**前缀人类密钥:
- 账户/计划/商品/优惠券/…:`code-<您的代码>`
- 网站:`subdomain-<名称>`
- 发票:`number-<发票号码>`
- 订阅/交易:`uuid-<uuid>`
值在插值前进行URL编码,因此包含特殊字符的代码可以正常工作,并且路径遍历段被拒绝。
### 分页
Recurly使用基于游标的分页。`list`操作接受 `limit`(1–200),`order`(`asc`/`desc`),`sort`,`cursor`,`ids`,`begin_time`,`end_time`,以及资源特定的筛选器(`state`,`type`等)。响应包含Recurly原生的 `has_more`/`next`,以及此服务器添加的 `_pagination` 提示:
```json
{ "object": "list", "has_more": true, "next": "/accounts?cursor=…", "data": [ … ],
"_pagination": { "has_more": true, "next_cursor": "…" } }
```
将 `_pagination.next_cursor` 作为 `cursor` 传回以获取下一页。
### 发票PDF
`recurly_invoices` `get_pdf` 以base64包装器返回PDF,而不是损坏的字符串:
```json
{ "object": "binary_file", "content_type": "application/pdf", "encoding": "base64", "byte_length": 12345, "data": "JVBERi0…" }
```
### 覆盖说明
- **写入操作故意不建模。** 这是一个只读服务器;客户端只能发出 `GET` 请求。
- **超出公共集的筛选器** 可以通过 `recurly_request` (`{ "path": "/...", "query": { … } }`) 达到,如果特定列表端点接受未在其类型化工具上建模的参数。
## 开发
```bash
npm install
npm test # vitest,154个测试
npm run typecheck
npm run lint
npm run build # 生成dist/
npm run validate # 启动构建的服务器,检查工具模式(期望31个工具)
npm run dev # tsx src/bin.ts(用于本地标准输入/输出测试)
```
## 贡献
在 <https://github.com/francktrouillez/recurly-mcp/issues> 上欢迎问题和拉取请求。
错误报告最有用的是:调用的工具和操作,参数(隐藏机密),以及响应。
## 许可证
MIT