Skip to main content
Glama
Raistlin82

SAP OData to MCP Server

by Raistlin82

Discover Service Entities

discover-service-entities

Explore SAP service entities and their capabilities to understand available data for querying, creating, updating, or deleting operations within SAP systems.

Instructions

List all entities and their capabilities within a specific SAP service. Use this after finding a service to understand what data you can work with.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
serviceIdYesThe SAP service ID to explore
showCapabilitiesNoShow CRUD capabilities for each entity

Implementation Reference

  • Input validation schema for 'discover-service-entities' tool, defining serviceId (required), entityPattern (optional regex filter), includeProperties and includeNavigations (optional booleans). Used for safe input sanitization.
    export const EntityDiscoverySchema = z.object({
      serviceId: serviceName,
      entityPattern: z
        .string()
        .min(1)
        .max(200)
        .regex(/^[a-zA-Z0-9_\-*?.[\]]*$/, 'Invalid entity pattern')
        .optional(),
      includeProperties: z.boolean().optional(),
      includeNavigations: z.boolean().optional(),
    });
  • ValidationSchemas object maps tool names to their Zod schemas, including 'discover-service-entities': EntityDiscoverySchema. Used by validateMCPToolInput function.
    export const ValidationSchemas = {
      // Discovery tools
      'search-sap-services': ServiceDiscoverySchema,
      'discover-service-entities': EntityDiscoverySchema,
      'get-entity-schema': EntitySchemaSchema,
    
      // CRUD operation tools
      'execute-entity-operation': EntityOperationSchema,
      'sap-odata-read': EntityReadSchema,
      'sap-odata-create': EntityCreateSchema,
      'sap-odata-update': EntityUpdateSchema,
      'sap-odata-delete': EntityDeleteSchema,
    
      // System tools
      'sap-health-check': HealthCheckSchema,
      'sap-system-info': SystemInfoSchema,
    } as const;
  • getServiceMetadata fetches and parses service $metadata to extract entityTypes array, which is core logic for discovering entities in a service. Likely called by the tool handler.
    private async getServiceMetadata(service: ODataService): Promise<ServiceMetadata> {
      try {
        const destination = await this.sapClient.getDestination({
          type: 'design-time',
          operation: 'discovery',
        });
    
        const response = await executeHttpRequest(destination, {
          method: 'GET',
          url: service.metadataUrl,
          headers: {
            Accept: 'application/xml',
          },
        });
        return this.parseMetadata(response.data, service.odataVersion);
      } catch (error) {
        this.logger.error(`Failed to get metadata for service ${service.id}:`, error);
        throw error;
      }
    }
    
    private parseMetadata(metadataXml: string, odataVersion: string): ServiceMetadata {
  • Registers sap-service-metadata resource that provides entity list for serviceId via sap://service/{serviceId}/metadata URI. Provides entity discovery data, possibly used alongside or by the tool.
    // Workflow guide removed - now using routing-rules.json in hierarchical-tool-registry
    
    this.mcpServer.registerResource(
      'sap-service-metadata',
      new ResourceTemplate('sap://service/{serviceId}/metadata', { list: undefined }),
      {
        title: 'SAP Service Metadata',
        description: 'Metadata information for SAP OData services',
      },
      async (uri, variables) => {
        // variables: Record<string, unknown> from SDK
        const serviceId = typeof variables.serviceId === 'string' ? variables.serviceId : '';
        const service = this.discoveredServices.find(s => s.id === serviceId);
        if (!service) {
          throw new Error(`Service not found: ${serviceId}`);
        }
        return {
          contents: [
            {
              uri: uri.href,
              text: JSON.stringify(
                {
                  service: {
                    id: service.id,
                    title: service.title,
                    description: service.description,
                    url: service.url,
                    version: service.version,
                  },
                  entities:
                    service.metadata?.entityTypes?.map(entity => ({
                      name: entity.name,
                      entitySet: entity.entitySet,
                      properties: entity.properties,
                      keys: entity.keys,
                      operations: {
                        creatable: entity.creatable,
                        updatable: entity.updatable,
                        deletable: entity.deletable,
                      },
                    })) || [],
                },
                null,
                2
              ),
              mimeType: 'application/json',
            },
          ],
        };
      }
    );
    this.mcpServer.registerResource(
  • Parses $metadata XML to extract detailed EntityType information (name, properties, keys, navigations), essential for the tool's output.
      xmlDoc: Document,
      entitySets: Array<{ [key: string]: string | null }>
    ): EntityType[] {
      const entityTypes: EntityType[] = [];
      const nodes = xmlDoc.querySelectorAll('EntityType');
    
      nodes.forEach((node: Element) => {
        const entitySet = entitySets.find(
          entitySet => entitySet.entitytype?.split('.')[1] === node.getAttribute('Name')
        );
        const entityType: EntityType = {
          name: node.getAttribute('Name') || '',
          namespace: node.parentElement?.getAttribute('Namespace') || '',
          entitySet: entitySet?.name,
          creatable: entitySet?.creatable?.toLowerCase() === 'true',
          updatable: entitySet?.updatable?.toLowerCase() === 'true',
          deletable: entitySet?.deletable?.toLowerCase() === 'true',
          addressable: entitySet?.addressable?.toLowerCase() === 'true',
          properties: [],
          navigationProperties: [],
          keys: [],
        };
    
        // Extract properties
        const propNodes = node.querySelectorAll('Property');
        propNodes.forEach((propNode: Element) => {
          entityType.properties.push({
            name: propNode.getAttribute('Name') || '',
            type: propNode.getAttribute('Type') || '',
            nullable: propNode.getAttribute('Nullable') !== 'false',
            maxLength: propNode.getAttribute('MaxLength') ?? undefined,
          });
        });
    
        // Extract keys
        const keyNodes = node.querySelectorAll('Key PropertyRef');
        keyNodes.forEach((keyNode: Element) => {
          entityType.keys.push(keyNode.getAttribute('Name') || '');
        });
    
        entityTypes.push(entityType);
      });
    
      return entityTypes;
    }
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. While it mentions the tool lists entities and capabilities, it doesn't describe what the output looks like (e.g., format, structure), whether it's paginated, if there are rate limits, or authentication requirements. For a tool with no annotations and no output schema, this leaves significant behavioral gaps.

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 two sentences with zero waste. The first sentence states the purpose, and the second provides usage guidelines. It's appropriately sized and front-loaded, with every sentence earning its place.

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

Completeness3/5

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

Given the tool's moderate complexity (2 parameters, no annotations, no output schema), the description is adequate but incomplete. It covers purpose and basic usage but lacks details on output format, error handling, or behavioral traits. Without annotations or an output schema, more context would be helpful for an agent to use it effectively.

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 already fully documents both parameters (serviceId and showCapabilities). The description doesn't add any parameter-specific details beyond what the schema provides, such as examples or constraints. This meets the baseline of 3 for high schema coverage.

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 with 'List all entities and their capabilities within a specific SAP service.' It specifies the verb ('List'), resource ('entities and their capabilities'), and scope ('within a specific SAP service'). However, it doesn't explicitly differentiate from sibling tools like 'search-sap-services' or 'get-entity-schema,' which prevents a perfect score.

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

Usage Guidelines4/5

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

The description provides clear context with 'Use this after finding a service to understand what data you can work with.' This gives a specific when-to-use guideline (after service discovery) and implies its exploratory purpose. However, it doesn't explicitly state when NOT to use it or name alternatives among siblings, which would be needed for a score of 5.

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