A modern bridge connecting Dune Analytics data to intelligent agents
DuneLink provides two simple tools with basic descriptions and minimal parameter documentation. Both tools are READ_ONLY query operations against Dune Analytics. Naming is adequate (verb_noun pattern with 'get_' and 'run_'), but parameter descriptions are minimal (only 1 sentence each), output schemas are completely undocumented, and error handling returns raw strings without recovery guidance. The implementation shows Flask/MCP integration but lacks the structured output, pagination support, and LLM-optimized descriptions expected in production tools.
Get the latest results for a specific query ID as a CSV string on Dune Analytics
Run a query by ID and return results as a CSV string on Dune Analytics
Output schema completely undocumented. Tools return CSV strings (df.to_csv()) but no schema describes the CSV structure, headers, or data types. LLMs cannot plan downstream operations on returned data.
Parameter descriptions are minimal (single sentence). 'The Dune Analytics query ID' lacks format guidance, valid ranges, or examples.
Error handling returns raw exception strings ('HTTP error fetching query results: <error>', 'Error processing query results: <error>'). Per pattern:recovery-guide, errors must guide the LLM on next steps: what to retry, what requires user input, or what is unrecoverable.
Inferred effective spec: <=2025-11-25.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 41 | <=2025-11-25 | v2 |
| 2026-03-09 | F | 34 | - | v1 |
No pagination support. Tools return entire result sets as CSV strings. Per pattern:paginated-result, large results blow context windows. Tools should accept limit/offset and return total count.
CSV output is unstructured text. Per pattern:response-shaper, tools should return structured JSON objects with typed fields (e.g., {rows: [{col1: val, col2: val}], row_count: N, execution_time_ms: 1234}), not free-form strings that LLMs must parse.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). Both tools are correctly READ_ONLY per Risk field, but this metadata is not exposed to the MCP client via tool annotations.
run_query implements polling with a 60-attempt max (5 min timeout), but no timeout error returned to LLM includes retry guidance. If execution_id becomes invalid or times out, the error message should hint at retry strategy or alternative tools.