---
slug: "estebanforge-pi-asana"
source_type: "readme"
source_url: "https://cdn.jsdelivr.net/gh/EstebanForge/pi-asana@main/README.md"
repo: "https://github.com/EstebanForge/pi-asana"
source_file: "README.md"
branch: "main"
---
# @estebanforge/pi-asana

Asana Work Graph tool for the [pi coding agent](https://pi.dev). Adds 14 LLM-callable tools (asana_*) that query the Asana REST API over plain HTTP, mirroring a curated subset of the official Asana MCP tool set &mdash; **no MCP server install required**.

## Install

```bash
pi install npm:@estebanforge/pi-asana
```

## What it adds

| Tool | Purpose |
| --- | --- |
| `asana_search_objects` | Keyword search across an Asana workspace (one resource type per call: task / project / user / tag) |
| `asana_get_my_tasks` | Tasks assigned to the authenticated user (workspace required) |
| `asana_get_tasks` | Filtered task list (project / section / tag / assignee) |
| `asana_get_task` | Full detail for one task (notes truncated ~2000 chars) |
| `asana_get_task_description` | Full, untruncated notes/description for one task. Use when `asana_get_task`'s truncation marker fires. |
| `asana_get_task_comments` | Most-recent human comments on a task (default: last 5, max 50). On-demand. |
| `asana_get_comment` | Full, untruncated text of one comment (story). Use when `asana_get_task_comments`'s 700-char truncation marker fires. |
| `asana_get_project` | Full detail for one project (sections optional) |
| `asana_get_projects` | List projects in a workspace or team |
| `asana_get_status_overview` | Aggregated status report across projects |
| `asana_get_me` | Who am I in Asana + my workspaces |
| `asana_create_tasks` | Create up to 50 tasks in a single call. Write. |
| `asana_update_tasks` | Update up to 50 tasks in a single call. Write. |
| `asana_add_comment` | Add a text or HTML comment to a task. Write. |

Compact tool guidance is injected via the `before_agent_start` hook (no skill file, to keep token cost minimal). A `/asana <verb> [args]` slash command pins intent for direct invocation.

## How it works

Asana publishes an MCP server (`https://mcp.asana.com/v2/mcp`) for AI clients, but MCP tokens are workspace-scoped and **do not work with the Asana REST API** &mdash; they are only valid against the MCP server. This extension calls the Asana REST API directly (`https://app.asana.com/api/1.0/`) with a personal access token, so the same API surface Asana documents publicly is available inside pi without requiring you to register an MCP app, configure OAuth, or install an MCP adapter.

## Configuration

This extension reads **only** the `ASANA_ACCESS_TOKEN` environment variable. No file fallback, no other env vars, no config file, no keyring integration.

```bash
export ASANA_ACCESS_TOKEN="2/12345/67890:abcdef..."
```

Create a personal access token at <https://app.asana.com/0/my-apps> &rarr; **Create personal access token**. The token grants the same access your Asana user account has &mdash; no extra scopes to set.

If the environment variable is missing, every tool returns a single error message pointing to this section.

### Write review gate (default on)

The three write tools (`asana_add_comment`, `asana_create_tasks`, `asana_update_tasks`) prompt you for review before posting:

- **Comments** open in an editable preview &mdash; trim the model's prose, then accept (Enter) or cancel (Esc). The posted text is whatever you leave in the editor. The dialog title shows the target task's **name and Asana URL**, not just its GID.
- **Task batches** show a readable summary and ask yes/no. Each task (and its `parent`, where set) renders as `'Name' (url)` when resolvable.
- Summaries resolve GIDs to names + URLs best-effort; any GID that can't be resolved falls back to `gid: <gid>`, so nothing ever blocks on a lookup miss.
- In **headless** sessions (no interactive UI) the gate is skipped so unsupervised runs never deadlock, and no extra lookups are issued.

Toggle it:

| Command | Effect |
| --- | --- |
| `/asana config` | Settings modal (TUI) to toggle the gate; status line elsewhere. |
| `/asana confirm on` / `/asana confirm off` | One-shot toggle. |

The value is persisted in `<piDir>/pi-asana.json` (`{ "confirmWrite": bool }`), where `<piDir>` is `process.env.PI_CODING_AGENT_DIR || ~/.pi/agent`. The `asana-confirm-write` flag is also registered for `/settings` visibility and the `--asana-confirm-write` CLI override, but the gate reads the JSON file.

## Usage

You do not need to mention Asana. The agent reaches for these tools whenever a request touches Asana data:

```
What tasks do I have assigned this week?
```

```
Find the Wicket project in my workspace and list its incomplete tasks.
```

```
Show me the details of task 1234567890123456.
```

```
Create a task in the Bugs project: "Investigate flaky test",
  due Friday, assign it to me.
```

```
Mark task 1234567890123456 as complete.
```

Slash command (pinned intent): `/asana <verb>` prefills the editor with an explicit ask. Hit Enter to run.

| Invocation | Maps to |
| --- | --- |
| `/asana me` | asana_get_me |
| `/asana my` / `/asana my incomplete` / `/asana my completed` | asana_get_my_tasks |
| `/asana show <gid>` | asana_get_task |
| `/asana project <gid>` | asana_get_project |
| `/asana search <workspace> <query>` | asana_search_objects (defaults to resource_type=task) |
| `/asana status <gid>...` | asana_get_status_overview |
| `/asana comments <gid> [N]` | asana_get_task_comments (last N comments; default 5) |
| `/asana comment <gid>` | asana_get_comment (full text of one comment) |
| `/asana create <text>` | asana_create_tasks |
| `/asana config` | Toggle the write review gate (settings modal in TUI) |
| `/asana confirm on\|off` | Toggle the write review gate (one-shot) |

Bare `/asana` prints a usage reminder.

## Tool selection guidance

Reach for them in this order:

1. `asana_search_objects` &mdash; when you do not know a GID.
2. `asana_get_me` &mdash; identity + workspace membership lookup.
3. `asana_get_my_tasks` &mdash; shortcut for "what is on my plate".
4. `asana_get_tasks` / `asana_get_project(s)` &mdash; bulk read scoped to a project / section / tag / assignee.
5. `asana_get_task` &mdash; full detail on one task.
6. `asana_get_task_description` &mdash; the full, untruncated task notes/description. `asana_get_task` truncates notes to 2000 chars and prints a marker; reach for this when you need the whole body (acceptance criteria, background, implementation notes).
7. `asana_get_status_overview` &mdash; aggregated status report (do not chain a search before it).
8. `asana_get_task_comments` &mdash; clarifications and reviewer threads live in comments, not in `notes`. Pull on demand when the task context is a conversation, not a record. Each comment truncates at 700 chars; the footer names the `story_gid` to pass to `asana_get_comment`.
9. `asana_get_comment` &mdash; the full, untruncated body of a single comment. Reach for it when a comment's truncation marker fired and that comment is the work (a decision, a Q&A, a spec).
10. Write tools (`create_tasks`, `update_tasks`, `add_comment`) &mdash; only after you have the IDs. The extension shows the drafted payload for accept/edit/cancel; you do not need to ask the user first.

## Notes

- These tools make real calls against your Asana workspace. Write tools (`create_tasks`, `update_tasks`, `add_comment`) prompt you for review before posting when the write review gate is on (default); see [Configuration](#configuration).
- The typeahead endpoint (`asana_search_objects`) accepts only ONE resource type per call (single enum `task` / `project` / `user` / `tag`); it does not accept a CSV. Call the tool once per type to fan out across types.
- The `/tasks` endpoint requires either project/section/tag, OR (assignee AND workspace). `asana_get_my_tasks` enforces this by making `workspace` a required parameter.
- Asana enforces rate limits (~150 req/min per PAT). A 429 response surfaces a clear retry message.
- The 14-tool surface omits several official MCP tools that did not age well in an LLM agent context: interactive `*_preview` tools (Claude/ChatGPT-only confirmation UI), `get_attachments` (binary blobs), `search_tasks` (Premium-only; overlaps `search_objects`), `get_portfolio*` (niche), `get_agent*` (AI Teammates only), and `delete_task` (destructive &mdash; add on request).
- Do not pass secrets or PII in `notes` or `text` arguments to write tools &mdash; they land in your Asana workspace directly.

## License

MIT

Based on the [Asana REST API](https://developers.asana.com/reference) and the [Asana MCP V2 tool reference](https://developers.asana.com/docs/mcp-tools-reference).
