asana-gate 是做什么的?
asana-gate 是一个位于 Asana REST API 前的策略网关。
YAML 策略针对每个作用域(工作区、团队、项目组合、项目、板块、任务)规定了 Agent 可以执行哪些操作以及如何塑造其请求;网关会在每次请求时强制执行该策略,无论请求是通过 MCP 工具调用还是 asana-gate 命令到达的。
您通过它能看到或做的所有事情都由该策略决定,而非 Asana:策略隐藏的对象对您而言不存在,拒绝信息以消息开头为 asana-gate: 的 HTTP 风格错误返回。
首先阅读网关的回应
网关返回的每个对象都带有 allowed_actions:当前策略允许在此对象上执行的 <resource>:<verb> 操作,例如 task:update 或 story:create。
在写入之前检查它,因为缺少的操作会被拒绝:根据列出的操作进行规划,而不是尝试然后失败。
| 回应 | 含义 | 该怎么做 |
|---|---|---|
404 <type>: Not a recognized ID: <gid> | 该对象不存在,或策略隐藏了它;网关故意使两者难以区分(与 Asana 发送的相同 404) | 不要重试或尝试其他 gid。说明该对象在策略下不可见;其所有者可以运行 asana-gate explain <gid> 查看哪个规则隐藏了它 |
403 asana-gate: <action> is not permitted on <type> <gid> | 对象可见,但策略不允许在此处执行该操作 | 报告并提供来自 allowed_actions 的操作;扩大策略是所有者的事 |
403 asana-gate: updating <resource>.<member> is not permitted here (allowed fields: …) | 更新触及了规则 fields 允许列表之外的成员 | 仅使用允许的成员重新发送 |
400 asana-gate: the <resource> does not satisfy the policy: … | 策略的约束:缺少必需成员或将其清除,前缀或格式错误,值不允许,成员被禁止 | 完全按照消息说明修复请求并重新发送 |
428 asana-gate: <action> needs a person's confirmation | 策略希望人工批准此操作 | 在 MCP 中,回答客户端显示的提示;从 shell 中,使用 --yes 重新运行 |
429 asana-gate: <action> is limited to N per <period> | 策略对此作用域中此操作设置的速率上限 | 等待期间过去;不要循环重试 |
列表(项目、任务、搜索、自动完成、事件)会被静默过滤:隐藏的对象直接缺席,不会说明删除了多少,并且一个页面携带 next_page.offset 以使用 offset 继续。
Asana 自身的错误会原封不动地通过,不带 asana-gate: 前缀:402 表示工作区的计划缺少该功能(搜索、自定义字段、项目组合和目标需要付费计划),普通的 400 是 Asana 拒绝请求体,普通的 403 是令牌自身的权限(审计日志事件、工作区事件和组织导出需要企业层的服务账户;早期访问的 Agent 端点需要设置中 asana.enable 的 ai_teammate_actors 标志)。
寻找前缀:带前缀则是策略决定的,不带前缀则是 Asana 决定的。
通过 MCP 工作
服务器暴露了策略可能允许的精选工具,外加三个通用工具:
asana_create_tasks和asana_update_tasks一次最多处理 50 个任务,并按顺序为每个任务回应一个status_code和body;部分可能失败而其他成功。asana_request通过相同策略调用任何 Asana REST 操作(method、path(位于/api/1.0下)、query、body作为data对象);通过它发起的POST /batch一次最多处理 50 个动作。asana_operations列出每个操作所需的策略动作;asana_allowed_actions告诉您对某个对象可以做什么。
| 工具 | 命令行 | 作用 |
|---|---|---|
asana_search_tasks | asana-gate task search | 在工作区中进行全文和过滤任务搜索(Asana 搜索 API;仅限付费计划)。结果限于策略可见的任务。 |
asana_list_tasks | asana-gate task list | 列出项目、板块中的任务,或带有标签,或分配给用户的任务(需要提供项目、板块、标签或分配者之一)。每个任务带有 allowed_actions。 |
asana_get_task | asana-gate task get <task_gid> | 读取一个任务及其完整字段和 allowed_actions。 |
asana_create_task | asana-gate task create | 在一个或多个项目中(可选在板块中)、父任务下,或在工作区中创建任务(无归属)。 |
asana_update_task | asana-gate task update <task_gid> | 更新任务的字段。完成需要 task:complete,分配需要 task:assign;其他字段需要 task:update(可能限于允许列表)。 |
asana_create_tasks | asana-gate task create-many | 一次调用最多创建 50 个任务,每个任务如同 asana_create_task 一样。结果按顺序包含每个任务的一个 status_code 和 body;Asana 可能部分失败而其他成功。任何任务的策略拒绝都会在执行任何操作前拒绝整个调用,其消息会指明任务(actions[i])。 |
asana_update_tasks | asana-gate task update-many | 一次调用最多更新 50 个任务,每个任务如同 asana_update_task 一样。结果按顺序包含每个任务的一个 status_code 和 body;Asana 可能部分失败而其他成功。任何任务的策略拒绝都会在执行任何操作前拒绝整个调用,其消息会指明任务(actions[i])。 |
asana_delete_task | asana-gate task delete <task_gid> | 删除一个任务(在 Asana 中移至回收站)。 |
asana_list_subtasks | asana-gate task subtasks <task_gid> | 列出一个任务的直接子任务。 |
asana_create_subtask | — | 在一个任务下创建子任务;除非指定了项目,否则继承父级的作用域。 |
asana_set_task_parent | asana-gate task set-parent <task_gid> | 将一个任务设为另一个任务的子任务(或设为父级为 null 的顶层任务)。 |
asana_add_task_to_project | asana-gate task add-project <task_gid> | 将一个任务多归属到一个项目中,可选地放入一个板块。 |
asana_remove_task_from_project | asana-gate task remove-project <task_gid> | 从一个项目的任务中移除。 |
asana_move_task_to_section | asana-gate task move <task_gid> | 将一个任务移动到一个它所属项目的板块中(两端都需要 task:move)。 |
asana_add_tag_to_task | asana-gate task tag <task_gid> | 为一个任务应用标签(需要在任务作用域中有 tag:apply)。 |
asana_remove_tag_from_task | asana-gate task untag <task_gid> | 移除一个任务的标签(需要在任务作用域中有 tag:apply)。 |
asana_add_task_dependencies | asana-gate task add-dependencies <task_gid> | 标记此任务所依赖的任务;每个被引用的任务必须可见。 |
asana_remove_task_dependencies | asana-gate task remove-dependencies <task_gid> | 移除任务依赖。 |
asana_list_task_stories | asana-gate task comments <task_gid> | 列出一个任务的评论和活动(故事)。 |
asana_create_comment | asana-gate task comment <task_gid> | 向任务添加评论(故事)。 |
asana_update_story | asana-gate story update <story_gid> | 更新一个故事(评论)。 |