From d3b9aead966bf1fed95ced5e5705c61e817cd45a Mon Sep 17 00:00:00 2001 From: Markov Date: Mon, 23 Feb 2026 20:44:37 +0100 Subject: [PATCH] docs: MCP Tools Architecture --- MCP-TOOLS-ARCHITECTURE.md | 585 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 MCP-TOOLS-ARCHITECTURE.md diff --git a/MCP-TOOLS-ARCHITECTURE.md b/MCP-TOOLS-ARCHITECTURE.md new file mode 100644 index 0000000..9629eac --- /dev/null +++ b/MCP-TOOLS-ARCHITECTURE.md @@ -0,0 +1,585 @@ +# MCP Tools Architecture — Team Board + +**Версия:** 1.0 +**Дата:** 2026-02-23 +**Автор:** Winston (BMAD) + +--- + +## 1. Исследование MCP + +### Что такое MCP + +Model Context Protocol (MCP) — открытый стандарт для подключения AI приложений к внешним системам. MCP работает как "USB-C для AI" — стандартизированный способ подключения ИИ к данным, инструментам и рабочим процессам. + +**Архитектура клиент-сервер:** +- **MCP Host** (AI приложение): Управляет одним или множеством MCP клиентов +- **MCP Client**: Поддерживает соединение с MCP сервером и получает контекст +- **MCP Server**: Программа, предоставляющая контекст MCP клиентам + +**Двухуровневая архитектура:** + +1. **Data layer** (Протокол данных): + - JSON-RPC 2.0 для коммуникации клиент-сервер + - Управление жизненным циклом, capabilities negotiation + - Основные примитивы: Tools, Resources, Prompts + +2. **Transport layer** (Транспорт): + - **STDIO**: Прямое соединение между процессами (локальные серверы) + - **HTTP Streamable**: HTTP POST с Server-Sent Events (удаленные серверы) + +### Ключевые концепции MCP + +**Серверные примитивы:** +- **Tools**: Выполняемые функции (например, API вызовы, операции с файлами) +- **Resources**: Источники данных для контекста (содержимое файлов, записи БД) +- **Prompts**: Шаблоны для взаимодействия с языковыми моделями + +**Клиентские примитивы:** +- **Sampling**: Запрос language model completion от клиента +- **Elicitation**: Запрос дополнительной информации от пользователя +- **Logging**: Отправка логов для отладки + +**Lifecycle Management:** +1. Инициализация соединения +2. Negotiation capabilities через handshake +3. Динамическое обнаружение tools через `tools/list` +4. Выполнение tools через `tools/call` +5. Real-time уведомления о изменениях + +--- + +## 2. Анализ текущей архитектуры Picogent + +### Как работает сейчас + +Picogent — агент для Team Board с архитектурой: + +``` +Picogent Agent +├── WebSocket Transport (WsClientTransport) +├── REST Client (TrackerClient) +├── Event Router (EventRouter) +└── Claude API Integration +``` + +**Текущий стек:** +- **Transport**: WebSocket для событий + REST для мутаций +- **Events**: `task.assigned`, `message.new` → обработка через EventRouter +- **Actions**: Только REST API через TrackerClient +- **LLM**: Прямая интеграция с Claude API (Anthropic SDK) + +### Интеграционные точки + +1. **Agent.json конфигурация:** + ```json + { + "capabilities": ["coding", "review"], + "chat_listen": "mentions", + "task_listen": "assigned" + } + ``` + +2. **EventRouter обрабатывает:** + - `task.assigned` → запускает `runAgent()` + - `message.new` → отвечает если упомянут + +3. **TrackerClient предоставляет REST методы:** + - Tasks: `listTasks()`, `takeTask()`, `updateTask()` + - Messages: `sendMessage()`, `listMessages()` + - Projects: `listProjects()`, `getProject()` + +### Ограничения текущего подхода + +- **Монолитный EventRouter**: Вся логика в одном классе +- **Hardcoded инструменты**: REST методы зашиты в код агента +- **Нет tool discovery**: ИИ не знает какие действия доступны +- **Сложное расширение**: Добавление новых действий требует изменения кода + +--- + +## 3. Решение: MCP vs Function Calling + +### Сравнение подходов + +| Критерий | MCP Server | Function Calling | Рекомендация | +|----------|-----------|------------------|-------------| +| **Стандартизация** | ✅ Открытый стандарт | ❌ Зависит от LLM провайдера | MCP | +| **Совместимость** | ✅ Любые MCP hosts | ❌ Только Claude/OpenAI | MCP | +| **Tool Discovery** | ✅ Динамический `tools/list` | ❌ Статичные definitions | MCP | +| **Real-time updates** | ✅ Notifications | ❌ Нет | MCP | +| **Сложность реализации** | ⚠️ Средняя (протокол) | ✅ Простая (JSON schema) | Function Calling | +| **Готовые SDK** | ✅ Python, TypeScript | ❌ Самописные | MCP | + +### Гибридный подход — рекомендация + +**Используем Function Calling с MCP-совместимой архитектурой:** + +1. **Tool definitions** в формате совместимом с MCP +2. **Простая реализация** без полного MCP сервера +3. **Готовность к миграции** на полный MCP в будущем + +**Обоснование:** +- **Прагматизм**: Function calling проще реализовать и отладить +- **Быстрый результат**: Не нужен отдельный MCP сервер +- **Совместимость**: Структуры данных готовы для MCP +- **Эволюция**: Легко мигрировать на полный MCP позже + +--- + +## 4. Каталог инструментов + +### 4.1 Tasks (Задачи) + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `list_tasks` | Список задач с фильтрацией | `project_id?`, `status?`, `assignee?`, `labels?` | `TaskOut[]` | +| `get_task` | Получить задачу по ID | `task_id: string` | `TaskOut` | +| `create_task` | Создать новую задачу | `project_slug: string`, `title: string`, `description?`, `type?`, `priority?`, `assignee_slug?` | `TaskOut` | +| `update_task` | Обновить поля задачи | `task_id: string`, `title?`, `status?`, `priority?`, `assignee_slug?` | `TaskOut` | +| `take_task` | Взять задачу себе (атомарно) | `task_id: string`, `agent_slug: string` | `TaskOut` | +| `reject_task` | Отклонить задачу с причиной | `task_id: string`, `reason: string` | `{ok: true, reason: string}` | +| `assign_task` | Назначить задачу другому | `task_id: string`, `assignee_slug: string` | `TaskOut` | +| `watch_task` | Подписаться на уведомления | `task_id: string`, `agent_slug: string` | `{ok: true, watchers: string[]}` | + +**Пример tool definition:** +```json +{ + "name": "take_task", + "title": "Взять задачу в работу", + "description": "Атомарно назначить задачу агенту, если она свободна", + "inputSchema": { + "type": "object", + "properties": { + "task_id": {"type": "string", "description": "ID или ключ задачи (TE-15)"}, + "agent_slug": {"type": "string", "description": "Slug агента"} + }, + "required": ["task_id", "agent_slug"] + } +} +``` + +### 4.2 Steps (Этапы задач) + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `list_steps` | Этапы задачи | `task_id: string` | `StepOut[]` | +| `add_step` | Добавить этап в чеклист | `task_id: string`, `title: string` | `StepOut` | +| `complete_step` | Отметить этап выполненным | `task_id: string`, `step_id: string` | `StepOut` | +| `update_step` | Обновить название этапа | `task_id: string`, `step_id: string`, `title?: string`, `done?: boolean` | `StepOut` | + +### 4.3 Messages (Сообщения и комментарии) + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `send_message` | Отправить сообщение в чат или комментарий к задаче | `content: string`, `chat_id?: string`, `task_id?: string`, `mentions?: string[]` | `MessageOut` | +| `list_messages` | Получить сообщения | `chat_id?: string`, `task_id?: string`, `limit?: number` | `MessageOut[]` | +| `reply_message` | Ответить в треде | `parent_id: string`, `content: string` | `MessageOut` | + +**Unified Message модель** — одна сущность для: +- **Chat messages**: `chat_id` заполнен +- **Task comments**: `task_id` заполнен +- **Thread replies**: `parent_id` заполнен + +### 4.4 Projects (Проекты) + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `list_projects` | Список активных проектов | - | `ProjectOut[]` | +| `get_project` | Информация о проекте | `slug: string` | `ProjectOut` | + +### 4.5 Members (Участники) + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `list_members` | Участники проекта | - | `MemberOut[]` | +| `get_member` | Информация об участнике | `slug: string` | `MemberOut` | +| `update_my_status` | Обновить свой статус | `status: string` | `{status: string}` | + +### 4.6 Files (Файлы) — будущие + +| Tool Name | Description | Parameters | Returns | +|-----------|-------------|------------|---------| +| `upload_file` | Загрузить файл к сообщению | `message_id: string`, `filename: string`, `content: base64` | `AttachmentOut` | +| `list_files` | Файлы задачи/проекта | `task_id?: string`, `project_id?: string` | `AttachmentOut[]` | +| `download_file` | Скачать файл | `attachment_id: string` | `{filename: string, content: base64}` | + +--- + +## 5. Архитектура реализации + +### 5.1 Компонентная структура + +``` +picogent/ +├── src/ +│ ├── tools/ # MCP-совместимые tools +│ │ ├── registry.ts # Реестр всех tools +│ │ ├── tasks.ts # Task tools +│ │ ├── messages.ts # Message tools +│ │ ├── projects.ts # Project tools +│ │ └── members.ts # Member tools +│ ├── mcp/ +│ │ ├── types.ts # MCP-совместимые типы +│ │ ├── tool-executor.ts # Выполнение tools +│ │ └── tool-builder.ts # Построение tool definitions +│ ├── agent.ts # Интеграция с Claude + tools +│ └── router.ts # Обновлённый EventRouter +``` + +### 5.2 Tool Registry (Центральный реестр) + +```typescript +// tools/registry.ts +export interface ToolDefinition { + name: string; + title: string; + description: string; + inputSchema: JSONSchema; + handler: (params: any, context: ToolContext) => Promise; +} + +export interface ToolContext { + trackerClient: TrackerClient; + agentSlug: string; + transport: WsClientTransport; +} + +export class ToolRegistry { + private tools = new Map(); + + register(tool: ToolDefinition): void { + this.tools.set(tool.name, tool); + } + + list(): ToolDefinition[] { + return Array.from(this.tools.values()); + } + + async execute(name: string, params: any, context: ToolContext): Promise { + const tool = this.tools.get(name); + if (!tool) throw new Error(`Tool not found: ${name}`); + return tool.handler(params, context); + } +} +``` + +### 5.3 Task Tools Implementation + +```typescript +// tools/tasks.ts +import { ToolDefinition } from './registry.js'; + +export const takeTaskTool: ToolDefinition = { + name: 'take_task', + title: 'Взять задачу в работу', + description: 'Атомарно назначить задачу агенту, если она свободна', + inputSchema: { + type: 'object', + properties: { + task_id: { type: 'string', description: 'ID задачи' }, + agent_slug: { type: 'string', description: 'Slug агента' } + }, + required: ['task_id', 'agent_slug'] + }, + async handler(params, context) { + try { + const result = await context.trackerClient.takeTask( + params.task_id, + params.agent_slug + ); + return { + content: [{ + type: 'text', + text: `✅ Задача ${result.key} взята в работу` + }], + structuredContent: result + }; + } catch (error) { + return { + content: [{ + type: 'text', + text: `❌ Ошибка: ${error.message}` + }], + isError: true + }; + } + } +}; + +export const listTasksTool: ToolDefinition = { + name: 'list_tasks', + title: 'Список задач', + description: 'Получить список задач с фильтрацией', + inputSchema: { + type: 'object', + properties: { + project_id: { type: 'string', description: 'ID проекта' }, + status: { type: 'string', enum: ['backlog', 'todo', 'in_progress', 'in_review', 'done'] }, + assignee: { type: 'string', description: 'Slug исполнителя' } + } + }, + async handler(params, context) { + const tasks = await context.trackerClient.listTasks(params); + return { + content: [{ + type: 'text', + text: `Найдено задач: ${tasks.length}\n${tasks.map(t => `- ${t.key}: ${t.title} (${t.status})`).join('\n')}` + }], + structuredContent: tasks + }; + } +}; +``` + +### 5.4 Интеграция с Claude + +```typescript +// agent.ts (модифицированный) +import { ToolRegistry } from './tools/registry.js'; + +export async function* runAgent(prompt: string, options: AgentOptions): AsyncIterator { + const toolRegistry = new ToolRegistry(); + + // Регистрируем все tools + registerAllTools(toolRegistry); + + // Создаём tool definitions для Claude + const tools = toolRegistry.list().map(tool => ({ + name: tool.name, + description: tool.description, + input_schema: tool.inputSchema + })); + + const response = await anthropic.messages.create({ + model: options.model, + messages: [{ role: 'user', content: prompt }], + tools, + system: options.systemPrompt + }); + + // Обрабатываем tool calls + for (const content of response.content) { + if (content.type === 'tool_use') { + const result = await toolRegistry.execute( + content.name, + content.input, + { trackerClient: options.trackerClient, agentSlug: options.agentSlug } + ); + + yield { + type: 'text', + content: result.content?.[0]?.text || 'Tool executed', + sessionId: options.sessionId + }; + } else { + yield { + type: 'text', + content: content.text, + sessionId: options.sessionId + }; + } + } +} +``` + +### 5.5 Обновлённый EventRouter + +```typescript +// router.ts (упрощённый) +export class EventRouter { + constructor( + private config: AgentConfig, + private toolRegistry: ToolRegistry, + private taskTracker: TaskTracker, + ) {} + + async handleEvent(event: TrackerEvent): Promise { + const context = { + trackerClient: new TrackerClient(this.config.trackerUrl, this.config.token), + agentSlug: this.config.slug, + transport: this.taskTracker + }; + + switch (event.event) { + case 'task.assigned': + await this.handleTaskAssigned(event.data, context); + break; + case 'message.new': + await this.handleMessageNew(event.data, context); + break; + } + } + + private async handleTaskAssigned(data: any, context: ToolContext): Promise { + const task = data.task || data; + + // Строим промпт с доступными tools + const toolsDescription = this.toolRegistry.list() + .map(t => `- ${t.name}: ${t.description}`) + .join('\n'); + + const prompt = ` +# Задача: ${task.key} — ${task.title} + +${task.description || ''} + +## Доступные инструменты: +${toolsDescription} + +Выполни задачу используя доступные инструменты. +Начни с обновления статуса на "in_progress". +`; + + // Запускаем агента с tools + for await (const msg of runAgent(prompt, { + toolRegistry: this.toolRegistry, + agentSlug: this.config.slug, + trackerClient: context.trackerClient + })) { + // Логируем результат + console.log(`Agent output: ${msg.content}`); + } + } +} +``` + +### 5.6 Структура файлов + +``` +picogent/ +├── src/ +│ ├── tools/ +│ │ ├── registry.ts # Центральный реестр tools +│ │ ├── tasks.ts # 8 task tools +│ │ ├── steps.ts # 4 step tools +│ │ ├── messages.ts # 3 message tools +│ │ ├── projects.ts # 2 project tools +│ │ ├── members.ts # 3 member tools +│ │ └── index.ts # Export всех tools +│ ├── mcp/ +│ │ ├── types.ts # MCP-совместимые типы +│ │ └── executor.ts # Tool execution engine +│ ├── tracker/ +│ │ ├── client.ts # REST client (существующий) +│ │ └── types.ts # Tracker API types +│ ├── transport/ +│ │ └── ws-client.ts # WebSocket transport (существующий) +│ ├── agent.ts # Модифицированный для tools +│ ├── router.ts # Упрощённый EventRouter +│ └── index.ts # Точка входа +├── package.json # + @anthropic-ai/sdk dependency +└── agent.json # Конфигурация (существующая) +``` + +--- + +## 6. План реализации + +### Phase 1: Базовая инфраструктура tools (Неделя 1) + +**День 1-2: Создание Tool Registry** +- [ ] `src/tools/registry.ts` — интерфейсы и реестр +- [ ] `src/mcp/types.ts` — MCP-совместимые типы +- [ ] Тесты для registry + +**День 3-4: Интеграция с Claude** +- [ ] Модификация `agent.ts` для поддержки tools +- [ ] Tool execution pipeline +- [ ] Error handling для tool calls + +**День 5-7: Базовые Task Tools** +- [ ] `take_task`, `list_tasks`, `get_task` +- [ ] Интеграция с существующим TrackerClient +- [ ] Тестирование на простых задачах + +### Phase 2: Полный набор tools (Неделя 2) + +**День 1-3: Все Task и Step Tools** +- [ ] Реализация всех 8 task tools +- [ ] 4 step tools для чеклистов +- [ ] Валидация параметров и ошибок + +**День 4-5: Message Tools** +- [ ] `send_message`, `list_messages`, `reply_message` +- [ ] Поддержка unified модели (чат + комментарии) + +**День 6-7: Project и Member Tools** +- [ ] Project tools: `list_projects`, `get_project` +- [ ] Member tools: `list_members`, `update_my_status` +- [ ] Интеграционные тесты + +### Phase 3: Продвинутые возможности (Неделя 3) + +**День 1-2: Обновлённый EventRouter** +- [ ] Рефакторинг router.ts под tools +- [ ] Улучшенная обработка `task.assigned` +- [ ] Dynamic tool discovery + +**День 3-4: Error Handling и Reliability** +- [ ] Robust error handling в tools +- [ ] Retry logic для API calls +- [ ] Graceful degradation + +**День 5-7: Документация и тесты** +- [ ] Tool documentation +- [ ] Integration tests +- [ ] Performance тесты + +### Phase 4: Готовность к MCP миграции (Неделя 4) + +**День 1-3: MCP Compatibility Layer** +- [ ] Full MCP tool definitions format +- [ ] MCP server skeleton (не активный) +- [ ] Migration path documentation + +**День 4-5: Production Deploy** +- [ ] Deploy обновлённого Picogent +- [ ] Monitoring и логирование +- [ ] Performance optimization + +**День 6-7: Итерации на основе feedback** +- [ ] Bug fixes +- [ ] UX improvements +- [ ] Documentation updates + +### Критерии готовности + +**Phase 1 Complete:** +- ✅ Агент может взять задачу используя `take_task` tool +- ✅ Список задач через `list_tasks` tool работает +- ✅ Error handling для недоступных tools + +**Phase 2 Complete:** +- ✅ Все 20 tools реализованы и работают +- ✅ Агент может выполнить полный цикл: взять задачу → добавить этапы → обновить статус → прокомментировать + +**Phase 3 Complete:** +- ✅ Production-ready качество кода +- ✅ Comprehensive error handling +- ✅ Full integration test suite + +**Phase 4 Complete:** +- ✅ MCP-compatible архитектура +- ✅ Готовность к миграции на полный MCP сервер +- ✅ Документация для developers + +--- + +## Заключение + +**Выбранный подход** — гибридная архитектура с Function Calling в MCP-совместимом формате — даёт нам: + +1. **Быстрый результат**: Можно реализовать за 3-4 недели +2. **Простота**: Не требует отдельного MCP сервера +3. **Гибкость**: 20+ tools покрывают все операции Tracker API +4. **Масштабируемость**: Tool Registry легко расширяется +5. **Будущее**: Готовность к миграции на полный MCP + +**Ключевые преимущества:** +- **Dynamic tool discovery**: ИИ знает какие действия доступны +- **Structured error handling**: Понятные ошибки для self-correction +- **Unified architecture**: Все операции через единый интерфейс +- **MCP compatibility**: Готовность к стандарту будущего + +Team Board получает полнофункциональных агентов с богатым набором инструментов для автономной работы с задачами, проектами и командой. \ No newline at end of file