TeamStorm MCP
# 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: ...
```
При запросе на реализацию навык предписывает агенту получить
`teamstorm_get_task_context`, изучить репозиторий, реализовать и проверить
изменения, а затем добавить в задачу краткое описание результата. Явный запрет
пользователя на запись в 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_get_task` — получить основные данные задачи;
- `teamstorm_get_task_context` — получить агрегированный контекст для анализа;
- `teamstorm_get_comments` — получить комментарии в хронологическом порядке;
- `teamstorm_add_comment` — добавить комментарий;
- `teamstorm_get_attachments` — получить метаданные вложений;
- `teamstorm_get_links` — получить связанные задачи;
- `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/).
Документация используемого фреймворка:
- [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
Scored across 12 tools
Most tools target distinct resources and actions: task lookup, context, comments, attachments, links, workflow, and closure scheduling. The main ambiguity is between set_task_description and update_task, since both can modify the description, though the descriptions provide some guidance.
All tools follow a consistent teamstorm_<verb>_<noun> snake_case pattern, with clear verbs like get, add, set, update, schedule, and cancel. This makes the toolset highly predictable and easy to navigate.
12 tools is a well-scoped count for a task-management integration. Each tool supports a distinct part of the workflow: reading task context and related data, writing comments and updates, and managing closure scheduling.
The server covers the core workflow well: retrieving task requirements, updating task fields and descriptions, adding comments, and scheduling or canceling closure. There is no create, list, or delete task capability, but that appears outside the intended agent workflow, so the gaps are workable.