-
Notifications
You must be signed in to change notification settings - Fork 7
GIE-228: Leverage existing dashboards #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This commit enables listing Perses dashboards from a cluster, getting a specific one, as well as returning out of the box dashboards that we ship with OpenShift platform. The idea is to for the LLM to first look at Out of the box dashboards, to see if it can answer a user's question using panels from those. And if not search wider for any custom dashboards a user might have. We also allow users (and ourselves!) to specify an LLM-friendly description of PersesDashboard objects using an annotation operator.perses.dev/mcp-help! This would help the LLM accurately filter and select dashboards that match a user's query. Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
Signed-off-by: Saswata Mukherjee <saswataminsta@yahoo.com>
The MCP server can now find existing Perses dashboards in the cluster and narrow them down to panels that, upon visualization, help answer the user's concerns better. It is assumed that since the queries in these panels have been through human reviews and used in production, they do not need to be subject to the same validation and guardrails as we for the queries that the LLM comes up with on-the-fly. Upon the LLM sharing it's intent to render one or more panels after going through the existing dashboards, the MCP server will expose payloads representing panels in the same structure as found in jhadvig/genie-plugin, so the UI side has no problems graphing these out.
70bca15 to
08bb97a
Compare
| // DashboardWidget represents a dashboard widget in the format expected by genie-plugin UI. | ||
| // This matches the DashboardWidget interface from jhadvig/genie-plugin. | ||
| type DashboardWidget struct { | ||
| ID string `json:"id" jsonschema:"description=Unique identifier for the widget"` | ||
| ComponentType string `json:"componentType" jsonschema:"description=Type of Perses component to render (PersesTimeSeries, PersesPieChart, PersesTable)"` | ||
| Position PanelPosition `json:"position" jsonschema:"description=Layout position in 24-column grid (optional, included when available from dashboard layout)"` | ||
| Props DashboardWidgetProps `json:"props" jsonschema:"description=Properties passed to the Perses component"` | ||
| Breakpoint string `json:"breakpoint" jsonschema:"description=Responsive grid breakpoint (xl/lg/md/sm) inferred from panel width, defaults to lg if position unavailable"` | ||
| } | ||
|
|
||
| // DashboardWidgetProps contains the properties passed to Perses components. | ||
| type DashboardWidgetProps struct { | ||
| Query string `json:"query" jsonschema:"description=PromQL query string"` | ||
| Duration string `json:"duration" jsonschema:"description=Time duration for the query (e.g. 1h, 24h), defaults to 1h if not specified in dashboard"` | ||
| Start string `json:"start,omitempty" jsonschema:"description=Optional explicit start time as RFC3339 or Unix timestamp"` | ||
| End string `json:"end,omitempty" jsonschema:"description=Optional explicit end time as RFC3339 or Unix timestamp"` | ||
| Step string `json:"step" jsonschema:"description=Query resolution step width (e.g. 15s, 1m, 5m), defaults to 15s if not specified in dashboard"` | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inferred from the genie-plugin repository, specifically, this.
IIUC genie-web-client has no such agnostic interface yet that lets MCP servers instruct the bot on how to render panels (based on certain tools they may have to expose things in an expected format (format_panels_for_ui tool does this here)), as I wasn't able to find any there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rendering widgets through MCP tools is not yet supported, see this Slack thread for more details.
This PR is currently blocked by GIE-376.
The MCP server can now find existing Perses dashboards in the cluster
and narrow them down to panels that, upon visualization, help answer the
user's concerns better. It is assumed that since the queries in these
panels have been through human reviews and used in production, they do
not need to be subject to the same validation and guardrails as we for
the queries that the LLM comes up with on-the-fly.
Upon the LLM sharing it's intent to render one or more panels after
going through the existing dashboards, the MCP server will expose
payloads representing panels in the same structure as found in
jhadvig/genie-plugin, so the UI side has no problems graphing these out.
Builds on #2.
{ "conversation_id": "9a1925495e78c5fefaa84e6a7bc621ba85041f15e6ee8fa1", "response": "There is one available dashboard in the monitoring namespace:\n\n- **Name:** sample-dashboard\n- **Namespace:** monitoring", "rag_chunks": [], "referenced_documents": [], "truncated": false, "input_tokens": 2178, "output_tokens": 34, "available_quotas": {}, "tool_calls": [ { "id": "mcp_list_04e607c1-bc92-4e64-a101-4efe5eb23760", "name": "mcp_list_tools", "args": { "server_label": "obs" }, "type": "mcp_list_tools" }, { "id": "fc_f9d0408c-74c5-4223-85d3-7c23e6d15172", "name": "list_dashboards", "args": { "server_label": "obs" }, "type": "mcp_call" } ], "tool_results": [ { "id": "mcp_list_04e607c1-bc92-4e64-a101-4efe5eb23760", "status": "success", "content": "{\"server_label\": \"obs\", \"tools\": [{\"name\": \"execute_range_query\", \"description\": \"Execute a PromQL range query with flexible time specification.\\n\\nFor current time data queries, use only the 'duration' parameter to specify how far back\\nto look from now (e.g., '1h' for last hour, '30m' for last 30 minutes). In that case\\nSET 'end' to 'NOW' and leave 'start' empty.\\n\\nFor historical data queries, use explicit 'start' and 'end' times.\\n\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"duration\": {\"description\": \"Duration to look back from now (e.g., '1h', '30m', '1d', '2w') (optional)\", \"pattern\": \"^\\\\d+[smhdwy]$\", \"type\": \"string\"}, \"end\": {\"description\": \"End time as RFC3339 or Unix timestamp (optional). Use `NOW` for current time.\", \"type\": \"string\"}, \"query\": {\"description\": \"PromQL query string\", \"type\": \"string\"}, \"start\": {\"description\": \"Start time as RFC3339 or Unix timestamp (optional)\", \"type\": \"string\"}, \"step\": {\"description\": \"Query resolution step width (e.g., '15s', '1m', '1h')\", \"pattern\": \"^\\\\d+[smhdwy]$\", \"type\": \"string\"}}, \"required\": [\"query\", \"step\"]}}, {\"name\": \"format_panels_for_ui\", \"description\": \"Format selected dashboard panels for UI rendering in DashboardWidget format.\\n\\nAfter choosing relevant panels, use this to prepare them for display.\\n\\nReturns an array of DashboardWidget objects ready for direct rendering, with:\\n- id: Unique panel identifier\\n- componentType: Perses component name (PersesTimeSeries, PersesPieChart, PersesTable)\\n- position: Grid layout coordinates (x, y, w, h) in 24-column grid\\n- breakpoint: Responsive grid breakpoint (xl/lg/md/sm) inferred from panel width\\n- props: Component properties (query, duration, step, start, end)\\n\\nPanel IDs (fetched using get_dashboard_panels) must be provided to specify which panels to format.\\n\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"name\": {\"description\": \"Name of the dashboard containing the panels\", \"type\": \"string\"}, \"namespace\": {\"description\": \"Namespace of the dashboard\", \"type\": \"string\"}, \"panel_ids\": {\"description\": \"Comma-separated list of panel IDs to format (e.g. 'myPanelID-1,0_1-2')\", \"type\": \"string\"}}, \"required\": [\"name\", \"namespace\", \"panel_ids\"]}}, {\"name\": \"get_dashboard\", \"description\": \"Get a specific Dashboard by name and namespace. This tool is used to get the dashboard's panels and configuration.\\n\\nUse the list_dashboards tool first to find available dashboards, then use this tool to get the full specification of a specific dashboard, if needed (to gather more context).\\n\\nThe intended use of this tool is only to gather more context on one or more dashboards when the description from list_dashboards is insufficient.\\n\\nInformation about panels themselves should be gathered using get_dashboard_panels instead (e.g., looking at a \\\"kind: Markdown\\\" panel to gather more context).\\n\\nReturns the dashboard's full specification including panels, layouts, variables, and datasources in JSON format.\\n\\nFor most use cases, you will want to follow up with get_dashboard_panels to extract panel metadata for selection.\\n\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"name\": {\"description\": \"Name of the Dashboard\", \"type\": \"string\"}, \"namespace\": {\"description\": \"Namespace of the Dashboard\", \"type\": \"string\"}}, \"required\": [\"name\", \"namespace\"]}}, {\"name\": \"get_dashboard_panels\", \"description\": \"Get panel(s) information from a specific Dashboard.\\n\\nAfter finding a relevant dashboard (using list_dashboards and conditionally, get_dashboard), use this to see what panels it contains.\\n\\nReturns panel metadata including:\\n- Panel IDs (format: 'panelName' or 'panelName-N' for multi-query panels)\\n- Titles and descriptions\\n- PromQL queries (may contain variables like $namespace)\\n- Chart types (TimeSeriesChart, PieChart, Table)\\n\\nYou can optionally provide specific panel IDs to fetch only those panels. This is useful when you remember panel IDs from earlier calls and want to re-fetch just their metadata without retrieving the entire dashboard's panels.\\n\\nUse this information to identify which panels answer the user's question, then use format_panels_for_ui with the selected panel IDs to prepare them for display.\\n\", \"input_schema\": {\"type\": \"object\", \"properties\": {\"name\": {\"description\": \"Name of the Dashboard\", \"type\": \"string\"}, \"namespace\": {\"description\": \"Namespace of the Dashboard\", \"type\": \"string\"}, \"panel_ids\": {\"description\": \"Optional comma-separated list of panel IDs to filter. Panel IDs follow the format 'panelName' or 'panelName-N' where N is the query index (e.g. 'cpuUsage,memoryUsage-0,networkTraffic-1'). Use this to fetch metadata for specific panels you've seen in earlier calls. Leave empty to get all panels.\", \"type\": \"string\"}}, \"required\": [\"name\", \"namespace\"]}}, {\"name\": \"list_dashboards\", \"description\": \"List all PersesDashboard resources from the cluster.\\n\\nStart here when there is a need to visualize metrics.\\n\\nReturns dashboard summaries with name, namespace, labels, and descriptions.\\n\\nUse the descriptions to identify dashboards relevant to the user's question.\\n\\nIn the case that there is insufficient information in the description, use get_dashboard to fetch the full dashboard spec for more context. Doing so is an expensive operation, so only do this when necessary.\\n\\nFollow up with get_dashboard_panels to see what panels are available in the relevant dashboard(s).\\n\", \"input_schema\": {\"type\": \"object\", \"properties\": {}}}, {\"name\": \"list_metrics\", \"description\": \"List all available metrics in Prometheus\", \"input_schema\": {\"type\": \"object\", \"properties\": {}}}]}", "type": "mcp_list_tools", "round": 1 }, { "id": "fc_f9d0408c-74c5-4223-85d3-7c23e6d15172", "status": "success", "content": "{\"dashboards\":[{\"name\":\"sample-dashboard\",\"namespace\":\"monitoring\"}]}", "type": "mcp_call", "round": 1 } ] }Relevant Pod logs
Relevant SQLite DB snapshot
jhadvig/genie-pluginflow (genie-web-clientdoes not support this currently).