Skip to main content
Glama

MCP Svelte Docs Server

definition-tools.ts8.77 kB
import { McpServer } from 'tmcp'; import * as v from 'valibot'; import { DefinitionItem, get_all_identifiers, get_definition_by_identifier, load_definitions, suggest_similar_identifiers, } from '../db-definition-loader.js'; // Load all definitions let definitions: DefinitionItem[] = []; // Input validation schema const DefinitionSchema = v.object({ identifier: v.pipe( v.string(), v.minLength(1), v.description( 'Svelte 5 identifier to look up. Examples: "$state", "$derived", "$props", "$effect", "snippets", "onclick", "component-events". Use exact identifiers for best results.', ), ), format: v.pipe( v.optional(v.picklist(['syntax', 'quick', 'full']), 'full'), v.description( 'Response format: "syntax" returns just TypeScript signature (~50 words), "quick" returns definition + minimal example (~200 words), "full" returns complete definition with examples (~500-1000 words).', ), ), }); type FormatType = 'syntax' | 'quick' | 'full'; /** * Format definition content based on the requested format */ function format_definition_content( content: string, format: FormatType, ): string { switch (format) { case 'syntax': return extract_syntax_only(content); case 'quick': return extract_definition_and_example(content); case 'full': default: return content; } } /** * Extract just the syntax information from a definition */ function extract_syntax_only(content: string): string { const lines = content.split('\n'); const syntax_lines: string[] = []; // Include title const title_line = lines.find((line) => line.startsWith('# ')); if (title_line) { syntax_lines.push(title_line); syntax_lines.push(''); } // Extract key definition lines for (const line of lines) { if ( line.startsWith('**Definition:**') || line.startsWith('**Syntax:**') || line.startsWith('**Parameters:**') || line.startsWith('**Returns:**') || line.startsWith('**Variants:**') || line.startsWith('**Pattern:**') || line.startsWith('**Interface:**') || line.startsWith('**Examples:**') ) { syntax_lines.push(line); } // Include bullet points under these sections else if (line.startsWith('- ') && syntax_lines.length > 0) { syntax_lines.push(line); } // Include code blocks that look like syntax else if ( line.startsWith('```') || line.includes('$state') || line.includes('$derived') || line.includes('$props') || line.includes('$effect') ) { syntax_lines.push(line); } } return syntax_lines.join('\n').trim(); } /** * Extract definition and a minimal example */ function extract_definition_and_example(content: string): string { const lines = content.split('\n'); const quick_lines: string[] = []; let in_examples = false; let example_lines = 0; for (const line of lines) { // Always include title and definition sections if ( line.startsWith('# ') || line.startsWith('**Definition:**') || line.startsWith('**Syntax:**') || line.startsWith('**Parameters:**') || line.startsWith('**Returns:**') || line.startsWith('**Variants:**') || line.startsWith('**Pattern:**') || line.startsWith('**Interface:**') || line.startsWith('- ') ) { quick_lines.push(line); } // Start including examples but limit them else if (line.startsWith('## Examples')) { in_examples = true; quick_lines.push(line); } // Stop at Related section else if (line.startsWith('## Related')) { break; } // Include limited examples else if (in_examples && example_lines < 15) { quick_lines.push(line); if (line.trim()) { example_lines++; } } } return quick_lines.join('\n').trim(); } /** * Create error message with helpful suggestions */ function create_definition_error( identifier: string, definitions: DefinitionItem[], ): Error { const suggestions = suggest_similar_identifiers(identifier); const all_identifiers = get_all_identifiers(); let error_message = `Definition for '${identifier}' not found.`; if (suggestions.length > 0) { error_message += `\n\nDid you mean:\n${suggestions.map((s) => `• ${s}`).join('\n')}`; } // Add category-based suggestions const category_suggestions: string[] = []; if ( identifier.startsWith('$') || identifier.includes('state') || identifier.includes('derived') ) { category_suggestions.push( 'Runes: $state, $derived, $props, $effect', ); } if (identifier.includes('click') || identifier.includes('event')) { category_suggestions.push('Events: onclick, component-events'); } if (identifier.includes('snippet') || identifier.includes('slot')) { category_suggestions.push('Features: snippets'); } if (category_suggestions.length > 0) { error_message += `\n\nRelated categories:\n${category_suggestions.map((s) => `• ${s}`).join('\n')}`; } // Show available identifiers if not too many if (all_identifiers.length <= 20) { error_message += `\n\nAvailable identifiers:\n${all_identifiers.map((s) => `• ${s}`).join('\n')}`; } else { error_message += `\n\nUse format="syntax" for quicker responses, or try: $state, $derived, $props, $effect, snippets, onclick, component-events`; } return new Error(error_message); } /** * Handle definition lookup requests */ async function definition_handler(args: any) { try { // Validate input const { identifier, format = 'full' } = v.parse( DefinitionSchema, args, ); // Find the definition const definition = get_definition_by_identifier(identifier); if (!definition) { throw create_definition_error(identifier, definitions); } // Validate that definition content exists if ( !definition.content || definition.content.trim().length === 0 ) { throw new Error( `Definition for '${identifier}' exists but appears to be empty. Please try again later or contact support.`, ); } // Format the content based on requested format const formatted_content = format_definition_content( definition.content, format, ); // Add format info for context let response_content = formatted_content; if (format === 'syntax') { response_content += `\n\n*Use format="quick" or format="full" for more details.*`; } else if (format === 'quick') { response_content += `\n\n*Use format="full" for complete documentation.*`; } return { content: [ { type: 'text' as const, text: response_content, }, ], }; } catch (error) { // Re-throw with additional context for debugging const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred'; throw new Error(`Error in svelte_definition: ${errorMessage}`); } } /** * Register the definition tool with the MCP server * * This single tool replaces 13+ specialized tools with a unified interface * that provides authoritative, TypeScript-based Svelte 5 definitions. * * Usage Examples: * * Core runes: * - svelte_definition({ identifier: "$state" }) * - svelte_definition({ identifier: "$derived" }) * - svelte_definition({ identifier: "$props" }) * - svelte_definition({ identifier: "$effect" }) * * Features: * - svelte_definition({ identifier: "snippets" }) * - svelte_definition({ identifier: "onclick" }) * - svelte_definition({ identifier: "component-events" }) * * Format control: * - svelte_definition({ identifier: "$state", format: "syntax" }) // ~50 words * - svelte_definition({ identifier: "$state", format: "quick" }) // ~200 words * - svelte_definition({ identifier: "$state", format: "full" }) // ~500-1000 words * * Error handling: * - svelte_definition({ identifier: "$sate" }) // → "Did you mean $state?" * - svelte_definition({ identifier: "unknown" }) // → Lists available definitions */ export function register_definition_tools( server: McpServer<any>, ): void { // Load all definitions definitions = load_definitions(); if (definitions.length === 0) { console.warn( 'Warning: No definitions loaded. Definition tool will not work properly.', ); } else { console.log( `Loaded ${definitions.length} definitions:`, get_all_identifiers(), ); } // Register the single definition tool server.tool<typeof DefinitionSchema>( { name: 'svelte_definition', description: 'Get authoritative Svelte 5 definitions extracted from TypeScript declarations. Returns precise syntax, parameters, and variants for runes ($state, $derived, $props, $effect), features (snippets, onclick), and patterns (component-events). Use "syntax" format for quick reference (~50 words), "quick" for definition + example (~200 words), or "full" for complete documentation (~500-1000 words). Replaces 13+ specialized tools with a single, consistent interface.', schema: DefinitionSchema, }, definition_handler, ); }

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/spences10/mcp-svelte-docs'

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