6.3 KiB
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() заставляет:
- Сформулировать аргументы — выгрузить мысли из весов в текст.
- Прервать генерацию — сделать паузу и структурировать задачу.
- Создать внешнюю память — задокументировать пройденный этап.
Архитектура
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)
npm i -g vercel
vercel login # авторизация через браузер
vercel --prod # деплой
При первом запуске vercel задаст вопросы — отвечаем: Yes, наш аккаунт, No (новый проект), текущая директория. URL будет https://rubber-duck-mcp.vercel.app.
Вариант B: GitHub (автодеплой)
- Push в GitHub
- Vercel → Add New Project → выбрать репозиторий
- 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
npx create-next-app@latest rubber-duck-mcp --typescript --app- Установить
mcp-handler,@modelcontextprotocol/server,zod - Создать
lib/mcp.ts— функцияcreateMcpServer()с toolquack - Создать
app/api/mcp/route.ts— хендлер черезcreateMcpHandler npm run typecheck→ исправить ошибкиnpm run build→ убедиться- Тест локально: MCP Inspector + curl
- Деплой:
vercel --prod(или через GitHub) - Тест удалённо: MCP Inspector + curl к Vercel URL
- Подключение к Cursor и Claude Desktop — проверить что LLM вызывает quack
ФАЗА 2: quack_wisdom + Philosophy
- Создать
src/data/wisdoms.ts— база мудростей - Добавить tool
quack_wisdomвlib/mcp.ts - Зарегистрировать resource
about://rubber-duck npm run typecheck+npm run build- Тест локально: MCP Inspector видит оба tool + resource
vercel --prod→ тест удалённо- Подключение к Cursor/Cude — проверить quack_wisdom