Files
suno-mcp-server/NexusAI/README.md
T
OpenCode 62c692c5a1 Add managed provider keys: encrypted store + env>DB resolver
AES-256-GCM encryption (KeyCipher) with master key from NEXUS_MASTER_KEY,
never persisted. ProvidersStore in SQLite: CRUD, enable/disable, default,
encrypted api keys, masked views for UI. KeyResolver applies env>DB precedence
and supports multiple providers. context.ts registers providers dynamically
from resolved config; backward compatible with env-only setups.
2026-08-17 17:12:26 +07:00

162 lines
8.0 KiB
Markdown
Raw 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.
# NexusAI — универсальный MCP-сервис для агентов
Единый MCP-сервер (TypeScript, stdio), дающий агентам провайдер-абстрагированный доступ к:
- **TTS** — озвучка текста
- **STT** — распознавание речи (локально, faster-whisper)
- **Изображения** — генерация и правка
- **Видео** — text→video / image→video
- **Музыка** — генерация треков
- **Веб-поиск** — ответ с цитатами (search-augmented модели)
Первый провайдер — **NordRouter**. Архитектура расширяемая: RouterAI, GPTunnel, OpenRouter и облачные STT добавляются как новые адаптеры без изменения MCP-инструментов. Каждая операция логируется в SQLite (провайдер, модель, стоимость, статус, файл) — основа для будущей веб-админки.
## Структура
```
NexusAI/
├── packages/
│ ├── core/ # провайдеры, media-storage, journal, типы, registry
│ └── mcp-server/ # stdio MCP-сервер (10 инструментов)
├── sidecar/ # faster-whisper STT (PEP 723, запуск через uv)
├── .env.example
└── .opencode/opencode.json
```
## Установка
```bash
cd NexusAI
npm install
npm run build
```
> `better-sqlite3` собирается нативно. Если сборка прервалась: `npm rebuild better-sqlite3`.
Для STT нужен [`uv`](https://docs.astral.sh/uv/) и `ffmpeg`. Зависимости whisper `uv` ставит автоматически при первом запуске.
## Подключение к opencode
`.opencode/opencode.json`:
```json
{
"mcp": {
"nexusai": {
"type": "local",
"command": ["node", "/абс/путь/NexusAI/packages/mcp-server/dist/index.js"],
"env": {
"NORDROUTER_API_KEY": "sk-...",
"NEXUS_MEDIA_DIR": "/абс/путь/NexusAI/media-output",
"NEXUS_STT_MODEL": "small"
}
}
}
}
```
Переменные окружения — см. `.env.example`.
## Инструменты
| Инструмент | Назначение |
|---|---|
| `nexus_tts` | текст → речь (`audio/elevenlabs-tts`, `audio/gemini-3.1-flash-tts`, …) |
| `nexus_image` | генерация/правка изображений (`image/*`) |
| `nexus_video` | видео из текста/фото (`video/*`) |
| `nexus_music` | музыка (`music/*`) |
| `nexus_stt` | речь → текст (локально) |
| `nexus_web_search` | веб-поиск с цитатами (`perplexity/sonar*`, `search/*`) |
| `nexus_media_models` | список моделей провайдера (id, тип, цена) |
| `nexus_media_estimate` | оценка стоимости до запуска |
| `nexus_media_upload` | загрузка исходника (фото/аудио/видео) |
| `nexus_usage_stats` | траты и история из журнала |
### Единый формат вызова
```json
{
"provider": "nordrouter",
"model": "audio/elevenlabs-tts",
"input": { "text": "Привет, мир", "voice": "James · Husky, Engaging and Bold" },
"output": { "save": true, "embed": false }
}
```
- `provider` опционален (default из `NEXUS_DEFAULT_PROVIDER`).
- `input` пропускает любые модель-специфичные поля (`aspect_ratio`, `resolution`, `duration`, `sound`, …).
- `output.save` — сохранять файл локально (по умолчанию да).
- `output.embed` — встроить image/audio прямо в ответ MCP (с лимитом размера).
### Единый формат ответа
```json
{
"provider": "nordrouter",
"capability": "tts",
"model": "audio/elevenlabs-tts",
"status": "done",
"file_path": "/.../media-output/audio-...wav",
"mime_type": "audio/wav",
"result_url": "https://nordrouter.com/media/file/...",
"result_url_2": null,
"cost_usd": 0.0049
}
```
`result_url_2` заполняется для музыкальных моделей, отдающих два трека (Suno).
## Как это работает
- **Media** асинхронно: `POST /media/generate` → polling `GET /media/job/:id` → скачивание `result_url` в `NEXUS_MEDIA_DIR`. Таймаут зависит от типа (картинки — быстро, видео/музыка — до минут).
- **Web search** через OpenAI-совместимый `/v1/chat/completions` с sonar/`search/*`; цитаты берутся из `message.annotations[].url_citation`.
- **STT** локально: TS запускает `uv run sidecar/stt_server.py`; faster-whisper декодирует аудио (mp3/wav/ogg/m4a/webm) и возвращает `{text, language, segments}`.
- **Журнал** SQLite (`nexus.sqlite` в media-dir) пишет каждую операцию; `nexus_usage_stats` агрегирует траты.
- MCP работает по stdio — **все логи идут в stderr**.
## Ключи провайдеров
Ключи можно задавать двумя способами, с приоритетом **env → БД**:
1. **Env (приоритет)**`NORDROUTER_API_KEY``<NAME>_API_KEY` для других провайдеров). Просто для CI и локального запуска.
2. **Зашифрованная БД** — управляется из будущей админки. Ключи хранятся в SQLite, зашифрованные **AES-256-GCM** на мастер-ключе `NEXUS_MASTER_KEY` (сам мастер-ключ — только в env, в БД его нет).
Свойства слоя:
- В git/логи/БД сырой ключ не попадает; в UI показывается только маска `sk-…last4`.
- Бэкап БД не раскрывает ключи (нужен мастер-ключ).
- Ротация `NEXUS_MASTER_KEY` инвалидирует зашифрованные ключи — их нужно ввести заново.
- Без `NEXUS_MASTER_KEY` работают только env-ключи (сервер предупреждает в stderr).
Программное управление (пока до админки) — через `@nexusai/core`:
```ts
import { KeyCipher, ProvidersStore } from '@nexusai/core';
const cipher = new KeyCipher(process.env.NEXUS_MASTER_KEY);
const store = new ProvidersStore('./media-output/nexus.sqlite', cipher);
store.upsert({ name: 'nordrouter', type: 'nordrouter', apiKey: 'sk-...', isDefault: true });
store.setEnabled('nordrouter', true);
store.listViews(); // masked view for UI
```
Генерация мастер-ключа: `openssl rand -hex 32`.
## STT в ограниченных сетях
faster-whisper скачивает модель с HuggingFace. Если `huggingface.co` недоступен:
- задать зеркало: `HF_ENDPOINT=https://hf-mirror.com`
- либо предзагрузить модель и указать путь: `NEXUS_STT_MODEL=/abs/model-dir` + `NEXUS_STT_LOCAL_ONLY=1`
- либо кэш-директорию: `NEXUS_STT_DOWNLOAD_ROOT=./models`
## Расширение: новый провайдер
1. Реализовать `MediaProvider` / `SearchProvider` / `SttProvider` из `@nexusai/core`.
2. Зарегистрировать в `packages/mcp-server/src/context.ts`.
Инструменты и схемы менять не нужно — они провайдер-агностичны.
## Roadmap
- Фаза 2: веб-админка (отдельный пакет `admin`, Hono/Fastify + лёгкий фронт) на общем `core`: галерея контента, дашборд трат, управление провайдерами.
- Доп. провайдеры: RouterAI, GPTunnel, OpenRouter; облачный STT.