Asana MCP

Live

OAUTH 2.1

TASK MANAGEMENT

Project Management

Asana MCP gives agents OAuth 2.1 authenticated access to your task management: create work, search the workspace, and post project status updates.

  • Per-user credentials: each call uses the actual user's token, never a shared bot.
  • Encrypted per-tenant vault: AES-256, resolved at request time, never in LLM context.
  • Scoped before every call: pre-call scope check, 90-day SIEM-exportable audit chain.
Asana MCP
agent · Acme Q3
Run
What is on my plate this week, and is the website redesign on track?
S
asanamcp_get_my_tasks
78ms
Asana agent
9 tasks due this week, 3 overdue. Website redesign: 14 of 22 tasks complete, status on track, next milestone Oct 24.
Sources: 9 tasks, 2 projects
asanamcp
9 tasks
18:29
Message Claude...

Tools your work agent reaches for on Asana, scoped per user.

CALL ANY TOOL
Task management end to end: fetch your assignments, create and update work in bulk, search the workspace, and report project status.
asanamcp_search_tasks
Search tasks
Premium accounts only. Advanced task search with full-text and complex filters. DEFAULT tool for searching tasks: Use by default any time the user asks to search for tasks. Searches task names, descriptions, and comments. Returns tasks with gid, name, assignee, due_on, completed. When the user uses possessive language like 'my' (e.g., 'my tasks', 'my overdue tasks', 'my high-priority tasks'), you MUST always set assignee_any='me', in addition to any other applicable filters. Unless the user explicitly asks for completed tasks or all tasks, always set completed=false to filter to incomplete tasks only. Use get_tasks for non-Premium workspaces.
Parameters
Name
Type
Required
Description
assignee_any
string
Optional
Filter to tasks assigned to any of these users. Comma-separated list of user identifiers ("me", an email, or a user GID). Example: 'me,1234567890123456'
completed
boolean
Optional
Filter for completed or incomplete tasks.
completed_at_after
string
Optional
ISO 8601 datetime string for completion datetime after filter. Example: '2024-01-01T00:00:00.000Z'
completed_at_before
string
Optional
ISO 8601 datetime string for completion datetime before filter. Example: '2024-12-31T00:00:00.000Z'
completed_on_after
string
Optional
ISO 8601 date string for completion date after filter. Example: '2024-01-01'
completed_on_before
string
Optional
ISO 8601 date string for completion date before filter. Example: '2024-12-31'
created_at_after
string
Optional
ISO 8601 datetime string for creation datetime after filter. Example: '2024-01-01T00:00:00.000Z'
created_at_before
string
Optional
ISO 8601 datetime string for creation datetime before filter. Example: '2024-12-31T00:00:00.000Z'
created_by_any
string
Optional
Filter to tasks created by any of these users. Comma-separated list of user identifiers ("me", an email, or a user GID). Example: 'me,1234567890123456'
created_on_after
string
Optional
ISO 8601 date string for creation date after filter. Example: '2024-01-01'
created_on_before
string
Optional
ISO 8601 date string for creation date before filter. Example: '2024-12-31'
custom_fields
string
Optional
JSON string of custom field filters for task search. Each key is a custom field GID followed by a search operator. Each value must be a string, number, or boolean only. Values become search query parameters, so nested objects and arrays are invalid. Use .value for an exact string or number match; for single-select fields, use the option GID as the value. Use .is_set with a boolean to test whether the field has any value. Other supported operators are not_value, starts_with, ends_with, contains, less_than, greater_than, before, and after. For compatibility, a bare GID defaults to value for strings and numbers or is_set for booleans. Examples: {"4578152156.value":"1200123456789012"}; {"5678904321.greater_than":42}; {"1200999999999999.is_set":true}.
due_on
string
Optional
ISO 8601 date string for due date filter. Example: '2024-12-31'
due_on_after
string
Optional
ISO 8601 date string for due date after filter. Example: '2024-01-01'
due_on_before
string
Optional
ISO 8601 date string for due date before filter. Example: '2024-12-31'
followers_any
string
Optional
Filter to tasks followed by any of these users. Comma-separated list of user identifiers ("me", an email, or a user GID). Example: 'me,1234567890123456'
is_subtask
boolean
Optional
Filter to subtasks. Set to true to only return subtasks.
limit
number
Optional
Maximum number of results to return (1-100). Default: 50.
modified_at_after
string
Optional
ISO 8601 datetime string for modified datetime after filter. Example: '2024-01-01T00:00:00.000Z'
modified_on_after
string
Optional
ISO 8601 date string for modified date after filter. Example: '2024-01-01'
opt_fields
string
Optional
Comma-separated list of optional fields to include in the response. Name each subfield explicitly as parent.child; wildcard and glob syntax such as parent.* is not supported. Example: 'name,assignee,due_on,completed'
projects_any
string
Optional
Filter to tasks in any of these projects. Comma-separated list of project GIDs. Example: '1234567890123456,9876543210987654'
resource_subtype
string
Optional
Filters results by the task's resource_subtype (e.g., milestone).
sections_any
string
Optional
Filter to tasks in any of these sections or columns. Comma-separated list of section GIDs. Example: '1234567890123456'
sort_ascending
boolean
Optional
Sort in ascending order. Defaults to false.
sort_by
string
Optional
Field to sort by (e.g., 'due_date', 'created_at', 'completed_at', 'likes', 'modified_at'). Defaults to modified_at.
tags_any
string
Optional
Filter to tasks with any of these tags. Comma-separated list of tag GIDs. Example: '1234567890123456'
text
string
Optional
Text to search for in task name or description. Example: 'website redesign'
asanamcp_get_me
Get me
asanamcp_search_objects
Search objects
asanamcp_get_task
Get task
asanamcp_search_tasks_preview
Search tasks preview
asanamcp_get_user
Get user
asanamcp_add_comment
Add comment
Python · LlamaIndex
import { ScalekitClient } from "@scalekit-sdk/node";
import { createReactAgent } from "@langchain/langgraph/prebuilt";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

