Files
vasyanskandClaude Sonnet 5 8675c6833e
CI / Test (push) Failing after 26s
CI / Publish to npm (push) Skipped
Зафиксируй результат живой проверки MCP-сервера
Все 6 инструментов проверены живым MCP-протоколом против прода
реальным ключом: баланс, каталог (включая speech без цены), подбор
модели, оценка стоимости, usage, список ключей. Секрет нигде не
утёк (stderr пуст). Каталог TTS-моделей на проде изменился со
вчерашнего дня — отражается верно, это не баг сервера.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-24 11:04:59 +07:00

62 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`, которого у агента нет).