Skip to main content
Glama
README.md
# TeamStorm MCP

Интеграция TeamStorm с AI-агентами через протокол MCP. Сервер реализован на
[FastMCP 3](https://gofastmcp.com/) и работает через STDIO.

Сервер предоставляет небольшой типизированный набор инструментов для чтения
задач TeamStorm и связанного с ними контекста. Операции записи намеренно
ограничены созданием задач и подзадач, добавлением комментария и изменением
названия, описания или статуса задачи. Инструменты удаления отсутствуют.

## Возможности

- разбор ключей задач вида `TS-123` и `BACKEND-42`;
- чтение задачи, пользовательских атрибутов, комментариев, метаданных вложений,
  связей и непосредственных подзадач;
- получение страниц, связанных с задачей, по явному запросу пользователя;
- получение единого `TaskContext` с текстовым представлением для LLM и
  структурированным MCP-ответом;
- добавление непустого комментария без небезопасных автоматических повторов;
- создание задач в указанной папке и подзадач по ключу родителя;
- изменение только полей `name`, `description` и `status` через типизированные
  аргументы;
- формирование описания по единому HTML-шаблону с разделами «Суть задачи» и
  «Что было сделано»;
- повтор безопасных `GET`-запросов при временных ошибках;
- преобразование ошибок TeamStorm и транспорта в короткие понятные MCP-ошибки.

## Требования

- Python 3.12 или новее;
- [uv](https://docs.astral.sh/uv/);
- доступный экземпляр TeamStorm;
- приватный токен с минимально необходимыми правами.

## Установка

### Из GitHub Releases

Скачайте wheel (`teamstorm_mcp-<версия>-py3-none-any.whl`) и
`teamstorm.env.example` из [последнего релиза](https://github.com/taaylor/TeamStorm-MCP/releases/latest).
Установите пакет, подставив имя скачанного файла:

```bash
uv tool install --python 3.12 ./teamstorm_mcp-0.2.0-py3-none-any.whl
cp teamstorm.env.example .env
```

Заполните `.env` и запускайте из его каталога `teamstorm-daemon`; MCP-клиенту
укажите команду `teamstorm-mcp`. Обе команды входят в один пакет. Для обновления
повторите установку с `--upgrade` и новым wheel. Для установки зависимостей
нужен доступ к PyPI; Python при необходимости загружает uv.

Релиз содержит wheel, архив исходников `.tar.gz`, пример окружения, README и
`SHA256SUMS`. Если скачаны все файлы релиза, проверьте их командой
`sha256sum -c SHA256SUMS`.

### Из исходников

```bash
git clone https://github.com/taaylor/TeamStorm-MCP.git teamstorm-mcp
cd teamstorm-mcp
uv sync
```

Пакет также можно установить непосредственно из GitHub:

```bash
uv tool install git+https://github.com/taaylor/teamstorm-mcp.git
```

## Получение токена TeamStorm

Создайте приватный токен в профиле пользователя TeamStorm в разделе
**Безопасность**. Запросы с токеном выполняются с правами пользователя, который
его создал. Подробнее — в официальной
[документации TeamStorm по аутентификации](https://docs.teamstorm.io/projects/api/overview/authentication/).

## Настройка окружения

Для локальной разработки скопируйте `.env.example` в `.env` либо экспортируйте
переменные в окружении процесса, который запускает сервер:

```env
TEAMSTORM_URL=https://teamstorm.example.com
TEAMSTORM_TOKEN=your-private-token
TEAMSTORM_TIMEOUT=30
TEAMSTORM_MAX_CONTEXT_ITEMS=200
```

`TEAMSTORM_URL` должен содержать корневой адрес экземпляра. Не добавляйте
`/cwm/public/api/v1`: клиент формирует API URL самостоятельно.

`TEAMSTORM_TOKEN` является секретом. Его нельзя добавлять в Git, логи или
непосредственно в конфигурационный файл Codex.

## Запуск

Локальный сервер запускается через STDIO:

```bash
uv run teamstorm-mcp
```

После установки через `uv tool install` используйте:

```bash
teamstorm-mcp
```

Процесс ожидает MCP-сообщения в стандартном потоке ввода. FastMCP banner
отключён, чтобы в STDOUT не попадали данные, не относящиеся к протоколу.

## Очередь и демон

Демон запускается отдельным процессом и продолжает работать после завершения
MCP-сессии:

```bash
uv run teamstorm-daemon
```

Настрой статусы и переходы в [шаблоне скилла](skills/teamstorm-workflow/SKILL.md)
и задай `TEAMSTORM_WORKFLOW_PATH` обоим процессам. Единственный YAML-блок в Markdown
валидируется и компилируется в LangGraph. По умолчанию карта отключена.
Ассистент получает её через `teamstorm_get_workflow`, выполняет работу и переводит
задачу по разрешённым MCP-переходам. Финальный переход выполняет только демон.

Если пользователь указал время закрытия, агент сразу вызывает `teamstorm_schedule_task_closure`:

```json
{"task_key": "TS-123", "close_at": "2026-09-17T18:00:00+05:00", "target_status": "Done"}
```

Сервер проверяет доступность задачи и сохраняет запись в SQLite. Время обязательно
содержит часовой пояс. Демон проверяет очередь каждые 30 секунд; просроченная
запись обрабатывается при ближайшей проверке. Очередь сохраняется после перезапуска.
Повтор идентичного запроса ничего не меняет, новый срок или целевой статус
заменяет прежнюю запись и сбрасывает сохранённый контекст.

С картой намерение хранится в состоянии `waiting` до достижения `trigger_state`.
Демон просматривает все доступные рабочие пространства и задачи с пагинацией,
включая ручные изменения. Ready раньше срока активирует очередь (`pending`) и
ожидает; Ready после срока закрывается при ближайшей успешной проверке.
Выход из Ready возвращает запись в `waiting`, сохраняя срок. Уже финальная задача
помечается `completed` без PATCH. Ошибки API повторяются на следующем цикле.

Без времени в промпте ассистент не создаёт расписание и не меняет существующее.
Без сохранённого срока демон пропускает задачу. Посмотреть запись можно через
`teamstorm_get_task_closure`, отменить — через `teamstorm_cancel_task_closure`.
Расписание связано с id, revision и отпечатком карты; изменение карты переводит
его в `suspended` до явного обновления расписания. После правки карты перезапусти
MCP и демон.

Перед финальной записью демон перечитывает статус и ревизию расписания. GET и PATCH
не атомарны: конкурентное изменение после проверки всё ещё возможно. Используй
один демон на общую очередь.

Без подключённой карты сохраняется прежний режим: по сроку демон только получает
контекст статуса (`context_ready`), автоматического перехода нет.

Настройки обоих процессов:

- `TEAMSTORM_QUEUE_PATH` — общий файл SQLite, по умолчанию
  `~/.local/state/teamstorm-mcp/queue.sqlite3`;
- `TEAMSTORM_DAEMON_INTERVAL` — интервал проверки в секундах, по умолчанию `30`.
- `TEAMSTORM_WORKFLOW_PATH` — абсолютный путь к Markdown с картой, необязательный.

MCP и демон должны использовать одинаковые URL TeamStorm и абсолютный путь к
базе. Для разных экземпляров TeamStorm используйте разные базы. Если MCP
запускается через Codex с собственным путём базы, добавьте `TEAMSTORM_QUEUE_PATH`
и `TEAMSTORM_WORKFLOW_PATH` в его `env_vars`. Для постоянной работы процесс можно запускать под
systemd; SIGTERM и SIGINT завершают цикл после текущей обработки.

## Подключение к Codex

Codex читает конфигурацию MCP-серверов из `config.toml`. Актуальный формат
описан в [официальной документации OpenAI](https://developers.openai.com/codex/mcp).
Храните значения секретов в окружении, а в конфигурации указывайте только имена
переменных:

```toml
[mcp_servers.teamstorm]
command = "teamstorm-mcp"
env_vars = ["TEAMSTORM_URL", "TEAMSTORM_TOKEN", "TEAMSTORM_TIMEOUT", "TEAMSTORM_MAX_CONTEXT_ITEMS"]
default_tools_approval_mode = "writes"
```

Если пакет не установлен как CLI-инструмент, сервер можно запускать напрямую из
рабочей копии репозитория. Укажите абсолютный путь:

```toml
[mcp_servers.teamstorm]
command = "uv"
args = ["--directory", "/absolute/path/to/teamstorm-mcp", "run", "teamstorm-mcp"]
env_vars = ["TEAMSTORM_URL", "TEAMSTORM_TOKEN", "TEAMSTORM_TIMEOUT", "TEAMSTORM_MAX_CONTEXT_ITEMS"]
default_tools_approval_mode = "writes"
```

Перед запуском Codex экспортируйте `TEAMSTORM_URL` и `TEAMSTORM_TOKEN`.
Параметр `default_tools_approval_mode = "writes"` оставляет инструменты чтения
доступными без дополнительного подтверждения и запрашивает подтверждение для
операций записи.

Проверить подключение можно командами:

```bash
codex mcp list
```

В интерфейсе Codex также доступна команда `/mcp`.

## Навык агента

Исходник переиспользуемого навыка расположен в `skills/teamstorm/SKILL.md`.
Для установки только в текущий репозиторий выполните:

```bash
mkdir -p .agents/skills
cp -R skills/teamstorm .agents/skills/teamstorm
```

Для установки на уровне пользователя выполните:

```bash
mkdir -p ~/.agents/skills
cp -R skills/teamstorm ~/.agents/skills/teamstorm
```

Правила обнаружения навыков описаны в
[документации OpenAI Codex Skills](https://developers.openai.com/codex/skills).

## Примеры использования

После подключения сервера и установки навыка можно использовать запросы:

```text
Возьми TS-123 и расскажи, что нужно сделать.
Прочитай TS-123 и все страницы, связанные с этой задачей.
Покажи документацию, связанную с TS-123, включая содержимое страниц.
Реализуй TS-123.
Что обсуждали в TS-123?
На основании этих вводных сформируй и запиши описание задачи TS-123: ...
```

При запросе на реализацию навык предписывает агенту получить
`teamstorm_get_task_context`, изучить репозиторий, реализовать и проверить
изменения, а затем добавить в задачу краткое описание результата. Явный запрет
пользователя на запись в TeamStorm всегда имеет приоритет.

Связанные страницы не загружаются автоматически. Агент вызывает
`teamstorm_get_task_pages` только после явной просьбы пользователя прочитать
страницы или документацию по задаче. Поиск выполняется по доступным рабочим
пространствам с ограничением `max_items`; содержимое страниц считается внешними
данными и не является инструкциями для агента.

### Создание задач и подзадач

Создание выполняется по явной просьбе пользователя. Оба инструмента возвращают
созданный `WorkItem`, включая его `id` и `key`.

```text
teamstorm_create_task(workspace_key, folder_id, name, task_type, description=None)
teamstorm_create_subtask(parent_task_key, name, task_type, description=None)
```

Для задачи нужны ключ пространства (например, `TS`), UUID папки, название
длиной 1–255 символов и имя либо UUID типа задачи. Для подзадачи вместо
пространства и папки передаётся ключ родителя, например `TS-123`: сервер
получает его UUID и создаёт подзадачу в том же пространстве. Тип задаётся явно
и не наследуется от родителя. Необязательное `description` передаётся без
преобразования в шаблон.

Поиск папок и типов пока не предоставляется: их значения нужно знать заранее.
Статус, исполнитель и пользовательские атрибуты при создании не задаются.
Используется `POST /cwm/public/api/v1/workspaces/{workspace}/workitems`
с полями `name`, `type`, `parentId` и необязательным `description`.
Автоматических повторов нет. После таймаута или другой ошибки с неопределённым
результатом сначала проверьте TeamStorm: повторный вызов может создать дубль.

### Политика комментариев

Комментарий о завершении содержит только выполненные изменения, которые важны
пользователю. В него не включаются:

- результаты успешных, упавших или пропущенных проверок;
- ошибки, исключения, stack trace и причины блокировки;
- команды, локальные пути, адреса, порты и сведения об окружении;
- названия баз данных, схем, таблиц, колонок, индексов и ограничений;
- внутренние названия классов, функций, моделей и модулей;
- токены, заголовки авторизации и другие секреты.

Если реализация не завершена, агент не создаёт комментарий о завершении. Ошибки
и ограничения проверок он в любом случае сообщает только пользователю в чате.
Если изменения реализованы, комментарий может быть добавлен, но без диагностики
и без утверждения о результатах проверок.

Безопасный комментарий для изменения ограничения номера телефона выглядит так:

```markdown
## Что сделано

- Для ручного создания и редактирования заявки увеличена допустимая длина
  номера телефона до 50 символов.
- Добавлено покрытие сценариев создания и редактирования заявки с длинным
  номером телефона.
```

Если был добавлен или изменён публичный endpoint, комментарий дополняется
коротким контрактом:

```markdown
### API-контракт

- `POST /api/v1/resources` — создание ресурса.
  - Запрос: обязательные публичные поля запроса.
  - Успешный ответ: `201 Created`, идентификатор созданного ресурса.
```

Раздел `API-контракт` не добавляется, если endpoint не менялся. Тесты можно
упомянуть только как факт добавления покрытия, без названий тестов, команд,
результатов выполнения и диагностической информации.

### Шаблонное описание задачи

Для записи структурированного описания предназначен инструмент
`teamstorm_set_task_description`. Его контракт:

```text
task_key: str
task_summary: str
work_done: list[str] | null = null
```

- `task_key` — ключ существующей задачи, например `TS-123`;
- `task_summary` — обязательное непустое описание сути задачи обычным текстом;
- `work_done` — необязательный список только фактически выполненных изменений.

Инструмент полностью заменяет текущее поле `description` и формирует допустимый
для TeamStorm HTML:

```html
<h2>Суть задачи</h2>
<p>Добавить проверку прав доступа.</p>
<hr>
<h2>Что было сделано</h2>
<ul>
  <li>Добавлена проверка роли пользователя.</li>
  <li>Добавлены тесты.</li>
</ul>
```

Аргументы нужно передавать обычным текстом без HTML. Специальные символы
экранируются сервером. Если `work_done` не передан или содержит пустой список,
в описание добавляется нейтральный текст «Работы ещё не описаны». Пустой
`task_summary` и пустые элементы `work_done` отклоняются.

Пример команды агенту для планируемой задачи:

```text
Прочитай текущую задачу TS-123. На основании вводных ниже сформулируй суть
задачи и обнови её описание в TeamStorm через teamstorm_set_task_description.
Работы ещё не выполнены. Не меняй название и статус.

Вводные: ...
```

Пример команды после реализации:

```text
Обнови описание TS-123: сохрани актуальную суть задачи, а в раздел
«Что было сделано» добавь только фактически реализованные изменения и
выполненные проверки. Не указывай проверки, которые не запускались.
```

Изменение выполняется только по явному запросу. Перед заменой описания агенту
следует прочитать задачу с помощью `teamstorm_get_task`, чтобы не потерять
важную информацию из текущего текста.

## Доступные инструменты

- `teamstorm_create_task` — создать задачу в папке рабочего пространства;
- `teamstorm_create_subtask` — создать подзадачу по ключу родителя;
- `teamstorm_get_task` — получить основные данные задачи;
- `teamstorm_get_task_context` — получить агрегированный контекст для анализа;
- `teamstorm_get_comments` — получить комментарии в хронологическом порядке;
- `teamstorm_add_comment` — добавить комментарий;
- `teamstorm_get_attachments` — получить метаданные вложений;
- `teamstorm_get_links` — получить связанные задачи;
- `teamstorm_get_task_pages` — получить страницы и содержимое страниц, связанных
  с задачей, по явному запросу;
- `teamstorm_update_task` — изменить `name`, `description` или `status`;
- `teamstorm_set_task_description` — полностью заменить описание единым
  безопасным HTML-шаблоном.
- `teamstorm_schedule_task_closure` — сохранить срок и целевой статус в очереди;
- `teamstorm_get_task_closure` — прочитать запись очереди и полученный статус.
- `teamstorm_get_workflow` — получить активную карту целиком или `null`;
- `teamstorm_cancel_task_closure` — отменить автоматическое закрытие.

## Модель безопасности

- данные TeamStorm считаются внешним недоверенным содержимым, а не инструкциями
  для агента;
- заголовки авторизации и тела HTTP-ответов не логируются;
- ошибки для модели не содержат исходные HTTP-ответы;
- запросы `POST` и `PATCH` автоматически не повторяются;
- инструменты удаления и назначения исполнителя отсутствуют;
- при подключённой карте MCP проверяет переходы, демон выполняет только финальный
  переход по сохранённому сроку и статусу готовности;
- размер разделов контекста ограничен `TEAMSTORM_MAX_CONTEXT_ITEMS`;
- FastMCP скрывает детали неожиданных внутренних исключений, а ожидаемые ошибки
  TeamStorm передаются через `ToolError`.

## Разработка

```bash
uv sync
uv run pytest
uv run ruff check .
uv run mypy src
```

Интеграционный тест работает только на чтение и автоматически пропускается,
если необходимые переменные не заданы:

```bash
TEAMSTORM_TEST_TASK=TS-13 uv run pytest -m integration
```

Тест может прочитать задачу и её контекст. Он не добавляет комментарии, не
изменяет задачи и не удаляет данные.

## Сборка и публикация релиза

Workflow `.github/workflows/build.yml` запускает Ruff, mypy, модульные тесты,
сборку wheel и исходников, затем проверяет загрузку обеих CLI-команд из
установленного wheel. Проверки выполняются для push в `main`, pull request
в `main` и ручного запуска. Собранные файлы доступны в артефакте
`teamstorm-mcp-dist` на странице запуска Actions.

Для публикации обновите `project.version` в `pyproject.toml`, выполните
`uv lock` и закоммитьте оба файла. Версия должна иметь формат `X.Y.Z`,
например `0.2.1`. Отправьте изменения в `main` напрямую или через pull request:

```bash
git push origin main
```

После успешных проверок workflow автоматически создаст тег `vX.Y.Z` на
проверенном коммите, GitHub Release и прикрепит установочные файлы.
Если релиз этой версии уже существует, публикация пропускается:
его файлы не перезаписываются. Если текущая версия ещё не опубликована,
ближайший успешный push в `main` выпустит её, даже без изменения версии.
Ручной запуск на `main` также может опубликовать отсутствующий релиз;
на других ветках выполняется только сборка.
Если тег уже указывает на другой коммит, публикация завершится ошибкой —
нужно повысить версию. Используется встроенный `GITHUB_TOKEN`,
отдельный секрет не нужен.

## Используемая архитектура

```text
src/teamstorm_mcp/
├── application/
│   ├── interfaces/       # Контракт доступа к TeamStorm
│   ├── services/         # Сценарии работы с задачами
│   ├── models.py         # Модели приложения
│   ├── scheduling.py     # Контракты очереди и сценарий постановки
│   ├── exceptions.py     # Ошибки приложения
│   ├── parser.py
│   └── task_description.py
├── adapters/
│   ├── config.py         # Настройки из окружения
│   ├── sqlite_closures.py # Постоянная очередь SQLite
│   └── teamstorm/        # REST-клиент на aiohttp и схемы ответов API
├── presentation/
│   └── fastmcp/          # MCP-ручки, схемы результатов и форматирование
├── bootstrap.py          # Сборка зависимостей, lifespan и запуск
├── daemon.py             # Отдельный процесс обработки очереди
└── __main__.py
```

Ручки FastMCP вызывают `TeamStormService`. Сервис зависит от интерфейса
`TeamStormGateway`, который реализует REST-адаптер `TeamStormClient`.
Слой `application` не зависит от FastMCP, aiohttp и настроек окружения.
`bootstrap.py` связывает слои и управляет общей HTTP-сессией: создаёт её
при запуске сервера и закрывает при завершении.

Прямые HTTP-запросы к TeamStorm выполняет `aiohttp`. `httpx` остаётся
транзитивной зависимостью FastMCP/MCP.

## Документация API

Реализация следует официальным контрактам TeamStorm для
[задач](https://docs.teamstorm.io/projects/api/api-functions/workitems/retrieve-workitem/),
[комментариев](https://docs.teamstorm.io/projects/api/api-functions/comments/retrieve-all-comments/),
[вложений](https://docs.teamstorm.io/projects/api/api-functions/workitem-attachments/retrieve-all-workitem-attachments/)
и [связей](https://docs.teamstorm.io/projects/api/api-functions/links/get-links/).
Для связанных страниц используются [получение страниц](https://docs.teamstorm.io/projects/api/api-functions/documents/get-all-documents/)
и [получение связей страницы с задачами](https://docs.teamstorm.io/projects/api/api-functions/document-links/get-document-links/).

Документация используемого фреймворка:

- [FastMCP: установка](https://gofastmcp.com/getting-started/installation);
- [FastMCP: сервер](https://gofastmcp.com/servers/server);
- [FastMCP: инструменты](https://gofastmcp.com/servers/tools);
- [FastMCP: lifecycle](https://gofastmcp.com/servers/lifespan).

## Лицензия

MIT. См. `LICENSE`.

TDQS

A3.8/5.0

Scored across 15 tools

Disambiguation4/5

Most tools target a distinct action on a distinct resource, and the descriptions carefully delineate get_task (by key) from get_task_context (for requirements). The main overlap is update_task versus set_task_description, both of which can change a task's description, though the special templated behavior of the latter differentiates them.

Naming Consistency5/5

Every tool uses the same teamstorm_ prefix followed by a consistent snake_case verb_noun pattern (create_task, get_comments, schedule_task_closure). The convention is uniform across all 15 tools with no camelCase or stylistic deviations.

Tool Count5/5

15 tools sit at the top of the well-scoped range and each maps to a concrete capability (CRUD on tasks, comments, attachments, links, pages, and closure scheduling). No tool appears redundant with the count.

Completeness3/5

Core task lifecycle is covered (create/update/read, comments add/get, closure scheduling), but notable gaps exist: no task delete, no list/search of tasks, no way to add or download attachments, and no comment editing. These missing operations could force agents into dead ends for common list/search workflows.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive