@lglab/compose-ui-mcp 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +11 -4
- package/dist/index.js.map +1 -1
- package/dist/llms-full.txt +18 -0
- package/dist/llms.txt +18 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -101,12 +101,19 @@ A React component library built on Base UI primitives with Tailwind CSS v4 styli
|
|
|
101
101
|
- Tailwind CSS for styling
|
|
102
102
|
- TypeScript-first
|
|
103
103
|
|
|
104
|
-
##
|
|
104
|
+
## Available Tools
|
|
105
105
|
|
|
106
|
-
|
|
106
|
+
Use these tools to access component documentation:
|
|
107
107
|
|
|
108
|
-
-
|
|
109
|
-
-
|
|
108
|
+
- **find_components**: Fuzzy search all components by name
|
|
109
|
+
- **get_component**: Get full documentation for a specific component (supports section filtering)
|
|
110
|
+
|
|
111
|
+
## Styling Guidelines
|
|
112
|
+
|
|
113
|
+
- Components are **pre-styled and ready to use** - do not add custom CSS, Tailwind classes, or inline styles
|
|
114
|
+
- Only add custom styling if the user explicitly requests it
|
|
115
|
+
- Use built-in variant props (e.g., \`variant="outline"\`, \`size="sm"\`) for different appearances
|
|
116
|
+
- Use specific import paths: \`import { Button } from '@lglab/compose-ui/button'\`
|
|
110
117
|
`;
|
|
111
118
|
function registerOverviewResource(server) {
|
|
112
119
|
server.registerResource("overview", "compose-ui://overview", {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["inputSchema"],"sources":["../src/lib/component-data.ts","../src/resources/components.ts","../src/resources/overview.ts","../src/resources/index.ts","../src/lib/fuzzy-match.ts","../src/tools/find-components.ts","../src/lib/markdown-parser.ts","../src/tools/get-component.ts","../src/tools/index.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["import { readFile, readdir } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// After build, assets are copied to dist/ alongside index.js\n// In dev, we're in src/lib/ and assets are at ../../assets/llms\n// At runtime (from dist/index.js), llms is at ./llms\nconst LLMS_DIR = resolve(__dirname, 'llms')\n\nexport interface ComponentInfo {\n name: string\n slug: string\n description: string\n documentationUri: string\n}\n\nexport function slugToName(slug: string): string {\n return slug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n}\n\nfunction parseMarkdownFile(content: string, slug: string): ComponentInfo {\n const lines = content.split('\\n')\n\n // Extract title from first # heading\n let name = slugToName(slug)\n for (const line of lines) {\n if (line.startsWith('# ')) {\n name = line.slice(2).trim()\n break\n }\n }\n\n // Extract description (first non-empty line after the heading)\n let description = ''\n let foundHeading = false\n for (const line of lines) {\n if (line.startsWith('# ')) {\n foundHeading = true\n continue\n }\n if (foundHeading && line.trim() !== '') {\n description = line.trim()\n break\n }\n }\n\n return {\n name,\n slug,\n description,\n documentationUri: `compose-ui://components/${slug}`,\n }\n}\n\nexport async function getComponentContent(slug: string): Promise<string | null> {\n try {\n const filePath = resolve(LLMS_DIR, `${slug}.md`)\n return await readFile(filePath, 'utf-8')\n } catch {\n return null\n }\n}\n\nexport async function getComponentsList(): Promise<ComponentInfo[]> {\n try {\n const files = await readdir(LLMS_DIR)\n const mdFiles = files.filter((f) => f.endsWith('.md')).sort()\n\n const components: ComponentInfo[] = []\n\n for (const file of mdFiles) {\n const slug = file.replace('.md', '')\n const content = await readFile(resolve(LLMS_DIR, file), 'utf-8')\n components.push(parseMarkdownFile(content, slug))\n }\n\n return components\n } catch {\n return []\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { getComponentContent, getComponentsList } from '../lib/component-data.js'\n\nexport function registerComponentsResource(server: McpServer): void {\n server.registerResource(\n 'components',\n 'compose-ui://components',\n {\n title: 'Compose UI Components',\n description: 'List of all Compose UI components with metadata',\n mimeType: 'application/json',\n },\n async () => ({\n contents: [\n {\n uri: 'compose-ui://components',\n mimeType: 'application/json',\n text: JSON.stringify(await getComponentsList(), null, 2),\n },\n ],\n }),\n )\n}\n\nexport function registerComponentDocResource(server: McpServer): void {\n server.registerResource(\n 'component-doc',\n new ResourceTemplate('compose-ui://components/{slug}', { list: undefined }),\n {\n title: 'Component Documentation',\n description: 'Full markdown documentation for a Compose UI component',\n mimeType: 'text/markdown',\n },\n async (uri, variables) => {\n const slug = variables.slug as string\n const content = await getComponentContent(slug)\n if (!content) {\n throw new Error(`Component not found: ${slug}`)\n }\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'text/markdown',\n text: content,\n },\n ],\n }\n },\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nconst text = `# Compose UI\n\nA React component library built on Base UI primitives with Tailwind CSS v4 styling.\n\n## Key Principles\n- Composition over configuration\n- Base UI handles accessibility and behavior\n- Tailwind CSS for styling\n- TypeScript-first\n\n## Using This MCP Server\n\nTo work with Compose UI components, use the available tools:\n\n- \\`compose-ui://components\\`: List of available components\n- \\`compose-ui://components/{slug}\\`: Documentation for a specific component\n`\n\nexport function registerOverviewResource(server: McpServer): void {\n server.registerResource(\n 'overview',\n 'compose-ui://overview',\n {\n title: 'Compose UI Overview',\n description: 'Compose UI overview documentation',\n mimeType: 'text/plain',\n },\n async () => ({\n contents: [\n {\n uri: 'compose-ui://overview',\n mimeType: 'text/markdown',\n text,\n },\n ],\n }),\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerComponentDocResource, registerComponentsResource } from './components.js'\nimport { registerOverviewResource } from './overview.js'\n\nexport function registerResources(server: McpServer): void {\n registerOverviewResource(server)\n registerComponentsResource(server)\n registerComponentDocResource(server)\n}\n","export interface FuzzyMatchResult<T> {\n item: T\n score: number\n}\n\n/**\n * Calculate a fuzzy match score between a query and a target string.\n * Returns a score from 0 to 1, where 1 is a perfect match.\n */\nexport function fuzzyScore(query: string, target: string): number {\n const q = query.toLowerCase()\n const t = target.toLowerCase()\n\n // Exact match\n if (q === t) return 1.0\n\n // Target starts with query\n if (t.startsWith(q)) return 0.9\n\n // Target contains query as substring\n if (t.includes(q)) return 0.7\n\n // Check if all query characters appear in order\n let queryIndex = 0\n let matchCount = 0\n\n for (const char of t) {\n if (queryIndex < q.length && char === q[queryIndex]) {\n matchCount++\n queryIndex++\n }\n }\n\n // All query characters found in order\n if (queryIndex === q.length) {\n // Score based on how much of the query matched vs target length\n return 0.3 + (matchCount / t.length) * 0.3\n }\n\n // Partial character match - calculate Levenshtein-like similarity\n const commonChars = new Set([...q].filter((c) => t.includes(c)))\n const similarity = commonChars.size / Math.max(q.length, t.length)\n\n return similarity * 0.3\n}\n\n/**\n * Search items using fuzzy matching.\n * Returns items sorted by match score (highest first).\n */\nexport function fuzzySearch<T>(\n query: string,\n items: T[],\n getSearchableText: (item: T) => string,\n minScore = 0.1,\n): FuzzyMatchResult<T>[] {\n const results: FuzzyMatchResult<T>[] = []\n\n for (const item of items) {\n const text = getSearchableText(item)\n const score = fuzzyScore(query, text)\n\n if (score >= minScore) {\n results.push({ item, score })\n }\n }\n\n // Sort by score descending\n results.sort((a, b) => b.score - a.score)\n\n return results\n}\n\n/**\n * Find the best fuzzy match for a query.\n * Returns the best match if score is above minScore, otherwise null.\n */\nexport function findBestMatch<T>(\n query: string,\n items: T[],\n getSearchableText: (item: T) => string,\n minScore = 0.3,\n): FuzzyMatchResult<T> | null {\n const results = fuzzySearch(query, items, getSearchableText, minScore)\n return results.length > 0 ? results[0] : null\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\n\nimport { getComponentsList } from '../lib/component-data.js'\nimport { fuzzySearch } from '../lib/fuzzy-match.js'\n\nconst inputSchema = {\n query: z\n .string()\n .optional()\n .describe('Fuzzy search query. Omit to list all components.'),\n limit: z\n .number()\n .min(1)\n .max(100)\n .default(50)\n .describe('Maximum number of results to return (default: 50)'),\n}\n\ninterface FindComponentsResult {\n count: number\n components: Array<{\n slug: string\n name: string\n description: string\n }>\n}\n\nexport function registerFindComponentsTool(server: McpServer): void {\n server.registerTool(\n 'find_components',\n {\n description:\n 'Find Compose UI components. Call without query to list all, or with query for fuzzy search.',\n inputSchema,\n },\n async ({ query, limit }) => {\n const allComponents = await getComponentsList()\n\n let components: Array<{ slug: string; name: string; description: string }>\n\n if (query) {\n // Fuzzy search on both name and slug\n const results = fuzzySearch(query, allComponents, (c) => `${c.name} ${c.slug}`)\n\n components = results.slice(0, limit ?? 50).map((r) => ({\n slug: r.item.slug,\n name: r.item.name,\n description: r.item.description,\n }))\n } else {\n // Return all components up to limit\n components = allComponents.slice(0, limit ?? 50).map((c) => ({\n slug: c.slug,\n name: c.name,\n description: c.description,\n }))\n }\n\n const result: FindComponentsResult = {\n count: components.length,\n components,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n },\n )\n}\n","export type SectionType =\n | 'overview'\n | 'installation'\n | 'import'\n | 'examples'\n | 'resources'\n\nexport interface ParsedSection {\n type: SectionType\n title: string\n content: string\n}\n\nconst SECTION_MAPPINGS: Record<string, SectionType> = {\n installation: 'installation',\n import: 'import',\n examples: 'examples',\n resources: 'resources',\n}\n\ninterface RawSection {\n heading: string\n content: string\n}\n\n/**\n * Parse markdown content into sections based on ## headings.\n */\nexport function parseMarkdownSections(markdown: string): ParsedSection[] {\n const lines = markdown.split('\\n')\n const sections: ParsedSection[] = []\n\n // Find title and description (overview section)\n let title = ''\n const overviewLines: string[] = []\n let currentSection: RawSection | null = null\n const rawSections: RawSection[] = []\n\n for (const line of lines) {\n // Main title\n if (line.startsWith('# ') && !title) {\n title = line.slice(2).trim()\n continue\n }\n\n // Section heading\n if (line.startsWith('## ')) {\n // Save previous section\n if (currentSection) {\n rawSections.push(currentSection)\n } else if (overviewLines.length > 0) {\n // Save overview content collected before first ## heading\n sections.push({\n type: 'overview',\n title: title || 'Overview',\n content: `# ${title}\\n\\n${overviewLines.join('\\n').trim()}`,\n })\n }\n\n currentSection = {\n heading: line.slice(3).trim(),\n content: '',\n }\n continue\n }\n\n // Content lines\n if (currentSection) {\n currentSection.content += line + '\\n'\n } else if (title) {\n // Content before first ## heading is part of overview\n overviewLines.push(line)\n }\n }\n\n // Save last section\n if (currentSection) {\n rawSections.push(currentSection)\n } else if (overviewLines.length > 0 && sections.length === 0) {\n // No sections found, treat everything as overview\n sections.push({\n type: 'overview',\n title: title || 'Overview',\n content: `# ${title}\\n\\n${overviewLines.join('\\n').trim()}`,\n })\n }\n\n // Convert raw sections to typed sections\n for (const raw of rawSections) {\n const headingLower = raw.heading.toLowerCase()\n const sectionType = SECTION_MAPPINGS[headingLower] || 'overview'\n\n sections.push({\n type: sectionType,\n title: raw.heading,\n content: `## ${raw.heading}\\n${raw.content.trim()}`,\n })\n }\n\n return sections\n}\n\n/**\n * Extract specific sections from markdown content.\n * If no sections are specified, returns the full content.\n */\nexport function extractSections(markdown: string, sectionTypes?: SectionType[]): string {\n if (!sectionTypes || sectionTypes.length === 0) {\n return markdown\n }\n\n const parsed = parseMarkdownSections(markdown)\n const filtered = parsed.filter((s) => sectionTypes.includes(s.type))\n\n if (filtered.length === 0) {\n return ''\n }\n\n // If overview is requested, include the title\n const includesOverview = sectionTypes.includes('overview')\n const overviewSection = filtered.find((s) => s.type === 'overview')\n\n if (includesOverview && overviewSection) {\n const otherSections = filtered.filter((s) => s.type !== 'overview')\n return [overviewSection.content, ...otherSections.map((s) => s.content)].join('\\n\\n')\n }\n\n return filtered.map((s) => s.content).join('\\n\\n')\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\n\nimport {\n getComponentContent,\n getComponentsList,\n slugToName,\n} from '../lib/component-data.js'\nimport { fuzzySearch } from '../lib/fuzzy-match.js'\nimport { type SectionType, extractSections } from '../lib/markdown-parser.js'\n\nconst sectionTypes = [\n 'overview',\n 'installation',\n 'import',\n 'examples',\n 'resources',\n] as const\n\nconst inputSchema = {\n slug: z.string().describe('Component slug (e.g., \"button\", \"alert-dialog\")'),\n sections: z\n .array(z.enum(sectionTypes))\n .optional()\n .describe(\n 'Filter sections: \"overview\", \"installation\", \"import\", \"examples\", \"resources\". Default: all.',\n ),\n}\n\ninterface GetComponentSuccessResult {\n slug: string\n name: string\n found: true\n content: string\n}\n\ninterface GetComponentNotFoundResult {\n slug: string\n found: false\n suggestions: Array<{ slug: string; name: string; score: number }>\n message: string\n}\n\nexport function registerGetComponentTool(server: McpServer): void {\n server.registerTool(\n 'get_component',\n {\n description:\n 'Get documentation for a Compose UI component. Supports fuzzy matching if exact slug not found.',\n inputSchema,\n },\n async ({ slug, sections }) => {\n // Try exact match first\n const content = await getComponentContent(slug)\n\n if (content) {\n // Extract requested sections or return full content\n const filteredContent = extractSections(\n content,\n sections as SectionType[] | undefined,\n )\n\n const result: GetComponentSuccessResult = {\n slug,\n name: slugToName(slug),\n found: true,\n content: filteredContent || content,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n }\n\n // No exact match - try fuzzy matching\n const allComponents = await getComponentsList()\n const fuzzyResults = fuzzySearch(slug, allComponents, (c) => c.slug, 0.2)\n\n const suggestions = fuzzyResults.slice(0, 5).map((r) => ({\n slug: r.item.slug,\n name: r.item.name,\n score: Math.round(r.score * 100) / 100,\n }))\n\n const suggestionText =\n suggestions.length > 0\n ? `Did you mean '${suggestions[0].slug}'?`\n : 'No similar components found.'\n\n const result: GetComponentNotFoundResult = {\n slug,\n found: false,\n suggestions,\n message: `Component '${slug}' not found. ${suggestionText}`,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n },\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerFindComponentsTool } from './find-components.js'\nimport { registerGetComponentTool } from './get-component.js'\n\nexport function registerTools(server: McpServer): void {\n registerFindComponentsTool(server)\n registerGetComponentTool(server)\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerResources } from './resources/index.js'\nimport { registerTools } from './tools/index.js'\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'compose-ui-mcp',\n version: '0.1.0',\n })\n\n registerResources(server)\n registerTools(server)\n\n return server\n}\n","#!/usr/bin/env node\n\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\n\nimport { createServer } from './server.js'\n\nasync function main() {\n const server = createServer()\n const transport = new StdioServerTransport()\n\n await server.connect(transport)\n\n process.on('SIGINT', async () => {\n await server.close()\n process.exit(0)\n })\n}\n\nmain().catch((error) => {\n console.error('Server error:', error) // eslint-disable-line no-console\n process.exit(1)\n})\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["inputSchema"],"sources":["../src/lib/component-data.ts","../src/resources/components.ts","../src/resources/overview.ts","../src/resources/index.ts","../src/lib/fuzzy-match.ts","../src/tools/find-components.ts","../src/lib/markdown-parser.ts","../src/tools/get-component.ts","../src/tools/index.ts","../src/server.ts","../src/index.ts"],"sourcesContent":["import { readFile, readdir } from 'node:fs/promises'\nimport { dirname, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n// After build, assets are copied to dist/ alongside index.js\n// In dev, we're in src/lib/ and assets are at ../../assets/llms\n// At runtime (from dist/index.js), llms is at ./llms\nconst LLMS_DIR = resolve(__dirname, 'llms')\n\nexport interface ComponentInfo {\n name: string\n slug: string\n description: string\n documentationUri: string\n}\n\nexport function slugToName(slug: string): string {\n return slug\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n}\n\nfunction parseMarkdownFile(content: string, slug: string): ComponentInfo {\n const lines = content.split('\\n')\n\n // Extract title from first # heading\n let name = slugToName(slug)\n for (const line of lines) {\n if (line.startsWith('# ')) {\n name = line.slice(2).trim()\n break\n }\n }\n\n // Extract description (first non-empty line after the heading)\n let description = ''\n let foundHeading = false\n for (const line of lines) {\n if (line.startsWith('# ')) {\n foundHeading = true\n continue\n }\n if (foundHeading && line.trim() !== '') {\n description = line.trim()\n break\n }\n }\n\n return {\n name,\n slug,\n description,\n documentationUri: `compose-ui://components/${slug}`,\n }\n}\n\nexport async function getComponentContent(slug: string): Promise<string | null> {\n try {\n const filePath = resolve(LLMS_DIR, `${slug}.md`)\n return await readFile(filePath, 'utf-8')\n } catch {\n return null\n }\n}\n\nexport async function getComponentsList(): Promise<ComponentInfo[]> {\n try {\n const files = await readdir(LLMS_DIR)\n const mdFiles = files.filter((f) => f.endsWith('.md')).sort()\n\n const components: ComponentInfo[] = []\n\n for (const file of mdFiles) {\n const slug = file.replace('.md', '')\n const content = await readFile(resolve(LLMS_DIR, file), 'utf-8')\n components.push(parseMarkdownFile(content, slug))\n }\n\n return components\n } catch {\n return []\n }\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { getComponentContent, getComponentsList } from '../lib/component-data.js'\n\nexport function registerComponentsResource(server: McpServer): void {\n server.registerResource(\n 'components',\n 'compose-ui://components',\n {\n title: 'Compose UI Components',\n description: 'List of all Compose UI components with metadata',\n mimeType: 'application/json',\n },\n async () => ({\n contents: [\n {\n uri: 'compose-ui://components',\n mimeType: 'application/json',\n text: JSON.stringify(await getComponentsList(), null, 2),\n },\n ],\n }),\n )\n}\n\nexport function registerComponentDocResource(server: McpServer): void {\n server.registerResource(\n 'component-doc',\n new ResourceTemplate('compose-ui://components/{slug}', { list: undefined }),\n {\n title: 'Component Documentation',\n description: 'Full markdown documentation for a Compose UI component',\n mimeType: 'text/markdown',\n },\n async (uri, variables) => {\n const slug = variables.slug as string\n const content = await getComponentContent(slug)\n if (!content) {\n throw new Error(`Component not found: ${slug}`)\n }\n return {\n contents: [\n {\n uri: uri.href,\n mimeType: 'text/markdown',\n text: content,\n },\n ],\n }\n },\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nconst text = `# Compose UI\n\nA React component library built on Base UI primitives with Tailwind CSS v4 styling.\n\n## Key Principles\n- Composition over configuration\n- Base UI handles accessibility and behavior\n- Tailwind CSS for styling\n- TypeScript-first\n\n## Available Tools\n\nUse these tools to access component documentation:\n\n- **find_components**: Fuzzy search all components by name\n- **get_component**: Get full documentation for a specific component (supports section filtering)\n\n## Styling Guidelines\n\n- Components are **pre-styled and ready to use** - do not add custom CSS, Tailwind classes, or inline styles\n- Only add custom styling if the user explicitly requests it\n- Use built-in variant props (e.g., \\`variant=\"outline\"\\`, \\`size=\"sm\"\\`) for different appearances\n- Use specific import paths: \\`import { Button } from '@lglab/compose-ui/button'\\`\n`\n\nexport function registerOverviewResource(server: McpServer): void {\n server.registerResource(\n 'overview',\n 'compose-ui://overview',\n {\n title: 'Compose UI Overview',\n description: 'Compose UI overview documentation',\n mimeType: 'text/plain',\n },\n async () => ({\n contents: [\n {\n uri: 'compose-ui://overview',\n mimeType: 'text/markdown',\n text,\n },\n ],\n }),\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerComponentDocResource, registerComponentsResource } from './components.js'\nimport { registerOverviewResource } from './overview.js'\n\nexport function registerResources(server: McpServer): void {\n registerOverviewResource(server)\n registerComponentsResource(server)\n registerComponentDocResource(server)\n}\n","export interface FuzzyMatchResult<T> {\n item: T\n score: number\n}\n\n/**\n * Calculate a fuzzy match score between a query and a target string.\n * Returns a score from 0 to 1, where 1 is a perfect match.\n */\nexport function fuzzyScore(query: string, target: string): number {\n const q = query.toLowerCase()\n const t = target.toLowerCase()\n\n // Exact match\n if (q === t) return 1.0\n\n // Target starts with query\n if (t.startsWith(q)) return 0.9\n\n // Target contains query as substring\n if (t.includes(q)) return 0.7\n\n // Check if all query characters appear in order\n let queryIndex = 0\n let matchCount = 0\n\n for (const char of t) {\n if (queryIndex < q.length && char === q[queryIndex]) {\n matchCount++\n queryIndex++\n }\n }\n\n // All query characters found in order\n if (queryIndex === q.length) {\n // Score based on how much of the query matched vs target length\n return 0.3 + (matchCount / t.length) * 0.3\n }\n\n // Partial character match - calculate Levenshtein-like similarity\n const commonChars = new Set([...q].filter((c) => t.includes(c)))\n const similarity = commonChars.size / Math.max(q.length, t.length)\n\n return similarity * 0.3\n}\n\n/**\n * Search items using fuzzy matching.\n * Returns items sorted by match score (highest first).\n */\nexport function fuzzySearch<T>(\n query: string,\n items: T[],\n getSearchableText: (item: T) => string,\n minScore = 0.1,\n): FuzzyMatchResult<T>[] {\n const results: FuzzyMatchResult<T>[] = []\n\n for (const item of items) {\n const text = getSearchableText(item)\n const score = fuzzyScore(query, text)\n\n if (score >= minScore) {\n results.push({ item, score })\n }\n }\n\n // Sort by score descending\n results.sort((a, b) => b.score - a.score)\n\n return results\n}\n\n/**\n * Find the best fuzzy match for a query.\n * Returns the best match if score is above minScore, otherwise null.\n */\nexport function findBestMatch<T>(\n query: string,\n items: T[],\n getSearchableText: (item: T) => string,\n minScore = 0.3,\n): FuzzyMatchResult<T> | null {\n const results = fuzzySearch(query, items, getSearchableText, minScore)\n return results.length > 0 ? results[0] : null\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\n\nimport { getComponentsList } from '../lib/component-data.js'\nimport { fuzzySearch } from '../lib/fuzzy-match.js'\n\nconst inputSchema = {\n query: z\n .string()\n .optional()\n .describe('Fuzzy search query. Omit to list all components.'),\n limit: z\n .number()\n .min(1)\n .max(100)\n .default(50)\n .describe('Maximum number of results to return (default: 50)'),\n}\n\ninterface FindComponentsResult {\n count: number\n components: Array<{\n slug: string\n name: string\n description: string\n }>\n}\n\nexport function registerFindComponentsTool(server: McpServer): void {\n server.registerTool(\n 'find_components',\n {\n description:\n 'Find Compose UI components. Call without query to list all, or with query for fuzzy search.',\n inputSchema,\n },\n async ({ query, limit }) => {\n const allComponents = await getComponentsList()\n\n let components: Array<{ slug: string; name: string; description: string }>\n\n if (query) {\n // Fuzzy search on both name and slug\n const results = fuzzySearch(query, allComponents, (c) => `${c.name} ${c.slug}`)\n\n components = results.slice(0, limit ?? 50).map((r) => ({\n slug: r.item.slug,\n name: r.item.name,\n description: r.item.description,\n }))\n } else {\n // Return all components up to limit\n components = allComponents.slice(0, limit ?? 50).map((c) => ({\n slug: c.slug,\n name: c.name,\n description: c.description,\n }))\n }\n\n const result: FindComponentsResult = {\n count: components.length,\n components,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n },\n )\n}\n","export type SectionType =\n | 'overview'\n | 'installation'\n | 'import'\n | 'examples'\n | 'resources'\n\nexport interface ParsedSection {\n type: SectionType\n title: string\n content: string\n}\n\nconst SECTION_MAPPINGS: Record<string, SectionType> = {\n installation: 'installation',\n import: 'import',\n examples: 'examples',\n resources: 'resources',\n}\n\ninterface RawSection {\n heading: string\n content: string\n}\n\n/**\n * Parse markdown content into sections based on ## headings.\n */\nexport function parseMarkdownSections(markdown: string): ParsedSection[] {\n const lines = markdown.split('\\n')\n const sections: ParsedSection[] = []\n\n // Find title and description (overview section)\n let title = ''\n const overviewLines: string[] = []\n let currentSection: RawSection | null = null\n const rawSections: RawSection[] = []\n\n for (const line of lines) {\n // Main title\n if (line.startsWith('# ') && !title) {\n title = line.slice(2).trim()\n continue\n }\n\n // Section heading\n if (line.startsWith('## ')) {\n // Save previous section\n if (currentSection) {\n rawSections.push(currentSection)\n } else if (overviewLines.length > 0) {\n // Save overview content collected before first ## heading\n sections.push({\n type: 'overview',\n title: title || 'Overview',\n content: `# ${title}\\n\\n${overviewLines.join('\\n').trim()}`,\n })\n }\n\n currentSection = {\n heading: line.slice(3).trim(),\n content: '',\n }\n continue\n }\n\n // Content lines\n if (currentSection) {\n currentSection.content += line + '\\n'\n } else if (title) {\n // Content before first ## heading is part of overview\n overviewLines.push(line)\n }\n }\n\n // Save last section\n if (currentSection) {\n rawSections.push(currentSection)\n } else if (overviewLines.length > 0 && sections.length === 0) {\n // No sections found, treat everything as overview\n sections.push({\n type: 'overview',\n title: title || 'Overview',\n content: `# ${title}\\n\\n${overviewLines.join('\\n').trim()}`,\n })\n }\n\n // Convert raw sections to typed sections\n for (const raw of rawSections) {\n const headingLower = raw.heading.toLowerCase()\n const sectionType = SECTION_MAPPINGS[headingLower] || 'overview'\n\n sections.push({\n type: sectionType,\n title: raw.heading,\n content: `## ${raw.heading}\\n${raw.content.trim()}`,\n })\n }\n\n return sections\n}\n\n/**\n * Extract specific sections from markdown content.\n * If no sections are specified, returns the full content.\n */\nexport function extractSections(markdown: string, sectionTypes?: SectionType[]): string {\n if (!sectionTypes || sectionTypes.length === 0) {\n return markdown\n }\n\n const parsed = parseMarkdownSections(markdown)\n const filtered = parsed.filter((s) => sectionTypes.includes(s.type))\n\n if (filtered.length === 0) {\n return ''\n }\n\n // If overview is requested, include the title\n const includesOverview = sectionTypes.includes('overview')\n const overviewSection = filtered.find((s) => s.type === 'overview')\n\n if (includesOverview && overviewSection) {\n const otherSections = filtered.filter((s) => s.type !== 'overview')\n return [overviewSection.content, ...otherSections.map((s) => s.content)].join('\\n\\n')\n }\n\n return filtered.map((s) => s.content).join('\\n\\n')\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { z } from 'zod'\n\nimport {\n getComponentContent,\n getComponentsList,\n slugToName,\n} from '../lib/component-data.js'\nimport { fuzzySearch } from '../lib/fuzzy-match.js'\nimport { type SectionType, extractSections } from '../lib/markdown-parser.js'\n\nconst sectionTypes = [\n 'overview',\n 'installation',\n 'import',\n 'examples',\n 'resources',\n] as const\n\nconst inputSchema = {\n slug: z.string().describe('Component slug (e.g., \"button\", \"alert-dialog\")'),\n sections: z\n .array(z.enum(sectionTypes))\n .optional()\n .describe(\n 'Filter sections: \"overview\", \"installation\", \"import\", \"examples\", \"resources\". Default: all.',\n ),\n}\n\ninterface GetComponentSuccessResult {\n slug: string\n name: string\n found: true\n content: string\n}\n\ninterface GetComponentNotFoundResult {\n slug: string\n found: false\n suggestions: Array<{ slug: string; name: string; score: number }>\n message: string\n}\n\nexport function registerGetComponentTool(server: McpServer): void {\n server.registerTool(\n 'get_component',\n {\n description:\n 'Get documentation for a Compose UI component. Supports fuzzy matching if exact slug not found.',\n inputSchema,\n },\n async ({ slug, sections }) => {\n // Try exact match first\n const content = await getComponentContent(slug)\n\n if (content) {\n // Extract requested sections or return full content\n const filteredContent = extractSections(\n content,\n sections as SectionType[] | undefined,\n )\n\n const result: GetComponentSuccessResult = {\n slug,\n name: slugToName(slug),\n found: true,\n content: filteredContent || content,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n }\n\n // No exact match - try fuzzy matching\n const allComponents = await getComponentsList()\n const fuzzyResults = fuzzySearch(slug, allComponents, (c) => c.slug, 0.2)\n\n const suggestions = fuzzyResults.slice(0, 5).map((r) => ({\n slug: r.item.slug,\n name: r.item.name,\n score: Math.round(r.score * 100) / 100,\n }))\n\n const suggestionText =\n suggestions.length > 0\n ? `Did you mean '${suggestions[0].slug}'?`\n : 'No similar components found.'\n\n const result: GetComponentNotFoundResult = {\n slug,\n found: false,\n suggestions,\n message: `Component '${slug}' not found. ${suggestionText}`,\n }\n\n return {\n content: [\n {\n type: 'text' as const,\n text: JSON.stringify(result, null, 2),\n },\n ],\n }\n },\n )\n}\n","import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerFindComponentsTool } from './find-components.js'\nimport { registerGetComponentTool } from './get-component.js'\n\nexport function registerTools(server: McpServer): void {\n registerFindComponentsTool(server)\n registerGetComponentTool(server)\n}\n","import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\n\nimport { registerResources } from './resources/index.js'\nimport { registerTools } from './tools/index.js'\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: 'compose-ui-mcp',\n version: '0.1.0',\n })\n\n registerResources(server)\n registerTools(server)\n\n return server\n}\n","#!/usr/bin/env node\n\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\n\nimport { createServer } from './server.js'\n\nasync function main() {\n const server = createServer()\n const transport = new StdioServerTransport()\n\n await server.connect(transport)\n\n process.on('SIGINT', async () => {\n await server.close()\n process.exit(0)\n })\n}\n\nmain().catch((error) => {\n console.error('Server error:', error) // eslint-disable-line no-console\n process.exit(1)\n})\n"],"mappings":"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"}
|
package/dist/llms-full.txt
CHANGED
|
@@ -46,6 +46,24 @@
|
|
|
46
46
|
- Alert Dialog
|
|
47
47
|
- Accordion
|
|
48
48
|
|
|
49
|
+
## For AI Assistants
|
|
50
|
+
|
|
51
|
+
**MCP Server (Preferred)**
|
|
52
|
+
If you have access to MCP tools, use the `compose-ui` MCP server:
|
|
53
|
+
- `find_components` - Fuzzy search all components
|
|
54
|
+
- `get_component` - Get detailed docs for a specific component
|
|
55
|
+
|
|
56
|
+
**Styling Guidelines**
|
|
57
|
+
- Components are **pre-styled and ready to use** - do not add custom CSS, Tailwind classes, or inline styles
|
|
58
|
+
- Only add custom styling if the user explicitly requests it
|
|
59
|
+
- Use built-in variant props (e.g., `variant="outline"`, `size="sm"`) for different appearances
|
|
60
|
+
- For theming, use CSS variables - don't override component styles directly
|
|
61
|
+
|
|
62
|
+
**Best Practices**
|
|
63
|
+
- Always refer to this library as "Compose UI", not "Base UI" (Base UI is the underlying primitive library)
|
|
64
|
+
- Copy examples directly from the documentation - they are complete and working
|
|
65
|
+
- Use specific import paths: `import { Button } from '@lglab/compose-ui/button'` (not from '@lglab/compose-ui')
|
|
66
|
+
|
|
49
67
|
---
|
|
50
68
|
|
|
51
69
|
# Tooltip
|
package/dist/llms.txt
CHANGED
|
@@ -11,6 +11,24 @@ Key features:
|
|
|
11
11
|
- CSS variable-based theming (compatible with Tailwind v4)
|
|
12
12
|
- Tree-shakable ESM exports
|
|
13
13
|
|
|
14
|
+
## For AI Assistants
|
|
15
|
+
|
|
16
|
+
**MCP Server (Preferred)**
|
|
17
|
+
If you have access to MCP tools, use the `compose-ui` MCP server:
|
|
18
|
+
- `find_components` - Fuzzy search all components
|
|
19
|
+
- `get_component` - Get detailed docs for a specific component
|
|
20
|
+
|
|
21
|
+
**Styling Guidelines**
|
|
22
|
+
- Components are **pre-styled and ready to use** - do not add custom CSS, Tailwind classes, or inline styles
|
|
23
|
+
- Only add custom styling if the user explicitly requests it
|
|
24
|
+
- Use built-in variant props (e.g., `variant="outline"`, `size="sm"`) for different appearances
|
|
25
|
+
- For theming, use CSS variables - don't override component styles directly
|
|
26
|
+
|
|
27
|
+
**Best Practices**
|
|
28
|
+
- Always refer to this library as "Compose UI", not "Base UI" (Base UI is the underlying primitive library)
|
|
29
|
+
- Copy examples directly from the documentation - they are complete and working
|
|
30
|
+
- Use specific import paths: `import { Button } from '@lglab/compose-ui/button'` (not from '@lglab/compose-ui')
|
|
31
|
+
|
|
14
32
|
## Getting Started
|
|
15
33
|
|
|
16
34
|
- [Quick Start](https://compose-ui.dev/overview/quick-start): Installation and basic usage
|