docs: add mcp server implementation plan
This commit is contained in:
+175
@@ -0,0 +1,175 @@
|
||||
# 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://<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.json` → `url: "https://<project>.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
|
||||
Reference in New Issue
Block a user