Files
rubber-duck-mcp/mcp-server.md
T

9.0 KiB
Raw Blame History

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 — текстовый документ, который сервер отдаёт при запросе. Модель читает его и понимает контекст.


Архитектура

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. StreamableHTTPServerTransportstateless (sessionIdGenerator: undefined)
  3. Подключение + обработка запроса

Локально: index.ts с app.listen(3000).


Деплой на Vercel

vercel.json: маппинг /mcpapi/mcp.ts через @vercel/node.

  1. Push в GitHub
  2. Vercel → Add New Project → выбрать репозиторий
  3. Deploy
  4. URL: https://<project>.vercel.app/mcp

Ограничения: таймаут 10 сек (Hobby), 60 сек (Pro). Stateless — каждый вызов независим.


Тестирование

Локально: npm run dev → MCP Inspector или curl POST на /mcp.

Удалённо: curl -i https://<project>.vercel.app/mcp → MCP Inspector с удалённым URL.


Подключение к клиентам

  • Cursor: Settings → Features → MCP → Streamable HTTP → URL /mcp
  • Claude Desktop: claude_desktop_config.jsonurl: "https://<project>.vercel.app/mcp"
  • VS Code: .vscode/mcp.jsontype: "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