Skip to main content
Glama
Raistlin82

SAP OData to MCP Server

by Raistlin82

UI Data Grid

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}`
                }]
            };
        }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden for behavioral disclosure. It mentions 'creates' (implying a write/mutation operation) and lists features like sorting and export, but doesn't address critical aspects: whether this requires authentication, what happens to existing data, if it's idempotent, rate limits, or what the output looks like (since no output schema exists). For a creation tool with zero annotation coverage, this is insufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core purpose ('Creates interactive data grids') and lists key features. There's no wasted verbiage or redundancy—every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool creates something (implied mutation), has no annotations, no output schema, and 3 parameters (with nested objects), the description is incomplete. It doesn't cover behavioral traits, output format, error handling, or integration context (e.g., how this fits with SAP entities mentioned in the schema). For a creation tool in this context, more guidance is needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all parameters (entityType, columns, features). The description adds no parameter-specific information beyond what's in the schema—it doesn't explain what 'SAP entity type' means, column usage, or feature implications. Baseline 3 is appropriate when the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Creates interactive data grids with sorting, filtering, and export capabilities.' It specifies the action ('creates'), resource ('interactive data grids'), and key features. However, it doesn't explicitly differentiate from sibling UI tools like 'ui-dashboard-composer' or 'ui-form-generator' beyond the generic 'data grids' term.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like 'ui-dashboard-composer' or 'ui-report-builder', nor does it specify prerequisites, use cases, or exclusions. The agent must infer usage from the tool name and description alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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