// Asana tools scoped to this user
const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["asanamcp"], toolNames: [
    "asanamcp_get_my_tasks",
    "asanamcp_create_tasks",
    "asanamcp_search_tasks"] },
  pageSize: 100,
});

const agent = createReactAgent({ llm, tools });
await agent.invoke({ messages: [{ role: "user", content: "What tasks are due this week?" }] });
import OpenAI from "openai";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const openai = new OpenAI();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["asanamcp"] }, pageSize: 100,
});

const res = await openai.chat.completions.create({
  model: "gpt-5",
  messages: [{ role: "user", content: "Which of my projects are at risk this sprint?" }],
  tools,
});

// Execute the tool call with the user's vaulted Asana credential
await sk.tools.executeTool(res.choices[0].message.tool_calls[0], "user_123");
import Anthropic from "@anthropic-ai/sdk";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);
const anthropic = new Anthropic();

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["asanamcp"] }, pageSize: 100,
});

const msg = await anthropic.messages.create({
  model: "claude-sonnet-5",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Create tasks for each action item from today's standup." }],
  tools,
});

// Tool call runs with the user's vaulted Asana credential
await sk.tools.executeTool(msg.content, "user_123");
import { Agent } from "@google/adk/agents";
import { ScalekitClient } from "@scalekit-sdk/node";

const sk = new ScalekitClient(env.SCALEKIT_ENV_URL, env.SCALEKIT_CLIENT_ID, env.SCALEKIT_CLIENT_SECRET);

const { tools } = await sk.tools.listScopedTools("user_123", {
  filter: { connectionNames: ["asanamcp"] }, pageSize: 100,
});

const agent = new Agent({
  name: "asana_work_agent",
  model: "gemini-2.5-pro",
  instruction: "Manage Asana tasks and projects for the signed-in user.",
  tools,
});

