@mindfiredigital/ignix-lite-mcp 1.2.0 → 1.4.0

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.
Files changed (90) hide show
  1. package/README.md +108 -0
  2. package/dist/server.js +187 -1954
  3. package/dist/server.js.map +1 -1
  4. package/dist/utils/check-api.js +2 -0
  5. package/dist/utils/check-api.js.map +1 -1
  6. package/package.json +14 -6
  7. package/.turbo/turbo-build.log +0 -25
  8. package/CHANGELOG.md +0 -7
  9. package/dist/manifests/accordion.json +0 -61
  10. package/dist/manifests/alert.json +0 -69
  11. package/dist/manifests/avatar.json +0 -75
  12. package/dist/manifests/badge.json +0 -74
  13. package/dist/manifests/breadcrumb.json +0 -87
  14. package/dist/manifests/button.json +0 -85
  15. package/dist/manifests/card.json +0 -91
  16. package/dist/manifests/checkbox.json +0 -122
  17. package/dist/manifests/codeblock.json +0 -63
  18. package/dist/manifests/combobox.json +0 -33
  19. package/dist/manifests/dialog.json +0 -64
  20. package/dist/manifests/divider.json +0 -47
  21. package/dist/manifests/dropdown.json +0 -105
  22. package/dist/manifests/form.json +0 -81
  23. package/dist/manifests/grid.json +0 -143
  24. package/dist/manifests/input.json +0 -99
  25. package/dist/manifests/meter.json +0 -103
  26. package/dist/manifests/navigation.json +0 -70
  27. package/dist/manifests/progress.json +0 -88
  28. package/dist/manifests/radio.json +0 -121
  29. package/dist/manifests/select.json +0 -109
  30. package/dist/manifests/skeleton.json +0 -101
  31. package/dist/manifests/tab.json +0 -88
  32. package/dist/manifests/table.json +0 -92
  33. package/dist/manifests/textarea.json +0 -117
  34. package/dist/manifests/toast.json +0 -157
  35. package/dist/manifests/tooltip.json +0 -115
  36. package/dist/vector-index.json +0 -14015
  37. package/src/context/api-context.ts +0 -14
  38. package/src/global.d.ts +0 -15
  39. package/src/manifests/accordion.json +0 -61
  40. package/src/manifests/alert.json +0 -69
  41. package/src/manifests/avatar.json +0 -75
  42. package/src/manifests/badge.json +0 -74
  43. package/src/manifests/breadcrumb.json +0 -87
  44. package/src/manifests/button.json +0 -85
  45. package/src/manifests/card.json +0 -91
  46. package/src/manifests/checkbox.json +0 -122
  47. package/src/manifests/codeblock.json +0 -63
  48. package/src/manifests/combobox.json +0 -33
  49. package/src/manifests/dialog.json +0 -64
  50. package/src/manifests/divider.json +0 -47
  51. package/src/manifests/dropdown.json +0 -105
  52. package/src/manifests/form.json +0 -81
  53. package/src/manifests/grid.json +0 -143
  54. package/src/manifests/index.ts +0 -45
  55. package/src/manifests/input.json +0 -99
  56. package/src/manifests/meter.json +0 -103
  57. package/src/manifests/navigation.json +0 -70
  58. package/src/manifests/progress.json +0 -88
  59. package/src/manifests/radio.json +0 -121
  60. package/src/manifests/select.json +0 -109
  61. package/src/manifests/skeleton.json +0 -101
  62. package/src/manifests/tab.json +0 -88
  63. package/src/manifests/table.json +0 -92
  64. package/src/manifests/textarea.json +0 -117
  65. package/src/manifests/toast.json +0 -157
  66. package/src/manifests/tooltip.json +0 -115
  67. package/src/server.ts +0 -201
  68. package/src/tools/build-index.ts +0 -55
  69. package/src/tools/check-a11y.ts +0 -106
  70. package/src/tools/embedder.ts +0 -18
  71. package/src/tools/generate-theme.ts +0 -42
  72. package/src/tools/get-emmet.ts +0 -64
  73. package/src/tools/get-manifests.ts +0 -55
  74. package/src/tools/intent-engine.ts +0 -197
  75. package/src/tools/list-components.ts +0 -20
  76. package/src/tools/search-index.ts +0 -66
  77. package/src/tools/theme-palette.ts +0 -65
  78. package/src/tools/theme-tokens.ts +0 -176
  79. package/src/tools/validator.ts +0 -367
  80. package/src/types.ts +0 -63
  81. package/src/utils/a11y-rules.ts +0 -873
  82. package/src/utils/a11y-types.ts +0 -15
  83. package/src/utils/check-api.ts +0 -13
  84. package/src/utils/cosine.ts +0 -15
  85. package/src/utils/emmet-helpers.ts +0 -171
  86. package/src/utils/intent-helpers.ts +0 -66
  87. package/src/utils/intent-parser.ts +0 -186
  88. package/src/utils/tokenizer.ts +0 -7
  89. package/tsconfig.json +0 -14
  90. package/tsup.config.ts +0 -13
