# Feature: клиентский MCP-сервер для openrusrouter.ru Дата: 2026-10-24 ## Задача Клиентский MCP-сервер (TypeScript/Node, npm-пакет, stdio) для быстрой настройки интеграции и выбора модели прямо из Claude Desktop/Code/Cursor/OpenCode. ## Research (консилиум) - architect/api/security/devops. Ключевая находка security-агента: Bearer-ключ сам по себе НЕ read-only (доступны платежи/промокоды/тикеты) — периметр «только чтение» держится ИСКЛЮЧИТЕЛЬНО дисциплиной самого MCP-пакета (узкий HTTP-клиент на 7 строго заданных GET-методов, без универсального `fetch(url, method)`). - Мутации API-ключей (создание/отзыв) физически недоступны Bearer-ключом — серверный инвариант `cabinet.sessionOnly`, не наше решение, а факт из кода бэкенда (`cabinet/middleware.go:118`). - Решение владельца: список ВСЕХ ключей аккаунта показывать (поля обрезаны, секрет никогда не возвращается). ## Plan Детальный план по файлам (Plan-агент), с уточнениями по факту: `/api/keys` и `/v1/auth/key` оборачивают массив/объект в `{keys:[...]}`/`{data:{...}}` (не так, как в OpenAPI-спеке бэкенда — расхождение зафиксировано в коде и README). ## Реализация (3 волны, параллельные exec-агенты) - Волна 1: репозиторий `pub/openrusrouter-mcp`, живые проверки 7 эндпоинтов с фикстурами, package.json/tsconfig/eslint, утилиты (config/redact/errors/ money/sanitize/cache) с тестами. - Волна 2: `client.ts` (заморожен, ровно 7 методов, никакого произвольного HTTP), `catalog.ts` (join `/api/models`+`/v1/models`), 6 MCP-инструментов (list_models, pick_model, estimate_cost, get_balance, get_usage, list_api_keys), entry point с перенаправлением console в stderr. - Волна 3: README (быстрый старт для 4 клиентов, явный блок «чего тут нет и почему»), CHANGELOG, CI (`.gitea/workflows/ci.yaml`: test на каждый push, publish только по тегу `v*`, секрет `NPM_TOKEN` в `env:` шага). ## Validation - `npm run typecheck && npm test && npm run build && npm run lint && npm pack --dry-run` — чисто, 64/64 теста. - **Живой smoke-тест через настоящий MCP-протокол** (`StdioClientTransport`) против `https://openrusrouter.ru` реальным ключом: - `get_balance` — сходится с кабинетом. - `list_models` (text, speech) — корректные данные, у speech `price_note` без цифр. - `pick_model` — работает. - `estimate_cost` — верно отказывает для speech-модели и несуществующего id, верно считает для текстовой модели (сверено вручную). - `get_usage` — реальные данные за 7 дней, совпадают со вчерашними TTS- тестами (elevenlabs, whisper). - `list_api_keys` — показывает все ключи аккаунта, `is_current_key` верно определяет используемый, секрет нигде не виден. - stderr пуст, ключ нигде не утёк (`KEY_LEAK_IN_STDERR: false`). - Побочно замечено: каталог TTS-моделей на проде изменился со вчера (Gemini/ voxtral пропали из списка speech) — это действие администратора в кабинете, не баг MCP-сервера; подтверждено, что `estimate_cost`/`list_models` честно отражают актуальный каталог, а не кэш старых данных. ## Статус Done (код + живая проверка). НЕ запушено в удалённый репозиторий, НЕ опубликовано в npm — оба действия требуют отдельного подтверждения (публикация — необратимое публичное действие, нужен секрет `NPM_TOKEN`, которого у агента нет).