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:
search(query="your search terms")
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
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Search terms using natural language. Be specific and include technical terms. |
Implementation Reference
- src/lib/BaseServerHandler.ts:400-493 (handler)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 ); } } }
- src/lib/search.ts:29-117 (handler)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); }
- src/lib/BaseServerHandler.ts:324-357 (schema)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"] }
- src/lib/BaseServerHandler.ts:220-220 (registration)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);