sap_note_get
Retrieve complete SAP Note details including full HTML content, step-by-step solutions, and metadata by providing a specific Note ID to access detailed problem descriptions and implementation guides.
Instructions
Fetch complete content and metadata for a specific SAP Note by ID. Returns full HTML content, solution details, and all metadata.
SAP Notes contain: • Detailed problem description • Step-by-step solution instructions • Root cause analysis • Affected releases/versions • Related notes and references • Corrections and patches • Implementation guides
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ USE WHEN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ • You have a Note ID from sap_note_search results • User asks for details about a specific note (e.g., "get details for note 2744792") • You need full solution steps, not just the summary • User wants to see the complete note content • You're following the search → get workflow pattern
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DO NOT USE WHEN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ • You don't have a specific Note ID (use sap_note_search first) • User hasn't asked for detailed note content (summaries may suffice) • Note ID is invalid (contains spaces or special characters) • You're just browsing/searching (use sap_note_search instead)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PARAMETER REQUIREMENTS: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Note ID Format: • Typically alphanumeric characters only • No spaces, no prefixes • Valid examples: "2744792", "438342", "3089413", "123ABC" • Invalid examples: "Note 2744792", "SAP Note 2744792", ""
If user input includes text, extract the ID only: "Note 2744792" → "2744792" "SAP Note 438342" → "438342"
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ WORKFLOW PATTERN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Typical usage flow:
Search for relevant notes: sap_note_search(q="OData 415 error")
Review search results, identify relevant note IDs: Results: [{id: "2744792", ...}, {id: "438342", ...}]
Fetch full content for top 2-3 relevant notes: sap_note_get(id="2744792") sap_note_get(id="438342")
Synthesize solution from full note content
Do NOT fetch all notes - only get details for the most relevant 2-3.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ERROR HANDLING: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Common errors and solutions:
• "Note ID must contain only alphanumeric characters" → Validate ID format before calling → Extract alphanumeric ID only from user input
• "Note not found" → Note ID doesn't exist or is invalid → Try searching again with different terms
• "Access denied" → Some notes require special S-user permissions → Inform user to access directly on SAP Support Portal
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BEST PRACTICES: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Always validate Note ID format (alphanumeric) before calling
Only fetch notes that are clearly relevant from search results
Limit to 2-3 note fetches per user query
Parse and summarize the HTML content field for users
Include the note URL in your response
Extract key sections: Symptom, Solution, Affected Releases
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| id | Yes | SAP Note ID: Typically 6-8 digits, but may include letters or vary in length. Valid examples: • "2744792" (7 digits) • "438342" (6 digits) • "12345678" (8 digits) • "123ABC" (mixed alphanumeric) Invalid examples: • "Note 2744792" (contains text prefix - extract ID only) • "" (empty) If user input includes text (e.g., "Note 2744792" or "SAP Note 2744792"), extract only the ID portion before calling this tool. | |
| lang | No | Language code for note content. • EN (English) - Default, recommended for most cases • DE (German) - Use if note exists in German and user requests it Note: Not all notes are available in both languages. | EN |
Implementation Reference
- src/mcp-server.ts:189-256 (handler)MCP handler function for sap_note_get tool: authenticates user, fetches note via SapNotesApiClient, formats markdown/text output with structured dataasync ({ id, lang = 'EN' }) => { logger.info(`📄 [sap_note_get] Getting note details for ID: ${id}`); try { // Ensure authentication logger.warn('🔐 Starting authentication for note retrieval...'); const token = await this.authenticator.ensureAuthenticated(); logger.warn('✅ Authentication successful for note retrieval'); // Get note details const noteDetail = await this.sapNotesClient.getNote(id, token); if (!noteDetail) { return { content: [{ type: 'text', text: `SAP Note ${id} not found or not accessible.` }], isError: true }; } // Structure the output const output = { id: noteDetail.id, title: noteDetail.title, summary: noteDetail.summary, component: noteDetail.component || null, priority: noteDetail.priority || null, category: noteDetail.category || null, releaseDate: noteDetail.releaseDate, language: noteDetail.language, url: noteDetail.url, content: noteDetail.content }; // Format display text let resultText = `**SAP Note ${output.id} - Detailed Information**\n\n`; resultText += `**Title:** ${output.title}\n`; resultText += `**Summary:** ${output.summary}\n`; resultText += `**Component:** ${output.component || 'Not specified'}\n`; resultText += `**Priority:** ${output.priority || 'Not specified'}\n`; resultText += `**Category:** ${output.category || 'Not specified'}\n`; resultText += `**Release Date:** ${output.releaseDate}\n`; resultText += `**Language:** ${output.language}\n`; resultText += `**URL:** ${output.url}\n\n`; resultText += `**Content:**\n${output.content}\n\n`; logger.info(`✅ [sap_note_get] Successfully retrieved note ${id}`); return { content: [{ type: 'text', text: resultText }], structuredContent: output }; } catch (error) { logger.error(`❌ Note retrieval failed for ${id}:`, error); const errorMessage = error instanceof Error ? error.message : 'Unknown retrieval error'; return { content: [{ type: 'text', text: `Failed to retrieve SAP Note ${id}: ${errorMessage}` }], isError: true }; } }
- src/mcp-server.ts:181-257 (registration)Registration of sap_note_get tool on McpServer with schema, description, and handler functionthis.mcpServer.registerTool( 'sap_note_get', { title: 'Get SAP Note Details', description: SAP_NOTE_GET_DESCRIPTION, inputSchema: NoteGetInputSchema, outputSchema: NoteGetOutputSchema }, async ({ id, lang = 'EN' }) => { logger.info(`📄 [sap_note_get] Getting note details for ID: ${id}`); try { // Ensure authentication logger.warn('🔐 Starting authentication for note retrieval...'); const token = await this.authenticator.ensureAuthenticated(); logger.warn('✅ Authentication successful for note retrieval'); // Get note details const noteDetail = await this.sapNotesClient.getNote(id, token); if (!noteDetail) { return { content: [{ type: 'text', text: `SAP Note ${id} not found or not accessible.` }], isError: true }; } // Structure the output const output = { id: noteDetail.id, title: noteDetail.title, summary: noteDetail.summary, component: noteDetail.component || null, priority: noteDetail.priority || null, category: noteDetail.category || null, releaseDate: noteDetail.releaseDate, language: noteDetail.language, url: noteDetail.url, content: noteDetail.content }; // Format display text let resultText = `**SAP Note ${output.id} - Detailed Information**\n\n`; resultText += `**Title:** ${output.title}\n`; resultText += `**Summary:** ${output.summary}\n`; resultText += `**Component:** ${output.component || 'Not specified'}\n`; resultText += `**Priority:** ${output.priority || 'Not specified'}\n`; resultText += `**Category:** ${output.category || 'Not specified'}\n`; resultText += `**Release Date:** ${output.releaseDate}\n`; resultText += `**Language:** ${output.language}\n`; resultText += `**URL:** ${output.url}\n\n`; resultText += `**Content:**\n${output.content}\n\n`; logger.info(`✅ [sap_note_get] Successfully retrieved note ${id}`); return { content: [{ type: 'text', text: resultText }], structuredContent: output }; } catch (error) { logger.error(`❌ Note retrieval failed for ${id}:`, error); const errorMessage = error instanceof Error ? error.message : 'Unknown retrieval error'; return { content: [{ type: 'text', text: `Failed to retrieve SAP Note ${id}: ${errorMessage}` }], isError: true }; } } );
- src/schemas/sap-notes.ts:161-291 (schema)Zod schemas for sap_note_get input validation (NoteGetInputSchema) and output structure (NoteGetOutputSchema), including detailed descriptions for LLM guidanceexport const NoteGetInputSchema = { id: z .string() .min(1, "Note ID cannot be empty") .regex(/^[0-9A-Za-z]+$/, "Note ID must contain only alphanumeric characters") .describe( `SAP Note ID: Typically 6-8 digits, but may include letters or vary in length. Valid examples: • "2744792" (7 digits) • "438342" (6 digits) • "12345678" (8 digits) • "123ABC" (mixed alphanumeric) Invalid examples: • "Note 2744792" (contains text prefix - extract ID only) • "" (empty) If user input includes text (e.g., "Note 2744792" or "SAP Note 2744792"), extract only the ID portion before calling this tool.` ), lang: z .enum(['EN', 'DE']) .default('EN') .describe( `Language code for note content. • EN (English) - Default, recommended for most cases • DE (German) - Use if note exists in German and user requests it Note: Not all notes are available in both languages.` ), }; /** * Output schema shape for sap_note_get (for MCP SDK) */ export const NoteGetOutputSchema = { id: z .string() .describe('SAP Note ID (6-8 digits) that was fetched'), title: z .string() .describe('Full note title describing the issue, error, or topic'), summary: z .string() .describe( 'Executive summary of the note content (high-level overview of the problem and solution)' ), component: z .string() .nullable() .describe( `SAP component code this note relates to (e.g., 'CA-UI5-CTR' for UI5 controls, 'MM-IM' for Inventory Management). Format: [Area]-[Module]-[Submodule] null if not specified.` ), priority: z .string() .nullable() .describe( `Note priority level indicating urgency: • "Very High" - Critical issues, security vulnerabilities • "High" - Important fixes, significant bugs • "Medium" - Standard corrections and improvements • "Low" - Minor issues, cosmetic fixes • "Recommendation" - Best practices, optimization tips null if priority is not assigned.` ), category: z .string() .nullable() .describe( `Note category/type indicating the nature of the note: • "Correction" - Bug fixes, error corrections • "Consulting" - Implementation guidance, best practices • "Performance" - Performance optimization tips • "Security" - Security patches, vulnerability fixes • "Master Data" - Data migration, master data issues • etc. null if category is not specified.` ), releaseDate: z .string() .describe( 'Date when note was published or last updated (ISO 8601 format: YYYY-MM-DD or full timestamp)' ), language: z .string() .describe('Language of the note content (EN or DE)'), url: z .string() .url() .describe( 'Direct URL to view the note on SAP Support Portal. Share this link with users so they can access the official source.' ), content: z .string() .describe( `Full HTML content of the SAP Note including all sections: Typical sections in note content: • Symptom - Description of the problem/error • Reason and Prerequisites - Root cause analysis • Solution - Detailed step-by-step instructions to resolve the issue • Affected Releases - Which SAP versions are impacted • Related Notes - Links to other relevant notes • Additional Information - Extra context, warnings, or tips Important: This is raw HTML content. You should: 1. Parse the HTML to extract key sections 2. Summarize the Symptom and Solution for the user 3. Keep technical details but make them readable 4. Preserve any code snippets, configuration steps, or warnings 5. If content is very long (>5000 chars), focus on Symptom and Solution sections Do not return raw HTML to the user - extract and format the relevant information.` ), };
- src/sap-notes-api.ts:193-254 (helper)Core helper method SapNotesApiClient.getNote() implementing multiple fallback strategies (Playwright browser automation, raw HTTP API, OData endpoints) to fetch complete SAP note content and metadataasync getNote(noteId: string, token: string): Promise<SapNoteDetail | null> { logger.info(`📄 Fetching SAP Note: ${noteId}`); try { // Try Playwright-based raw notes API first (most likely to get actual content) try { logger.info(`🎭 Trying Playwright approach for note ${noteId}`); const note = await this.getNoteWithPlaywright(noteId, token); if (note) { logger.info(`✅ Retrieved SAP Note ${noteId} via Playwright`); return note; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.warn(`⚠️ Playwright approach failed: ${errorMessage}, trying HTTP fallbacks`); } // Try the raw notes API with HTTP (might get redirects) try { const rawResponse = await this.makeRawRequest(`/Detail?q=${noteId}&t=E&isVTEnabled=false`, token); if (rawResponse.ok) { const note = await this.parseRawNoteDetail(rawResponse, noteId); if (note) { logger.info(`✅ Retrieved SAP Note ${noteId} via raw HTTP API`); return note; } } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.debug(`Raw notes HTTP API failed: ${errorMessage}, trying OData fallbacks`); } // Fallback to OData endpoints const fallbackEndpoints = [ `/services/odata/svt/snogwscorr/Notes('${noteId}')?$format=json`, `/services/odata/svt/snogwscorr/KnowledgeBaseEntries?$filter=SapNote eq '${noteId}'&$format=json`, `/support/notes/${noteId}` // HTML fallback ]; for (const endpoint of fallbackEndpoints) { try { const response = await this.makeRequest(endpoint, token); const note = await this.parseNoteResponse(response, noteId); if (note) { logger.info(`✅ Retrieved SAP Note ${noteId} via fallback`); return note; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); logger.warn(`⚠️ Endpoint ${endpoint} failed: ${errorMessage}`); } } logger.warn(`❌ SAP Note ${noteId} not found`); return null; } catch (error) { logger.error(`❌ Failed to get SAP Note ${noteId}:`, error); const errorMessage = error instanceof Error ? error.message : String(error); throw new Error(`Failed to get SAP Note ${noteId}: ${errorMessage}`); } }
- src/schemas/sap-notes.ts:379-464 (schema)Detailed tool description SAP_NOTE_GET_DESCRIPTION used in registration to guide LLM on when/how to use sap_note_get tool, including workflow with sap_note_search and parameter validation tipsexport const SAP_NOTE_GET_DESCRIPTION = `Fetch complete content and metadata for a specific SAP Note by ID. Returns full HTML content, solution details, and all metadata. SAP Notes contain: • Detailed problem description • Step-by-step solution instructions • Root cause analysis • Affected releases/versions • Related notes and references • Corrections and patches • Implementation guides ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ USE WHEN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ • You have a Note ID from sap_note_search results • User asks for details about a specific note (e.g., "get details for note 2744792") • You need full solution steps, not just the summary • User wants to see the complete note content • You're following the search → get workflow pattern ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ DO NOT USE WHEN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ • You don't have a specific Note ID (use sap_note_search first) • User hasn't asked for detailed note content (summaries may suffice) • Note ID is invalid (contains spaces or special characters) • You're just browsing/searching (use sap_note_search instead) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ PARAMETER REQUIREMENTS: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Note ID Format: • Typically alphanumeric characters only • No spaces, no prefixes • Valid examples: "2744792", "438342", "3089413", "123ABC" • Invalid examples: "Note 2744792", "SAP Note 2744792", "" If user input includes text, extract the ID only: "Note 2744792" → "2744792" "SAP Note 438342" → "438342" ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ WORKFLOW PATTERN: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Typical usage flow: 1. Search for relevant notes: sap_note_search(q="OData 415 error") 2. Review search results, identify relevant note IDs: Results: [{id: "2744792", ...}, {id: "438342", ...}] 3. Fetch full content for top 2-3 relevant notes: sap_note_get(id="2744792") sap_note_get(id="438342") 4. Synthesize solution from full note content Do NOT fetch all notes - only get details for the most relevant 2-3. ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ERROR HANDLING: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Common errors and solutions: • "Note ID must contain only alphanumeric characters" → Validate ID format before calling → Extract alphanumeric ID only from user input • "Note not found" → Note ID doesn't exist or is invalid → Try searching again with different terms • "Access denied" → Some notes require special S-user permissions → Inform user to access directly on SAP Support Portal ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BEST PRACTICES: ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1. Always validate Note ID format (alphanumeric) before calling 2. Only fetch notes that are clearly relevant from search results 3. Limit to 2-3 note fetches per user query 4. Parse and summarize the HTML content field for users 5. Include the note URL in your response 6. Extract key sections: Symptom, Solution, Affected Releases`;