get-sail-guidance
Retrieve SAIL coding guidance and best practices from Appian's Aurora design system documentation. Specify technology like HTML or CSS for broader support.
Instructions
Get SAIL coding guidance and best practices
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| technology | No | Technology or framework (e.g., 'sail', 'html', 'css') |
Implementation Reference
- src/index.ts:474-549 (registration)Registration of the get-sail-guidance tool with schema and handler on the MCP server
// Tool 7: Get SAIL guidance server.tool( "get-sail-guidance", "Get SAIL coding guidance and best practices", { technology: z.string().describe("Technology or framework (e.g., 'sail', 'html', 'css')").optional(), }, async ({ technology }) => { // If no technology specified, list available guides if (!technology) { const codingGuides = designSystemData['coding-guides']; const guides = Object.entries(codingGuides).map( ([key, guide]) => `${key}: ${guide.title} - ${guide.body}` ); return { content: [ { type: "text", text: `Available coding guides:\n\n${guides.join("\n\n")}\n\nUse get-component-details with category 'coding-guides' to access specific guides.`, }, ], }; } // Look for technology-specific guide const normalizedTech = technology.toLowerCase(); const codingGuides = designSystemData['coding-guides']; // Check if there's a direct match or partial match let matchedGuide = null; let matchedKey = null; for (const [key, guide] of Object.entries(codingGuides)) { if (key.includes(normalizedTech) || guide.title.toLowerCase().includes(normalizedTech)) { matchedGuide = guide; matchedKey = key; break; } } if (!matchedGuide) { return { content: [ { type: "text", text: `No coding guide found for "${technology}". Available guides: ${Object.keys(codingGuides).join(", ")}`, }, ], }; } // Fetch the full guide content const repoContent = await fetchRepoContent(matchedGuide.filePath); if (!repoContent) { return { content: [ { type: "text", text: `Failed to fetch ${matchedGuide.title} guide. Basic info: ${matchedGuide.body}`, }, ], }; } return { content: [ { type: "text", text: `# ${matchedGuide.title}\n\n${repoContent.content}`, }, ], }; }, ); - src/index.ts:481-548 (handler)Handler function for get-sail-guidance: lists all available coding guides when no technology is specified, looks up matching guide by technology name, fetches full content via fetchRepoContent, and returns the guide text
async ({ technology }) => { // If no technology specified, list available guides if (!technology) { const codingGuides = designSystemData['coding-guides']; const guides = Object.entries(codingGuides).map( ([key, guide]) => `${key}: ${guide.title} - ${guide.body}` ); return { content: [ { type: "text", text: `Available coding guides:\n\n${guides.join("\n\n")}\n\nUse get-component-details with category 'coding-guides' to access specific guides.`, }, ], }; } // Look for technology-specific guide const normalizedTech = technology.toLowerCase(); const codingGuides = designSystemData['coding-guides']; // Check if there's a direct match or partial match let matchedGuide = null; let matchedKey = null; for (const [key, guide] of Object.entries(codingGuides)) { if (key.includes(normalizedTech) || guide.title.toLowerCase().includes(normalizedTech)) { matchedGuide = guide; matchedKey = key; break; } } if (!matchedGuide) { return { content: [ { type: "text", text: `No coding guide found for "${technology}". Available guides: ${Object.keys(codingGuides).join(", ")}`, }, ], }; } // Fetch the full guide content const repoContent = await fetchRepoContent(matchedGuide.filePath); if (!repoContent) { return { content: [ { type: "text", text: `Failed to fetch ${matchedGuide.title} guide. Basic info: ${matchedGuide.body}`, }, ], }; } return { content: [ { type: "text", text: `# ${matchedGuide.title}\n\n${repoContent.content}`, }, ], }; }, - src/index.ts:58-90 (helper)Helper function that fetches markdown content from GitHub repository, decodes base64, and parses frontmatter into structured sections
async function fetchRepoContent(filePath: string): Promise<ParsedMarkdown | null> { try { const url = `https://api.github.com/repos/${GITHUB_CONFIG.owner}/${GITHUB_CONFIG.repo}/contents/${filePath}`; console.error(`[DEBUG] Fetching: ${filePath}`); const response = await fetch(url, { headers: { 'Authorization': `token ${GITHUB_CONFIG.token}`, 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'design-system-mcp-server' } }); if (!response.ok) { console.error(`[ERROR] GitHub API error for ${filePath}: ${response.status} ${response.statusText}`); throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.json(); // GitHub API returns base64 encoded content const content = atob(data.content); console.error(`[DEBUG] Content fetched successfully: ${content.length} characters`); const parsed = parseFrontmatter(content); console.error(`[DEBUG] Content parsed: Design=${parsed.designSection.length}chars, Development=${parsed.developmentSection.length}chars`); return parsed; } catch (error) { console.error(`[ERROR] Failed to fetch repo content for ${filePath}:`, error); return null; } } - src/index.ts:478-479 (schema)Input schema for get-sail-guidance: optional technology string parameter
{ technology: z.string().describe("Technology or framework (e.g., 'sail', 'html', 'css')").optional(), - src/design-system-data.ts:312-318 (registration)Definition of the 'sail-coding-guide' data item in the designSystemData registry that maps to the guide content fetched by the tool
'coding-guides': { 'sail-coding-guide': { title: 'SAIL Coding Guide', body: 'Comprehensive guide for generating valid Appian SAIL interfaces using documented components and best practices.', filePath: 'docs/SAIL_CODING_GUIDE.md' } }