# MCP-сервер «Rubber Duck» — план реализации ## Контекст Проект **rubber-duck** — интерактивная уточка для дебага. MCP-сервер расширяет концепцию: LLM-модель (Claude, Cursor) может «обращаться к уточке» за кряком и мудростью. Сервер — **отдельный репозиторий**, деплой на **Vercel**, стек: **Express + TypeScript + Streamable HTTP**. --- ## Философия сервера Сервер не решает задачи за модель. Он — **Explicit Reasoning Buffer** (буфер явных рассуждений). Когда модель застревает в логическом цикле или склонна к галлюцинациям, вызов `quack()` заставляет её: 1. **Сформулировать аргументы** — чтобы вызвать инструмент, модель должна выгрузить промежуточные мысли из весов в текст. Неявные рассуждения становятся явными данными. 2. **Прервать генерацию** — вместо того чтобы «проскочить» сложный момент, модель делает паузу и структурирует задачу. 3. **Создать внешнюю память** — записывая статус в «уточку», модель формирует краткое резюме пройденных этапов. Описывается через **Resource** `about://rubber-duck` — текстовый документ, который сервер отдаёт при запросе. Модель читает его и понимает контекст. --- ## Архитектура ```txt rubber-duck-mcp/ ├── api/mcp.ts — Express handler для Vercel Serverless ├── src/ │ ├── server.ts — McpServer: регистрация tools + resources │ ├── tools/ │ │ ├── quack.ts — Tool: случайный кряк │ │ └── quack-wisdom.ts — Tool: кряк + мудрость программиста (ФАЗА 2) │ ├── data/ │ │ └── wisdoms.ts — Массив цитат/мудростей (ФАЗА 2) │ └── index.ts — Express dev-сервер (localhost) ├── vercel.json ├── package.json └── tsconfig.json ``` --- ## Зависимости - **@modelcontextprotocol/sdk** — McpServer + StreamableHTTPServerTransport - **express** — HTTP-сервер - **@types/express, typescript** — типизация - **tsx** — dev-запуск TypeScript без сборки --- ## Инструменты (Tools) ### Tool #1: `quack` (ФАЗА 1 — полная реализация) - **Назначение**: Заставляет модель остановиться и сформулировать мысль - **Аргументы**: `mood` (опциональный) — `"happy" | "confused" | "excited" | "sleepy"` - **Логика**: Без аргументов — случайный кряк. С `mood` — кряк подбирается по настроению - **Возвращает**: `TextContent` с текстом кряка ### Tool #2: `quack_wisdom` (ФАЗА 2 — после проверки Tool #1) - **Назначение**: Кряк + случайная мудрость для программиста - **Аргументы**: `topic` (опциональный) — `"debugging" | "life" | "code" | "random"` - **Логика**: Генерирует кряк, выбирает мудрость из базы (фильтр по topic), форматирует - **Возвращает**: `TextContent` — кряк + мудрость + автор ### База мудростей (`data/wisdoms.ts`) — ФАЗА 2 Массив `{ text, author?, topic? }`. Классические цитаты (Kernighan, Knuth, Stallman) + юмористические фразы. Каждая запись с полем `topic` для фильтрации. --- ## Resource: философия сервера — ФАЗА 2 - **URI**: `about://rubber-duck` - **Название**: "About Rubber Duck MCP" - **Содержимое**: Текстовый документ (~10-15 строк): - Что это (Explicit Reasoning Buffer) - Зачем (замедление, фиксация контекста, внешняя память) - Как использовать (вызывай quack() когда застрял) --- ## Промпты **Не используются.** Промпты — шаблоны для пользователя в UI. Для простого сервера из двух тулзов избыточны: модель свободно вызывает инструменты сама. --- ## Express-хендлер Один эндпоинт `POST /mcp`. На каждый запрос: 1. Новый `McpServer` (с tools + resources) 2. `StreamableHTTPServerTransport` — **stateless** (`sessionIdGenerator: undefined`) 3. Подключение + обработка запроса Локально: `index.ts` с `app.listen(3000)`. --- ## Деплой на Vercel `vercel.json`: маппинг `/mcp` → `api/mcp.ts` через `@vercel/node`. 1. Push в GitHub 2. Vercel → Add New Project → выбрать репозиторий 3. Deploy 4. URL: `https://.vercel.app/mcp` Ограничения: таймаут 10 сек (Hobby), 60 сек (Pro). Stateless — каждый вызов независим. --- ## Тестирование **Локально**: `npm run dev` → MCP Inspector или curl POST на `/mcp`. **Удалённо**: `curl -i https://.vercel.app/mcp` → MCP Inspector с удалённым URL. --- ## Подключение к клиентам - **Cursor**: Settings → Features → MCP → Streamable HTTP → URL `/mcp` - **Claude Desktop**: `claude_desktop_config.json` → `url: "https://.vercel.app/mcp"` - **VS Code**: `.vscode/mcp.json` → `type: "http"`, url `/mcp` --- ## Чеклист | Проверка | Результат | | ------------------------ | --------------------------------- | | `npm run typecheck` | 0 ошибок | | `npm run build` | Сборка OK | | MCP Inspector (локально) | Видит tools + resource | | curl `tools/call` | Возвращает кряк / кряк + мудрость | | Vercel deploy | 200 OK | | MCP Inspector (удалённо) | Работает | | Cursor/Claude | LLM вызывает инструменты | --- ## Порядок реализации ### ФАЗА 1: Tool #1 (quack) — полный цикл 1. Инициализация проекта: `package.json`, `tsconfig.json`, зависимости 2. `src/tools/quack.ts` — Tool #1 (quack) 3. `src/server.ts` — McpServer + регистрация quack tool (без resource) 4. `src/index.ts` — Express dev-сервер 5. `api/mcp.ts` + `vercel.json` — Vercel конфигурация 6. `npm run typecheck` → исправить ошибки 7. `npm run build` → убедиться что компилируется 8. **Тест MCP Inspector локально** — вызвать quack, проверить ответ 9. **Тест curl локально** — POST запрос, проверить JSON-RPC ответ 10. `git init` + `git push` → деплой на Vercel 11. **Тест MCP Inspector удалённо** — проверить что работает через Vercel URL 12. **Тест curl удалённо** — POST запрос к Vercel endpoint 13. **Подключение к Cursor** — проверить что LLM видит и вызывает quack 14. **Подключение к Claude Desktop** — проверить что LLM видит и вызывает quack ### ФАЗА 2: Tool #2 + Philosophy (после проверки ФАЗЫ 1) 1. `src/data/wisdoms.ts` — наполнить базу мудростей 2. `src/tools/quack-wisdom.ts` — Tool #2 (quack_wisdom) 3. Добавить регистрацию quack_wisdom в `src/server.ts` 4. Зарегистрировать Resource `about://rubber-duck` в `src/server.ts` 5. `npm run typecheck` → исправить ошибки 6. `npm run build` → проверить 7. **Тест MCP Inspector локально** — проверить что видит оба tool + resource 8. **Тест curl локально** — вызвать quack_wisdom 9. `git push` → автодеплой на Vercel 10. **Тест MCP Inspector удалённо** — проверить что оба tool работают 11. **Подключение к Cursor/Claude** — проверить что LLM использует quack_wisdom