Skip to content

feat: task-level commands, filter DSL, and chart create fix (v0.4.0)#1

Open
vishaldubey01 wants to merge 2 commits intomainfrom
feat/task-level-commands
Open

feat: task-level commands, filter DSL, and chart create fix (v0.4.0)#1
vishaldubey01 wants to merge 2 commits intomainfrom
feat/task-level-commands

Conversation

@vishaldubey01
Copy link
Contributor

@vishaldubey01 vishaldubey01 commented Mar 14, 2026

What changed

Overhaul of the CLI to add task-level commands that abstract away multi-step MCP workflows and raw JSON construction.

New features

Flag-based chart creation (charts create)

amp charts create --event _active --metric uniques \
  --interval 7 --range "Last 90 Days" --save --name "WAU"

Filter DSL — human-readable filters instead of JSON:

--filter "user:country is US"
--filter "event:platform is iOS,Android"
--filter "user:gp:plan is enterprise,growth"

Top-level funnel command

amp funnel "Sign Up" "Add to Cart" "Purchase" \
  --range "Last 30 Days" --conversion-window 7d --save

Top-level retention command

amp retention --start-event _new --return-event _active \
  --range "Last 90 Days" --interval 7 --method nday --save

Dashboard create with --charts flag

amp dashboards create --name "KPIs" --charts abc123 def456 ghi789 --cols 3

Fixes

  • charts create fixed — now uses query_dataset → save_chart_edits instead of the nonexistent create_chart MCP tool
  • saveChart() in mcp-client.ts — wraps in { charts: [...] } array as the MCP tool actually expects
  • extractEditId — also checks chartEditId field from query_dataset responses

New files

  • src/utils/filters.ts — Filter DSL parser, group-by parser, conversion window parser, bracket parser, date range builder
  • src/commands/funnel.ts — Top-level funnel command
  • src/commands/retention.ts — Top-level retention command

Version bump

0.3.2 → 0.4.0


Note

Medium Risk
Changes the MCP request shapes for query_dataset and save_chart_edits and reroutes charts create through the query+save flow, which could break existing CLI workflows if the MCP contract differs. New top-level commands add additional dataset query paths that need validation across chart types and option parsing.

Overview
Adds task-level CLI commands to build and query common analyses without hand-writing JSON: a top-level amp funnel and amp retention, plus a filters DSL (--filter, --group-by, conversion windows, bracket parsing) to generate chart definitions from flags.

Reworks charts create to support flag-based definitions and to query via query_dataset and optionally persist via save_chart_edits (new --save), instead of directly calling create_chart; dashboards create can now accept --charts and auto-generate a row layout.

Updates MCP client payloads to match expected tool contracts (definition.app injection for query_dataset, { charts: [...] } for save_chart_edits) and improves extractEditId to recognize chartEditId; bumps version to 0.4.0.

Written by Cursor Bugbot for commit 3c13b4d. This will update automatically on new commits. Configure here.

- Fix charts create to use query_dataset → save_chart_edits (create_chart doesn't exist)
- Add flag-based chart creation: --event, --metric, --interval, --range, --filter, --group-by, --save
- New filter DSL parser: "user:country is US" → MCP filter JSON
- New top-level amp funnel command with positional steps
- New top-level amp retention command
- Enhanced dashboard create with --charts flag for auto-layout
- Fix saveChart() to wrap in { charts: [...] } array as MCP expects
- Fix extractEditId to also check chartEditId field
- Bump version to 0.4.0
w: "week",
m: "month",
};
return { value, unit: unitMap[suffix] };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conversion window "m" maps to "month" not "minute"

High Severity

The unitMap in parseConversionWindow maps "m" to "month", but the help text documents "30m" as an example clearly meaning 30 minutes. A user passing --conversion-window 30m would get a 30-month conversion window instead of 30 minutes, producing wildly incorrect funnel results.

Additional Locations (1)
Fix in Cursor Fix in Web

"greater",
"less",
"is",
];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Operator order makes "set is not" unreachable

Medium Severity

In the OPERATORS array, "is not" (index 0) appears before "set is not" (index 4). Since the matching loop breaks on first match and " is not " is a substring found within " set is not ", a filter like "user:tags set is not active" matches "is not" first, yielding property key "tags set" instead of "tags" with operator "set is not".

Additional Locations (1)
Fix in Cursor Fix in Web

const valueStr = rest.slice(matchedIdx + 1 + matchedOp.length).trim();
const values = valueStr ? valueStr.split(",").map((v) => v.trim()).filter(Boolean) : [];

const group_type = scope === "user" ? "User" : "User"; // always "User" for group_type
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dead ternary always returns same value for group_type

Low Severity

parseFilter has scope === "user" ? "User" : "User" which always evaluates to "User" regardless of scope. In contrast, parseGroupBy returns "User" or "Event" based on scope. This dead ternary either masks a real bug (event-scoped filters getting the wrong group_type) or is needlessly misleading.

Fix in Cursor Fix in Web

- charts: wrap in {type, params} with app injected by queryDataset()
- funnel: use 'order' not 'funnelOrder', wrap events/segments in params
- retention: use 'retentionEvents' array, 'retentionMethod', 'retentionBrackets'
- mcp-client: inject definition.app from projectId in queryDataset()
- mcp-client: make description required (empty string) in saveChart()

All commands tested live against Amplitude MCP server.
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 4 total unresolved issues (including 3 from previous reviews).

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

return obj;
}
return undefined;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildDateRange is exported but never called anywhere

Low Severity

buildDateRange is a new exported function imported into charts.ts, funnel.ts, and retention.ts but never actually called in any of them. All three commands build date range parameters inline instead. This is dead code — both the function definition and all three imports are unused.

Additional Locations (2)
Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant