135 lines
6.3 KiB
Markdown
135 lines
6.3 KiB
Markdown
# MCP-сервер «Rubber Duck» — план реализации
|
||
|
||
## Контекст
|
||
|
||
Проект **rubber-duck** — интерактивная уточка для дебага. MCP-сервер расширяет концепцию: LLM (Claude, Cursor) может «обращаться к уточке» за кряком и мудростью. Сервер — отдельный репозиторий, деплой на Vercel (Hobby, бесплатно).
|
||
|
||
---
|
||
|
||
## Стек
|
||
|
||
| Что | Пакет | Зачем |
|
||
| ----------- | ------------------------------------- | ------------------------------------------------- |
|
||
| Фреймворк | **Next.js 15+** (App Router) | Route Handlers на Vercel, autodeploy из коробки |
|
||
| MCP-адаптер | **`mcp-handler` ^2.1.1** | HTTP-адаптер от Vercel, stateless Streamable HTTP |
|
||
| MCP SDK | **`@modelcontextprotocol/server` ^2** | McpServer, registerTool, registerResource |
|
||
| Валидация | **`zod` ^4** | Schema для input тулзов |
|
||
|
||
`@vercel/mcp-adapter` и `@modelcontextprotocol/sdk` v1 — **устарели**. Используем `mcp-handler` v2 + `@modelcontextprotocol/server` v2.
|
||
|
||
---
|
||
|
||
## Философия сервера
|
||
|
||
Сервер — **Explicit Reasoning Buffer** (буфер явных рассуждений). Не решает задачи за модель. Когда LLM застревает в логическом цикле, вызов `quack()` заставляет:
|
||
|
||
1. **Сформулировать аргументы** — выгрузить мысли из весов в текст.
|
||
2. **Прервать генерацию** — сделать паузу и структурировать задачу.
|
||
3. **Создать внешнюю память** — задокументировать пройденный этап.
|
||
|
||
---
|
||
|
||
## Архитектура
|
||
|
||
```txt
|
||
rubber-duck-mcp/
|
||
├── app/
|
||
│ ├── layout.tsx — корневой layout
|
||
│ ├── page.tsx — заглушка
|
||
│ └── api/mcp/route.ts — MCP-хендлер (GET + POST)
|
||
├── lib/
|
||
│ └── mcp.ts — McpServer + инструменты
|
||
├── package.json
|
||
├── tsconfig.json
|
||
└── next.config.ts
|
||
```
|
||
|
||
---
|
||
|
||
## Инструменты
|
||
|
||
### Tool #1: `quack` (ФАЗА 1)
|
||
|
||
Заставляет модель остановиться. Аргумент `mood` (опциональный): `"happy" | "confused" | "excited" | "sleepy"`. Без аргумента — случайный кряк из общей пуллы. Возвращает `TextContent` с текстом кряка.
|
||
|
||
### Tool #2: `quack_wisdom` (ФАЗА 2)
|
||
|
||
Кряк + случайная мудрость программиста. Аргумент `topic` (опциональный): `"debugging" | "life" | "code" | "random"`. База мудростей — массив `{ text, author?, topic? }` в `src/data/wisdoms.ts`.
|
||
|
||
### Resource: `about://rubber-duck` (ФАЗА 2)
|
||
|
||
Текстовый документ (~10-15 строк) с описанием философии сервера. Модель читает его и понимает контекст.
|
||
|
||
---
|
||
|
||
## Деплой на Vercel
|
||
|
||
### Вариант A: Vercel CLI (без GitHub)
|
||
|
||
```bash
|
||
npm i -g vercel
|
||
vercel login # авторизация через браузер
|
||
vercel --prod # деплой
|
||
```
|
||
|
||
При первом запуске `vercel` задаст вопросы — отвечаем: Yes, наш аккаунт, No (новый проект), текущая директория. URL будет `https://rubber-duck-mcp.vercel.app`.
|
||
|
||
### Вариант B: GitHub (автодеплой)
|
||
|
||
1. Push в GitHub
|
||
2. Vercel → Add New Project → выбрать репозиторий
|
||
3. Framework: Next.js (автоопределение) → Deploy
|
||
|
||
### Лимиты Hobby (бесплатно)
|
||
|
||
Таймаут функции 300с, деплои 100/день, проектов 200. Для quack ответ за ~1мс — лимиты не актуальны. `vercel.json` не нужен.
|
||
|
||
---
|
||
|
||
## Подключение к клиентам
|
||
|
||
**Cursor:** Settings → Features → MCP → Streamable HTTP → URL `/api/mcp`
|
||
|
||
**Claude Desktop:** в `claude_desktop_config.json` прописать `"url": "https://<project>.vercel.app/api/mcp"`. Если клиент не поддерживает Streamable HTTP — через `mcp-remote` как бридж.
|
||
|
||
---
|
||
|
||
## Чеклист
|
||
|
||
| Проверка | Результат |
|
||
| ------------------------ | ------------------ |
|
||
| `npm run typecheck` | 0 ошибок |
|
||
| `npm run build` | Сборка OK |
|
||
| MCP Inspector (локально) | Видит tools |
|
||
| curl `tools/call` | Возвращает кряк |
|
||
| `vercel --prod` | Деплой OK |
|
||
| MCP Inspector (удалённо) | Работает |
|
||
| Cursor / Claude | LLM вызывает quack |
|
||
|
||
---
|
||
|
||
## Порядок реализации
|
||
|
||
### ФАЗА 1: quack
|
||
|
||
1. `npx create-next-app@latest rubber-duck-mcp --typescript --app`
|
||
2. Установить `mcp-handler`, `@modelcontextprotocol/server`, `zod`
|
||
3. Создать `lib/mcp.ts` — функция `createMcpServer()` с tool `quack`
|
||
4. Создать `app/api/mcp/route.ts` — хендлер через `createMcpHandler`
|
||
5. `npm run typecheck` → исправить ошибки
|
||
6. `npm run build` → убедиться
|
||
7. Тест локально: MCP Inspector + curl
|
||
8. Деплой: `vercel --prod` (или через GitHub)
|
||
9. Тест удалённо: MCP Inspector + curl к Vercel URL
|
||
10. Подключение к Cursor и Claude Desktop — проверить что LLM вызывает quack
|
||
|
||
### ФАЗА 2: quack_wisdom + Philosophy
|
||
|
||
1. Создать `src/data/wisdoms.ts` — база мудростей
|
||
2. Добавить tool `quack_wisdom` в `lib/mcp.ts`
|
||
3. Зарегистрировать resource `about://rubber-duck`
|
||
4. `npm run typecheck` + `npm run build`
|
||
5. Тест локально: MCP Inspector видит оба tool + resource
|
||
6. `vercel --prod` → тест удалённо
|
||
7. Подключение к Cursor/Cude — проверить quack_wisdom
|