asana-admin-mcp
asana-admin-mcp
MCP server สำหรับ จัดโครงสร้าง Asana — portfolio, custom field / dropdown, project, section, project template, team (แท็บ People) เติมช่องที่ Asana connector ตัวมาตรฐานทำไม่ได้ (ตัวนั้นเน้น task/read)
⚠️ Dashboard ทำไม่ได้ — และไม่ใช่ข้อจำกัดของ MCP ตัวนี้
Asana ไม่เปิด public API สำหรับ Dashboard / chart / widget / project view tab เลย (ไล่ครบ 175 endpoints ใน OpenAPI spec ทางการ — ไม่มีสักตัว)
ทางเดียวที่ automate ได้คือ project_duplicate — สเปคระบุว่าเวลา duplicate project นั้น
Project Views (แท็บ List / Board / Dashboard) ถูกก๊อปตามไปเสมอและปิดไม่ได้
→ ตั้ง Dashboard ไว้ใน "โปรเจกต์ต้นแบบ" หนึ่งอัน แล้ว duplicate ทุกครั้งที่ต้องการโปรเจกต์ใหม่
🟡 ยังไม่ได้พิสูจน์: สเปคเขียนว่า "Project Views" ตามไป แต่ไม่ได้บอกชัดว่า chart ที่ตั้งไว้ใน Dashboard ตามไปด้วยหรือได้แค่แท็บเปล่า — ตรวจไม่ได้ผ่าน API (ไม่มี endpoint ให้อ่าน chart) ต้องเปิดดูด้วยตา smoke test 2026-08-17 duplicate โปรเจกต์ที่ไม่มี chart จึงยังไม่ตอบข้อนี้
หมายเหตุ: Project Template ไม่พา Dashboard ไปด้วย (ยังเป็น feature request ค้างอยู่ในฟอรัม Asana) ต้องใช้ duplicate ไม่ใช่ template
ติดตั้ง
1. เอา Asana token ก่อน (ทุกคนต้องมีของตัวเอง)
ทำตาม GET-TOKEN.md → เซฟไว้ที่ ~/.asana_token
printf '%s' 'วาง_token_ตรงนี้' > ~/.asana_token && chmod 600 ~/.asana_tokentoken ผูกกับสิทธิ์รายบุคคล ห้ามใช้ของคนอื่น — log ใน Asana จะขึ้นชื่อเจ้าของ token
2. ติดตั้ง plugin (แนะนำ)
ใน Claude Code พิมพ์ 2 บรรทัด:
/plugin marketplace add plakorp/asana-admin-mcp
/plugin install asana-admin@asana-admin-mcpClaude Code จะ clone repo + รัน npm ci ให้เอง แล้วลงทะเบียน MCP ให้ — ไม่ต้องแตะ ~/.claude.json
อัปเดตทีหลังก็ /plugin update
ต้องมี Node 20+ ในเครื่อง (node -v เช็ก)
วิธีที่ 2 — ติดตั้งมือ (ถ้าไม่อยากใช้ plugin)
clone repo แล้วดับเบิลคลิก ติดตั้ง-asana-admin-mcp.command
สคริปต์จะขอ token, รัน npm install, แล้วเขียน ~/.claude.json ให้ (backup ทุกครั้ง)
อย่าใช้ทั้ง 2 วิธีพร้อมกัน — จะได้ MCP ชื่อ
asana-adminซ้อนกัน 2 ตัว
Token อ่านจาก env ASANA_TOKEN ก่อน ถ้าไม่มีค่อย fallback ไป ~/.asana_token
→ ตัว token ไม่เคยอยู่ในรีโปและไม่ต้องอยู่ใน ~/.claude.json
Tools (40)
ทุก tool รับ gid ไม่ใช่ชื่อ — ใช้ asana_find แปลงชื่อ → gid ก่อน
Discovery
Tool | ทำอะไร |
| ตัวเอง + workspace ทั้งหมด (เริ่มที่นี่ เพราะเกือบทุก create ต้องใช้ |
| typeahead หา gid จากชื่อ — project / portfolio / custom_field / task / team / user / tag / goal |
| custom field ใน workspace หรือที่ผูกกับ project/portfolio — คืน |
Portfolio
Tool | ทำอะไร |
| สร้าง portfolio |
| rename / เปลี่ยนสี / public |
| ดูโปรเจกต์ใน portfolio ตามลำดับที่แสดงจริง |
| เพิ่มโปรเจกต์เข้า portfolio + ระบุตำแหน่งได้ ( |
| ถอดโปรเจกต์ออก (ต้องส่ง |
Custom field / dropdown
Tool | ทำอะไร |
| สร้าง field — |
| rename / แก้ description |
| เพิ่มค่าใน dropdown + ระบุตำแหน่งได้ |
| rename / เปลี่ยนสี / |
| จัดลำดับค่าใน dropdown |
| ผูก field เข้า project หรือ portfolio ( |
| ถอด field ออกจาก project/portfolio เดียว — ตัว field และค่าบนที่อื่นไม่ถูกแตะ |
| 🔴 ลบ field ถาวร หายจากทุกโปรเจกต์ในองค์กรพร้อมค่าบน task (ต้อง |
Asana ลบค่า dropdown ไม่ได้ — ทำได้แค่
enabled:falseงานที่เคยเลือกค่านั้นไว้จะยังเก็บค่าเดิม🔴 กับดักที่เกือบหลอกได้ (2026-08-27):
DELETE /enum_options/{gid}มี route จริง — ตอบ"enum_option: Not a recognized ID"ไม่ใช่"No matching route"แต่พอยิงจริงกลับได้ 403Enum option deletion is forbidden⇒ route มีอยู่ ≠ เรียกได้ เป็นคนละคำถาม และมีแค่การยิงจริงเท่านั้นที่ตอบข้อหลัง ตรงข้ามกับDELETE /custom_fields/{gid}ที่ undocumented เหมือนกันแต่ทำงานจริง (smoke ยืนยัน)
Knowledge pages ⚠️ undocumented API
Tool | ทำอะไร |
| สร้างหน้าใน Knowledge → Pages |
| rename / แก้เนื้อหา / privacy |
| อ่านหน้าเต็มรวม |
| หน้าทั้งหมดใน workspace |
🔴 Asana ไม่ประกาศ endpoint นี้ที่ไหนเลย — ไม่มีใน OpenAPI spec และไม่มีใน
developers.asana.com/llms.txtค้นพบด้วยการ probe ตรง ๆ เมื่อ 2026-08-17 Knowledge Page = resource ชื่อnote(/notes, permalink/note/{gid}) ของที่ไม่ประกาศเปลี่ยนได้ทุกเมื่อ — ถ้าวันหนึ่ง 404 นั่นคือ Asana ไม่ใช่บั๊กของเราnpm run smokeครอบคลุมส่วนนี้ไว้เพื่อให้รู้ตัวเร็ว
ข้อจำกัดของ HTML ที่วัดเอง:
<p>ใช้ไม่ได้ →xml_parsing_error(ขึ้นบรรทัดใหม่ด้วย newline แทน)<h1><h2>ส่งได้ แต่ถูกเก็บเป็น<strong>— ระดับหัวข้อไม่รอดใช้ได้:
strongemusulolliablockquotecodeprehrimgtableprivacy_setting:members_only(ค่าตั้งต้น) |public_to_domain
🔴 4 กับดักที่ทำให้คนคิดว่า "ทำไม่ได้" (วัดจริง 2026-08-21)
1. ตารางทำได้ — แต่ไม่มีเขียนไว้ที่ไหนเลย
ส่ง <table><tr><td>…</td></tr></table> ได้ตรง ๆ Asana เก็บเป็น native table จริง ไม่ใช่ข้อความ
ไม่มี thead / th — ทำหัวตารางด้วยการใส่ <strong> ในเซลล์แถวแรก
Asana จะแปะบรรทัด ⚠ This table cannot be viewed on Mobile ให้เองเหนือตาราง (เราไม่ต้องเขียน)
2. page_get อ่านตารางกลับมาไม่ได้ — ห้ามใช้ตัดสินว่าเขียนสำเร็จไหม
ตารางที่อยู่บนหน้าจะคืนมาเป็นบรรทัด placeholder เปล่า ๆ:
<i>⚠ This table cannot be viewed on Mobile. Please view it on Web. ⚠</i>ไม่มีแถว ไม่มีเซลล์เลย → ยืนยันด้วยการเปิดเว็บดูเท่านั้น ถ้าดูจาก page_get จะสรุปผิดว่าโดน strip
3. ⚠️ round-trip ลบตารางทิ้งแบบเงียบ ๆ
html_text = replace ทั้ง body ไม่ใช่ append → การเพิ่มเนื้อหาต้อง page_get แล้วต่อ string เอง
แต่เพราะข้อ 2 การ page_get → page_update ธรรมดา จะลบตารางเดิมที่มีอยู่บนหน้าไปทั้งหมด
ก่อนเขียนทับหน้าที่ไม่ได้เขียนเอง → เปิดเว็บเช็คก่อนว่ามีตารางอยู่ไหม
4. link ต้องรอ enrich — ไม่ใช่พัง
ใส่ permalink ธรรมดาใน href แล้ว Asana จะ enrich เป็น mention ให้เอง
แต่ หลังเขียนเสร็จทันทีจะยังโชว์เป็น URL ดิบ ต้อง reload ก่อน
และ label ที่แสดงจะถูกเขียนทับด้วยชื่อจริงของ page เสมอ ไม่ว่าจะใส่ข้อความอะไรไว้
เพิ่มเติม: ตารางเกิน ~5 คอลัมน์จะล้นกรอบเนื้อหา คอลัมน์ขวาสุดโดนตัด — ยุบคอลัมน์ก่อน
Project template ✅ มีจริง (ที่เคยเข้าใจว่าไม่มี)
Tool | ทำอะไร |
| template ของทีม — ใน organization ต้องส่ง |
| record เต็ม รวม |
| สร้างโปรเจกต์จริงจาก template — default = dry run ต้องส่ง |
🔴 กับดักที่ทำให้ทุกคนสรุปว่า "ไม่มี template API" (วัด 2026-08-27):
bangkokbank.comเป็น organization ไม่ใช่ workspace ⇒GET /project_templates?workspace={gid}ตอบ 400 "Not a valid regular workspace. You provided an organization" ซึ่งอ่านเผิน ๆ เหมือน endpoint พัง ทั้งที่แค่ต้องเปลี่ยนเป็น?team={gid}⚠️ template ไม่พา Dashboard widget ไปด้วย — ถ้าโปรเจกต์ใหม่ต้องมี chart ให้ใช้
project_duplicate
Team / People
Tool | ทำอะไร |
| ทีมของเรา (หรือ |
| record ทีม + 6 access-level setting ที่บอกว่าใครมีสิทธิ์เชิญ/เอาคนออก/เปลี่ยนชื่อ |
| สร้างทีม ( |
| rename / description / visibility |
| คนในทีม พร้อม |
| เพิ่มคนที่อยู่ใน org แล้วเข้าทีม (รับ gid / email / |
| เอาคนออกจากทีม (ต้อง |
เพดานที่วัดแล้ว 2026-08-27:
🔴 ลบทีมไม่ได้ —
DELETE /teams/{gid}ตอบNo matching routeสร้างแล้วสร้างเลย ตั้งชื่อให้ถูกตั้งแต่แรก🟡 เชิญคนเข้า org / ปิดบัญชี (
POST /users,DELETE /users/{gid}) ตอบ 403 ไม่ใช่ 404 ⇒ route มีจริง แต่ Personal Access Token สิทธิ์ไม่ถึง ต้องเป็น org admin / service account นี่คือเพดานสิทธิ์ ไม่ใช่เพดานความสามารถ
Rule / Form / Dashboard / View — ไม่มี route เลย
ยิงตรงแล้วได้ No matching route for request ทุกตัว (2026-08-27):
/rules · /rule_triggers · /projects/{gid}/rules · /automations · /forms · /dashboards · /widgets · /project_views
⇒ upgrade MCP ไม่ช่วย MCP เป็นแค่ท่อต่อ REST API — ไม่มี endpoint ก็จบ
(ยกเว้น POST /rule_triggers/{gid}/run สำหรับ rule ที่ตั้ง trigger เป็น Web request is received
ซึ่งต้องให้คนก๊อป URL มาให้ เพราะไม่มี GET /rules ให้ auto-discover)
Project / Section
Tool | ทำอะไร |
| สร้างโปรเจกต์ (ใน organization ต้องมี |
| rename / notes / สี / |
| เขียนค่า custom field ของ project — ทางเดียวที่จะเติมคอลัมน์ที่เห็นใน portfolio List view เพราะค่าอยู่บน project ไม่ใช่บน portfolio |
| ก๊อปโปรเจกต์ พา Dashboard ไปด้วย — ทางออกเดียวของเรื่อง dashboard (คืน job, ทำงาน async) |
| section ตามลำดับ + gid |
| เพิ่ม section + ระบุตำแหน่งได้ |
| rename section |
| จัดลำดับ section |
Attachment
Tool | ทำอะไร |
| อัปโหลดไฟล์จากเครื่องขึ้นไปแนบกับ task (parent เป็น project / project brief ก็ได้) — สูงสุด 100 MB |
| ไฟล์ที่แนบอยู่แล้ว + gid ที่ต้องใช้ตอนลบ |
| ลบไฟล์ที่แนบ (ต้อง |
/attachments เป็น endpoint เดียวในเซิร์ฟเวอร์นี้ที่ ไม่ใช่ JSON — ต้องส่ง multipart/form-data
เลยไม่ผ่าน req() แต่ใช้ upload() ใน client.js แทน (ห้ามตั้ง header Content-Type เอง
ต้องปล่อยให้ fetch เขียน boundary ให้)
Asana ไม่มี API เอาไฟล์ที่แนบอยู่แล้วไปแปะ task อื่น — ต้องอัปใหม่
ไม่มี tool สำหรับลบ project / portfolio / team โดยตั้งใจ — ลบพวกนี้กู้ไม่ได้ ให้ทำในหน้าเว็บ
(team ลบผ่าน API ไม่ได้อยู่แล้ว — DELETE /teams/{gid} ตอบ No matching route)
ส่วน custom_field_delete มีให้ แต่บังคับ confirm: true และควรลอง custom_field_detach ก่อนเสมอ
สี (ใช้ได้กับ portfolio / project / enum option)
none red orange yellow-orange yellow yellow-green green blue-green
aqua blue indigo purple magenta hot-pink pink cool-gray
ทดสอบ
ASANA_TOKEN=$(cat ~/.asana_token) npm run smokeสร้างของจริงใน workspace แรกของ token ชื่อขึ้นต้น ZZ-mcp-smoke-* → ตรวจทุก tool → ลบทิ้งเองทั้งหมด
ถ้าไม่ใส่ token จะรันแค่ครึ่งแรก (server boot + list tools)
หมายเหตุการทำงาน
429 → retry อัตโนมัติ 3 ครั้ง ตาม
Retry-Aftererror จาก Asana ส่งกลับเป็นข้อความจริงจาก API (บอกว่า field ไหนหาย / gid ไหนผิด) ไม่ใช่แค่ status code
ฟิลด์ที่ไม่ได้ส่ง จะไม่ถูกแตะ —
portfolio_updateที่ส่งแค่nameไม่ล้างสี