Skip to main content
Glama
marianfoo

SAP Documentation MCP Server

by marianfoo

sap_help_get

Retrieve complete SAP Help Portal page content using exact result IDs from search results to access detailed documentation and metadata.

Instructions

GET SAP HELP PAGE: sap_help_get(result_id="sap-help-12345abc")

FUNCTION NAME: sap_help_get (or mcp_sap-docs-remote_sap_help_get)

RETRIEVES: Complete SAP Help Portal page content REQUIRES: Exact result_id from sap_help_search

USAGE PATTERN:

  1. Get ID from sap_help_search results

  2. Use exact ID (don't modify the format)

  3. Receive full page content + metadata

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
result_idYesExact ID from sap_help_search results. Copy the ID exactly as returned.

Implementation Reference

  • Core handler function that implements the sap_help_get tool logic: extracts loio from result_id, fetches metadata and page content from SAP Help private APIs, converts HTML to markdown text, adds metadata, and truncates if necessary.
    export async function getSapHelpContent(resultId: string): Promise<string> {
      try {
        // Extract loio from the result ID
        const loio = resultId.replace('sap-help-', '');
        if (!loio || loio === resultId) {
          throw new Error("Invalid SAP Help result ID. Use an ID from sap_help_search results.");
        }
    
        // First try to get from cache
        const cache = global.sapHelpSearchCache || new Map();
        let hit = cache.get(loio);
    
        if (!hit) {
          // If not in cache, search again to get the full hit data
          const searchParams = {
            transtype: "standard,html,pdf,others", 
            state: "PRODUCTION,TEST,DRAFT",
            product: "",
            version: "",
            q: loio, // Search by loio to find the specific document
            to: "19",
            area: "content",
            advancedSearch: "0",
            excludeNotSearchable: "1",
            language: "en-US",
          };
    
          const searchUrl = `${BASE}/http.svc/elasticsearch?${toQuery(searchParams)}`;
          const searchResponse = await fetch(searchUrl, {
            headers: {
              Accept: "application/json",
              "User-Agent": "mcp-sap-docs/help-get",
              Referer: BASE,
            },
          });
    
          if (!searchResponse.ok) {
            throw new Error(`Failed to find document: ${searchResponse.status} ${searchResponse.statusText}`);
          }
    
          const searchData: SapHelpSearchResponse = await searchResponse.json();
          const results = searchData?.data?.results || [];
          hit = results.find(r => r.loio === loio);
    
          if (!hit) {
            throw new Error(`Document with loio ${loio} not found`);
          }
        }
    
        // Prepare metadata request parameters
        const topic_url = `${hit.loio}.html`;
        let product_url = hit.productId;
        let deliverable_url;
    
        try {
          const { productUrlSeg, deliverableLoio } = parseDocsPathParts(hit.url);
          deliverable_url = deliverableLoio;
          if (!product_url) product_url = productUrlSeg;
        } catch (e) {
          if (!product_url) {
            throw new Error("Could not determine product_url from hit; missing productId and unparsable url");
          }
        }
    
        const language = hit.language || "en-US";
    
        // Get deliverable metadata
        const metadataParams = {
          product_url,
          topic_url,
          version: "LATEST",
          loadlandingpageontopicnotfound: "true",
          deliverable_url,
          language,
          deliverableInfo: "1",
          toc: "1",
        };
    
        const metadataUrl = `${BASE}/http.svc/deliverableMetadata?${toQuery(metadataParams)}`;
        const metadataResponse = await fetch(metadataUrl, {
          headers: {
            Accept: "application/json",
            "User-Agent": "mcp-sap-docs/help-metadata",
            Referer: BASE,
          },
        });
    
        if (!metadataResponse.ok) {
          throw new Error(`Metadata request failed: ${metadataResponse.status} ${metadataResponse.statusText}`);
        }
    
        const metadataData: SapHelpMetadataResponse = await metadataResponse.json();
        const deliverable_id = metadataData?.data?.deliverable?.id;
        const buildNo = metadataData?.data?.deliverable?.buildNo;
        const file_path = metadataData?.data?.filePath || topic_url;
    
        if (!deliverable_id || !buildNo || !file_path) {
          throw new Error("Missing required metadata: deliverable_id, buildNo, or file_path");
        }
    
        // Get page content
        const pageParams = {
          deliverableInfo: "1",
          deliverable_id,
          buildNo,
          file_path,
        };
    
        const pageUrl = `${BASE}/http.svc/pagecontent?${toQuery(pageParams)}`;
        const pageResponse = await fetch(pageUrl, {
          headers: {
            Accept: "application/json",
            "User-Agent": "mcp-sap-docs/help-content",
            Referer: BASE,
          },
        });
    
        if (!pageResponse.ok) {
          throw new Error(`Page content request failed: ${pageResponse.status} ${pageResponse.statusText}`);
        }
    
        const pageData: SapHelpPageContentResponse = await pageResponse.json();
        const title = pageData?.data?.currentPage?.t || pageData?.data?.deliverable?.title || hit.title;
        const bodyHtml = pageData?.data?.body || "";
    
        if (!bodyHtml) {
          return `# ${title}\n\nNo content available for this page.`;
        }
    
        // Convert HTML to readable text while preserving structure
        const cleanText = bodyHtml
          .replace(/<script[^>]*>[\s\S]*?<\/script>/gi, '') // Remove scripts
          .replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '') // Remove styles
          .replace(/<h([1-6])[^>]*>/gi, (_, level) => '\n' + '#'.repeat(parseInt(level)) + ' ') // Convert headings
          .replace(/<\/h[1-6]>/gi, '\n') // Close headings
          .replace(/<p[^>]*>/gi, '\n') // Paragraphs
          .replace(/<\/p>/gi, '\n')
          .replace(/<br[^>]*>/gi, '\n') // Line breaks
          .replace(/<li[^>]*>/gi, '• ') // List items
          .replace(/<\/li>/gi, '\n')
          .replace(/<code[^>]*>/gi, '`') // Inline code
          .replace(/<\/code>/gi, '`')
          .replace(/<pre[^>]*>/gi, '\n```\n') // Code blocks
          .replace(/<\/pre>/gi, '\n```\n')
          .replace(/<[^>]+>/g, '') // Remove remaining HTML tags
          .replace(/\s*\n\s*\n\s*/g, '\n\n') // Clean up multiple newlines
          .replace(/^\s+|\s+$/g, '') // Trim
          .trim();
    
        // Build the full content with metadata
        const fullContent = `# ${title}
    
    **Source:** SAP Help Portal
    **URL:** ${ensureAbsoluteUrl(hit.url)}
    **Product:** ${hit.product || hit.productId || "Unknown"}
    **Version:** ${hit.version || hit.versionId || "Latest"}
    **Language:** ${hit.language || "en-US"}
    ${hit.snippet ? `**Summary:** ${hit.snippet}` : ''}
    
    ---
    
    ${cleanText}
    
    ---
    
    *This content is from the SAP Help Portal and represents official SAP documentation.*`;
    
        // Apply intelligent truncation if content is too large
        const truncationResult = truncateContent(fullContent);
        
        return truncationResult.content;
    
      } catch (error: any) {
        throw new Error(`Failed to get SAP Help content: ${error.message}`);
      }
    }
  • Dispatch logic within the MCP CallToolRequestSchema handler that invokes getSapHelpContent when the tool name is 'sap_help_get', handles logging, error wrapping, and formats the response using createDocumentResponse.
    if (name === "sap_help_get") {
      const { result_id } = args as { result_id: string };
      
      // Enhanced logging with timing
      const timing = logger.logToolStart(name, result_id, clientMetadata);
      
      try {
        const content = await getSapHelpContent(result_id);
        
        // Transform SAP Help content to structured format
        const document: DocumentResult = {
          id: result_id,
          title: `SAP Help Document (${result_id})`,
          text: content,
          url: `https://help.sap.com/#${result_id}`,
          metadata: {
            source: 'sap-help',
            resultId: result_id,
            contentLength: content.length
          }
        };
        
        logger.logToolSuccess(name, timing.requestId, timing.startTime, 1, { 
          contentLength: content.length,
          resultId: result_id
        });
        
        return createDocumentResponse(document);
      } catch (error) {
        logger.logToolError(name, timing.requestId, timing.startTime, error);
        return createErrorResponse(
          `Error retrieving SAP Help content. Please try again later.`,
          timing.requestId
        );
      }
    }
  • Tool schema registration in ListToolsRequestSchema response, defining the name, description, and input schema requiring 'result_id' parameter.
                name: "sap_help_get", 
                description: `GET SAP HELP PAGE: sap_help_get(result_id="sap-help-12345abc")
    
    FUNCTION NAME: sap_help_get (or mcp_sap-docs-remote_sap_help_get)
    
    RETRIEVES: Complete SAP Help Portal page content
    REQUIRES: Exact result_id from sap_help_search
    
    USAGE PATTERN:
    1. Get ID from sap_help_search results  
    2. Use exact ID (don't modify the format)
    3. Receive full page content + metadata`,
                inputSchema: {
                  type: "object",
                  properties: {
                    result_id: {
                      type: "string",
                      description: "Exact ID from sap_help_search results. Copy the ID exactly as returned.",
                      examples: [
                        "sap-help-12345abc",
                        "sap-help-98765def"
                      ]
                    }
                  },
                  required: ["result_id"]
                }
              },

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/marianfoo/mcp-sap-docs'

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