Skip to main content
Glama
Raistlin82

SAP OData to MCP Server

by Raistlin82

ui-data-grid

Create interactive data grids from SAP OData services to visualize, sort, filter, and export entity data for analysis and reporting.

Instructions

Creates interactive data grids with sorting, filtering, and export capabilities

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
entityTypeYesSAP entity type for the grid
columnsYesGrid column definitions
featuresNoGrid feature enablement

Implementation Reference

  • Registration of the 'ui-data-grid' tool with MCP server, including title, description, input schema, and handler reference.
    public async register(): Promise<void> { this.mcpServer.registerTool( "ui-data-grid", { title: "UI Data Grid Generator", description: `Generate interactive data grids for SAP entities with advanced features. Features: - Dynamic columns from SAP entity metadata - Sorting, filtering, and grouping capabilities - Export to Excel/CSV/PDF formats - Virtual scrolling for large datasets - Column resizing and reordering - Responsive design for mobile/desktop - Real-time data refresh - Selection modes (single/multiple) - Custom cell formatters and templates Required scope: ui.grids Examples: - Basic customer grid: {"entitySet": "Customers"} - Products with custom columns: {"entitySet": "Products", "columns": [...]} - Orders with filtering: {"entitySet": "Orders", "features": {"filtering": true, "export": true}}`, inputSchema: UIDataGridSchema }, async (args: Record<string, unknown>) => { return await this.handleDataGridGeneration(args); } ); this.logger.info("βœ… UI Data Grid tool registered successfully"); }
  • Input schema using Zod for validating parameters such as entitySet, columns, features, pageSize, and dataQuery for the UI data grid tool.
    const UIDataGridSchema = { entitySet: z.string().describe("SAP entity set name (e.g., 'Customers', 'Products', 'Orders')"), serviceId: z.string().optional().describe("SAP service ID containing the entity set"), columns: z.array(z.object({ key: z.string().describe("Field name from entity"), label: z.string().describe("Column header display name"), type: z.enum(['text', 'number', 'date', 'boolean', 'custom']).optional().describe("Column data type"), width: z.string().optional().describe("Column width (e.g., '150px', '20%')"), sortable: z.boolean().optional().describe("Enable sorting for this column"), filterable: z.boolean().optional().describe("Enable filtering for this column"), formatter: z.string().optional().describe("Custom formatter function name"), template: z.string().optional().describe("Custom cell template") })).optional().describe("Custom column configurations"), features: z.object({ sorting: z.boolean().optional().describe("Enable sorting functionality"), filtering: z.boolean().optional().describe("Enable filtering functionality"), grouping: z.boolean().optional().describe("Enable grouping functionality"), export: z.boolean().optional().describe("Enable export functionality"), columnResize: z.boolean().optional().describe("Enable column resizing"), virtualScrolling: z.boolean().optional().describe("Enable virtual scrolling for large datasets") }).optional().describe("Grid feature toggles"), pageSize: z.number().min(1).max(1000).optional().describe("Number of rows per page"), selectionMode: z.enum(['none', 'single', 'multiple']).optional().describe("Row selection mode"), initialData: z.array(z.record(z.any())).optional().describe("Initial data to display"), dataQuery: z.object({ filter: z.string().optional().describe("OData $filter query"), orderby: z.string().optional().describe("OData $orderby query"), select: z.string().optional().describe("OData $select query"), top: z.number().optional().describe("OData $top query"), skip: z.number().optional().describe("OData $skip query") }).optional().describe("Initial data query parameters"), theme: z.enum(['sap_horizon', 'sap_fiori_3']).optional().describe("SAP UI theme"), responsive: z.boolean().optional().describe("Enable responsive design") };
  • Main handler function that validates input, checks authorization, fetches metadata and data, generates grid configuration and UI, enhances with SAP styles/scripts, and returns the interactive data grid response.
    private async handleDataGridGeneration(args: unknown): Promise<any> { try { // Validate input parameters const params = z.object(UIDataGridSchema).parse(args); this.logger.info(`πŸ“Š Generating UI data grid for entity set: ${params.entitySet}`); // Check authentication and authorization const authCheck = await this.checkUIAccess('ui.grids'); if (!authCheck.hasAccess) { return { content: [{ type: "text", text: `❌ Authorization denied: ${authCheck.reason || 'Access denied for UI grid generation'}\n\nRequired scope: ui.grids` }] }; } // Step 1: Get entity metadata const entityMetadata = await this.getEntityMetadata(params.entitySet, params.serviceId); // Step 2: Generate columns from metadata or use custom const gridColumns = params.columns ? params.columns.map(col => ({ ...col, formatter: undefined // Convert string formatters to undefined for now })) : await this.generateColumnsFromMetadata(entityMetadata); // Step 3: Fetch initial data if query provided const initialData = params.initialData || await this.fetchInitialData(params.entitySet, params.dataQuery); // Step 4: Create grid configuration const gridConfig: GridConfig = { entitySet: params.entitySet, columns: gridColumns, features: { sorting: true, filtering: true, export: true, columnResize: true, virtualScrolling: Boolean(params.pageSize && params.pageSize > 100), ...params.features }, pageSize: params.pageSize || 20, selectionMode: params.selectionMode || 'single' }; // Step 5: Generate grid UI const gridResult = await this.componentLibrary.generateDataGrid(gridConfig); // Step 6: Add SAP-specific enhancements const enhancedResult = await this.enhanceGridResult(gridResult, params, initialData); // Step 7: Prepare response const response = this.createGridResponse(enhancedResult, gridConfig, initialData); this.logger.info(`βœ… UI data grid generated successfully for ${params.entitySet}`); return { content: [ { type: "text", text: `# SAP ${params.entitySet} Data Grid\n\n` + `Interactive data grid generated successfully.\n\n` + `## Grid Features:\n` + `- Columns: ${gridColumns.length}\n` + `- Sorting: ${gridConfig.features?.sorting ? 'βœ…' : '❌'}\n` + `- Filtering: ${gridConfig.features?.filtering ? 'βœ…' : '❌'}\n` + `- Export: ${gridConfig.features?.export ? 'βœ…' : '❌'}\n` + `- Virtual Scrolling: ${gridConfig.features?.virtualScrolling ? 'βœ…' : '❌'}\n` + `- Page Size: ${gridConfig.pageSize}\n` + `- Selection Mode: ${gridConfig.selectionMode}\n\n` + `## Data:\n` + `- Initial Rows: ${initialData.length}\n` + `- Entity Set: ${params.entitySet}\n\n` + `## Usage:\n` + `Embed this grid in your SAP application or use via MCP client.` }, { type: "resource", data: response, mimeType: "application/json" } ] }; } catch (error) { this.logger.error(`❌ Failed to generate UI data grid`, error as Error); return { content: [{ type: "text", text: `❌ Failed to generate UI data grid: ${(error as Error).message}` }] }; } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Raistlin82/btp-sap-odata-to-mcp-server-optimized'

If you have feedback or need assistance with the MCP directory API, please join our Discord server