This server has 4 tools with basic Asana integration. Naming is clear and verb-driven (get-*, update-*). Descriptions are present but minimal (10-50 chars, well below the 194-char production baseline). All tools have Zod-based input schemas with type definitions, which is correct. However, there are critical gaps: (1) Parameters lack detailed descriptions, most have bare 10-20 char descriptions that don't explain format, constraints, or when to use them; (2) Output schemas are completely undocumented, no indication what fields are returned, whether results are paginated, or what IDs downstream tools expect; (3) Error handling is generic, catch-all JSON.stringify of errors with no recovery guidance; (4) No security annotations despite one write tool (update-asana-task); (5) No validation of required parameters beyond Zod's optional() markers; (6) API tokens are injected via Bun.env but there's no documentation of secret injection pattern. The tools work but fall short of production quality.
Get sections for a project from Asana
Get a single task from Asana by ID
Get tasks from Asana
Update a single task in Asana by ID
Parameter descriptions are too short and lack actionable detail. E.g., 'The project ID to filter sections on' (40 chars) does not explain format, whether it's required, how to obtain it, or what happens if omitted. Production baseline is 72 chars with format hints. All 4 tools affected.
Output schemas are completely undocumented. Each tool returns JSON.stringify(result.data) with no indication of field names, types, pagination, or which IDs downstream tools can use. LLMs cannot reason about what to extract or how to chain calls.
Error handling is generic catch-all JSON.stringify(error) with no recovery guidance. LLM receives 'Error listing sections: {...}' with no hint what to do next: retry? Call a different tool? Ask the user? Violates error-classification and recovery-guide patterns.
Inferred effective spec: 2026-07-28+.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 42 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | - | v1 |
update-asana-task is a destructive write tool but has no permission gate, dry-run option, or confirmation step. An LLM could modify tasks without verification. No destructiveHint annotation in tool definition.
No pagination support. get-asana-tasks and get-asana-sections could return hundreds of items. If API returns large result sets, the entire JSON is passed to LLM context, wasting tokens and increasing hallucination. No limit parameter, no page/offset, no next_cursor documented.
Tool descriptions are too short (10-50 chars, production baseline 194 chars). 'Get sections for a project from Asana' lacks context: when should this be called vs other tools? What structure does it return? What permissions does it need? Short descriptions force LLMs to guess.
Secret injection via Bun.env is not documented. Tool descriptions don't explain that Asana access token and workspace ID come from server-side configuration, not parameters. If a future reader adds them as parameters, credentials leak into logs.
Parameter 'sections.any' and 'projects.any' and 'assignee.any' use Asana's query language dot notation. This is not self-documenting. The description 'The section ID' doesn't hint why it's named 'sections.any' or that it's a filter, not a direct lookup. LLMs may struggle to form valid queries.
No validation feedback. If an LLM passes an invalid Asana project ID or task ID, the error is 'Error getting task: {...}' with no hint whether the ID doesn't exist, the user lacks permission, or the API is down. Violates actionable-errors guidance.