Skip to content

fix: improve create_card dataset_query schema for MCP compatibility#15

Open
Kai-Oesterling wants to merge 1 commit intoCognitionAI:mainfrom
Kai-Oesterling:fix/create-card-dataset-query-schema
Open

fix: improve create_card dataset_query schema for MCP compatibility#15
Kai-Oesterling wants to merge 1 commit intoCognitionAI:mainfrom
Kai-Oesterling:fix/create-card-dataset-query-schema

Conversation

@Kai-Oesterling
Copy link
Copy Markdown

Problem

The create_card tool fails with HTTP 400 errors when called via MCP clients (Claude Desktop, etc.). The Metabase API rejects the request because the dataset_query object isn't properly structured.

Root Cause

The current schema definition:

dataset_query: z.object({}).passthrough().optional()

While passthrough() should allow additional properties, MCP clients don't properly serialize deeply nested objects when the base schema is an empty object {}.

Example Error

When trying to create a card with a native SQL query:

{
  "name": "Test Card",
  "dataset_query": {
    "type": "native",
    "database": 2,
    "native": { "query": "SELECT * FROM users" }
  }
}

The API returns: Request failed with status code 400

Solution

Define explicit Zod schemas for the two main query types:

  1. Native SQL queries:
const nativeQuerySchema = z.object({
  type: z.literal("native"),
  database: z.number(),
  native: z.object({
    query: z.string(),
    "template-tags": z.record(z.any()).optional(),
  }).passthrough(),
}).passthrough();
  1. MBQL queries:
const mbqlQuerySchema = z.object({
  type: z.literal("query"),
  database: z.number(),
  query: z.object({
    "source-table": z.number().optional(),
  }).passthrough(),
}).passthrough();

Combined with z.union() to accept either format.

Additional Improvements

  • Enhanced tool description with examples of both query formats
  • Added default values for display ("table") and visualization_settings ({})
  • Listed available display types in description

Testing

Tested with:

  • SQL Server database (native queries)
  • Creating cards via direct API call with the same payload structure
  • Card creation now succeeds where it previously failed

Breaking Changes

None. The schema is more specific but still accepts all valid Metabase query formats via passthrough().

The previous schema using `z.object({}).passthrough()` for dataset_query
caused issues when MCP clients passed nested objects. The Metabase API
returned 400 errors because the dataset_query structure wasn't being
properly validated and passed through.

This fix:
- Adds explicit schema for native queries with database, type, and native fields
- Adds explicit schema for MBQL queries with database, type, and query fields  
- Maintains backward compatibility with passthrough() for additional fields
- Improves description to guide users on required structure

Tested with SQL Server native queries - cards now create successfully.
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