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:
Get ID from sap_help_search results
Use exact ID (don't modify the format)
Receive full page content + metadata
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result_id | Yes | Exact ID from sap_help_search results. Copy the ID exactly as returned. |
Implementation Reference
- src/lib/sapHelp.ts:151-326 (handler)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}`); } }
- src/lib/BaseServerHandler.ts:649-684 (registration)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 ); } }
- src/lib/BaseServerHandler.ts:296-322 (schema)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"] } },