jui-tools-mcp-server 2.5.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 (172) hide show
  1. package/.github/workflows/test.yml +35 -0
  2. package/README.md +148 -0
  3. package/data/attribute_definitions.json +4248 -0
  4. package/data/attribute_semantics.json +137 -0
  5. package/data/binding_semantics.json +115 -0
  6. package/data/component_metadata.json +769 -0
  7. package/data/coverage.json +114 -0
  8. package/data/screen_identity.json +350 -0
  9. package/dist/cli_runner.d.ts +10 -0
  10. package/dist/cli_runner.js +33 -0
  11. package/dist/config.d.ts +19 -0
  12. package/dist/config.js +67 -0
  13. package/dist/data/component_metadata.d.ts +30 -0
  14. package/dist/data/component_metadata.js +498 -0
  15. package/dist/data/derived.d.ts +198 -0
  16. package/dist/data/derived.js +293 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.js +130 -0
  19. package/dist/spec_loader.d.ts +110 -0
  20. package/dist/spec_loader.js +445 -0
  21. package/dist/tools/api/list_api_models.d.ts +10 -0
  22. package/dist/tools/api/list_api_models.js +37 -0
  23. package/dist/tools/api/list_api_specs.d.ts +19 -0
  24. package/dist/tools/api/list_api_specs.js +42 -0
  25. package/dist/tools/api/preview_api_model_sync.d.ts +11 -0
  26. package/dist/tools/api/preview_api_model_sync.js +34 -0
  27. package/dist/tools/context/get_project_config.d.ts +3 -0
  28. package/dist/tools/context/get_project_config.js +20 -0
  29. package/dist/tools/context/list_component_specs.d.ts +3 -0
  30. package/dist/tools/context/list_component_specs.js +35 -0
  31. package/dist/tools/context/list_layouts.d.ts +3 -0
  32. package/dist/tools/context/list_layouts.js +118 -0
  33. package/dist/tools/context/list_screen_specs.d.ts +3 -0
  34. package/dist/tools/context/list_screen_specs.js +37 -0
  35. package/dist/tools/context/read_layout_file.d.ts +3 -0
  36. package/dist/tools/context/read_layout_file.js +25 -0
  37. package/dist/tools/context/read_spec_file.d.ts +3 -0
  38. package/dist/tools/context/read_spec_file.js +27 -0
  39. package/dist/tools/doc/doc_generate_component.d.ts +3 -0
  40. package/dist/tools/doc/doc_generate_component.js +38 -0
  41. package/dist/tools/doc/doc_generate_html.d.ts +3 -0
  42. package/dist/tools/doc/doc_generate_html.js +46 -0
  43. package/dist/tools/doc/doc_generate_spec.d.ts +3 -0
  44. package/dist/tools/doc/doc_generate_spec.js +38 -0
  45. package/dist/tools/doc/doc_init_component.d.ts +3 -0
  46. package/dist/tools/doc/doc_init_component.js +30 -0
  47. package/dist/tools/doc/doc_init_spec.d.ts +3 -0
  48. package/dist/tools/doc/doc_init_spec.js +33 -0
  49. package/dist/tools/doc/doc_rules_init.d.ts +3 -0
  50. package/dist/tools/doc/doc_rules_init.js +25 -0
  51. package/dist/tools/doc/doc_rules_show.d.ts +3 -0
  52. package/dist/tools/doc/doc_rules_show.js +21 -0
  53. package/dist/tools/doc/doc_validate_component.d.ts +3 -0
  54. package/dist/tools/doc/doc_validate_component.js +39 -0
  55. package/dist/tools/doc/doc_validate_spec.d.ts +3 -0
  56. package/dist/tools/doc/doc_validate_spec.js +40 -0
  57. package/dist/tools/jui/jui_build.d.ts +3 -0
  58. package/dist/tools/jui/jui_build.js +31 -0
  59. package/dist/tools/jui/jui_generate_converter.d.ts +3 -0
  60. package/dist/tools/jui/jui_generate_converter.js +43 -0
  61. package/dist/tools/jui/jui_generate_project.d.ts +3 -0
  62. package/dist/tools/jui/jui_generate_project.js +43 -0
  63. package/dist/tools/jui/jui_generate_screen.d.ts +3 -0
  64. package/dist/tools/jui/jui_generate_screen.js +22 -0
  65. package/dist/tools/jui/jui_init.d.ts +3 -0
  66. package/dist/tools/jui/jui_init.js +42 -0
  67. package/dist/tools/jui/jui_migrate_layouts.d.ts +3 -0
  68. package/dist/tools/jui/jui_migrate_layouts.js +25 -0
  69. package/dist/tools/jui/jui_sync_tool.d.ts +3 -0
  70. package/dist/tools/jui/jui_sync_tool.js +33 -0
  71. package/dist/tools/jui/jui_verify.d.ts +3 -0
  72. package/dist/tools/jui/jui_verify.js +43 -0
  73. package/dist/tools/spec/get_binding_rules.d.ts +3 -0
  74. package/dist/tools/spec/get_binding_rules.js +8 -0
  75. package/dist/tools/spec/get_data_source.d.ts +3 -0
  76. package/dist/tools/spec/get_data_source.js +41 -0
  77. package/dist/tools/spec/get_modifier_order.d.ts +3 -0
  78. package/dist/tools/spec/get_modifier_order.js +14 -0
  79. package/dist/tools/spec/get_platform_mapping.d.ts +3 -0
  80. package/dist/tools/spec/get_platform_mapping.js +20 -0
  81. package/dist/tools/spec/get_screen_identity.d.ts +3 -0
  82. package/dist/tools/spec/get_screen_identity.js +22 -0
  83. package/dist/tools/spec/lookup_attribute.d.ts +3 -0
  84. package/dist/tools/spec/lookup_attribute.js +14 -0
  85. package/dist/tools/spec/lookup_component.d.ts +3 -0
  86. package/dist/tools/spec/lookup_component.js +15 -0
  87. package/dist/tools/spec/search_components.d.ts +3 -0
  88. package/dist/tools/spec/search_components.js +14 -0
  89. package/dist/tools/test/test_artifacts_pull.d.ts +3 -0
  90. package/dist/tools/test/test_artifacts_pull.js +48 -0
  91. package/dist/tools/test/test_artifacts_status.d.ts +3 -0
  92. package/dist/tools/test/test_artifacts_status.js +28 -0
  93. package/dist/tools/test/test_generate_description.d.ts +3 -0
  94. package/dist/tools/test/test_generate_description.js +27 -0
  95. package/dist/tools/test/test_generate_flow.d.ts +3 -0
  96. package/dist/tools/test/test_generate_flow.js +29 -0
  97. package/dist/tools/test/test_generate_screen.d.ts +3 -0
  98. package/dist/tools/test/test_generate_screen.js +29 -0
  99. package/dist/tools/test/test_mock_generate.d.ts +3 -0
  100. package/dist/tools/test/test_mock_generate.js +64 -0
  101. package/dist/tools/test/test_report.d.ts +3 -0
  102. package/dist/tools/test/test_report.js +26 -0
  103. package/dist/tools/test/test_validate.d.ts +3 -0
  104. package/dist/tools/test/test_validate.js +43 -0
  105. package/docs/design.md +227 -0
  106. package/install.sh +90 -0
  107. package/package.json +24 -0
  108. package/scripts/fetch-definitions.js +101 -0
  109. package/scripts/fetch-manifest.js +60 -0
  110. package/src/cli_runner.ts +55 -0
  111. package/src/config.ts +88 -0
  112. package/src/data/derived.ts +305 -0
  113. package/src/index.ts +157 -0
  114. package/src/spec_loader.ts +591 -0
  115. package/src/tools/api/list_api_models.ts +44 -0
  116. package/src/tools/api/list_api_specs.ts +53 -0
  117. package/src/tools/api/preview_api_model_sync.ts +41 -0
  118. package/src/tools/context/get_project_config.ts +27 -0
  119. package/src/tools/context/list_component_specs.ts +44 -0
  120. package/src/tools/context/list_layouts.ts +131 -0
  121. package/src/tools/context/list_screen_specs.ts +46 -0
  122. package/src/tools/context/read_layout_file.ts +35 -0
  123. package/src/tools/context/read_spec_file.ts +38 -0
  124. package/src/tools/doc/doc_generate_component.ts +43 -0
  125. package/src/tools/doc/doc_generate_html.ts +40 -0
  126. package/src/tools/doc/doc_generate_spec.ts +43 -0
  127. package/src/tools/doc/doc_init_component.ts +32 -0
  128. package/src/tools/doc/doc_init_spec.ts +37 -0
  129. package/src/tools/doc/doc_rules_init.ts +29 -0
  130. package/src/tools/doc/doc_rules_show.ts +27 -0
  131. package/src/tools/doc/doc_validate_component.ts +47 -0
  132. package/src/tools/doc/doc_validate_spec.ts +48 -0
  133. package/src/tools/jui/jui_build.ts +31 -0
  134. package/src/tools/jui/jui_generate_converter.ts +41 -0
  135. package/src/tools/jui/jui_generate_project.ts +37 -0
  136. package/src/tools/jui/jui_generate_screen.ts +28 -0
  137. package/src/tools/jui/jui_init.ts +38 -0
  138. package/src/tools/jui/jui_migrate_layouts.ts +29 -0
  139. package/src/tools/jui/jui_sync_tool.ts +33 -0
  140. package/src/tools/jui/jui_verify.ts +43 -0
  141. package/src/tools/spec/get_binding_rules.ts +16 -0
  142. package/src/tools/spec/get_data_source.ts +53 -0
  143. package/src/tools/spec/get_modifier_order.ts +22 -0
  144. package/src/tools/spec/get_platform_mapping.ts +28 -0
  145. package/src/tools/spec/get_screen_identity.ts +31 -0
  146. package/src/tools/spec/lookup_attribute.ts +22 -0
  147. package/src/tools/spec/lookup_component.ts +23 -0
  148. package/src/tools/spec/search_components.ts +22 -0
  149. package/src/tools/test/test_artifacts_pull.ts +47 -0
  150. package/src/tools/test/test_artifacts_status.ts +34 -0
  151. package/src/tools/test/test_generate_description.ts +33 -0
  152. package/src/tools/test/test_generate_flow.ts +33 -0
  153. package/src/tools/test/test_generate_screen.ts +33 -0
  154. package/src/tools/test/test_mock_generate.ts +58 -0
  155. package/src/tools/test/test_report.ts +32 -0
  156. package/src/tools/test/test_validate.ts +43 -0
  157. package/tests/__snapshots__/derived.test.ts.snap +279 -0
  158. package/tests/bundled_snapshot.test.ts +155 -0
  159. package/tests/cli_runner.test.ts +120 -0
  160. package/tests/config.test.ts +212 -0
  161. package/tests/derived.test.ts +114 -0
  162. package/tests/helpers.ts +272 -0
  163. package/tests/setup.ts +27 -0
  164. package/tests/snapshot_completeness.test.ts +152 -0
  165. package/tests/spec_loader.test.ts +488 -0
  166. package/tests/tools_cli.test.ts +687 -0
  167. package/tests/tools_context.test.ts +274 -0
  168. package/tests/tools_spec.test.ts +225 -0
  169. package/tests/tools_test.test.ts +284 -0
  170. package/tsconfig.json +15 -0
  171. package/uninstall.sh +46 -0
  172. package/vitest.config.ts +15 -0
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Derived / static content that the MCP server exposes alongside attribute definitions.
3
+ *
4
+ * These values do not depend on
5
+ * attribute_definitions.json — they encode platform conventions (modifier order,
6
+ * binding syntax, cross-platform value mapping). Kept in TS so the MCP can serve
7
+ * them at startup without any build step.
8
+ */
9
+ export declare function categorizeCommonAttributes(commonAttrs: Record<string, any>): any;
10
+ export declare const MODIFIER_ORDER: {
11
+ description: string;
12
+ swift: {
13
+ order: string[];
14
+ criticalRules: string[];
15
+ };
16
+ kotlin: {
17
+ order: string[];
18
+ criticalRules: string[];
19
+ };
20
+ react: {
21
+ note: string;
22
+ classOrder: string[];
23
+ dynamicStyles: string;
24
+ };
25
+ };
26
+ export declare const BINDING_RULES: {
27
+ description: string;
28
+ format: {
29
+ bindingExpression: string;
30
+ negation: string;
31
+ defaultValue: string;
32
+ nestedPath: string;
33
+ };
34
+ directions: {
35
+ "two-way": {
36
+ description: string;
37
+ swift: string;
38
+ kotlin: string;
39
+ react: string;
40
+ applicableAttributes: string[];
41
+ };
42
+ "read-only": {
43
+ description: string;
44
+ swift: string;
45
+ kotlin: string;
46
+ react: string;
47
+ applicableAttributes: string[];
48
+ };
49
+ };
50
+ criticalRules: string[];
51
+ };
52
+ export declare const PLATFORM_MAPPING: {
53
+ description: string;
54
+ values: {
55
+ matchParent: {
56
+ swift: string;
57
+ kotlin: string;
58
+ react: string;
59
+ };
60
+ wrapContent: {
61
+ swift: string;
62
+ kotlin: string;
63
+ react: string;
64
+ };
65
+ };
66
+ contentMode: {
67
+ aspectFit: {
68
+ swift: string;
69
+ kotlin: string;
70
+ react: string;
71
+ };
72
+ aspectFill: {
73
+ swift: string;
74
+ kotlin: string;
75
+ react: string;
76
+ };
77
+ scaleToFill: {
78
+ swift: string;
79
+ kotlin: string;
80
+ react: string;
81
+ };
82
+ };
83
+ textAlign: {
84
+ left: {
85
+ swift: string;
86
+ kotlin: string;
87
+ react: string;
88
+ };
89
+ center: {
90
+ swift: string;
91
+ kotlin: string;
92
+ react: string;
93
+ };
94
+ right: {
95
+ swift: string;
96
+ kotlin: string;
97
+ react: string;
98
+ };
99
+ };
100
+ fontWeight: {
101
+ bold: {
102
+ swift: string;
103
+ kotlin: string;
104
+ react: string;
105
+ };
106
+ light: {
107
+ swift: string;
108
+ kotlin: string;
109
+ react: string;
110
+ };
111
+ thin: {
112
+ swift: string;
113
+ kotlin: string;
114
+ react: string;
115
+ };
116
+ medium: {
117
+ swift: string;
118
+ kotlin: string;
119
+ react: string;
120
+ };
121
+ semibold: {
122
+ swift: string;
123
+ kotlin: string;
124
+ react: string;
125
+ };
126
+ };
127
+ orientation: {
128
+ horizontal: {
129
+ swift: string;
130
+ kotlin: string;
131
+ react: string;
132
+ };
133
+ vertical: {
134
+ swift: string;
135
+ kotlin: string;
136
+ react: string;
137
+ };
138
+ none: {
139
+ swift: string;
140
+ kotlin: string;
141
+ react: string;
142
+ };
143
+ };
144
+ gravity: {
145
+ center: {
146
+ swift: string;
147
+ kotlin: string;
148
+ react: string;
149
+ };
150
+ centerHorizontal: {
151
+ swift_vertical: string;
152
+ kotlin_vertical: string;
153
+ react: string;
154
+ };
155
+ centerVertical: {
156
+ swift_horizontal: string;
157
+ kotlin_horizontal: string;
158
+ react: string;
159
+ };
160
+ };
161
+ types: {
162
+ String: {
163
+ swift: string;
164
+ kotlin: string;
165
+ react: string;
166
+ };
167
+ Int: {
168
+ swift: string;
169
+ kotlin: string;
170
+ react: string;
171
+ };
172
+ Float: {
173
+ swift: string;
174
+ kotlin: string;
175
+ react: string;
176
+ };
177
+ Double: {
178
+ swift: string;
179
+ kotlin: string;
180
+ react: string;
181
+ };
182
+ Bool: {
183
+ swift: string;
184
+ kotlin: string;
185
+ react: string;
186
+ };
187
+ Array: {
188
+ swift: string;
189
+ kotlin: string;
190
+ react: string;
191
+ };
192
+ Dictionary: {
193
+ swift: string;
194
+ kotlin: string;
195
+ react: string;
196
+ };
197
+ };
198
+ };
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Derived / static content that the MCP server exposes alongside attribute definitions.
3
+ *
4
+ * These values do not depend on
5
+ * attribute_definitions.json — they encode platform conventions (modifier order,
6
+ * binding syntax, cross-platform value mapping). Kept in TS so the MCP can serve
7
+ * them at startup without any build step.
8
+ */
9
+ // ----- categorizeCommonAttributes ----------------------------------------
10
+ const CATEGORY_KEYS = {
11
+ sizing: new Set([
12
+ "width", "height", "minWidth", "maxWidth", "minHeight", "maxHeight",
13
+ "weight", "widthWeight", "heightWeight", "maxWidthWeight", "maxHeightWeight",
14
+ "minWidthWeight", "minHeightWeight", "aspectWidth", "aspectHeight",
15
+ "aspectRatio", "frame", "rect", "wrapContent",
16
+ ]),
17
+ spacing: new Set([
18
+ "padding", "paddings", "paddingTop", "paddingBottom", "paddingLeft",
19
+ "paddingRight", "paddingStart", "paddingEnd", "rightPadding", "leftPadding",
20
+ "minTopPadding", "minBottomPadding", "minLeftPadding", "minRightPadding",
21
+ "maxTopPadding", "maxBottomPadding", "maxLeftPadding", "maxRightPadding",
22
+ "margins", "topMargin", "bottomMargin", "leftMargin", "rightMargin",
23
+ "startMargin", "endMargin", "minTopMargin", "minBottomMargin",
24
+ "minLeftMargin", "minRightMargin", "maxTopMargin", "maxBottomMargin",
25
+ "maxLeftMargin", "maxRightMargin", "innerPadding", "insets", "insetHorizontal",
26
+ ]),
27
+ visual: new Set([
28
+ "background", "tapBackground", "highlightBackground", "disabledBackground",
29
+ "defaultBackground", "cornerRadius", "borderWidth", "borderColor",
30
+ "borderStyle", "alpha", "opacity", "shadow", "clipToBounds", "tintColor",
31
+ "effectStyle",
32
+ ]),
33
+ visibility: new Set(["visibility", "hidden"]),
34
+ interaction: new Set([
35
+ "onclick", "onClick", "onLongPress", "onPan", "onPinch", "canTap",
36
+ "enabled", "userInteractionEnabled", "touchDisabledState",
37
+ "touchEnabledViewIds",
38
+ ]),
39
+ layout: new Set([
40
+ "centerInParent", "centerVertical", "centerHorizontal", "alignTop",
41
+ "alignBottom", "alignLeft", "alignRight", "alignTopOfView",
42
+ "alignBottomOfView", "alignLeftOfView", "alignRightOfView",
43
+ "alignTopView", "alignBottomView", "alignLeftView", "alignRightView",
44
+ "alignCenterVerticalView", "alignCenterHorizontalView", "toView",
45
+ "gravity", "indexBelow", "indexAbove",
46
+ "keyBottomView", "keyTopView", "keyLeftView", "keyRightView",
47
+ ]),
48
+ lifecycle: new Set(["onAppear", "onDisappear"]),
49
+ accessibility: new Set(["id", "testId", "className", "tag"]),
50
+ binding: new Set([
51
+ "binding", "bind", "binding_id", "binding_group", "propertyName",
52
+ "bindingScript", "data", "shared_data",
53
+ ]),
54
+ };
55
+ export function categorizeCommonAttributes(commonAttrs) {
56
+ const categories = {
57
+ sizing: {},
58
+ spacing: {},
59
+ visual: {},
60
+ visibility: {},
61
+ interaction: {},
62
+ layout: {},
63
+ lifecycle: {},
64
+ accessibility: {},
65
+ binding: {},
66
+ other: {},
67
+ };
68
+ for (const [key, attrDef] of Object.entries(commonAttrs)) {
69
+ if (key.startsWith("_"))
70
+ continue;
71
+ let placed = false;
72
+ for (const [category, keys] of Object.entries(CATEGORY_KEYS)) {
73
+ if (keys.has(key)) {
74
+ categories[category][key] = attrDef;
75
+ placed = true;
76
+ break;
77
+ }
78
+ }
79
+ if (!placed)
80
+ categories.other[key] = attrDef;
81
+ }
82
+ // Drop empty categories
83
+ const filtered = {};
84
+ for (const [name, attrs] of Object.entries(categories)) {
85
+ if (Object.keys(attrs).length > 0)
86
+ filtered[name] = attrs;
87
+ }
88
+ return {
89
+ description: "Common attributes shared across all components",
90
+ source: "attribute_definitions.json common section",
91
+ categories: filtered,
92
+ };
93
+ }
94
+ // ----- modifier order (platform rendering) -------------------------------
95
+ export const MODIFIER_ORDER = {
96
+ description: "Platform-specific modifier application order. Order affects rendering.",
97
+ swift: {
98
+ order: [
99
+ "centerAlignment",
100
+ "edgeAlignment",
101
+ "padding",
102
+ "frameConstraints (min/max)",
103
+ "frameSize (width/height)",
104
+ "insets/insetHorizontal",
105
+ "background",
106
+ "cornerRadius",
107
+ "border",
108
+ "margins",
109
+ "alpha/opacity",
110
+ "shadow",
111
+ "clipping",
112
+ "offset",
113
+ "visibility (hidden/opacity ternary)",
114
+ "safeAreaInsets",
115
+ "disabled",
116
+ "tag (for TabView)",
117
+ "tintColor",
118
+ "onClick/onTapGesture",
119
+ "lifecycle (onAppear/onDisappear)",
120
+ "confirmationDialog",
121
+ "accessibilityIdentifier",
122
+ ],
123
+ criticalRules: [
124
+ "background MUST come after padding (background includes padding area)",
125
+ "border MUST come after cornerRadius (for rounded border)",
126
+ "frame MUST come before margins (size before external spacing)",
127
+ "Image: .resizable() must come first, then .aspectRatio",
128
+ "Label: .leading alignment added to frame for textAlign to work",
129
+ ],
130
+ },
131
+ kotlin: {
132
+ order: [
133
+ "testTag",
134
+ "margins",
135
+ "weight (caller applies)",
136
+ "size (width/height, matchParent/wrapContent, min/max/aspectRatio)",
137
+ "alpha/opacity",
138
+ "shadow/elevation",
139
+ "background (cornerRadius -> clip -> border -> bgColor)",
140
+ "clickable",
141
+ "padding",
142
+ "alignment (RowScope/ColumnScope/BoxScope)",
143
+ ],
144
+ criticalRules: [
145
+ "Modifier.then() chains left-to-right; order matters",
146
+ "margins before size (outside to inside)",
147
+ "cornerRadius must be applied as clip before background",
148
+ ],
149
+ },
150
+ react: {
151
+ note: "React uses Tailwind CSS classes; ordering is less strict",
152
+ classOrder: [
153
+ "layout (flex, flex-col/row)",
154
+ "sizing (w-*, h-*)",
155
+ "spacing (p-*, m-*)",
156
+ "typography (text-*, font-*)",
157
+ "visual (bg-*, rounded-*, border-*, shadow-*)",
158
+ "opacity",
159
+ "overflow",
160
+ "cursor/interaction",
161
+ ],
162
+ dynamicStyles: "Values not mappable to Tailwind use inline style objects",
163
+ },
164
+ };
165
+ // ----- binding rules -----------------------------------------------------
166
+ export const BINDING_RULES = {
167
+ description: "JsonUI binding syntax rules",
168
+ format: {
169
+ bindingExpression: "@{propertyName}",
170
+ negation: "@{!propertyName} (boolean value attributes only — validator error elsewhere)",
171
+ defaultValue: "@{propertyName ?? default} (one ?? max; string default in single or double quotes, or true/false/number; null = unresolved)",
172
+ nestedPath: "@{user.name} / @{items[0].title} (dot path + bracket index — canonical on all platforms; see semantics)",
173
+ },
174
+ directions: {
175
+ "two-way": {
176
+ description: "Component state changes reflect back to data model",
177
+ swift: "$data.propertyName",
178
+ kotlin: "mutableStateOf + updateData(mapOf(key to value))",
179
+ react: "value={data.prop} + auto-generated onChange handler",
180
+ applicableAttributes: [
181
+ "TextField.text",
182
+ "TextView.text",
183
+ "Switch.isOn",
184
+ "Toggle.isOn",
185
+ "CheckBox.checked",
186
+ "Slider.value",
187
+ "Segment.selectedIndex",
188
+ "Radio.selectedIndex",
189
+ "SelectBox.selectedIndex",
190
+ "TabView.selectedIndex",
191
+ ],
192
+ },
193
+ "read-only": {
194
+ description: "Display data values only (no write-back)",
195
+ swift: "data.propertyName",
196
+ kotlin: "data[propertyName]",
197
+ react: "{data.propertyName}",
198
+ applicableAttributes: [
199
+ "Label.text",
200
+ "*.width / *.height (frame values)",
201
+ "*.enabled",
202
+ "*.hidden / *.visibility",
203
+ "*.background / *.fontColor",
204
+ "*.fontSize",
205
+ "*.opacity / *.alpha",
206
+ ],
207
+ },
208
+ },
209
+ criticalRules: [
210
+ "Two-way binding expressions must be a single flat identifier — no dots, brackets, ??, or ! (binding-two-way-complex)",
211
+ "Frame values (width, height, etc.) MUST be read-only (data.). $data. is NOT allowed",
212
+ "Two-way binding is only for stateful input components",
213
+ "React auto-generates onPropertyNameChange for two-way bindings",
214
+ "Kotlin Dynamic uses updateData(mapOf(key to value)) for data updates",
215
+ "onclick (lowercase) = selector format (string), onClick (camelCase) = binding format (@{handler})",
216
+ ],
217
+ };
218
+ // ----- platform mapping (cross-platform value conversion) ----------------
219
+ export const PLATFORM_MAPPING = {
220
+ description: "Cross-platform attribute value conversion mapping",
221
+ values: {
222
+ matchParent: {
223
+ swift: ".infinity (frame maxWidth/maxHeight)",
224
+ kotlin: "fillMaxWidth() / fillMaxHeight()",
225
+ react: "w-full / h-full",
226
+ },
227
+ wrapContent: {
228
+ swift: "Default (no frame specified)",
229
+ kotlin: "wrapContentWidth() / wrapContentHeight()",
230
+ react: "w-fit / h-fit",
231
+ },
232
+ },
233
+ contentMode: {
234
+ aspectFit: { swift: ".fit", kotlin: "ContentScale.Fit", react: "object-contain" },
235
+ aspectFill: { swift: ".fill", kotlin: "ContentScale.Crop", react: "object-cover" },
236
+ scaleToFill: {
237
+ swift: ".fill (no aspectRatio)",
238
+ kotlin: "ContentScale.FillBounds",
239
+ react: "object-fill",
240
+ },
241
+ },
242
+ textAlign: {
243
+ left: { swift: ".leading", kotlin: "TextAlign.Start", react: "text-left" },
244
+ center: { swift: ".center", kotlin: "TextAlign.Center", react: "text-center" },
245
+ right: { swift: ".trailing", kotlin: "TextAlign.End", react: "text-right" },
246
+ },
247
+ fontWeight: {
248
+ bold: { swift: ".bold", kotlin: "FontWeight.Bold", react: "font-bold" },
249
+ light: { swift: ".light", kotlin: "FontWeight.Light", react: "font-light" },
250
+ thin: { swift: ".thin", kotlin: "FontWeight.Thin", react: "font-thin" },
251
+ medium: { swift: ".medium", kotlin: "FontWeight.Medium", react: "font-medium" },
252
+ semibold: {
253
+ swift: ".semibold",
254
+ kotlin: "FontWeight.SemiBold",
255
+ react: "font-semibold",
256
+ },
257
+ },
258
+ orientation: {
259
+ horizontal: { swift: "HStack", kotlin: "Row", react: "flex flex-row" },
260
+ vertical: { swift: "VStack", kotlin: "Column", react: "flex flex-col" },
261
+ none: { swift: "ZStack", kotlin: "Box", react: "relative" },
262
+ },
263
+ gravity: {
264
+ center: {
265
+ swift: ".center",
266
+ kotlin: "Alignment.Center",
267
+ react: "items-center justify-center",
268
+ },
269
+ centerHorizontal: {
270
+ swift_vertical: ".center HStack alignment",
271
+ kotlin_vertical: "Alignment.CenterHorizontally",
272
+ react: "items-center (flex-col)",
273
+ },
274
+ centerVertical: {
275
+ swift_horizontal: ".center VStack alignment",
276
+ kotlin_horizontal: "Alignment.CenterVertically",
277
+ react: "items-center (flex-row)",
278
+ },
279
+ },
280
+ types: {
281
+ String: { swift: "String", kotlin: "String", react: "string" },
282
+ Int: { swift: "Int", kotlin: "Int", react: "number" },
283
+ Float: { swift: "CGFloat", kotlin: "Float", react: "number" },
284
+ Double: { swift: "Double", kotlin: "Double", react: "number" },
285
+ Bool: { swift: "Bool", kotlin: "Boolean", react: "boolean" },
286
+ Array: { swift: "[T]", kotlin: "List<T>", react: "T[]" },
287
+ Dictionary: {
288
+ swift: "[String: Any]",
289
+ kotlin: "Map<String, Any>",
290
+ react: "Record<string, any>",
291
+ },
292
+ },
293
+ };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { SpecLoader, mcpRootFromImportMetaUrl } from "./spec_loader.js";
5
+ import { ServerConfig } from "./config.js";
6
+ // --- Group A: Component Spec Lookup ---
7
+ import { register as registerLookupComponent } from "./tools/spec/lookup_component.js";
8
+ import { register as registerLookupAttribute } from "./tools/spec/lookup_attribute.js";
9
+ import { register as registerSearchComponents } from "./tools/spec/search_components.js";
10
+ import { register as registerGetModifierOrder } from "./tools/spec/get_modifier_order.js";
11
+ import { register as registerGetBindingRules } from "./tools/spec/get_binding_rules.js";
12
+ import { register as registerGetScreenIdentity } from "./tools/spec/get_screen_identity.js";
13
+ import { register as registerGetPlatformMapping } from "./tools/spec/get_platform_mapping.js";
14
+ import { register as registerGetDataSource } from "./tools/spec/get_data_source.js";
15
+ // --- Group B: Project Context ---
16
+ import { register as registerGetProjectConfig } from "./tools/context/get_project_config.js";
17
+ import { register as registerListScreenSpecs } from "./tools/context/list_screen_specs.js";
18
+ import { register as registerListComponentSpecs } from "./tools/context/list_component_specs.js";
19
+ import { register as registerListLayouts } from "./tools/context/list_layouts.js";
20
+ import { register as registerReadSpecFile } from "./tools/context/read_spec_file.js";
21
+ import { register as registerReadLayoutFile } from "./tools/context/read_layout_file.js";
22
+ // --- Group C: jui CLI ---
23
+ import { register as registerJuiInit } from "./tools/jui/jui_init.js";
24
+ import { register as registerJuiGenerateProject } from "./tools/jui/jui_generate_project.js";
25
+ import { register as registerJuiGenerateScreen } from "./tools/jui/jui_generate_screen.js";
26
+ import { register as registerJuiGenerateConverter } from "./tools/jui/jui_generate_converter.js";
27
+ import { register as registerJuiBuild } from "./tools/jui/jui_build.js";
28
+ import { register as registerJuiVerify } from "./tools/jui/jui_verify.js";
29
+ import { register as registerJuiMigrateLayouts } from "./tools/jui/jui_migrate_layouts.js";
30
+ import { register as registerJuiSyncTool } from "./tools/jui/jui_sync_tool.js";
31
+ // --- Group E: API Model Discovery ---
32
+ import { register as registerListApiSpecs } from "./tools/api/list_api_specs.js";
33
+ import { register as registerListApiModels } from "./tools/api/list_api_models.js";
34
+ import { register as registerPreviewApiModelSync } from "./tools/api/preview_api_model_sync.js";
35
+ // --- Group D: jsonui-doc CLI ---
36
+ import { register as registerDocInitSpec } from "./tools/doc/doc_init_spec.js";
37
+ import { register as registerDocInitComponent } from "./tools/doc/doc_init_component.js";
38
+ import { register as registerDocValidateSpec } from "./tools/doc/doc_validate_spec.js";
39
+ import { register as registerDocValidateComponent } from "./tools/doc/doc_validate_component.js";
40
+ import { register as registerDocGenerateSpec } from "./tools/doc/doc_generate_spec.js";
41
+ import { register as registerDocGenerateComponent } from "./tools/doc/doc_generate_component.js";
42
+ import { register as registerDocGenerateHtml } from "./tools/doc/doc_generate_html.js";
43
+ import { register as registerDocRulesInit } from "./tools/doc/doc_rules_init.js";
44
+ import { register as registerDocRulesShow } from "./tools/doc/doc_rules_show.js";
45
+ // --- Group F: jsonui-test CLI ---
46
+ import { register as registerTestValidate } from "./tools/test/test_validate.js";
47
+ import { register as registerTestGenerateScreen } from "./tools/test/test_generate_screen.js";
48
+ import { register as registerTestGenerateFlow } from "./tools/test/test_generate_flow.js";
49
+ import { register as registerTestGenerateDescription } from "./tools/test/test_generate_description.js";
50
+ import { register as registerTestReport } from "./tools/test/test_report.js";
51
+ import { register as registerTestMockGenerate } from "./tools/test/test_mock_generate.js";
52
+ import { register as registerTestArtifactsPull } from "./tools/test/test_artifacts_pull.js";
53
+ import { register as registerTestArtifactsStatus } from "./tools/test/test_artifacts_status.js";
54
+ function log(message) {
55
+ console.error(`[jui-tools] ${new Date().toISOString()} ${message}`);
56
+ }
57
+ log("Server starting...");
58
+ const server = new McpServer({
59
+ name: "jui-tools",
60
+ version: "2.0.0",
61
+ });
62
+ // Initialize spec loader for Group A
63
+ // Resolves attribute_definitions.json via 4-layer fallback:
64
+ // JSONUI_CLI_PATH env > ./.jsonui-cli/ > ~/.jsonui-cli/ > bundled snapshot in data/.
65
+ const mcpRoot = mcpRootFromImportMetaUrl(import.meta.url);
66
+ const loader = new SpecLoader(mcpRoot);
67
+ const source = loader.getDataSource();
68
+ log(`attribute_definitions: [${source.attributeDefinitions.layer}] ${source.attributeDefinitions.path} (${source.attributeDefinitions.freshness})`);
69
+ log(`component_metadata: [${source.componentMetadata.layer}] ${source.componentMetadata.path} (${source.componentMetadata.freshness})`);
70
+ log(`Loaded ${source.componentCount} components, ${source.commonAttributeCount} common attributes`);
71
+ // Initialize server config for Groups B/C/D
72
+ const config = new ServerConfig();
73
+ // Register Group A: Component Spec Lookup (7 tools)
74
+ registerLookupComponent(server, loader);
75
+ registerLookupAttribute(server, loader);
76
+ registerSearchComponents(server, loader);
77
+ registerGetModifierOrder(server, loader);
78
+ registerGetBindingRules(server, loader);
79
+ registerGetScreenIdentity(server, loader);
80
+ registerGetPlatformMapping(server, loader);
81
+ registerGetDataSource(server, loader);
82
+ // Register Group B: Project Context (6 tools)
83
+ registerGetProjectConfig(server, config);
84
+ registerListScreenSpecs(server, config);
85
+ registerListComponentSpecs(server, config);
86
+ registerListLayouts(server, config);
87
+ registerReadSpecFile(server, config);
88
+ registerReadLayoutFile(server, config);
89
+ // Register Group C: jui CLI (8 tools)
90
+ registerJuiInit(server, config);
91
+ registerJuiGenerateProject(server, config);
92
+ registerJuiGenerateScreen(server, config);
93
+ registerJuiGenerateConverter(server, config);
94
+ registerJuiBuild(server, config);
95
+ registerJuiVerify(server, config);
96
+ registerJuiMigrateLayouts(server, config);
97
+ registerJuiSyncTool(server, config);
98
+ // Register Group D: jsonui-doc CLI (9 tools)
99
+ registerDocInitSpec(server, config);
100
+ registerDocInitComponent(server, config);
101
+ registerDocValidateSpec(server, config);
102
+ registerDocValidateComponent(server, config);
103
+ registerDocGenerateSpec(server, config);
104
+ registerDocGenerateComponent(server, config);
105
+ registerDocGenerateHtml(server, config);
106
+ registerDocRulesInit(server, config);
107
+ registerDocRulesShow(server, config);
108
+ // Register Group E: API Model Discovery (3 tools)
109
+ registerListApiSpecs(server, config);
110
+ registerListApiModels(server, config);
111
+ registerPreviewApiModelSync(server, config);
112
+ // Register Group F: jsonui-test CLI (8 tools)
113
+ // mock serve is intentionally NOT exposed (long-running local HTTP server that
114
+ // executes run-targets — kept to direct CLI use only). test_mock_generate
115
+ // covers both scaffold (default) and drift-check (check=true) modes.
116
+ registerTestValidate(server, config);
117
+ registerTestGenerateScreen(server, config);
118
+ registerTestGenerateFlow(server, config);
119
+ registerTestGenerateDescription(server, config);
120
+ registerTestReport(server, config);
121
+ registerTestMockGenerate(server, config);
122
+ registerTestArtifactsPull(server, config);
123
+ registerTestArtifactsStatus(server, config);
124
+ log(`Registered 41 tools (7 spec + 6 context + 8 jui + 9 doc + 3 api + 8 test)`);
125
+ async function main() {
126
+ const transport = new StdioServerTransport();
127
+ await server.connect(transport);
128
+ log("Server connected and ready.");
129
+ }
130
+ main().catch(console.error);