update_card_parameters
Update the parameters list on a Metabase card to control filter widgets and dashboard parameter wiring. Each parameter defines widget type, target, and defaults. Allows merge or full replacement.
Instructions
Set the card-level parameters list on a saved question.
Card parameters drive the filter widgets shown on a card's own page AND are what Metabase uses to wire dashboard parameters into the card. For a date filter to render as a date picker (instead of a plain text box), the card must have a matching parameter entry — the template-tag type alone is not enough.
Each parameter is a dict. Common keys:
id: the template-tag's UUID (must match
dataset_query.native.template-tags[name].id)name: display name, e.g. "Start date"
slug: URL slug, e.g. "start_date"
type: widget type, e.g. "date/single", "date/range", "date/all-options", "category", "string/=", "number/="
target: link back to the template tag, e.g. ["variable", ["template-tag", "start_date"]] (for text/number/date vars) ["dimension", ["template-tag", "start_date"]] (for field filters)
default: default value (optional)
values_source_type / values_source_config: dropdown data source (optional)
values_query_type: "list" | "search" | "none" (optional)
Args:
card_id: The ID of the card whose parameters should be updated.
parameters: List of parameter configs. When merge=False (default)
this replaces the card's entire parameters list. When merge=True,
entries are matched by id (or by slug if id is missing) and
merged into existing parameters; new entries are appended.
Returns: The updated card object.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| card_id | Yes | ||
| parameters | Yes | ||
| merge | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- server.py:1096-1178 (handler)The `update_card_parameters` tool registered with FastMCP via @mcp.tool decorator. Sets card-level `parameters` list on a saved question. Supports merge mode (by id/slug) or full replacement. Sends PUT /card/{card_id} with the parameters payload.
async def update_card_parameters( card_id: int, parameters: list[dict[str, Any]], ctx: Context, merge: bool = False, ) -> dict[str, Any]: """ Set the card-level `parameters` list on a saved question. Card parameters drive the filter widgets shown on a card's own page AND are what Metabase uses to wire dashboard parameters into the card. For a date filter to render as a date picker (instead of a plain text box), the card must have a matching parameter entry — the template-tag type alone is not enough. Each parameter is a dict. Common keys: - id: the template-tag's UUID (must match `dataset_query.native.template-tags[name].id`) - name: display name, e.g. "Start date" - slug: URL slug, e.g. "start_date" - type: widget type, e.g. "date/single", "date/range", "date/all-options", "category", "string/=", "number/=" - target: link back to the template tag, e.g. ["variable", ["template-tag", "start_date"]] (for text/number/date vars) ["dimension", ["template-tag", "start_date"]] (for field filters) - default: default value (optional) - values_source_type / values_source_config: dropdown data source (optional) - values_query_type: "list" | "search" | "none" (optional) Args: card_id: The ID of the card whose parameters should be updated. parameters: List of parameter configs. When `merge=False` (default) this replaces the card's entire parameters list. When `merge=True`, entries are matched by `id` (or by `slug` if `id` is missing) and merged into existing parameters; new entries are appended. Returns: The updated card object. """ if not parameters: raise ToolError("`parameters` must contain at least one entry.") try: await ctx.info(f"Updating parameters on card {card_id}") if merge: card = await metabase_client.request("GET", f"/card/{card_id}") existing: list[dict[str, Any]] = list(card.get("parameters") or []) def key(p: dict[str, Any]) -> Any: return p.get("id") or p.get("slug") by_key = {key(p): dict(p) for p in existing if key(p) is not None} ordered_keys = [key(p) for p in existing if key(p) is not None] for incoming in parameters: k = key(incoming) if k is None: raise ToolError( "When merge=True, each parameter must include 'id' or 'slug'." ) if k in by_key: by_key[k].update(incoming) else: by_key[k] = dict(incoming) ordered_keys.append(k) new_params = [by_key[k] for k in ordered_keys] else: new_params = list(parameters) result = await metabase_client.request( "PUT", f"/card/{card_id}", json={"parameters": new_params} ) await ctx.info( f"Successfully updated {len(new_params)} parameter(s) on card {card_id}" ) return result except ToolError: raise except Exception as e: error_msg = f"Error updating parameters on card {card_id}: {e}" await ctx.error(error_msg) raise ToolError(error_msg) from e - server.py:1095-1178 (registration)The tool is registered via the @mcp.tool decorator on the `update_card_parameters` async function, using FastMCP's automatic tool registration mechanism.
@mcp.tool async def update_card_parameters( card_id: int, parameters: list[dict[str, Any]], ctx: Context, merge: bool = False, ) -> dict[str, Any]: """ Set the card-level `parameters` list on a saved question. Card parameters drive the filter widgets shown on a card's own page AND are what Metabase uses to wire dashboard parameters into the card. For a date filter to render as a date picker (instead of a plain text box), the card must have a matching parameter entry — the template-tag type alone is not enough. Each parameter is a dict. Common keys: - id: the template-tag's UUID (must match `dataset_query.native.template-tags[name].id`) - name: display name, e.g. "Start date" - slug: URL slug, e.g. "start_date" - type: widget type, e.g. "date/single", "date/range", "date/all-options", "category", "string/=", "number/=" - target: link back to the template tag, e.g. ["variable", ["template-tag", "start_date"]] (for text/number/date vars) ["dimension", ["template-tag", "start_date"]] (for field filters) - default: default value (optional) - values_source_type / values_source_config: dropdown data source (optional) - values_query_type: "list" | "search" | "none" (optional) Args: card_id: The ID of the card whose parameters should be updated. parameters: List of parameter configs. When `merge=False` (default) this replaces the card's entire parameters list. When `merge=True`, entries are matched by `id` (or by `slug` if `id` is missing) and merged into existing parameters; new entries are appended. Returns: The updated card object. """ if not parameters: raise ToolError("`parameters` must contain at least one entry.") try: await ctx.info(f"Updating parameters on card {card_id}") if merge: card = await metabase_client.request("GET", f"/card/{card_id}") existing: list[dict[str, Any]] = list(card.get("parameters") or []) def key(p: dict[str, Any]) -> Any: return p.get("id") or p.get("slug") by_key = {key(p): dict(p) for p in existing if key(p) is not None} ordered_keys = [key(p) for p in existing if key(p) is not None] for incoming in parameters: k = key(incoming) if k is None: raise ToolError( "When merge=True, each parameter must include 'id' or 'slug'." ) if k in by_key: by_key[k].update(incoming) else: by_key[k] = dict(incoming) ordered_keys.append(k) new_params = [by_key[k] for k in ordered_keys] else: new_params = list(parameters) result = await metabase_client.request( "PUT", f"/card/{card_id}", json={"parameters": new_params} ) await ctx.info( f"Successfully updated {len(new_params)} parameter(s) on card {card_id}" ) return result except ToolError: raise except Exception as e: error_msg = f"Error updating parameters on card {card_id}: {e}" await ctx.error(error_msg) raise ToolError(error_msg) from e