docs/MCP-TOOLS-ARCHITECTURE.md

585 lines
23 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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<any>;
}
export interface ToolContext {
trackerClient: TrackerClient;
agentSlug: string;
transport: WsClientTransport;
}
export class ToolRegistry {
private tools = new Map<string, ToolDefinition>();
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<any> {
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<AgentMessage> {
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<void> {
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<void> {
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 получает полнофункциональных агентов с богатым набором инструментов для автономной работы с задачами, проектами и командой.