Que fait asana-gate ?
asana-gate est une passerelle de politiques placée devant l'API REST d'Asana. Une politique YAML définit, par périmètre (espace de travail, équipe, portfolio, projet, section, tâche), les actions qu'un agent peut entreprendre et la manière dont ses requêtes sont formatées ; la passerelle les applique à chaque requête, qu'elle arrive sous forme d'appel d'outil MCP ou de commande asana-gate. Tout ce que vous pouvez voir ou faire via asana-gate est déterminé par cette politique, pas par Asana : les objets que la politique cache n'existent pas pour vous, et les refus se présentent sous forme d'erreurs de type HTTP dont le message commence par asana-gate:.
Lisez d'abord les réponses de la passerelle
Chaque objet renvoyé par la passerelle contient allowed_actions : les actions <ressource>:<verbe> que la politique autorise sur cet objet à ce moment, comme task:update ou story:create. Vérifiez-le avant d'écrire, car une action qui en est absente sera refusée : planifiez en fonction de ce qui est listé plutôt que d'essayer et d'échouer.
| Réponse | Signification | Que faire |
|---|---|---|
404 <type>: ID non reconnu : <gid> | L'objet n'existe pas, ou la politique le cache ; la passerelle rend délibérément les deux cas indiscernables (le même 404 qu'Asana envoie) | Ne réessayez pas et n'essayez pas d'autres gid. Dites que l'objet n'est pas visible selon la politique ; son propriétaire peut exécuter asana-gate explain <gid> pour voir quelle règle le cache |
403 asana-gate: <action> n'est pas autorisée sur <type> <gid> | L'objet est visible, mais la politique n'autorise pas cette action sur celui-ci | Signalez-le et proposez une action parmi allowed_actions ; l'élargissement de la politique relève du propriétaire |
403 asana-gate: la mise à jour de <ressource>.<membre> n'est pas autorisée ici (champs autorisés : …) | La mise à jour a touché un membre en dehors de la liste autorisée de fields de la règle | Renvoyez avec uniquement les membres autorisés |
400 asana-gate: la <ressource> ne satisfait pas la politique : … | Une contrainte de la politique : un membre requis est manquant ou effacé, un préfixe ou un format est incorrect, une valeur n'est pas autorisée, un membre est interdit | Corrigez la requête exactement comme le message l'indique et renvoyez-la |
428 asana-gate: <action> nécessite la confirmation d'une personne | La politique exige qu'un humain approuve cette action | Via MCP, répondez à la sollicitation affichée par le client ; depuis un terminal, relancez avec --yes |
429 asana-gate: <action> est limitée à N par <période> | Un plafond de débit que la politique définit pour cette action dans ce périmètre | Attendez la fin de la période ; ne bouclez pas dessus |
Les listes (projets, tâches, recherche, typeahead, événements) sont filtrées silencieusement : les objets cachés sont simplement absents, rien n'indique combien ont été retirés, et une page comporte next_page.offset pour continuer avec offset. Les propres erreurs d'Asana sont transmises sans modification, sans le préfixe asana-gate: : un 402 signifie que le plan de l'espace de travail ne dispose pas de la fonctionnalité (recherche, champs personnalisés, portfolios et buts nécessitent un plan payant), un 400 simple est le rejet du corps par Asana, un 403 simple est la permission du jeton lui-même (les événements du journal d'audit, les événements d'espace de travail et les exportations d'organisation nécessitent un compte de service sur un niveau Enterprise ; les points d'accès Agents en accès anticipé nécessitent le drapeau ai_teammate_actors dans le paramètre asana.enable des réglages). Cherchez le préfixe : avec lui, la politique a décidé ; sans lui, c'est Asana qui a décidé.
Travailler via MCP
Le serveur expose les outils sélectionnés que la politique pourrait éventuellement autoriser, plus trois outils génériques :
asana_create_tasksetasana_update_tasksprennent jusqu'à 50 tâches à la fois et répondent avec unstatus_codeet unbodypar tâche, dans l'ordre ; certaines peuvent échouer tandis que d'autres réussissent.asana_requestappelle n'importe quelle opération REST Asana (method,pathen dessous de/api/1.0,query,bodyen tant qu'objetdata) en passant par la même politique ; unPOST /batchvia cet outil accepte jusqu'à 50 actions.asana_operationsliste les opérations avec l'action de politique dont chacune a besoin ;asana_allowed_actionsindique ce que vous pouvez faire avec un objet.
| Outil | Ligne de commande | Ce qu'il fait |
|---|---|---|
asana_search_tasks | asana-gate task search | Recherche de tâches en texte intégral et par filtre dans l'espace de travail (API de recherche Asana ; plans payants uniquement). Les résultats sont limités aux tâches que la politique rend visibles. |
asana_list_tasks | asana-gate task list | Liste les tâches dans un projet, une section, avec un tag, ou assignées à un utilisateur (l'un des paramètres projet, section, tag ou assigné est requis). Chaque tâche contient allowed_actions. |
asana_get_task | asana-gate task get <task_gid> | Lit une tâche avec ses champs complets et allowed_actions. |
asana_create_task | asana-gate task create | Crée une tâche dans un ou plusieurs projets (éventuellement dans une section), sous une tâche parente, ou sans rattachement dans l'espace de travail. |
asana_update_task | asana-gate task update <task_gid> | Met à jour les champs d'une tâche. Compléter nécessite task:complete, assigner nécessite task:assign ; les autres champs nécessitent task:update (éventuellement limité à une liste autorisée). |
asana_create_tasks | asana-gate task create-many | Crée jusqu'à 50 tâches en un seul appel, chacune comme le ferait asana_create_task. Le résultat contient un status_code et un body par tâche, dans l'ordre ; Asana peut faire échouer certaines tandis que d'autres réussissent. Un refus de politique pour une tâche rejette l'ensemble de l'appel avant toute exécution, et son message nomme la tâche (actions[i]). |
asana_update_tasks | asana-gate task update-many | Met à jour jusqu'à 50 tâches en un seul appel, chacune comme le ferait asana_update_task. Le résultat contient un status_code et un body par tâche, dans l'ordre ; Asana peut faire échouer certaines tandis que d'autres réussissent. Un refus de politique pour une tâche rejette l'ensemble de l'appel avant toute exécution, et son message nomme la tâche (actions[i]). |
asana_delete_task | asana-gate task delete <task_gid> | Supprime une tâche (elle est déplacée dans la corbeille d'Asana). |
asana_list_subtasks | asana-gate task subtasks <task_gid> | Liste les sous-tâches directes d'une tâche. |
asana_create_subtask | — | Crée une sous-tâche sous une tâche ; elle hérite du périmètre du parent sauf si des projets sont spécifiés. |
asana_set_task_parent | asana-gate task set-parent <task_gid> | Fait d'une tâche une sous-tâche d'une autre (ou une tâche de niveau supérieur avec un parent null). |
asana_add_task_to_project | asana-gate task add-project <task_gid> | Rattache une tâche à un projet, éventuellement dans une section. |
asana_remove_task_from_project | asana-gate task remove-project <task_gid> | Retire une tâche d'un de ses projets. |
asana_move_task_to_section | asana-gate task move <task_gid> | Déplace une tâche dans une section d'un projet auquel elle appartient (nécessite task:move aux deux extrémités). |
asana_add_tag_to_task | asana-gate task tag <task_gid> | Applique un tag à une tâche (nécessite tag:apply dans le périmètre de la tâche). |
asana_remove_tag_from_task | asana-gate task untag <task_gid> | Retire un tag d'une tâche (nécessite tag:apply dans le périmètre de la tâche). |
asana_add_task_dependencies | asana-gate task add-dependencies <task_gid> | Marque les tâches dont cette tâche dépend ; chaque tâche référencée doit être visible. |
asana_remove_task_dependencies | asana-gate task remove-dependencies <task_gid> | Supprime les dépendances d'une tâche. |
asana_list_task_stories | asana-gate task comments <task_gid> | Liste les commentaires et l'activité (histoires) d'une tâche. |
asana_create_comment | asana-gate task comment <task_gid> | Ajoute un commentaire (histoire) à une tâche. |
asana_update_story | asana-gate task update-comment <story_gid> | Met à jour le texte d'un commentaire (histoire). |
asana_delete_story | asana-gate task delete-comment <story_gid> | Supprime un commentaire (histoire). |
asana_create_project | asana-gate project create | Crée un projet dans un espace de travail ou une équipe, avec des champs et un statut de coloris parmi les options de l'équipe. |
asana_update_project | asana-gate project update <project_gid> | Met à jour les champs d'un projet. |
asana_delete_project | asana-gate project delete <project_gid> | Supprime un projet (le déplace dans la corbeille). |
asana_get_project | asana-gate project get <project_gid> | Lit un projet avec ses champs. |
asana_list_projects | asana-gate project list | Liste les projets visibles dans l'espace de travail ou l'équipe (l'un d'eux doit être donné). |
asana_list_project_sections | asana-gate project sections <project_gid> | Liste les sections d'un projet dans l'ordre (la première section est Nouvelle section). |
asana_create_project_section | asana-gate project add-section <project_gid> | Ajoute une section à un projet. |
asana_add_custom_field_to_project | asana-gate project add-custom-field <project_gid> | Ajoute un champ personnalisé à un projet (pour les projets disposant de champs personnalisés ; nécessite l'action de politique project:update). |
asana_get_workspace | asana-gate workspace get <workspace_gid> | Lit un espace de travail. |
asana_list_workspaces | asana-gate workspace list | Liste les espaces de travail visibles. |
asana_list_teams | asana-gate team list | Liste les équipes d'un espace de travail. |
asana_get_team | asana-gate team get <team_gid> | Lit une équipe. |
asana_list_team_projects | asana-gate team projects <team_gid> | Liste les projets d'une équipe. |
asana_list_team_users | asana-gate team users <team_gid> | Liste les membres d'une équipe. |
asana_get_user | asana-gate user get <user_gid> | Lit un utilisateur. |
asana_list_users | asana-gate user list | Liste les utilisateurs (dans un espace de travail, ou l'espace de travail par défaut). |
asana_get_current_user | asana-gate user me | Lit l'utilisateur actuel. |
asana_get_portfolio | asana-gate portfolio get <portfolio_gid> | Lit un portfolio. |
asana_list_portfolios | asana-gate portfolio list | Liste les portfolios visibles. |
asana_list_portfolio_items | asana-gate portfolio items <portfolio_gid> | Liste les éléments d'un portfolio (projets, portfolios). |
asana_get_custom_field | asana-gate custom-field get <custom_field_gid> | Lit un champ personnalisé. |
asana_list_custom_fields | asana-gate custom-field list | Liste les champs personnalisés dans un espace de travail ou un projet (selon l'API ; l'un ou l'autre doit être donné). |
asana_get_project_brief | asana-gate project brief <project_gid> | Lit le briefing d'un projet. |
asana_update_project_brief | asana-gate project update-brief <project_gid> | Met à jour le briefing d'un projet. |
asana_get_section | asana-gate section get <section_gid> | Lit une section. |
asana_list_task_enums | asana-gate task enums | Liste les tâches enum (prédéfinies) disponibles pour les champs personnalisés de type énumération (via le point d'accès typeahead d'Asana). |
asana_request | asana-gate raw <method> <path> | Appelle n'importe quelle opération REST Asana via la politique (avec la possibilité d'envoyer des données --data). Avec POST /batch, jusqu'à 50 actions ; chaque élément de lot est exécuté individuellement dans la politique. |
asana_operations | asana-gate operations | Renvoie la liste de toutes les opérations avec l'action de politique dont chacune a besoin. |
asana_allowed_actions | asana-gate allowed-actions <type> <gid> | Interroge la politique sur ce qui est autorisé sur un objet par son type et son gid (ne fait pas d'appel à l'API Asana ; la politique elle-même décide). |
Travailler en ligne de commande
Tous les outils MCP sont accessibles via la commande asana-gate. La syntaxe générale est:
asana-gate <ressource> <action> [<id>] [--key value]
Les clés et valeurs de la ligne de commande correspondent aux paramètres de l'outil MCP : les clés --d'un_trait_deviennent un_trait. Les valeurs booléennes s'écrivent --flag ou --no-flag. Les listes et les objets sont des chaînes JSON.
Obtenez l'aide d'une sous-commande avec asana-gate help <commande> ou asana-gate <commande> --help. asana-gate explain <gid> interroge la politique pour savoir quelle règle s'applique à un gid : elle indique si c'est un refus (masqué) ou une autorisation. asana-gate dump-policy imprime la politique active au format YAML pour vérifier sa configuration.
Lorsqu'une action nécessite --yes (confirmation humaine), vous pouvez la passer sur la ligne de commande pour éviter la sollicitation interactive. asana-gate lui-même supporte des options globales :
| Option | Signification |
|---|---|
--asana-token | Jeton d'accès personnel Asana (remplace ASANA_TOKEN). |
--policy | Chemin vers le fichier de politique YAML (remplace ASANA_GATE_POLICY). |
--verbose | Imprime la correspondance détaillée des règles et la requête/réponse HTTP. |
--no-color | Désactive la coloration de la sortie. |
--output | Format de sortie : text (tableaux simples, par défaut) ou json. |
--version | Imprime la version. |
--yes | Confirme toutes les actions qui nécessitent --yes dans la politique (à utiliser avec précaution). |
Écrire une politique
C'est la partie cruciale : une politique est un fichier YAML qui dit, par périmètre, ce qui est autorisé et comment les requêtes sont modifiées avant d'atteindre Asana. Chaque règle contient :
scope: une paire clé-valeur identifiant le périmètre (par exempleworkspace:"1201234567890",project:"1201234567890).where: optionnel. Une condition sur les propriétés de l'objet pour que la règle s'applique (par exempletags: ["1201234567890"]).allow: liste des actions autorisées (par exemple['task:create', 'task:update']).deny: liste des actions refusées (a priorité surallow).confirm: optionnel.truepour exiger une confirmation humaine sur chaque action autorisée.constraints: contraintes sur les valeurs autorisées pour certains membres, requises, préfixées, formatées, ou interdites.fields: liste autorisée des champs que l'agent peut mettre à jour dans une actionupdate; tout champ en dehors est refusé.rate: plafond de débitN/period(période parmisecond,minute,hour,day).
Exemple de règle :
- scope:
workspace: "1201234567890"
where:
projects: ["1201234567890"]
allow:
- task:create
- task:update
- task:move
- story:create
deny:
- task:delete
confirm: true
constraints:
required_members: ["name", "projects"]
prefixes:
name: "[DEV] "
forbidden_members: ["due_on", "assignee"]
rate: 50/minute
Le moteur de politique évalue les règles dans l'ordre pour chaque requête et applique la première règle correspondante ; si aucune règle ne correspond, l'action est refusée. Utilisez asana-gate explain <gid> pour déboguer quelle règle s'applique à un objet.
Configuration
- Jeton Asana :
ASANA_TOKEN(variable d'environnement) ou--asana-token. - Fichier de politique :
ASANA_GATE_POLICY(variable d'environnement, chemin vers un fichier YAML) ou--policy. - Les outils MCP peuvent être configurés dans
claude_desktop_config.json:
{
"mcpServers": {
"asana-gate": {
"command": "npx",
"args": ["-y", "asana-gate"]
}
}
}
Dépannage
- Le
404d'une tâche que vous venez de voir peut signifier que la politique a changé ou que le gid est incorrect. - Le préfixe
asana-gate:dans l'erreur signifie que la politique a refusé ; sans lui, c'est Asana. asana-gate dump-policyimprime la politique active.asana-gate explain <gid>dit pourquoi un objet est caché ou autorisé.- Les paramètres régionaux de la politique ne sont pas traduits dans son mécanisme ; l'interface utilisateur peut être en anglais.
Notes de version
- v1.0.0 : Version initiale.
- v1.1.0 : Ajout du support MCP et de la ligne de commande.
- v2.0.0 : Réécriture complète du moteur de politique, ajout des contraintes et du plafond de débit.
Licence
MIT