From af8cb9dda6f2938cb182ebc54ae071d4a6d553b2 Mon Sep 17 00:00:00 2001 From: Brandon Pereira Date: Thu, 4 Jun 2026 11:12:43 -0600 Subject: [PATCH 1/2] fix: improve MCP alias descriptions and examples for readable chart legends The MCP tool schemas described the alias field as just 'Display label for this series' and all example tiles in mcpTilesParam omitted aliases entirely. This caused LLMs to skip aliases, resulting in chart legends showing raw ClickHouse expressions like count() or quantile(0.95)(Duration) instead of human-readable labels. Changes: - Add aliases to every example tile in mcpTilesParam (except heatmap) - Expand alias field descriptions in both dashboard and query schemas to explain what aliases are used for and what happens without them --- .../api/src/mcp/tools/dashboards/schemas.ts | 20 +++++++++++++------ packages/api/src/mcp/tools/query/schemas.ts | 6 +++++- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/api/src/mcp/tools/dashboards/schemas.ts b/packages/api/src/mcp/tools/dashboards/schemas.ts index e8c25b8997..9c7bf031eb 100644 --- a/packages/api/src/mcp/tools/dashboards/schemas.ts +++ b/packages/api/src/mcp/tools/dashboards/schemas.ts @@ -98,7 +98,15 @@ const mcpTileSelectItemSchema = z .default('') .describe('Filter in Lucene syntax. Example: "level:error"'), whereLanguage: SearchConditionLanguageSchema.optional().default('lucene'), - alias: z.string().optional().describe('Display label for this series'), + alias: z + .string() + .optional() + .describe( + 'Display label for this series — used in chart legends, table column headers, CSV exports, and onClick templates. ' + + 'Always set a short, human-readable alias (e.g. "Requests", "P95 Latency", "Error Rate"). ' + + 'Without an alias the UI shows the raw ClickHouse expression (e.g. count(), quantile(0.95)(Duration)) which is hard to read. ' + + 'Heatmap select items are the only exception (no alias needed).', + ), level: externalQuantileLevelSchema .optional() .describe('Percentile level for aggFn="quantile"'), @@ -659,15 +667,15 @@ export const mcpTilesParam = z 'The config block varies by displayType – use clickstack_list_sources for sourceId and connectionId values.\n\n' + 'Example tiles:\n' + '1. Line chart: { "name": "Error Rate", "config": { "displayType": "line", "sourceId": "", ' + - '"groupBy": "ResourceAttributes[\'service.name\']", "select": [{ "aggFn": "count", "where": "StatusCode:STATUS_CODE_ERROR" }] } }\n' + + '"groupBy": "ResourceAttributes[\'service.name\']", "select": [{ "aggFn": "count", "where": "StatusCode:STATUS_CODE_ERROR", "alias": "Errors" }] } }\n' + '2. Table: { "name": "Top Endpoints", "config": { "displayType": "table", "sourceId": "", ' + - '"groupBy": "SpanAttributes[\'http.route\']", "select": [{ "aggFn": "count" }, ' + - '{ "aggFn": "avg", "valueExpression": "Duration", "numberFormat": { "output": "duration", "factor": 0.000000001 } }] } }\n' + + '"groupBy": "SpanAttributes[\'http.route\']", "select": [{ "aggFn": "count", "alias": "Requests" }, ' + + '{ "aggFn": "avg", "valueExpression": "Duration", "alias": "Avg Duration", "numberFormat": { "output": "duration", "factor": 0.000000001 } }] } }\n' + ' (per-series numberFormat lets one column render as a duration while a sibling count column stays a plain number)\n' + '3. Number: { "name": "Total Requests", "config": { "displayType": "number", "sourceId": "", ' + - '"select": [{ "aggFn": "count" }], "numberFormat": { "output": "number", "average": true } } }\n' + + '"select": [{ "aggFn": "count", "alias": "Requests" }], "numberFormat": { "output": "number", "average": true } } }\n' + '4. Number (duration): { "name": "P95 Latency", "config": { "displayType": "number", "sourceId": "", ' + - '"select": [{ "aggFn": "quantile", "level": 0.95, "valueExpression": "Duration" }], ' + + '"select": [{ "aggFn": "quantile", "level": 0.95, "valueExpression": "Duration", "alias": "P95 Latency" }], ' + '"numberFormat": { "output": "duration", "factor": 0.000000001 } } }\n' + '5. Heatmap: { "name": "Latency Heatmap", "config": { "displayType": "heatmap", "sourceId": "", ' + '"select": [{ "valueExpression": "Duration" }], ' + diff --git a/packages/api/src/mcp/tools/query/schemas.ts b/packages/api/src/mcp/tools/query/schemas.ts index 19abd9c71c..6bcdd91ab4 100644 --- a/packages/api/src/mcp/tools/query/schemas.ts +++ b/packages/api/src/mcp/tools/query/schemas.ts @@ -104,7 +104,11 @@ export const mcpSelectItemSchema = z.object({ alias: z .string() .optional() - .describe('Display label for this series. Example: "Error rate"'), + .describe( + 'Display label for this series — used in chart legends, table column headers, CSV exports, and onClick templates. ' + + 'Always set a short, human-readable alias (e.g. "Requests", "P95 Latency", "Error Rate"). ' + + 'Without an alias the UI shows the raw ClickHouse expression (e.g. count(), quantile(0.95)(Duration)) which is hard to read.', + ), level: z .union([z.literal(0.5), z.literal(0.9), z.literal(0.95), z.literal(0.99)]) .optional() From da3840e2043ab3125e51440e45bc3d1dff6a93df Mon Sep 17 00:00:00 2001 From: Brandon Pereira Date: Thu, 4 Jun 2026 11:13:00 -0600 Subject: [PATCH 2/2] chore: add changeset for MCP alias improvements --- .changeset/mcp-alias-descriptions.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/mcp-alias-descriptions.md diff --git a/.changeset/mcp-alias-descriptions.md b/.changeset/mcp-alias-descriptions.md new file mode 100644 index 0000000000..61cc48e4b8 --- /dev/null +++ b/.changeset/mcp-alias-descriptions.md @@ -0,0 +1,5 @@ +--- +'@hyperdx/api': patch +--- + +fix(mcp): improve alias field descriptions and examples for readable chart legends