Прочитать ленту комментариев задачи Asana целиком, с постраничностью, которой нет у поштучных запросов: много комментариев, нужный не виден. НЕ запись - `asana-project`, связи - `asana-blockers`.
8 stars
0 votes
0 copies
0 views
Added September 29, 2026
developmentpythonbashapi
Works with
cli
api
mcp
Security analysis
A92/100
mediumInstalls packages at runtime which could introduce malicious dependencies
Installs into .claude/skills of the current project.
Are you the author of Asana Comments?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/dewil-asana-comments)
---
name: asana-comments
description: Прочитать ленту комментариев задачи Asana целиком, с постраничностью, которой нет у поштучных запросов: много комментариев, нужный не виден. НЕ запись - `asana-project`, связи - `asana-blockers`.
---
# asana-comments
Постраничное чтение комментариев (stories) задачи Asana через REST. Скрипт-эталон - `scripts/asana-comments.py` (top-level папка `scripts/` в корне проекта). Только stdlib, из внешнего - опционально `certifi`.
## Зачем отдельный скрипт под чтение ленты
Лента комментариев - единственная часть Asana, где поштучный запрос молча отдает неполные данные. У хостового Asana MCP (`mcp.asana.com/v2/mcp`), пока он использовался, в схеме `get_task` стояло `comment_limit` = `"Max comments to return (1-50)"`, `maximum: 50`, а курсора по ленте не было вовсе: пагинация (`offset`) есть только у `get_tasks`, то есть для списка задач.
Следствие переживает сам MCP и повторяется в любом наивном запросе одной задачи: **часть ленты остается недостижимой, и выглядит это не как обрезка, а как отсутствие комментариев** - готовый ложный вывод "там ничего нет" по живой задаче (учебный случай `rules/silent-failure.md`: ответ одинаков при полной и урезанной ленте). REST-эндпоинт `/tasks/{gid}/stories` пагинацию поддерживает, скрипт ее и разматывает.
## Когда применять
- В задаче много комментариев, а нужны свежие.
- Пользователь ссылается на комментарий, которого в обычной выдаче не видно.
- Нужен отбор по дате или вся история целиком.
## Когда НЕ применять
- Задачи, статусы, проекты, создание задач, **написание** комментария - это единичные операции, они делаются REST напрямую тем же PAT (`POST /tasks/{gid}/stories` с `html_text` для комментария). Исключение - пакетное разворачивание/досыпка доски из JSON-плана: скилл `asana-project`.
- Лента короткая и уже получена целиком - лишний канал не заводить.
## CLI
```bash
python3 scripts/asana-comments.py <task_gid> # последние 10 комментариев
python3 scripts/asana-comments.py <task_gid> --last 30
python3 scripts/asana-comments.py <task_gid> --auth ~/.config/asana/auth-work.json --last 30
python3 scripts/asana-comments.py <task_gid> --all --system # вся история + системные события
python3 scripts/asana-comments.py <task_gid> --since 2026-07-20
```
`task_gid` - последнее число в URL задачи.
Флаги:
- `--auth <файл>` - файл PAT нужного аккаунта, имеет приоритет над окружением.
- `--last <N>` - сколько последних показать (по умолчанию 10). Лента приходит от старых к новым, поэтому "последние" берутся с конца.
- `--all` - показать все, игнорируя `--last`.
- `--system` - включить системные события (назначения, смены статуса), а не только комментарии.
- `--since <YYYY-MM-DD>` - только начиная с этой даты, граница включительно.
## Авторизация: нужен именно Personal Access Token
Порядок выбора PAT: `--auth <файл>` -> непустой `ASANA_TOKEN` -> `~/.config/asana/auth.json`. Краевые пробелы токена удаляются, `~` в пути раскрывается. Формат файла - `{"token": "..."}`, права 600. Ошибка явно указанного файла останавливает команду без перехода к окружению или стандартному файлу. При нескольких аккаунтах `--auth <файл>` обязателен в каждой команде, включая чтение и dry-run. Без токена скрипт печатает готовые команды настройки. Токен - секрет: в синкаемые папки, заметки, чаты и артефакты не класть (см. `rules/secrets-handling.md`).
**Как получить PAT - проговаривать пользователю по шагам, здесь ошибаются регулярно:**
1. Открыть консоль разработчика Asana - **корневую** страницу "Мои приложения" (не страницу конкретного приложения).
2. Прокрутить **ниже** списка приложений до блока "Личные токены доступа" / "Personal access tokens".
3. "+ Create new token" -> скопировать строку вида `2/...`. Показывается один раз.
4. **Не создавать приложение.** Кнопка "Create app" на виду и провоцирует пойти по ней, но credentials приложения к REST не подходят.
**Три способа получить 401, каждый пойман на живом инциденте:**
- **OAuth-токен MCP-сервера не работает против REST** - актуально для сервисов, которые еще ведутся через MCP; у самой Asana MCP снят полностью (см. "Граница скилла"). Он audience-bound к `mcp.asana.com`, а `app.asana.com/api/1.0` его не принимает; лежит в `~/.claude/.credentials.json` -> `mcpOAuth`, refresh-токена рядом нет. Доставать его оттуда бессмысленно и хрупко.
- **client_id приложения** - это цифры. Не подходит.
- **client_secret приложения** - 32 hex-символа. Не подходит.
Отличать по форме: PAT длинный (50+ символов) и начинается с цифры и слэша (`2/...`). Если значение на это не похоже - выдан не тот секрет.
## Troubleshooting
- **401 при валидном на вид токене** - сверить форму значения по признакам выше. Чаще всего это client_id, client_secret или OAuth-токен MCP.
- **`CERTIFICATE_VERIFY_FAILED` на macOS** - сборка с python.org не видит системные CA. Скрипт сам подхватывает `certifi`, если тот установлен (`pip3 install --user certifi`).
- **Пусто по живой задаче** - проверить, не отфильтровал ли `--since`, и не нужен ли `--system`: по умолчанию показываются только комментарии, без системных событий.
## Граница скилла
Скрипт делает ровно одно - постраничное чтение ленты - и ничего не пишет: он read-only по своей природе (только GET). Остальная работа с Asana распределена так:
- пакетная запись (развернуть или досыпать доску из плана) - скилл `asana-project`, тот же токен;
- единичные операции (одна задача, статус, комментарий) - REST напрямую: база `https://app.asana.com/api/1.0`, заголовок `Authorization: Bearer <token>`.
**Asana MCP в этой схеме не участвует.** Он был основным каналом до 17.08.2026 и снят: за одну сессию дисконнекты, зависание вызова на 300 с и `Not Authorized` сразу после переавторизации - при нуле сбоев у скриптов на PAT. Плюс OAuth молча берет аккаунт из того браузера, где человек залогинен, так что привязка не к тому аккаунту происходит незаметно (`rules/mcp-multi-account.md`). Не хватает поштучной операции - дописать маленький скрипт на том же токене, а не возвращать MCP.
## Связанные файлы
- `scripts/asana-comments.py` в корне проекта - эталонный скрипт.
- `~/.config/asana/auth.json` - PAT, вне репозитория, права 600.
- `rules/secrets-handling.md` - общее правило обращения с токенами.