{"_id":"@duytnb79/asana-mcp","_rev":"2-4ad7c7376ea43b19994504848e470ce4","name":"@duytnb79/asana-mcp","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@duytnb79/asana-mcp","version":"0.1.0","keywords":["mcp","asana","personal-access-token"],"license":"MIT","_id":"@duytnb79/asana-mcp@0.1.0","maintainers":[{"name":"tamaki_di","email":"duytnb2608.work@gmail.com"}],"homepage":"https://github.com/duytnb79/asana-mcp-server#readme","bugs":{"url":"https://github.com/duytnb79/asana-mcp-server/issues"},"bin":{"asana-mcp":"dist/index.js"},"dist":{"shasum":"c5f8780f22cbdbdf1f73ee33ac6b98a0ab37eead","tarball":"https://registry.npmjs.org/@duytnb79/asana-mcp/-/asana-mcp-0.1.0.tgz","fileCount":13,"integrity":"sha512-VtnU8jq9GWj0aQuY2PqSgBUodJXJ1qWffhfzE0jAACXin5DrtDaZjt+JzducJCtWlN6A2LguR2cM0EzrPAdR1w==","signatures":[{"sig":"MEUCIDGxeFdsb1oglewlVA+ZLR0AkXie/2HwaAIg9CJCO+BhAiEA4IgpLSL6/iq8AxFF2Phg8EeP/JuiV95KMZnRDuEq1eE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":34763},"main":"dist/index.js","type":"module","engines":{"node":">=24"},"gitHead":"0e68df400f37247de3ab4266ca58fb908034d74a","scripts":{"dev":"tsx src/index.ts","build":"tsc -p tsconfig.json","start":"node dist/index.js","typecheck":"tsc --noEmit -p tsconfig.json","test:connection":"node scripts/test-connection.mjs"},"_npmUser":{"name":"tamaki_di","email":"duytnb2608.work@gmail.com"},"repository":{"url":"git+https://github.com/duytnb79/asana-mcp-server.git","type":"git"},"_npmVersion":"11.13.0","description":"Asana MCP server with personal access token authentication","directories":{},"_nodeVersion":"24.16.0","dependencies":{"zod":"3.25.76","dotenv":"17.4.2","@modelcontextprotocol/sdk":"1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"4.23.1","typescript":"5.9.3","@types/node":"24.13.3"},"_npmOperationalInternal":{"tmp":"tmp/asana-mcp_0.1.0_1785477153401_0.25562617681207844","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@duytnb79/asana-mcp","version":"0.1.1","description":"Asana MCP server with personal access token authentication","type":"module","bin":{"asana-mcp":"dist/index.js"},"main":"dist/index.js","publishConfig":{"access":"public"},"scripts":{"build":"tsc -p tsconfig.json","dev":"tsx src/index.ts","start":"node dist/index.js","test":"tsx --test tests/**/*.test.ts","test:connection":"node scripts/test-connection.mjs","typecheck":"tsc --noEmit -p tsconfig.json"},"repository":{"type":"git","url":"git+https://github.com/duytnb79/asana-mcp-server.git"},"homepage":"https://github.com/duytnb79/asana-mcp-server#readme","bugs":{"url":"https://github.com/duytnb79/asana-mcp-server/issues"},"keywords":["mcp","asana","personal-access-token"],"license":"MIT","engines":{"node":">=24"},"dependencies":{"@modelcontextprotocol/sdk":"1.30.0","dotenv":"17.4.2","zod":"3.25.76"},"devDependencies":{"@types/node":"24.13.3","tsx":"4.23.1","typescript":"5.9.3"},"gitHead":"38b0b03fe939bd5ef861c97da5b01dc3cd7924cf","_id":"@duytnb79/asana-mcp@0.1.1","_nodeVersion":"24.16.0","_npmVersion":"11.13.0","dist":{"integrity":"sha512-KzZNMVuZkZ2e29jcgZvKNSvmLMKHq18UdG1Db315EPlTDoaIfrX1J+ls//NIlX6y07Gnx2c37hFY1fPzw+vxFQ==","shasum":"4daad02f1dc548de8fccd71d191a590536db430d","tarball":"https://registry.npmjs.org/@duytnb79/asana-mcp/-/asana-mcp-0.1.1.tgz","fileCount":14,"unpackedSize":42580,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIB03TAYGSjj9p0e/apvdOVmGIAHmNld2Buwg0K8np9gPAiEA8OwjynEfd6g/7Mj9uGK3xIcfoQ11Ka9NwYArQpupwBE="}]},"_npmUser":{"name":"tamaki_di","email":"duytnb2608.work@gmail.com"},"directories":{},"maintainers":[{"name":"tamaki_di","email":"duytnb2608.work@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/asana-mcp_0.1.1_1786339760635_0.08253908512350439"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-31T05:52:33.226Z","modified":"2026-08-10T05:29:21.033Z","0.1.0":"2026-07-31T05:52:33.546Z","0.1.1":"2026-08-10T05:29:20.850Z"},"bugs":{"url":"https://github.com/duytnb79/asana-mcp-server/issues"},"license":"MIT","homepage":"https://github.com/duytnb79/asana-mcp-server#readme","keywords":["mcp","asana","personal-access-token"],"repository":{"type":"git","url":"git+https://github.com/duytnb79/asana-mcp-server.git"},"description":"Asana MCP server with personal access token authentication","maintainers":[{"name":"tamaki_di","email":"duytnb2608.work@gmail.com"}],"readme":"# @duytnb79/asana-mcp\n\nA read-only local MCP server for Asana that uses an Asana personal access token (PAT).\n\nIt runs over stdio and calls GET endpoints in the standard Asana REST API at `https://app.asana.com/api/1.0`. It is separate from Asana's hosted MCP server at `https://mcp.asana.com/v2/mcp`, which requires a registered MCP app and OAuth.\n\n## Requirements\n\n- Node.js 24+\n- An Asana personal access token\n- Access to the Asana workspaces, projects, and tasks you want to use\n\nCreate a PAT in the Asana developer console and treat it like a password. The server can only access data and perform actions allowed for the Asana user who owns the token.\n\n## Installation\n\n### Local clone\n\n```bash\nnpm install\nnpm run build\ncp .env.example .env\nnode dist/index.js\n```\n\n### Published package\n\nAfter this package is published, it can be run with:\n\n```bash\nnpx -y @duytnb79/asana-mcp\n```\n\nOr installed globally:\n\n```bash\nnpm install -g @duytnb79/asana-mcp\nasana-mcp\n```\n\n## Configuration\n\nCreate a `.env` file or provide environment variables through your MCP client:\n\n```bash\nASANA_ACCESS_TOKEN=\"your_asana_personal_access_token\"\nASANA_TIMEOUT_MS=\"10000\"\nASANA_MAX_PAGE_SIZE=\"100\"\nASANA_MAX_IMAGE_BYTES=\"10485760\"\n```\n\nRequired:\n\n- `ASANA_ACCESS_TOKEN`\n\nOptional:\n\n- `ASANA_TIMEOUT_MS` — request timeout in milliseconds; defaults to `10000`\n- `ASANA_MAX_PAGE_SIZE` — maximum page size exposed by list/search tools; defaults to `100` and must be between `1` and `100`\n- `ASANA_MAX_IMAGE_BYTES` — maximum downloaded image size in bytes; defaults to `10485760` (10 MiB)\n\nThe server automatically loads `.env` when running locally.\n\n## Test the Asana connection\n\nCopy the example environment file, replace the placeholder with your real PAT, then run the read-only connection test:\n\n```bash\ncp .env.example .env\n# Edit .env and set ASANA_ACCESS_TOKEN\nnpm run test:connection\n```\n\nA successful response starts with:\n\n```text\nAsana connection successful.\n```\n\nIt then prints the authenticated user and accessible workspaces. This test calls only `GET /users/me`; it does not create or modify Asana data.\n\n## MCP client configuration\n\n### Local build\n\n```json\n{\n  \"mcpServers\": {\n    \"asana\": {\n      \"command\": \"node\",\n      \"args\": [\n        \"/absolute/path/to/asana-mcp-server/dist/index.js\"\n      ],\n      \"env\": {\n        \"ASANA_ACCESS_TOKEN\": \"your_asana_personal_access_token\"\n      }\n    }\n  }\n}\n```\n\nAlternatively, run through npm from the project directory:\n\n```json\n{\n  \"mcpServers\": {\n    \"asana\": {\n      \"command\": \"npm\",\n      \"args\": [\"start\"],\n      \"cwd\": \"/absolute/path/to/asana-mcp-server\",\n      \"env\": {\n        \"ASANA_ACCESS_TOKEN\": \"your_asana_personal_access_token\"\n      }\n    }\n  }\n}\n```\n\n### Published package\n\n```json\n{\n  \"mcpServers\": {\n    \"asana\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@duytnb79/asana-mcp\"],\n      \"env\": {\n        \"ASANA_ACCESS_TOKEN\": \"your_asana_personal_access_token\"\n      }\n    }\n  }\n}\n```\n\n## Available tools\n\n### Read tools\n\n- `list_projects`\n  - Lists projects in a workspace.\n  - Supports `archived`, `limit`, `offset`, and `opt_fields`.\n- `list_tasks`\n  - Lists tasks in a project in project priority order.\n  - Supports `completed_since`, `limit`, `offset`, and `opt_fields`.\n- `get_task`\n  - Gets one task by GID.\n- `search_tasks`\n  - Searches a workspace by assignee, completion state, modified time, project, or text.\n  - Asana search is eventually consistent and may lag recent writes by 10–60 seconds.\n  - The search endpoint does not support normal Asana offset pagination and returns at most 100 items.\n- `list_sections`\n  - Lists sections in a project.\n  - Supports `limit`, `offset`, and `opt_fields`.\n- `list_task_comments`\n  - Returns the newest human comments from one task, excluding assignment, due-date, and other system activity stories.\n  - Accepts `task_gid` and an optional `limit` from 1 to 100; the default is 20.\n  - Scans the task's paginated story history, filters comments, and returns the requested number in newest-first order.\n- `list_task_attachments`\n  - Lists attachment metadata for a task with offset pagination; temporary download URLs are not exposed.\n- `read_attachment_image`\n  - Downloads one attachment by GID and returns MCP image content for visual analysis.\n  - Supports PNG, JPEG, WebP, and GIF up to `ASANA_MAX_IMAGE_BYTES`; SVG and non-image files are rejected.\n\nThe server does not register task creation, task update, or comment-writing tools. Its Asana client issues GET requests only.\n\n## Pagination\n\nAsana list endpoints return an opaque `next_page.offset`. The MCP response exposes it as `meta.next_offset`.\n\nPass that value back as `offset` to retrieve the next page. Only use offsets returned by Asana; they can expire when underlying data changes.\n\n## Input/output fields\n\nAsana returns compact objects by default. Use `opt_fields` to request additional properties, for example:\n\n```json\n{\n  \"project_gid\": \"12345\",\n  \"limit\": 50,\n  \"opt_fields\": [\n    \"name\",\n    \"completed\",\n    \"assignee.name\",\n    \"due_on\",\n    \"permalink_url\"\n  ]\n}\n```\n\nKeep `opt_fields` focused. Very broad or deeply nested responses are more expensive and may be rate-limited.\n\n## Rate limits and errors\n\n- Asana returns HTTP `429` when a token is rate-limited.\n- The server reports the `Retry-After` value when Asana provides it and does not retry requests automatically.\n- Authentication, permission, validation, not-found, timeout, and server errors are converted into readable MCP errors.\n- The PAT is sent only in the `Authorization: Bearer` header and is never placed in request URLs.\n\n## Security\n\n- Never commit `.env` or a PAT.\n- Prefer a dedicated PAT with the minimum user permissions needed for this integration.\n- Rotate the PAT if it is exposed.\n- The PAT still inherits the permissions of its Asana account; read-only behavior is enforced by this server's GET-only client and exposed tools, not by changing the PAT itself.\n- This server intentionally exposes specific read operations rather than a generic HTTP passthrough tool.\n- Image downloads never receive the Asana authorization header, validate redirects, reject local/private IP literals, verify image signatures, and enforce a bounded in-memory size.\n\n## Development\n\n```bash\nnpm run dev\nnpm run typecheck\nnpm run build\nnpm start\n```\n","readmeFilename":"README.md"}