await agent.run("Post a status update to the Q3 launch project.");
Try these prompts
Copy any prompt into your agent. Each maps directly to an Asana tool. Click to copy, paste into your agent, done.
Stay on top of work
Copy the prompt
Copied
What tasks are assigned to me and due this week?
Copy the prompt
Copied
Search the workspace for tasks mentioning the pricing page.
Copy the prompt
Copied
Show every open task in the mobile app project, grouped by assignee.
Create and update
Copy the prompt
Copied
Create a task for each action item in this meeting summary.
Copy the prompt
Copied
Mark these 5 tasks complete and add a closing comment to each.
Copy the prompt
Copied
Draft the Q3 launch project and show me a preview before creating it.
Report status
Copy the prompt
Copied
Give me a status overview of the design team's projects.
Copy the prompt
Copied
Post an on-track status update to the website redesign project.
Copy the prompt
Copied
List my portfolios and the health of every project inside them.
SEE HOW AUTH WORKS
Your users connect once. Their Asana credentials stay vaulted, every call is scope-checked, and every action is logged.
1
Authorize
Your user connects
Asana MCP
once. We tie it to their identity and the meetings they approved — no shared bot account, no org-wide access
Who:
user ‘A’
when:
Once per user
access:
Limited to user
2
Store
Their
Asana MCP
token lives in a vault scoped to them. User A's meetings are never reachable by an agent acting for user B, even on the same connection
vault:
encrypted
scope:
per-user
tokens:
auto-refreshed
3
Resolve
When your agent calls a
Asana MCP
tool, we fetch the right token server-side. It never touches your agent, never appears in the LLM context, never shows up in your logs
speed:
~40ms
check:
before every call
seen by:
nobody
4
Audit
Every
Asana MCP
tool call is logged — who triggered it, which meeting was fetched, what came back. 90 days of history, tied to the user who authorized it
history:
90 days
export:
SIEM-ready
logged:
every call
Test other agents
See the same per-user auth pattern across other project management connectors.
Engineering Teams
Engineering standup agent
Pulls commits from GitHub and GitLab, tracks issue movement in Jira, and posts a per-engineer standup brief to Slack. Each engineer's activity is read on their own delegated OAuth.
Engineering Teams
DevOps assistant agent
Polls GitHub for failing checks and stale PRs, opens Linear issues for the ones that need work, and posts a daily digest to Slack. It acts as the engineer, not a shared service account.
Engineering Teams
Slack triage
Polls Slack for new messages, classifies bugs and support requests with a LangGraph router, files GitHub issues or Zendesk tickets, and confirms in the thread.
People Ops and HR teams
Performance review collector
Collects review feedback from Airtable and Google Forms scoped to each manager's direct reports, writes per-employee summaries to Notion, and DMs the manager a Slack digest.
Test other agents
See the same per-user auth pattern across other project management connectors.
ENGINEERING
Engineering standup agent
Pull commits from GitHub and GitLab, track Jira issue movement, and post a per-engineer standup brief to Slack.
ENGINEERING
DevOps assistant agent
Poll GitHub for failing checks and stale pull requests, open Linear issues for the ones that need work, and digest to Slack.
ENGINEERING
Slack triage agent
Classify new Slack messages as bugs or support requests, file the GitHub issue or Zendesk ticket, and reply in the thread.
PEOPLE OPS
Performance review collector agent
Collect review feedback from Airtable and Google Forms per manager, summarise each report in Notion, and DM the digest in Slack.
Why Scalekit
Secure your agent's access. Connectors ship in minutes
01.
Shared tokens break per-user analytics
A shared Asana token looks fine in a demo. In production every task created, updated, or deleted is attributed to one service account, and you cannot tell who did what. Scalekit resolves the credential of the actual user who triggered the agent, never a shared bot.
// shared token
audit → bot_service_account

// scalekit
audit → user_abc ✓
02.
Authentication is not authorization
03.
Multi-tenancy is architectural
04.
Asana today. Ten connectors tomorrow.
“Our agents act across Salesforce, Gong, Google Drive, and more, on behalf of every customer. Scalekit behind the scenes meant we can keep adding tools without ever rebuilding how credentials or tool calling work.”
Venu Madhav Kattagoni
Head of Engineering / Von
FAQs
Frequently Asked Questions
Does the agent access Asana as the user or through a shared key?
As the user. Scalekit resolves the credential of the person who triggered the agent at request time, so every task created, comment posted, and status update in your audit trail is attributed to a real user, not a shared service account.
Where is the Asana token stored?
In an AES-256 encrypted vault with per-tenant namespacing. Tokens are resolved at request time, never enter LLM context, refresh automatically, and can be revoked from one dashboard.
Can I limit what the agent does in Asana?
Yes. Filter by tool name in listScopedTools to expose only what you want, for example read and search tools without create or update. Scalekit also enforces scope checks before every API call.
What happens when a user revokes access?
The credential is invalidated at the next tool call. The call fails closed, other users' connections are unaffected, and the revocation is logged in the audit chain.
Can the agent permanently delete tasks?
Only if you let it. Asana's delete_task removes a task and its subtasks with no undo, so most teams exclude it from listScopedTools and keep the agent on create, update, and search. Asana MCP also ships preview tools, like create_task_preview and create_project_preview, that show the user a draft before anything is written.
Start in your coding agent
Up and running in one command
Install the Scalekit skill in your editor of choice. Connector, auth, tools, prompt, all wired up
Claude Code REPL
/plugin marketplace add scalekit-inc/claude-code-authstack
/plugin install agentkit@scalekit-auth-stack
Cursor Code REPL
# ~/.cursor/mcp.json
{
""mcpServers"": {
""asanamcp"": {
""url"": ""https://mcp.scalekit.com/asanamcp"",
""headers"": { ""Authorization"": ""Bearer $SCALEKIT_TOKEN"" }
}
}
}
Codex Code REPL
# ~/.codex/config.toml
[mcp_servers.asanamcp]
url = ""https://mcp.scalekit.com/asanamcp""
auth_env = ""SCALEKIT_TOKEN""
Copilot Code REPL
# .vscode/mcp.json
{
""servers"": {
""asanamcp"": {
""url"": ""https://mcp.scalekit.com/asanamcp"",
""type"": ""http""
}
}
}