package/src/server.ts DELETED
@@ -1,201 +0,0 @@
1
- import { Server } from '@modelcontextprotocol/sdk/server/index.js'
2
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
- import {
4
- ListToolsRequestSchema,
5
- CallToolRequestSchema
6
- } from '@modelcontextprotocol/sdk/types.js'
7
-
8
- import { listComponents } from './tools/list-components.js'
9
- import { getManifest } from './tools/get-manifests.js'
10
- import { getEmmet } from './tools/get-emmet.js'
11
- import { validate } from './tools/validator.js'
12
- import { howToBuild } from './tools/intent-engine.js'
13
- import { apiContext } from './context/api-context.js'
14
- import { generateTheme } from './tools/generate-theme.js'
15
- import { checkA11y } from './tools/check-a11y.js'
16
-
17
- type ValidateArgs = {
18
- html?: string
19
- }
20
-
21
- type IntentArgs = {
22
- description?: string
23
- }
24
-
25
- type A11yArgs = {
26
- html?: string
27
- }
28
-
29
- const server = new Server(
30
- {
31
- name: 'ignix-lite',
32
- version: '2.0.0'
33
- },
34
-
35
- {
36
- capabilities: {
37
- tools: {}
38
- }
39
- }
40
- )
41
-
42
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
43
- tools: [
44
- {
45
- name: 'list_components',
46
- description: 'List all ignix-lite components',
47
- inputSchema: {
48
- type: 'object',
49
- properties: {}
50
- }
51
- },
52
-
53
- {
54
- name: 'get_manifest',
55
- description: 'Get component manifest',
56
- inputSchema: {
57
- type: 'object',
58
- properties: {
59
- name: {
60
- type: 'string'
61
- }
62
- },
63
-
64
- required: ['name']
65
- }
66
- },
67
-
68
- {
69
- name: 'get_emmet',
70
- description: 'Get emmet pattern',
71
- inputSchema: {
72
- type: 'object',
73
- properties: {
74
- name: {
75
- type: 'string'
76
- }
77
- },
78
- required: ['name']
79
- }
80
- },
81
-
82
- {
83
- name: 'validate',
84
- description: 'Validate ignix-lite html',
85
- inputSchema: {
86
- type: 'object',
87
- properties: {
88
- html: {
89
- type: 'string'
90
- }
91
- },
92
- required: ['html']
93
- }
94
- },
95
-
96
- {
97
- name: 'how_to_build',
98
- description: 'Convert plain english to ignix-lite UI',
99
- inputSchema: {
100
- type: 'object',
101
- properties: {
102
- description: {
103
- type: 'string'
104
- }
105
- },
106
- required: ['description']
107
- }
108
- },
109
- {
110
- name: 'generate_theme',
111
-
112
- description: 'Generate ignix theme tokens',
113
-
114
- inputSchema: {
115
- type: 'object',
116
-
117
- properties: {
118
- prompt: {
119
- type: 'string'
120
- }
121
- },
122
-
123
- required: ['prompt']
124
- }
125
- },
126
- {
127
- name: 'check_a11y',
128
-
129
- description: 'Check accessibility',
130
-
131
- inputSchema: {
132
- type: 'object',
133
-
134
- properties: {
135
- html: {
136
- type: 'string'
137
- }
138
- },
139
-
140
- required: ['html']
141
- }
142
- }
143
- ]
144
- }))
145
-
146
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
147
- const { name, arguments: args } = request.params
148
-
149
- switch (name) {
150
- case 'list_components':
151
- return listComponents()
152
-
153
- case 'get_manifest':
154
- return getManifest(args)
155
-
156
- case 'get_emmet':
157
- return getEmmet(args)
158
-
159
- case 'validate': {
160
- const validateArgs = args as ValidateArgs
161
-
162
- return validate(validateArgs.html ?? '')
163
- }
164
-
165
- case 'how_to_build': {
166
- const intentArgs = args as IntentArgs
167
-
168
- return await howToBuild(intentArgs.description ?? '')
169
- }
170
- case 'generate_theme': {
171
- return generateTheme(args)
172
- }
173
- case 'check_a11y': {
174
- const a11yArgs = args as A11yArgs
175
-
176
- return checkA11y(a11yArgs.html ?? '')
177
- }
178
-
179
- default:
180
- return {
181
- content: [
182
- {
183
- type: 'text',
184
-
185
- text: JSON.stringify({
186
- error: `Unknown tool: ${name}`
187
- })
188
- }
189
- ]
190
- }
191
- }
192
- })
193
-
194
- async function start() {
195
- console.log('API loaded')
196
- console.log(apiContext.length)
197
- const transport = new StdioServerTransport()
198
- await server.connect(transport)
199
- console.log('Ignix MCP started')
200
- }
201
- start()
@@ -1,55 +0,0 @@
1
- import { readdirSync, readFileSync, writeFileSync } from 'fs'
2
- import { embedText } from './embedder.js'
3
-
4
- type Example = {
5
- label?: string
6
- emmet?: string
7
- html?: string
8
- }
9
-
10
- interface Manifest {
11
- component?: string
12
- description?: string
13
- element?: string
14
- emmet?: string
15
- states?: string[]
16
- do?: string[]
17
- dont?: string[]
18
- examples?: Example[]
19
- }
20
-
21
- const files = readdirSync('src/manifests')
22
-
23
- const index = files
24
- .filter((file) => file.endsWith('.json'))
25
- .map((file) => {
26
- const manifest: Manifest = JSON.parse(
27
- readFileSync(`src/manifests/${file}`, 'utf8')
28
- )
29
-
30
- const searchable = [
31
- manifest.component ?? '',
32
- manifest.description ?? '',
33
- manifest.element ?? '',
34
- manifest.emmet ?? '',
35
-
36
- ...(manifest.states ?? []),
37
- ...(manifest.do ?? []),
38
- ...(manifest.dont ?? []),
39
- ...(manifest.examples ?? []).flatMap((x: Example) => [
40
- x.label ?? '',
41
- x.emmet ?? '',
42
- x.html ?? ''
43
- ])
44
- ].join(' ')
45
-
46
- return {
47
- name: manifest.component,
48
- emmet: manifest.emmet,
49
- searchable,
50
- embedding: embedText(searchable)
51
- }
52
- })
53
-
54
- writeFileSync('dist/vector-index.json', JSON.stringify(index, null, 2))
55
- console.log('Vector index built')
@@ -1,106 +0,0 @@
1
- import { parse } from 'node-html-parser'
2
- import type { MCPResponse } from '../types.js'
3
- import type { A11yIssue, RuleResult } from '../utils/a11y-types.js'
4
- import {
5
- checkImages,
6
- checkFormLabels,
7
- checkEmptyLabels,
8
- checkButtons,
9
- checkLinks,
10
- checkAriaStates,
11
- checkDuplicateIds,
12
- checkTabIndex,
13
- checkHeadings,
14
- checkTables,
15
- checkDialogs,
16
- checkRoles,
17
- checkAutocomplete,
18
- checkFocusStyle,
19
- checkLang
20
- } from '../utils/a11y-rules.js'
21
-
22
- // Rule-specific confidence scores to avoid arbitrary hardcoding (addresses CodeRabbit feedback)
23
- const RULE_CONFIDENCES: Record<string, { error: number; warning: number }> = {
24
- 'WCAG 1.1.1 Non-text Content': { error: 0.99, warning: 0.80 },
25
- 'WCAG 1.3.1 Form Labels': { error: 0.98, warning: 0.78 },
26
- 'WCAG 2.4.6 Empty Labels': { error: 0.95, warning: 0.75 },
27
- 'WCAG 4.1.2 Button Names': { error: 0.99, warning: 0.80 },
28
- 'WCAG 2.4.4 Link Purpose': { error: 0.97, warning: 0.75 },
29
- 'WCAG 3.3.1 Error Identification': { error: 0.98, warning: 0.75 },
30
- 'WCAG 4.1.2 ARIA State Values': { error: 0.96, warning: 0.75 },
31
- 'WCAG 4.1.1 Parsing': { error: 0.99, warning: 0.80 },
32
- 'WCAG 2.1.1 Keyboard': { error: 0.95, warning: 0.75 },
33
- 'WCAG 2.4.6 Heading Hierarchy': { error: 0.95, warning: 0.75 },
34
- 'WCAG 1.3.1 Table Structure': { error: 0.97, warning: 0.75 },
35
- 'WCAG 4.1.2 Dialog Accessibility': { error: 0.98, warning: 0.75 },
36
- 'WCAG 4.1.2 ARIA Role Requirements': { error: 0.98, warning: 0.75 },
37
- 'WCAG 1.3.5 Input Purpose': { error: 0.95, warning: 0.75 },
38
- 'WCAG 2.4.7 Focus Visible': { error: 0.95, warning: 0.75 },
39
- 'WCAG 3.1.1 Language of Page': { error: 0.99, warning: 0.80 }
40
- }
41
-
42
- function getConfidenceForRule(
43
- ruleName: string,
44
- type: 'error' | 'warning'
45
- ): number {
46
- const conf = RULE_CONFIDENCES[ruleName]
47
- if (conf) {
48
- return type === 'error' ? conf.error : conf.warning
49
- }
50
- return type === 'error' ? 0.98 : 0.75
51
- }
52
-
53
- function computeScore(issues: A11yIssue[]): number {
54
- const errors = issues.filter((i) => i.type === 'error').length
55
- const warnings = issues.filter((i) => i.type === 'warning').length
56
- return Math.max(0, 100 - errors * 10 - warnings * 3)
57
- }
58
-
59
- function getPassingRules(results: RuleResult[]): string[] {
60
- return results.filter((r) => r.issues.length === 0).map((r) => r.ruleName)
61
- }
62
-
63
- export function checkA11y(html: string): MCPResponse {
64
- const root = parse(html)
65
-
66
- const results: RuleResult[] = [
67
- checkImages(root),
68
- checkFormLabels(root),
69
- checkEmptyLabels(root),
70
- checkButtons(root),
71
- checkLinks(root),
72
- checkAriaStates(root),
73
- checkDuplicateIds(root),
74
- checkTabIndex(root),
75
- checkHeadings(root),
76
- checkTables(root),
77
- checkDialogs(root),
78
- checkRoles(root),
79
- checkAutocomplete(root),
80
- checkFocusStyle(root),
81
- checkLang(root)
82
- ]
83
-
84
- const rawIssues = results.flatMap((r) => r.issues)
85
- const issues: A11yIssue[] = rawIssues.map((i) => ({
86
- ...i,
87
- confidence: getConfidenceForRule(i.rule, i.type)
88
- }))
89
- const passes = getPassingRules(results)
90
- const score = computeScore(issues)
91
-
92
- return {
93
- content: [
94
- {
95
- type: 'text',
96
- text: JSON.stringify({
97
- score,
98
- passes,
99
- issues,
100
- wcag: 'AA',
101
- tokens_used: Math.min(60, 20 + issues.length * 3)
102
- })
103
- }
104
- ]
105
- }
106
- }
@@ -1,18 +0,0 @@
1
- const VOCAB_SIZE = 512
2
-
3
- export function embedText(text: string): number[] {
4
- const vector = new Array(VOCAB_SIZE).fill(0)
5
- const words = text
6
- .toLowerCase()
7
- .replace(/[^a-z0-9\s]/g, ' ')
8
- .split(/\s+/)
9
- .filter(Boolean)
10
- words.forEach((word) => {
11
- let hash = 0
12
- for (let i = 0; i < word.length; i++) {
13
- hash = (hash * 31 + word.charCodeAt(i)) % VOCAB_SIZE
14
- }
15
- vector[hash] += 1
16
- })
17
- return vector
18
- }
@@ -1,42 +0,0 @@
1
- import { z } from 'zod'
2
- import type { MCPResponse } from '../types.js'
3
- import { resolveTokens, buildCss } from './theme-tokens.js'
4
-
5
- const schema = z.object({ prompt: z.string().min(1) })
6
-
7
- export function generateTheme(args: unknown): MCPResponse {
8
- const parsed = schema.safeParse(args)
9
-
10
- if (!parsed.success) {
11
- return {
12
- content: [
13
- {
14
- type: 'text',
15
- text: JSON.stringify({
16
- error: 'Invalid input',
17
- suggestion: 'Expected { prompt: string }',
18
- tokens_used: 2
19
- })
20
- }
21
- ]
22
- }
23
- }
24
-
25
- const { prompt } = parsed.data
26
- const tokens = resolveTokens(prompt.toLowerCase().trim())
27
-
28
- return {
29
- content: [
30
- {
31
- type: 'text',
32
- text: JSON.stringify({
33
- prompt,
34
- primary: tokens.resolvedPrimary,
35
- isDark: tokens.isDark,
36
- css: buildCss(tokens),
37
- tokens_used: 10
38
- })
39
- }
40
- ]
41
- }
42
- }
@@ -1,64 +0,0 @@
1
- import { z } from 'zod'
2
- import { manifests } from '../manifests/index.js'
3
- import type { MCPResponse } from '../types.js'
4
-
5
- const schema = z.object({
6
- name: z.string()
7
- })
8
-
9
- export function getEmmet(args: unknown): MCPResponse {
10
- const parsed = schema.safeParse(args)
11
-
12
- if (!parsed.success) {
13
- return {
14
- content: [
15
- {
16
- type: 'text',
17
-
18
- text: JSON.stringify({
19
- error: 'Invalid input',
20
-
21
- suggestion: 'Expected { name: string }',
22
-
23
- tokens_used: 2
24
- })
25
- }
26
- ]
27
- }
28
- }
29
-
30
- const { name } = parsed.data
31
-
32
- const manifest = manifests[name]
33
-
34
- if (!manifest) {
35
- return {
36
- content: [
37
- {
38
- type: 'text',
39
-
40
- text: JSON.stringify({
41
- error: `Unknown component: ${name}`,
42
- suggestion: 'Call list_components() first',
43
- tokens_used: 2
44
- })
45
- }
46
- ]
47
- }
48
- }
49
-
50
- return {
51
- content: [
52
- {
53
- type: 'text',
54
-
55
- text: JSON.stringify({
56
- component: manifest.component,
57
- emmet: manifest.emmet,
58
- tokens: manifest.tokens,
59
- tokens_used: 3
60
- })
61
- }
62
- ]
63
- }
64
- }
@@ -1,55 +0,0 @@
1
- import { z } from 'zod'
2
- import { manifests } from '../manifests/index.js'
3
- import type { MCPResponse } from '../types.js'
4
-
5
- const schema = z.object({
6
- name: z.string()
7
- })
8
-
9
- export function getManifest(args: unknown): MCPResponse {
10
- const parsed = schema.safeParse(args)
11
-
12
- if (!parsed.success) {
13
- return {
14
- content: [
15
- {
16
- type: 'text',
17
- text: JSON.stringify({
18
- error: 'Invalid input',
19
- suggestion: 'Expected { name: string }',
20
- tokens_used: 2
21
- })
22
- }
23
- ]
24
- }
25
- }
26
-
27
- const { name } = parsed.data
28
-
29
- const manifest = manifests[name]
30
-
31
- if (!manifest) {
32
- return {
33
- content: [
34
- {
35
- type: 'text',
36
-
37
- text: JSON.stringify({
38
- error: `Unknown component: ${name}`,
39
- suggestion: 'Call list_components() first',
40
- tokens_used: 2
41
- })
42
- }
43
- ]
44
- }
45
- }
46
-
47
- return {
48
- content: [
49
- {
50
- type: 'text',
51
- text: JSON.stringify(manifest)
52
- }
53
- ]
54
- }
55
- }