npm package: @openaisdk/billing-mcp
Description: MCP server: управление планами и ценами Billing API (catalog)
Author: Anatoliy Tukov
Latest version: 1.0.0

# `@openaisdk/billing-mcp` (billing-catalog MCP)

[MCP](https://modelcontextprotocol.io/)‑сервер по stdio для работы с **каталогом** Billing Platform через REST API: **проекты**, **планы**, **цены**, **фичи** и привязки фич к планам (`plan-features`). Подходит для Cursor, Claude Desktop и любых клиентов с поддержкой MCP.

**Пакет в репозитории:** `packages/billing-catalog-mcp`  
**Имя на npm:** `@openaisdk/billing-mcp`  
**Бинарь:** `billing-catalog-mcp`

---

## Контекст и цель

В multi-tenant billing у **tenant** есть один или несколько **projects**. У каждого **project** свой каталог: **plans**, **prices**, **features**, **entitlements** (через подписки). Этот MCP не заменяет Admin UI и не обслуживает checkout — он даёт агентам и разработчикам **программный доступ к каталогу** того project, к которому привязан integration key.

**Зачем использовать MCP:** настройка демо-каталога, сценарии в IDE с ИИ, скриптоподобные операции без написания отдельного HTTP-клиента.

---

## Аудитория

- Разработчики платформы и интеграторы, у которых уже есть доступ к Billing API.
- Команды, которые подключают MCP в Cursor/другом клиенте для работы с планами и ценами.

---

## Термины

| Термин | Значение |
|--------|----------|
| **Tenant** | Изолированный арендатор платформы; определяется на стороне API по ключу. |
| **Project** | Продукт/линейка внутри tenant; у него свой каталог. `projectId` — UUID. |
| **Plan** | Тарифный план (код уникален в рамках project). |
| **Price** | Цена для плана (интервал `month` / `year`, сумма в минорных единицах). |
| **Feature** | Возможность или лимит (`boolean` / `limit`). |
| **Plan-feature** | Привязка фичи к плану с флагом и/или лимитом. |
| **Project-scoped API key** | Ключ M2M из Admin UI → Интеграция; даёт доступ только к данным своего project (см. ADR-010). |

---

## Scope: что делает сервер

**Реализовано в коде:**

- Чтение списка **projects** tenant’а (в рамках прав ключа).
- CRUD **plans** и **prices** для выбранного `projectId`.
- Список/создание **features**, список/создание **plan-features**.
- Вспомогательные инструменты для **локальной разработки и пилотов**: сброс каталога проекта (через dev-эндпоинт API), сид MegaRetro, идемпотентное обновление фич/лимитов MegaRetro.

**Не входит в scope пакета:**

- Подписки, инвойсы, customer accounts, checkout, webhooks (для этого — Billing API/SDK/Admin UI).
- Обход аутентификации без ключа: модель **только Bearer project-scoped key** (см. ниже).

---

## Предпосылки

1. Развёрнутый **Billing API** (локально или удалённо).
2. **Project-scoped integration key** (`BILLING_API_KEY`): создаётся в **Admin UI → Интеграция** или выдаётся после `pnpm db:seed` в консоли (локальная разработка).
3. **UUID project** — в аргументах инструментов (`projectId`) **или** в переменной **`BILLING_PROJECT_ID`** (тот же договор, что у `@openaisdk/billing-sdk`).

**Auth (ADR-010):** `Authorization: Bearer <BILLING_API_KEY>`. Если задан **`BILLING_HTTP_X_TENANT_ID`**, в запросы добавляется заголовок `x-tenant-id` (как в OpenAPI/SDK). Tenant/project по-прежнему резолвятся из ключа на стороне API.

---

## Установка

### Из npm (потребители вне монорепозитория)

```bash
pnpm add -g @openaisdk/billing-mcp@latest
# или без глобальной установки — см. npx ниже
```

### Из монорепозитория `saas-billing`

```bash
pnpm install
pnpm --filter @openaisdk/billing-mcp run build
```

Запуск собранного сервера:

```bash
node packages/billing-catalog-mcp/dist/index.js
```

Локальная отладка без сборки:

```bash
pnpm --filter @openaisdk/billing-mcp run dev
```

---

## Переменные окружения

Сервер подгружает `.env` из **текущей рабочей директории** процесса (`dotenv/config`). В Cursor обычно задают `env` в конфиге MCP или `cwd` на корень проекта, где лежит `.env`.

| Переменная | Обязательно | Описание |
|------------|-------------|----------|
| `BILLING_API_KEY` | **Да** | Project-scoped integration key (Bearer). Без него процесс завершится при старте. |
| `BILLING_API_URL` | Нет | Base URL Billing API **без** завершающего `/`. По умолчанию `http://127.0.0.1:4001`. |
| `BILLING_PROJECT_ID` | Нет | UUID проекта: подставляется, если в аргументе инструмента не передан `projectId`. |
| `BILLING_HTTP_X_TENANT_ID` | Нет | UUID tenant → заголовок `x-tenant-id` (согласовано с SDK / OpenAPI). |

Устаревший алиас: `BILLING_API_BASE_URL` (используется только если `BILLING_API_URL` пуст).

**Безопасность:** не коммитьте ключи. Для CI используйте секреты окружения.

Источник истины по именам — `.env.example` в каталоге пакета и `@openaisdk/billing-sdk` (те же четыре переменные).

---

## Подключение MCP-клиента (пример Cursor)

Файл настроек: `.cursor/mcp.json` (или аналог в вашем клиенте).

### Вариант A: `npx` (после публикации пакета)

```json
{
  "mcpServers": {
    "billing-catalog": {
      "command": "npx",
      "args": ["-y", "@openaisdk/billing-mcp@latest"],
      "env": {
        "BILLING_API_URL": "http://127.0.0.1:4001",
        "BILLING_API_KEY": "<project-scoped-key>",
        "BILLING_PROJECT_ID": "<project-uuid>",
        "BILLING_HTTP_X_TENANT_ID": "<tenant-uuid>"
      }
    }
  }
}
```

### Вариант B: сборка из клонированного репозитория

```json
{
  "mcpServers": {
    "billing-catalog": {
      "command": "node",
      "args": ["packages/billing-catalog-mcp/dist/index.js"],
      "cwd": "${workspaceFolder}",
      "env": {
        "BILLING_API_URL": "http://127.0.0.1:4001",
        "BILLING_API_KEY": "<из вывода pnpm db:seed или Admin UI>",
        "BILLING_PROJECT_ID": "<из seed / Admin UI>",
        "BILLING_HTTP_X_TENANT_ID": "<из seed / Admin UI>"
      }
    }
  }
}
```

После изменения конфигурации перезапустите MCP в клиенте (в Cursor: Settings → MCP → Restart).

**Локальный быстрый старт credentials:** `pnpm db:seed` — в консоли появятся в том числе project UUID и API key; подставьте их в `env` и используйте UUID как `projectId` в инструментах.

Дополнительно по нескольким MCP-серверам репозитория: [docs/mcp-integration-guide.md](../../docs/mcp-integration-guide.md).

---

## Инструменты (tools)

Ответы приходят как **JSON-текст** в content MCP. При ошибке HTTP или валидации клиент получит сообщение с префиксом `Error: ...`.

### Проекты

| Tool | Назначение |
|------|------------|
| `billing_list_projects` | `GET /v1/projects` — проекты tenant’а, доступные ключу. Аргументов нет. |

### Планы

| Tool | Назначение |
|------|------------|
| `billing_list_plans` | Список планов. Нужен `projectId`. |
| `billing_get_plan` | План по ID: `projectId`, `planId`. |
| `billing_create_plan` | Создание: `projectId`, `code`, `name`; опционально `description`, `isPublic`, `isActive`, `sortOrder`. |
| `billing_update_plan` | PATCH: `projectId`, `planId`; поля плана кроме `code`. |

### Цены

| Tool | Назначение |
|------|------------|
| `billing_list_prices` | Список цен проекта. |
| `billing_get_price` | Цена по ID: `projectId`, `priceId`. |
| `billing_create_price` | Создание: `projectId`, `code`, `amountMinor`, `interval` (`month` \| `year`). Нужен **`planId` или `planCode`**. Опционально: `currency` (по умолчанию `RUB`), `intervalCount`, `trialDays`, `isActive`. |
| `billing_update_price` | PATCH: `projectId`, `priceId`. Поля: `code`, `amountMinor`, `currency`, `interval`, `intervalCount`, `trialDays`, `isActive`. План сменить нельзя. |

### Фичи и plan-features

| Tool | Назначение |
|------|------------|
| `billing_list_features` | Список фич проекта. |
| `billing_create_feature` | Создать фичу: `projectId`, `code`, `name`, `kind` (`boolean` \| `limit`). |
| `billing_list_plan_features` | Привязки фич к плану. Нужны `projectId` и **`planId` или `planCode`**. |
| `billing_create_plan_feature` | Привязать фичу к плану: `projectId`, `featureId`, плюс **`planId` или `planCode`**. Для лимитов: `limitValue` (для безлимита — `null` в JSON аргумента); для boolean — `enabled`. |

### Разработка и сиды MegaRetro

| Tool | Назначение |
|------|------------|
| `billing_reset_project_catalog` | `POST /v1/dev/projects/:projectId/reset-catalog` — жёсткий сброс каталога и связанных billing-сущностей проекта. На стороне API действует **DevOnlyGuard**: в **production** недоступно. Не удаляет customer accounts и сам project. |
| `billing_reset_and_seed_megaretro_catalog` | Сброс проекта (как выше), затем полный сид каталога MegaRetro (планы, цены, trial, фичи, add-on и т.д. по внутреннему канону репозитория). |
| `billing_upsert_megaretro_features_and_limits` | Без сброса: идемпотентно создаёт недостающие фичи и привязки для планов free/team/business/enterprise. |

Инструменты с «MegaRetro» в названии заточены под **пилотный каталог** первого consumer’а; для других продуктов используйте обычные CRUD-инструменты.

---

## Ошибки и ограничения

- **Нет ключа:** при старте — ошибка с текстом про `BILLING_API_KEY`.
- **HTTP-ошибки API:** возвращаются как `Error: HTTP <status>: <body>`.
- **Dev reset:** эндпоинт `/v1/dev/...` отключён в production-сборке API; не рассчитывайте на сброс в бою.
- **Суммы:** `amountMinor` — в **минорных единицах** (копейки для RUB).
- **`planCode`:** резолвится через список планов проекта; при опечатке будет ошибка «план не найден».

---

## Верификация (чеклист)

- [ ] Billing API доступен по `BILLING_API_URL` (или дефолт localhost).
- [ ] `BILLING_API_KEY` — действующий project-scoped key; при необходимости заданы `BILLING_PROJECT_ID` / `BILLING_HTTP_X_TENANT_ID`.
- [ ] Вызов `billing_list_projects` возвращает JSON со списком проектов.
- [ ] Вызов `billing_list_plans` с правильным `projectId` возвращает планы (или пустой массив).
- [ ] После изменения `mcp.json` MCP перезапущен.

---

## Ссылки

- [MCP Integration Guide](../../docs/mcp-integration-guide.md) — обзор MCP в репозитории и auth после ADR-010.
- [ADR-010: Project-scoped Integration Auth](../../docs/adr/ADR-010-project-scoped-integration-auth.md).
- [Consumer integration guide](../../docs/consumer-integration-guide.md) — M2M-интеграция приложений (шире, чем MCP).
- Публичные контракты API: [docs/api/public-api-v1.md](../../docs/api/public-api-v1.md), [docs/api/admin-api.md](../../docs/api/admin-api.md) (актуальные пути уточняйте по OpenAPI/Swagger вашего стенда).

---

## Лицензия

MIT (см. `package.json`).