ui-dashboard-composer
Create comprehensive KPI dashboards with charts and real-time data from SAP systems to visualize business metrics and monitor performance.
Instructions
Creates comprehensive KPI dashboards with charts and real-time data
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| dashboardTitle | Yes | Title for the dashboard | |
| widgets | Yes | Dashboard widget configurations | |
| layout | No | Dashboard layout style |
Implementation Reference
- src/tools/ui/ui-dashboard-composer-tool.ts:107-150 (registration)Registers the 'ui-dashboard-composer' tool with the MCP server, specifying title, detailed description, input schema, and the handler function that delegates to handleDashboardComposition.public async register(): Promise<void> { this.mcpServer.registerTool( "ui-dashboard-composer", { title: "UI Dashboard Composer", description: `Create interactive KPI dashboards with widgets, charts, and real-time updates. Features: - Multiple widget types (KPI cards, charts, tables, gauges, timelines) - Flexible grid-based layout system - Real-time data refresh and updates - Interactive filters and drill-down capabilities - Chart.js integration for advanced visualizations - Export to PDF, Excel, PowerPoint, and images - Responsive design for mobile and desktop - SAP Fiori design language compliance - Custom aggregations and calculations - WebSocket support for live data Required scope: ui.dashboards Widget Types: - kpi-card: Key performance indicator cards - chart: Bar, line, pie, doughnut, and radar charts - table: Data tables with sorting and filtering - list: Simple list displays - gauge: Circular and linear progress gauges - timeline: Event timelines and process flows - map: Geographic data visualization - custom: Custom HTML/JavaScript widgets Examples: - Sales dashboard: {"title": "Sales Overview", "widgets": [...]} - Executive summary: {"title": "Executive KPIs", "layout": {"type": "grid", "columns": 3}} - Real-time monitoring: {"refreshInterval": 30, "widgets": [...]}`, inputSchema: UIDashboardComposerSchema }, async (args: Record<string, unknown>) => { return await this.handleDashboardComposition(args); } ); this.logger.info("β UI Dashboard Composer tool registered successfully"); }
- Comprehensive Zod input schema defining all parameters for dashboard configuration including layout, widgets, data sources, filters, theme, and export options.const UIDashboardComposerSchema = { title: z.string().describe("Dashboard title"), description: z.string().optional().describe("Dashboard description"), layout: z.object({ type: z.enum(['grid', 'flexbox', 'absolute']).describe("Layout type"), columns: z.number().min(1).max(12).optional().describe("Number of columns for grid layout"), gap: z.string().optional().describe("Gap between widgets (e.g., '1rem')"), responsive: z.boolean().optional().describe("Enable responsive design") }).describe("Dashboard layout configuration"), widgets: z.array(z.object({ id: z.string().describe("Unique widget identifier"), type: z.enum(['kpi-card', 'chart', 'table', 'list', 'gauge', 'timeline', 'map', 'custom']).describe("Widget type"), title: z.string().describe("Widget title"), position: z.object({ row: z.number().min(0).describe("Grid row position"), col: z.number().min(0).describe("Grid column position"), width: z.number().min(1).max(12).describe("Widget width (grid columns)"), height: z.number().min(1).describe("Widget height (grid rows)") }).describe("Widget position and size"), config: z.record(z.any()).optional().describe("Widget-specific configuration"), dataSource: z.object({ entitySet: z.string().describe("SAP entity set for data"), query: z.object({ filter: z.string().optional(), select: z.string().optional(), orderby: z.string().optional(), top: z.number().optional() }).optional().describe("OData query parameters"), aggregation: z.object({ groupBy: z.array(z.string()).optional().describe("Fields to group by"), measures: z.array(z.object({ field: z.string(), operation: z.enum(['sum', 'avg', 'count', 'min', 'max']) })).optional().describe("Aggregation measures") }).optional().describe("Data aggregation configuration"), refresh: z.number().optional().describe("Refresh interval in seconds") }).describe("Data source configuration") })).describe("Dashboard widgets"), datasources: z.array(z.object({ id: z.string().describe("Data source identifier"), entitySet: z.string().describe("SAP entity set"), query: z.string().optional().describe("Custom OData query"), cacheTtl: z.number().optional().describe("Cache TTL in seconds"), transform: z.string().optional().describe("Data transformation function name") })).optional().describe("Shared data sources"), refreshInterval: z.number().min(5).max(3600).optional().describe("Global refresh interval in seconds"), theme: z.enum(['sap_horizon', 'sap_fiori_3', 'dark', 'light']).optional().describe("Dashboard theme"), filters: z.array(z.object({ field: z.string().describe("Filter field name"), label: z.string().describe("Filter display label"), type: z.enum(['select', 'daterange', 'text', 'number']).describe("Filter type"), options: z.array(z.object({ value: z.string(), label: z.string() })).optional().describe("Options for select filters"), defaultValue: z.any().optional().describe("Default filter value") })).optional().describe("Global dashboard filters"), exportOptions: z.object({ pdf: z.boolean().optional(), excel: z.boolean().optional(), powerpoint: z.boolean().optional(), image: z.boolean().optional() }).optional().describe("Export format options") };
- Core handler function that parses input, checks authorization, validates and prepares widgets/data, generates dashboard layout and UI using component library, enhances with SAP styles/scripts, and returns markdown summary with JSON resource containing full dashboard config.private async handleDashboardComposition(args: unknown): Promise<any> { try { // Validate input parameters const params = z.object(UIDashboardComposerSchema).parse(args); this.logger.info(`π Generating dashboard: ${params.title} with ${params.widgets.length} widgets`); // Check authentication and authorization const authCheck = await this.checkUIAccess('ui.dashboards'); if (!authCheck.hasAccess) { return { content: [{ type: "text", text: `β Authorization denied: ${authCheck.reason || 'Access denied for UI dashboard generation'}\n\nRequired scope: ui.dashboards` }] }; } // Step 1: Validate and prepare widget configurations const validatedWidgets = await this.validateAndPrepareWidgets(params.widgets); // Step 2: Prepare data sources const dataSources = await this.prepareDashboardDataSources(validatedWidgets, params.datasources); // Step 3: Create dashboard layout const layoutDefinition: LayoutDefinition = { type: params.layout.type, config: { columns: params.layout.columns || 4, gap: params.layout.gap || '1rem', responsive: params.layout.responsive !== false ? { breakpoints: { mobile: { columns: 1, gap: '0.5rem' }, tablet: { columns: 2, gap: '1rem' }, desktop: { columns: 4, gap: '1rem' } } } : undefined }, components: this.createWidgetComponents(validatedWidgets) }; // Step 4: Create dashboard configuration const dashboardConfig: DashboardConfig = { layout: layoutDefinition, widgets: validatedWidgets, datasources: dataSources, refreshInterval: params.refreshInterval || 60, theme: params.theme || 'sap_horizon' }; // Step 5: Generate dashboard UI const dashboardResult = await this.componentLibrary.generateDashboard(dashboardConfig); // Step 6: Add SAP-specific enhancements const enhancedResult = await this.enhanceDashboardResult(dashboardResult, params); // Step 7: Prepare response const response = this.createDashboardResponse(enhancedResult, params, dataSources); this.logger.info(`β Dashboard '${params.title}' generated successfully`); return { content: [ { type: "text", text: `# ${params.title}\n\n` + `${params.description || 'Interactive SAP dashboard with real-time KPIs'}\n\n` + `## Dashboard Overview:\n` + `- Widgets: ${params.widgets.length}\n` + `- Layout: ${params.layout.type} (${params.layout.columns || 4} columns)\n` + `- Theme: ${params.theme || 'sap_horizon'}\n` + `- Refresh: Every ${params.refreshInterval || 60} seconds\n` + `- Filters: ${params.filters?.length || 0}\n\n` + `## Widget Types:\n` + params.widgets.map(w => `- ${w.type}: ${w.title}`).join('\n') + '\n\n' + `## Data Sources:\n` + `- Entity Sets: ${Array.from(new Set(params.widgets.map(w => w.dataSource.entitySet))).join(', ')}\n` + `- Real-time Updates: ${params.refreshInterval ? 'β ' : 'β'}\n\n` + `## Features:\n` + `- Export Options: ${Object.entries(params.exportOptions || {}).filter(([k, v]) => v).map(([k]) => k.toUpperCase()).join(', ') || 'Basic'}\n` + `- Responsive Design: β \n` + `- Interactive Filters: ${params.filters?.length ? 'β ' : 'β'}\n\n` + `Embed this dashboard in your SAP application or use via MCP client.` }, { type: "resource", data: response, mimeType: "application/json" } ] }; } catch (error) { this.logger.error(`β Failed to generate dashboard`, error as Error); return { content: [{ type: "text", text: `β Failed to generate dashboard: ${(error as Error).message}` }] }; } }