Skip to main content
Glama
marianfoo

SAP Documentation MCP Server

search

Search SAP technical documentation for ABAP, UI5, CAP, and related technologies using specific queries to find relevant code examples and solutions.

Instructions

SEARCH SAP DOCS: search(query="search terms")

FUNCTION NAME: search

COVERS: ABAP (all versions), UI5, CAP, wdi5, OpenUI5 APIs, Cloud SDK AUTO-DETECTS: ABAP versions from query (e.g. "LOOP 7.57", defaults to 7.58)

TYPICAL WORKFLOW:

  1. search(query="your search terms")

  2. fetch(id="result_id_from_step_1")

QUERY TIPS: • Be specific: "CAP action binary parameter" not just "CAP" • Include error codes: "415 error CAP action" • Use technical terms: "LargeBinary MediaType XMLHttpRequest" • For ABAP: Include version like "7.58" or "latest"

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
queryYesSearch terms using natural language. Be specific and include technical terms.

Implementation Reference

  • MCP CallToolRequestSchema handler logic for the 'search' tool. Extracts query parameter, calls the core search function, transforms results into ChatGPT-compatible JSON format with id, title, url, snippet, score, metadata. Includes error handling and fallback to legacy search implementation.
    if (name === "sap_docs_search" || name === "search") {
      const { query } = args as { query: string };
      
      // Enhanced logging with timing
      const timing = logger.logToolStart(name, query, clientMetadata);
      
      try {
        // Use hybrid search with reranking
        const results = await search(query, { 
          k: CONFIG.RETURN_K 
        });
        
        const topResults = results;
        
        if (topResults.length === 0) {
          logger.logToolSuccess(name, timing.requestId, timing.startTime, 0, { fallback: false });
          return createErrorResponse(
            `No results for "${query}". Try UI5 controls ("button", "table"), CAP topics ("actions", "binary"), testing ("wdi5", "e2e"), ABAP with versions ("SELECT 7.58"), or include error codes ("415 error").`,
            timing.requestId
          );
        }
        
        // Transform results to ChatGPT-compatible format with id, title, url
        const searchResults: SearchResult[] = topResults.map((r, index) => {
          // Extract library_id and topic from document ID
          const libraryIdMatch = r.id.match(/^(\/[^\/]+)/);
          const libraryId = libraryIdMatch ? libraryIdMatch[1] : (r.sourceId ? `/${r.sourceId}` : r.id);
          const topic = r.id.startsWith(libraryId) ? r.id.slice(libraryId.length + 1) : '';
          
          const config = getDocUrlConfig(libraryId);
          const docUrl = config ? generateDocumentationUrl(libraryId, '', r.text, config) : null;
          
          return {
            // ChatGPT-required format: id, title, url
            id: r.id,  // Use full document ID as required by ChatGPT
            title: r.text.split('\n')[0] || r.id,
            url: docUrl || `#${r.id}`,
            // Additional fields for backward compatibility
            library_id: libraryId,
            topic: topic,
            snippet: r.text ? r.text.substring(0, CONFIG.EXCERPT_LENGTH_MAIN) + '...' : '',
            score: r.finalScore,
            metadata: {
              source: r.sourceId || 'sap-docs',
              library: libraryId,
              bm25Score: r.bm25,
              rank: index + 1
            }
          };
        });
        
        logger.logToolSuccess(name, timing.requestId, timing.startTime, topResults.length, { fallback: false });
        
        return createSearchResponse(searchResults);
      } catch (error) {
        logger.logToolError(name, timing.requestId, timing.startTime, error, false);
        logger.info('Attempting fallback to original search after hybrid search failure');
        
        // Fallback to original search
        try {
          const res: SearchResponse = await searchLibraries(query);
          
          if (!res.results.length) {
            logger.logToolSuccess(name, timing.requestId, timing.startTime, 0, { fallback: true });
            return createErrorResponse(
              res.error || `No fallback results for "${query}". Try UI5 controls ("button", "table"), CAP topics ("actions", "binary"), testing ("wdi5", "e2e"), ABAP with versions ("SELECT 7.58"), or include error codes.`,
              timing.requestId
            );
          }
          
          // Transform fallback results to structured format
          const fallbackResults: SearchResult[] = res.results.map((r, index) => ({
            id: r.id || `fallback-${index}`,
            title: r.title || 'SAP Documentation',
            url: r.url || `#${r.id}`,
            snippet: r.description ? r.description.substring(0, 200) + '...' : '',
            metadata: {
              source: 'fallback-search',
              rank: index + 1
            }
          }));
          
          logger.logToolSuccess(name, timing.requestId, timing.startTime, res.results.length, { fallback: true });
          
          return createSearchResponse(fallbackResults);
        } catch (fallbackError) {
          logger.logToolError(name, timing.requestId, timing.startTime, fallbackError, true);
          return createErrorResponse(
            `Search temporarily unavailable. Wait 30 seconds and retry, try sap_community_search instead, or use more specific search terms.`,
            timing.requestId
          );
        }
      }
    }
  • Core implementation of the search logic: performs BM25 FTS search across multiple query variants, applies source boosts, smart ABAP version filtering (latest by default), ranking by final score. Called by MCP tool handler.
    export async function search(
      query: string,
      { k = CONFIG.RETURN_K } = {}
    ): Promise<SearchResult[]> {
      // Load metadata for boosts and query expansion
      loadMetadata();
      const sourceBoosts = getSourceBoosts();
      
      // Expand query with synonyms and acronyms
      const queryVariants = expandQueryTerms(query);
      const seen = new Map<string, any>();
      
      // Check if query contains specific ABAP version
      const versionMatch = query.match(/\b(7\.\d{2}|latest)\b/i);
      const requestedVersion = versionMatch ? versionMatch[1].toLowerCase() : null;
      const requestedVersionId = requestedVersion ? requestedVersion.replace('.', '') : null;
      
      // Search with all query variants (union approach)
      for (const variant of queryVariants) {
        try {
          const rows = searchFTS(variant, {}, k);
          for (const r of rows) {
            if (!seen.has(r.id)) {
              seen.set(r.id, r);
            }
          }
        } catch (error) {
          console.warn(`FTS query failed for variant "${variant}":`, error);
          continue;
        }
        if (seen.size >= k) break; // enough candidates
      }
      
      let rows = Array.from(seen.values()).slice(0, k);
      
      // Smart ABAP version filtering - only show latest unless version specified
      if (!requestedVersion) {
        // For general ABAP queries without version, aggressively filter out older versions
        rows = rows.filter(r => {
          const id = r.id || '';
          
          // Keep all non-ABAP-docs sources
          if (!id.includes('/abap-docs-')) return true;
          
          // For ABAP docs, ONLY keep latest version for general queries
          return id.includes('/abap-docs-latest/');
        });
        
        console.log(`Filtered to latest ABAP version only: ${rows.length} results`);
      } else {
        // For version-specific queries, ONLY show the requested version and non-ABAP sources
        rows = rows.filter(r => {
          const id = r.id || '';
          
          // Keep all non-ABAP-docs sources (style guides, cheat sheets, etc.)
          if (!id.includes('/abap-docs-')) return true;
          
          // For ABAP docs, ONLY keep the specifically requested version
          return id.includes(`/abap-docs-${requestedVersionId}/`);
        });
        
        console.log(`Filtered to ABAP version ${requestedVersion} only: ${rows.length} results`);
      }
      
      // Convert to consistent format with source boosts
      const results = rows.map(r => {
        const sourceId = extractSourceId(r.libraryId || r.id);
        let boost = sourceBoosts[sourceId] || 0;
        
        // Additional boost for version-specific queries
        if (requestedVersionId && r.id.includes(`/abap-docs-${requestedVersionId}/`)) {
          boost += 1.0; // Extra boost for requested version
        }
        
        return {
          id: r.id,
          text: `${r.title || ""}\n\n${r.description || ""}\n\n${r.id}`,
          bm25: r.bm25Score,
          sourceId,
          path: r.id,
          finalScore: (-r.bm25Score) * (1 + boost) // Convert to descending with boost
        };
      });
      
      // Results are already filtered above, just sort them
      
      // Sort by final score (higher = better)
      return results.sort((a, b) => b.finalScore - a.finalScore);
    }
  • Tool schema and metadata definition for 'search' tool, including name, detailed description, inputSchema with 'query' parameter (type string, description, examples), used in ListToolsRequestSchema response.
                name: "search",
                description: `SEARCH SAP DOCS: search(query="search terms")
    
    FUNCTION NAME: search
    
    COVERS: ABAP (all versions), UI5, CAP, wdi5, OpenUI5 APIs, Cloud SDK
    AUTO-DETECTS: ABAP versions from query (e.g. "LOOP 7.57", defaults to 7.58)
    
    TYPICAL WORKFLOW:
    1. search(query="your search terms") 
    2. fetch(id="result_id_from_step_1")
    
    QUERY TIPS:
    • Be specific: "CAP action binary parameter" not just "CAP"
    • Include error codes: "415 error CAP action"
    • Use technical terms: "LargeBinary MediaType XMLHttpRequest"
    • For ABAP: Include version like "7.58" or "latest"`,
                inputSchema: {
                  type: "object",
                  properties: {
                    query: {
                      type: "string",
                      description: "Search terms using natural language. Be specific and include technical terms.",
                      examples: [
                        "CAP binary data LargeBinary MediaType",
                        "UI5 button properties",
                        "wdi5 testing locators", 
                        "ABAP SELECT statements 7.58",
                        "415 error CAP action parameter"
                      ]
                    }
                  },
                  required: ["query"]
                }
  • Registers the 'search' tool by setting up ListToolsRequestSchema and CallToolRequestSchema handlers on the MCP Server instance.
    private static setupToolHandlers(srv: Server): void {
  • src/server.ts:26-26 (registration)
    Invokes BaseServerHandler.configureServer(srv) which sets up tool handlers including the 'search' tool registration.
    BaseServerHandler.configureServer(srv);
Behavior3/5

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

With no annotations provided, the description carries the full burden. It discloses useful behavioral context: auto-detection of ABAP versions, coverage of specific technologies, and that results require a follow-up 'fetch' operation. However, it doesn't mention rate limits, authentication requirements, or what happens with invalid queries.

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

Conciseness3/5

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

The description is structured with clear sections (COVERS, AUTO-DETECTS, TYPICAL WORKFLOW, QUERY TIPS) but contains some redundancy (repeating 'search(query=') and could be more front-loaded. The query tips section is valuable but makes the description longer than necessary for a single-parameter tool.

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?

For a search tool with no annotations and no output schema, the description provides good coverage of what the tool does and how to use it effectively. However, it doesn't explain what the search returns (just IDs for fetch operations) or address potential limitations, leaving gaps in understanding the complete tool behavior.

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

Parameters4/5

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

The schema has 100% description coverage for the single 'query' parameter, so baseline is 3. The description adds significant value by providing query tips with specific examples, explaining auto-detection behavior for ABAP versions, and listing the covered technologies - all meaningful semantic context beyond the schema's basic description.

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 searches SAP documentation across multiple technologies (ABAP, UI5, CAP, etc.), which is a specific verb+resource combination. However, it doesn't explicitly differentiate from sibling tools like 'sap_community_search' or 'sap_help_search' - it only mentions the typical workflow with 'fetch'.

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

Usage Guidelines3/5

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

The description provides a typical workflow showing this tool should be used first, followed by 'fetch', and includes query tips for effective use. However, it doesn't explicitly state when to use this tool versus the other search-related siblings (sap_community_search, sap_help_search, sap_help_get), leaving the distinction unclear.

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

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