Skip to content

feat: smart parameter resolution for execute_card#9

Open
dadader621 wants to merge 1 commit into
easecloudio:mainfrom
dadader621:fix/execute-card-smart-parameters
Open

feat: smart parameter resolution for execute_card#9
dadader621 wants to merge 1 commit into
easecloudio:mainfrom
dadader621:fix/execute-card-smart-parameters

Conversation

@dadader621

Copy link
Copy Markdown

Summary

This PR adds automatic parameter format resolution for the execute_card tool, making it significantly easier to pass query parameters — especially dimension-type parameters.

Problem

Currently, users must construct the full native Metabase parameter array manually to filter card results. This is especially painful for dimension-type parameters which require a specific format:

{
  "type": "string/=",
  "target": ["dimension", ["template-tag", "module_lv1"]],
  "value": ["L4"]
}

Most MCP clients (AI agents) don't know this format and end up passing parameters incorrectly, resulting in unfiltered results.

Solution

The execute_card tool now accepts two parameter formats:

1. Simplified format (new, recommended)

Pass a plain {name: value} object:

{
  "card_id": 28342,
  "parameters": {
    "site_name": "guangzhou",
    "module_lv1": "L4",
    "module_lv2": "XDriving"
  }
}

The tool automatically:

  1. Fetches the card's metadata to inspect template tags
  2. Determines each parameter's type (text, date, dimension, number)
  3. Constructs the correct native Metabase parameter format

2. Native array format (existing, preserved)

The original array format continues to work for backwards compatibility:

{
  "card_id": 28342,
  "parameters": [
    {"type": "string/=", "target": ["dimension", ["template-tag", "module_lv1"]], "value": ["L4"]}
  ]
}

Parameter type mapping

Template tag type Generated parameter format
text {type: "category", target: ["variable", ...], value: [...]}
date {type: "date/single", target: ["variable", ...], value: "..."}
dimension {type: "string/=", target: ["dimension", ...], value: [...]}
number {type: "number/=", target: ["variable", ...], value: [...]}

Testing

Tested against a real Metabase instance with a card containing all parameter types (text, date, dimension):

  • ✅ Simplified {name: value} format — correctly filters dimension parameters
  • ✅ Native array format — backwards compatible
  • ✅ No parameters — returns unfiltered results

Changes

  • src/handlers/card-tools.ts: Enhanced execute_card schema and added resolveSimplifiedParameters() method

Add automatic parameter format resolution for execute_card tool.
Users can now pass simplified {name: value} objects instead of
constructing the full Metabase parameter array manually.

The tool inspects the card's template tags to determine parameter
types (text, date, dimension, number) and builds the correct
native Metabase parameter format automatically.

This is especially useful for dimension-type parameters which
require a specific format that differs from text parameters.

Both simplified object format and native array format are
supported for backwards compatibility.
@dadader621

Copy link
Copy Markdown
Author

Hi @Courtneychow88, just wanted to ping here — would appreciate a review when you get a chance. Happy to address any feedback!

@safoorsafdar

Copy link
Copy Markdown
Contributor

Thanks for this — the approach of fetching template tag metadata to resolve the correct parameter format is exactly right, and the type dispatch (text/date/dimension/number) is a significant improvement over hardcoding. PR #7 has been closed in favour of this one.

Before we merge, four things to address:

1. Guard against non-native cards

If execute_card is called with a simplified {name: value} object on an MBQL/structured card (no template-tags), templateTags resolves to {} and every parameter silently falls through to the unknown-parameter branch emitting type: "category". Instead, throw a clear error:

if (card?.dataset_query?.type !== "native") {
  throw new McpError(
    ErrorCode.InvalidParams,
    "Simplified parameters are only supported for native (SQL) cards"
  );
}

2. Unknown parameter should throw, not silently fall back

The current fallback constructs a category parameter for any name that doesn't match a template tag — this silently produces a malformed or unfiltered result. Better to fail loudly:

throw new McpError(
  ErrorCode.InvalidParams,
  `Unknown parameter: "${name}". Known parameters: ${Object.keys(templateTags).join(", ")}`
);

3. Restore type in the JSON Schema for parameters

The current diff removes the type field from the parameters schema entry. MCP clients use this for validation and hinting. Replace with:

parameters: {
  description: "...",
  oneOf: [
    { type: "object" },
    { type: "array", items: { type: "object" } }
  ]
}

4. Document the date/single limitation

All date template tags are currently mapped to date/single regardless of widget-type. This is fine for simple date pickers but will fail for date/range, date/month-year, etc. Either respect tag["widget-type"] in the dispatch, or add a note in the tool description that users should fall back to the native array format for date range filters.

Happy to help with any of these if useful. The core logic is solid — these are the remaining gaps before it's production-safe.

@aaronelliotross

Copy link
Copy Markdown

This is great! Much better approach than mine. =)

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.

4 participants