@sberbusiness/triplex-next-mcp-server 0.24.0-beta1

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 (140) hide show
  1. package/README.md +124 -0
  2. package/bundle/.gitkeep +0 -0
  3. package/bundle/components/AbstractTree.md +198 -0
  4. package/bundle/components/AccordionBase.md +227 -0
  5. package/bundle/components/Alert.md +317 -0
  6. package/bundle/components/Amount.md +225 -0
  7. package/bundle/components/AmountField.md +289 -0
  8. package/bundle/components/Avatar.md +209 -0
  9. package/bundle/components/Badge.md +277 -0
  10. package/bundle/components/Body.md +167 -0
  11. package/bundle/components/Button.md +230 -0
  12. package/bundle/components/ButtonDropdown.md +159 -0
  13. package/bundle/components/ButtonIcon.md +122 -0
  14. package/bundle/components/Calendar.md +445 -0
  15. package/bundle/components/Card.md +374 -0
  16. package/bundle/components/CarouselExtended.md +250 -0
  17. package/bundle/components/Checkbox.md +126 -0
  18. package/bundle/components/CheckboxTree.md +280 -0
  19. package/bundle/components/CheckboxTreeExtended.md +321 -0
  20. package/bundle/components/CheckboxXGroup.md +68 -0
  21. package/bundle/components/CheckboxYGroup.md +67 -0
  22. package/bundle/components/Chip.md +404 -0
  23. package/bundle/components/ChipGroup.md +179 -0
  24. package/bundle/components/Col.md +221 -0
  25. package/bundle/components/CollapsableTree.md +255 -0
  26. package/bundle/components/Confirm.md +343 -0
  27. package/bundle/components/DateField.md +371 -0
  28. package/bundle/components/DatePickerExtended.md +342 -0
  29. package/bundle/components/DateRange.md +275 -0
  30. package/bundle/components/DesignTokens.md +385 -0
  31. package/bundle/components/Divider.md +196 -0
  32. package/bundle/components/DocumentNumberEdit.md +280 -0
  33. package/bundle/components/Dropdown.md +433 -0
  34. package/bundle/components/Ellipsis.md +208 -0
  35. package/bundle/components/EmptyView.md +99 -0
  36. package/bundle/components/ExpandAnimation.md +281 -0
  37. package/bundle/components/Footer.md +339 -0
  38. package/bundle/components/FormField.md +326 -0
  39. package/bundle/components/FormGroup.md +99 -0
  40. package/bundle/components/Gap.md +113 -0
  41. package/bundle/components/Header.md +280 -0
  42. package/bundle/components/HelpBox.md +154 -0
  43. package/bundle/components/IconWrapper.md +145 -0
  44. package/bundle/components/Island.md +197 -0
  45. package/bundle/components/IslandAccordion.md +230 -0
  46. package/bundle/components/IslandWidget.md +233 -0
  47. package/bundle/components/KeyDownListener.md +157 -0
  48. package/bundle/components/LightBox.md +322 -0
  49. package/bundle/components/Link.md +161 -0
  50. package/bundle/components/List.md +247 -0
  51. package/bundle/components/ListMaster.md +204 -0
  52. package/bundle/components/Loader.md +161 -0
  53. package/bundle/components/LoaderScreen.md +134 -0
  54. package/bundle/components/Marker.md +127 -0
  55. package/bundle/components/MarkerStatus.md +148 -0
  56. package/bundle/components/MediaWidth.md +169 -0
  57. package/bundle/components/MobileView.md +120 -0
  58. package/bundle/components/ModalWindow.md +308 -0
  59. package/bundle/components/MonthYearField.md +168 -0
  60. package/bundle/components/MultiselectField.md +213 -0
  61. package/bundle/components/Notification.md +233 -0
  62. package/bundle/components/NumberField.md +178 -0
  63. package/bundle/components/OrderedList.md +169 -0
  64. package/bundle/components/Overlay.md +237 -0
  65. package/bundle/components/Page.md +246 -0
  66. package/bundle/components/Pagination.md +298 -0
  67. package/bundle/components/Portal.md +119 -0
  68. package/bundle/components/Radio.md +174 -0
  69. package/bundle/components/Row.md +125 -0
  70. package/bundle/components/SMSField.md +160 -0
  71. package/bundle/components/SegmentedControl.md +235 -0
  72. package/bundle/components/SelectExtendedField.md +322 -0
  73. package/bundle/components/SelectField.md +213 -0
  74. package/bundle/components/Skeleton.md +129 -0
  75. package/bundle/components/Slider.md +157 -0
  76. package/bundle/components/SliderExtended.md +210 -0
  77. package/bundle/components/SliderRange.md +160 -0
  78. package/bundle/components/SmallInput.md +101 -0
  79. package/bundle/components/Spoiler.md +121 -0
  80. package/bundle/components/StatusTracker.md +151 -0
  81. package/bundle/components/Step.md +121 -0
  82. package/bundle/components/Stepper.md +163 -0
  83. package/bundle/components/Suggest.md +160 -0
  84. package/bundle/components/SuggestField.md +157 -0
  85. package/bundle/components/SwipeableArea.md +144 -0
  86. package/bundle/components/Table.md +199 -0
  87. package/bundle/components/Tabs.md +152 -0
  88. package/bundle/components/TabsExtended.md +273 -0
  89. package/bundle/components/TabsLine.md +189 -0
  90. package/bundle/components/Tag.md +135 -0
  91. package/bundle/components/TagColor.md +121 -0
  92. package/bundle/components/TagGroup.md +100 -0
  93. package/bundle/components/TextField.md +152 -0
  94. package/bundle/components/TextareaField.md +124 -0
  95. package/bundle/components/ThemeProvider.md +181 -0
  96. package/bundle/components/Tooltip.md +254 -0
  97. package/bundle/components/TopOverlay.md +145 -0
  98. package/bundle/components/TreeView.md +224 -0
  99. package/bundle/components/Triggers.md +121 -0
  100. package/bundle/guides/codestyle.md +205 -0
  101. package/bundle/guides/commits.md +166 -0
  102. package/bundle/guides/context.md +277 -0
  103. package/bundle/guides/stories.md +618 -0
  104. package/bundle/guides/template.md +154 -0
  105. package/bundle/guides/tests.md +301 -0
  106. package/bundle/icons.json +4156 -0
  107. package/bundle/manifest.json +796 -0
  108. package/bundle/release-notes/1.1.0.mdx +26 -0
  109. package/bundle/release-notes/1.1.1.mdx +14 -0
  110. package/bundle/release-notes/1.10.0.mdx +43 -0
  111. package/bundle/release-notes/1.11.0.mdx +19 -0
  112. package/bundle/release-notes/1.12.0.mdx +21 -0
  113. package/bundle/release-notes/1.13.0.mdx +43 -0
  114. package/bundle/release-notes/1.14.0.mdx +29 -0
  115. package/bundle/release-notes/1.15.0.mdx +56 -0
  116. package/bundle/release-notes/1.16.0.mdx +55 -0
  117. package/bundle/release-notes/1.17.0.mdx +15 -0
  118. package/bundle/release-notes/1.18.0.mdx +24 -0
  119. package/bundle/release-notes/1.19.0.mdx +48 -0
  120. package/bundle/release-notes/1.19.1.mdx +9 -0
  121. package/bundle/release-notes/1.2.0.mdx +80 -0
  122. package/bundle/release-notes/1.20.0.mdx +48 -0
  123. package/bundle/release-notes/1.21.0.mdx +66 -0
  124. package/bundle/release-notes/1.22.0.mdx +75 -0
  125. package/bundle/release-notes/1.23.0.mdx +50 -0
  126. package/bundle/release-notes/1.24.0.mdx +59 -0
  127. package/bundle/release-notes/1.25.0.mdx +52 -0
  128. package/bundle/release-notes/1.26.0.mdx +11 -0
  129. package/bundle/release-notes/1.3.0.mdx +21 -0
  130. package/bundle/release-notes/1.4.0.mdx +37 -0
  131. package/bundle/release-notes/1.5.0.mdx +24 -0
  132. package/bundle/release-notes/1.6.0.mdx +37 -0
  133. package/bundle/release-notes/1.6.1.mdx +11 -0
  134. package/bundle/release-notes/1.7.0.mdx +29 -0
  135. package/bundle/release-notes/1.8.0.mdx +38 -0
  136. package/bundle/release-notes/1.9.0.mdx +28 -0
  137. package/dist/index.d.ts +2 -0
  138. package/dist/index.js +324 -0
  139. package/dist/index.js.map +1 -0
  140. package/package.json +51 -0
package/dist/index.js ADDED
@@ -0,0 +1,324 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+
6
+ // src/server.ts
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+
9
+ // src/tools/index.ts
10
+ import { z } from "zod";
11
+
12
+ // src/parsers/loader.ts
13
+ import { existsSync, readFileSync } from "fs";
14
+ import { dirname, resolve } from "path";
15
+ import { fileURLToPath } from "url";
16
+
17
+ // src/parsers/parseComponent.ts
18
+ import matter from "gray-matter";
19
+ var SECTION_HEADING_RE = /^##\s+(.+?)\s*$/;
20
+ function parseComponent(raw) {
21
+ if (raw.raw === null) {
22
+ const fallback = raw.fallback ?? { name: raw.name, storiesPath: null };
23
+ return {
24
+ name: raw.name,
25
+ path: raw.path,
26
+ ai_ready: false,
27
+ category: null,
28
+ description: null,
29
+ figma: { file: null, node: null },
30
+ related: [],
31
+ tokens: [],
32
+ stories: fallback.storiesPath,
33
+ sections: {},
34
+ markdown: null
35
+ };
36
+ }
37
+ const parsed = matter(raw.raw);
38
+ const fm = parsed.data;
39
+ const body = parsed.content;
40
+ const sections = extractSections(body);
41
+ return {
42
+ name: raw.name,
43
+ path: raw.path,
44
+ ai_ready: true,
45
+ category: fm.category ?? null,
46
+ description: extractDescription(sections),
47
+ figma: {
48
+ file: nonEmpty(fm["figma-file"]),
49
+ node: nonEmpty(fm["figma-node"])
50
+ },
51
+ related: Array.isArray(fm.related) ? fm.related : [],
52
+ tokens: Array.isArray(fm.tokens) ? fm.tokens : [],
53
+ stories: fm.stories ?? null,
54
+ sections,
55
+ markdown: body
56
+ };
57
+ }
58
+ function extractSections(body) {
59
+ const sections = {};
60
+ let currentTitle = null;
61
+ let buffer = [];
62
+ const flush = () => {
63
+ if (currentTitle !== null) {
64
+ sections[currentTitle] = buffer.join("\n").trim();
65
+ }
66
+ };
67
+ for (const line of body.split("\n")) {
68
+ const match = SECTION_HEADING_RE.exec(line);
69
+ if (match) {
70
+ flush();
71
+ currentTitle = match[1];
72
+ buffer = [];
73
+ } else if (currentTitle !== null) {
74
+ buffer.push(line);
75
+ }
76
+ }
77
+ flush();
78
+ return sections;
79
+ }
80
+ function extractDescription(sections) {
81
+ const purpose = sections["\u041D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435"];
82
+ if (!purpose) {
83
+ return null;
84
+ }
85
+ const firstParagraph = purpose.split(/\n\s*\n/).map((p) => p.trim()).find((p) => p.length > 0);
86
+ return firstParagraph ?? null;
87
+ }
88
+ function nonEmpty(value) {
89
+ if (typeof value !== "string") {
90
+ return null;
91
+ }
92
+ const trimmed = value.trim();
93
+ return trimmed.length > 0 ? trimmed : null;
94
+ }
95
+
96
+ // src/parsers/loader.ts
97
+ var EMPTY_BUNDLE = {
98
+ schemaVersion: 1,
99
+ triplexVersion: "0.0.0",
100
+ generatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
101
+ components: [],
102
+ guides: [],
103
+ releaseNotes: []
104
+ };
105
+ var EMPTY_ICONS = {
106
+ schemaVersion: 1,
107
+ packageName: "@sberbusiness/icons-next",
108
+ packageVersion: "0.0.0",
109
+ generatedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
110
+ icons: []
111
+ };
112
+ function findPackageRoot(startDir) {
113
+ let dir = startDir;
114
+ while (dir !== dirname(dir)) {
115
+ if (existsSync(resolve(dir, "package.json"))) {
116
+ return dir;
117
+ }
118
+ dir = dirname(dir);
119
+ }
120
+ throw new Error(`package.json not found above ${startDir}`);
121
+ }
122
+ var PACKAGE_ROOT = findPackageRoot(dirname(fileURLToPath(import.meta.url)));
123
+ var BUNDLE_DIR = resolve(PACKAGE_ROOT, "bundle");
124
+ var MANIFEST_PATH = resolve(BUNDLE_DIR, "manifest.json");
125
+ var ICONS_PATH = resolve(BUNDLE_DIR, "icons.json");
126
+ function loadIcons() {
127
+ try {
128
+ return JSON.parse(readFileSync(ICONS_PATH, "utf-8"));
129
+ } catch {
130
+ console.error(`Failed to load icons from ${ICONS_PATH}. Run 'npm run fetch-icons' first.`);
131
+ return EMPTY_ICONS;
132
+ }
133
+ }
134
+ function loadBundle() {
135
+ let manifest;
136
+ try {
137
+ manifest = JSON.parse(readFileSync(MANIFEST_PATH, "utf-8"));
138
+ } catch {
139
+ console.error(
140
+ `Failed to load manifest from ${MANIFEST_PATH}. Run 'npm run fetch-bundle' first.`
141
+ );
142
+ return EMPTY_BUNDLE;
143
+ }
144
+ return {
145
+ schemaVersion: manifest.schemaVersion,
146
+ triplexVersion: manifest.triplexVersion,
147
+ generatedAt: manifest.generatedAt,
148
+ components: manifest.components.map((mc) => {
149
+ const raw = mc.file !== null ? {
150
+ name: mc.name,
151
+ path: mc.path,
152
+ raw: readFileSync(resolve(BUNDLE_DIR, mc.file), "utf-8"),
153
+ fallback: null
154
+ } : {
155
+ name: mc.name,
156
+ path: mc.path,
157
+ raw: null,
158
+ fallback: {
159
+ name: mc.name,
160
+ storiesPath: mc.storiesPath ?? null
161
+ }
162
+ };
163
+ return parseComponent(raw);
164
+ }),
165
+ guides: manifest.guides.map((g) => ({
166
+ topic: g.topic,
167
+ path: g.path,
168
+ raw: readFileSync(resolve(BUNDLE_DIR, g.file), "utf-8")
169
+ })),
170
+ releaseNotes: manifest.releaseNotes.map((n) => ({
171
+ version: n.version,
172
+ path: n.path,
173
+ raw: readFileSync(resolve(BUNDLE_DIR, n.file), "utf-8")
174
+ }))
175
+ };
176
+ }
177
+
178
+ // src/tools/index.ts
179
+ function registerTools(server) {
180
+ const bundle = loadBundle();
181
+ const icons = loadIcons();
182
+ const availableIconSizes = Array.from(new Set(icons.icons.map((i) => i.size))).sort(
183
+ (a, b) => a - b
184
+ );
185
+ server.tool(
186
+ "list_components",
187
+ "\u0421\u043F\u0438\u0441\u043E\u043A \u0432\u0441\u0435\u0445 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432 \u0434\u0438\u0437\u0430\u0439\u043D-\u0441\u0438\u0441\u0442\u0435\u043C\u044B Triplex \u0441 \u043A\u0440\u0430\u0442\u043A\u0438\u043C \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435\u043C \u0438 \u0444\u043B\u0430\u0433\u043E\u043C ai_ready.",
188
+ {},
189
+ async () => {
190
+ const list = bundle.components.map((c) => ({
191
+ name: c.name,
192
+ description: c.description,
193
+ category: c.category,
194
+ ai_ready: c.ai_ready
195
+ }));
196
+ return {
197
+ content: [{ type: "text", text: JSON.stringify(list, null, 2) }]
198
+ };
199
+ }
200
+ );
201
+ server.tool(
202
+ "get_component",
203
+ "\u041F\u043E\u043B\u043D\u0430\u044F \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0430\u0446\u0438\u044F \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430: \u043D\u0430\u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0435, props, \u0442\u043E\u043A\u0435\u043D\u044B, \u0438\u043D\u0432\u0430\u0440\u0438\u0430\u043D\u0442\u044B, accessibility, \u0441\u0435\u043A\u0446\u0438\u0438 AI.md.",
204
+ { name: z.string().describe("\u0418\u043C\u044F \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430, \u043D\u0430\u043F\u0440\u0438\u043C\u0435\u0440 'Button'") },
205
+ async ({ name }) => {
206
+ const component = bundle.components.find((c) => c.name.toLowerCase() === name.toLowerCase());
207
+ if (!component) {
208
+ return {
209
+ content: [
210
+ {
211
+ type: "text",
212
+ text: `\u041A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442 "${name}" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D. \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439\u0442\u0435 list_components \u0434\u043B\u044F \u0441\u043F\u0438\u0441\u043A\u0430 \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u043E\u0432.`
213
+ }
214
+ ],
215
+ isError: true
216
+ };
217
+ }
218
+ return {
219
+ content: [{ type: "text", text: JSON.stringify(component, null, 2) }]
220
+ };
221
+ }
222
+ );
223
+ server.tool(
224
+ "get_tokens",
225
+ "\u0414\u0438\u0437\u0430\u0439\u043D-\u0442\u043E\u043A\u0435\u043D\u044B: CSS-\u043F\u0435\u0440\u0435\u043C\u0435\u043D\u043D\u044B\u0435 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430 \u0438\u043B\u0438 \u0441\u043F\u0438\u0441\u043E\u043A \u0432\u0441\u0435\u0445 \u0442\u043E\u043A\u0435\u043D\u043E\u0432 \u0414\u0421.",
226
+ {
227
+ component: z.string().optional().describe("\u0418\u043C\u044F \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442\u0430 \u0434\u043B\u044F \u0444\u0438\u043B\u044C\u0442\u0440\u0430\u0446\u0438\u0438 \u0442\u043E\u043A\u0435\u043D\u043E\u0432. \u0415\u0441\u043B\u0438 \u043D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D\u043E \u2014 \u0432\u0441\u0435 \u0442\u043E\u043A\u0435\u043D\u044B.")
228
+ },
229
+ async ({ component }) => {
230
+ if (component) {
231
+ const comp = bundle.components.find(
232
+ (c) => c.name.toLowerCase() === component.toLowerCase()
233
+ );
234
+ if (!comp) {
235
+ return {
236
+ content: [
237
+ {
238
+ type: "text",
239
+ text: `\u041A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442 "${component}" \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D.`
240
+ }
241
+ ],
242
+ isError: true
243
+ };
244
+ }
245
+ return {
246
+ content: [{ type: "text", text: JSON.stringify(comp.tokens, null, 2) }]
247
+ };
248
+ }
249
+ const allTokens = bundle.components.filter((c) => c.tokens.length > 0).map((c) => ({ component: c.name, tokens: c.tokens }));
250
+ return {
251
+ content: [{ type: "text", text: JSON.stringify(allTokens, null, 2) }]
252
+ };
253
+ }
254
+ );
255
+ server.tool(
256
+ "list_icons",
257
+ "\u0421\u043F\u0438\u0441\u043E\u043A \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u0438\u043A\u043E\u043D\u043E\u043A \u0438\u0437 @sberbusiness/icons-next. \u0418\u0441\u043F\u043E\u043B\u044C\u0437\u0443\u0439 \u043F\u0435\u0440\u0435\u0434 \u0442\u0435\u043C \u043A\u0430\u043A \u0438\u043C\u043F\u043E\u0440\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0438\u043A\u043E\u043D\u043A\u0443, \u0447\u0442\u043E\u0431\u044B \u043D\u0435 \u043F\u0440\u0438\u0434\u0443\u043C\u0430\u0442\u044C \u043D\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044E\u0449\u0435\u0435 \u0438\u043C\u044F. \u0424\u0438\u043B\u044C\u0442\u0440\u0430\u0446\u0438\u044F \u043F\u043E \u043F\u043E\u0434\u0441\u0442\u0440\u043E\u043A\u0435 \u0432 \u0438\u043C\u0435\u043D\u0438 \u0438 \u043F\u043E \u0440\u0430\u0437\u043C\u0435\u0440\u0443.",
258
+ {
259
+ query: z.string().optional().describe(
260
+ "\u041F\u043E\u0434\u0441\u0442\u0440\u043E\u043A\u0430 \u0434\u043B\u044F \u043F\u043E\u0438\u0441\u043A\u0430 \u0432 \u0438\u043C\u0435\u043D\u0438 \u0438\u043A\u043E\u043D\u043A\u0438 (\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043E\u043D\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043C\u0430\u044F). \u041D\u0430\u043F\u0440. 'plus' \u0438\u043B\u0438 'arrow'."
261
+ ),
262
+ size: z.number().int().positive().optional().describe("\u0420\u0430\u0437\u043C\u0435\u0440 \u0438\u043A\u043E\u043D\u043A\u0438 \u0432 px (\u0441\u043C. availableSizes \u0432 \u043E\u0442\u0432\u0435\u0442\u0435 \u0434\u043B\u044F \u0434\u043E\u0441\u0442\u0443\u043F\u043D\u044B\u0445 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439)."),
263
+ limit: z.number().int().positive().max(500).optional().describe("\u041C\u0430\u043A\u0441\u0438\u043C\u0443\u043C \u0438\u043A\u043E\u043D\u043E\u043A \u0432 \u043E\u0442\u0432\u0435\u0442\u0435. \u041F\u043E \u0443\u043C\u043E\u043B\u0447\u0430\u043D\u0438\u044E 100.")
264
+ },
265
+ async ({ query, size, limit }) => {
266
+ if (icons.icons.length === 0) {
267
+ return {
268
+ content: [
269
+ {
270
+ type: "text",
271
+ text: "\u0421\u043F\u0438\u0441\u043E\u043A \u0438\u043A\u043E\u043D\u043E\u043A \u043F\u0443\u0441\u0442 \u2014 \u0441\u0435\u0440\u0432\u0435\u0440 \u043D\u0435 \u0441\u043C\u043E\u0433 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C bundle/icons.json. \u041F\u0440\u043E\u0432\u0435\u0440\u044C, \u0447\u0442\u043E 'npm run fetch-icons' \u043E\u0442\u0440\u0430\u0431\u043E\u0442\u0430\u043B \u043D\u0430 \u044D\u0442\u0430\u043F\u0435 \u0441\u0431\u043E\u0440\u043A\u0438."
272
+ }
273
+ ],
274
+ isError: true
275
+ };
276
+ }
277
+ const needle = query?.trim().toLowerCase() ?? "";
278
+ const max = limit ?? 100;
279
+ const matched = icons.icons.filter((ic) => {
280
+ if (size !== void 0 && ic.size !== size) return false;
281
+ if (needle && !ic.name.toLowerCase().includes(needle)) return false;
282
+ return true;
283
+ });
284
+ const truncated = matched.length > max;
285
+ const page = truncated ? matched.slice(0, max) : matched;
286
+ const payload = {
287
+ package: `${icons.packageName}@${icons.packageVersion}`,
288
+ totalInBundle: icons.icons.length,
289
+ matched: matched.length,
290
+ returned: page.length,
291
+ truncated,
292
+ availableSizes: availableIconSizes,
293
+ icons: page,
294
+ usage: "import { IconName } from '@sberbusiness/icons-next'; <IconName />"
295
+ };
296
+ return {
297
+ content: [{ type: "text", text: JSON.stringify(payload, null, 2) }]
298
+ };
299
+ }
300
+ );
301
+ }
302
+
303
+ // src/server.ts
304
+ function createServer() {
305
+ const server = new McpServer({
306
+ name: "triplex",
307
+ version: "0.1.0"
308
+ });
309
+ registerTools(server);
310
+ return server;
311
+ }
312
+
313
+ // src/index.ts
314
+ async function main() {
315
+ const server = createServer();
316
+ const transport = new StdioServerTransport();
317
+ await server.connect(transport);
318
+ console.error("Triplex MCP Server started");
319
+ }
320
+ main().catch((error) => {
321
+ console.error("Failed to start server:", error);
322
+ process.exit(1);
323
+ });
324
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/tools/index.ts","../src/parsers/loader.ts","../src/parsers/parseComponent.ts"],"sourcesContent":["import { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { createServer } from \"./server.js\";\n\nasync function main() {\n const server = createServer();\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error(\"Triplex MCP Server started\");\n}\n\nmain().catch((error) => {\n console.error(\"Failed to start server:\", error);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { registerTools } from \"./tools/index.js\";\n\nexport function createServer(): McpServer {\n const server = new McpServer({\n name: \"triplex\",\n version: \"0.1.0\",\n });\n\n registerTools(server);\n\n return server;\n}\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { loadBundle, loadIcons } from \"../parsers/loader.js\";\n\nexport function registerTools(server: McpServer): void {\n const bundle = loadBundle();\n const icons = loadIcons();\n const availableIconSizes = Array.from(new Set(icons.icons.map((i) => i.size))).sort(\n (a, b) => a - b,\n );\n\n server.tool(\n \"list_components\",\n \"Список всех компонентов дизайн-системы Triplex с кратким описанием и флагом ai_ready.\",\n {},\n async () => {\n const list = bundle.components.map((c) => ({\n name: c.name,\n description: c.description,\n category: c.category,\n ai_ready: c.ai_ready,\n }));\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(list, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"get_component\",\n \"Полная документация компонента: назначение, props, токены, инварианты, accessibility, секции AI.md.\",\n { name: z.string().describe(\"Имя компонента, например 'Button'\") },\n async ({ name }) => {\n const component = bundle.components.find((c) => c.name.toLowerCase() === name.toLowerCase());\n\n if (!component) {\n return {\n content: [\n {\n type: \"text\",\n text: `Компонент \"${name}\" не найден. Используйте list_components для списка доступных компонентов.`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(component, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"get_tokens\",\n \"Дизайн-токены: CSS-переменные компонента или список всех токенов ДС.\",\n {\n component: z\n .string()\n .optional()\n .describe(\"Имя компонента для фильтрации токенов. Если не указано — все токены.\"),\n },\n async ({ component }) => {\n if (component) {\n const comp = bundle.components.find(\n (c) => c.name.toLowerCase() === component.toLowerCase(),\n );\n\n if (!comp) {\n return {\n content: [\n {\n type: \"text\",\n text: `Компонент \"${component}\" не найден.`,\n },\n ],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(comp.tokens, null, 2) }],\n };\n }\n\n const allTokens = bundle.components\n .filter((c) => c.tokens.length > 0)\n .map((c) => ({ component: c.name, tokens: c.tokens }));\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(allTokens, null, 2) }],\n };\n },\n );\n\n server.tool(\n \"list_icons\",\n \"Список доступных иконок из @sberbusiness/icons-next. Используй перед тем как импортировать иконку, чтобы не придумать несуществующее имя. Фильтрация по подстроке в имени и по размеру.\",\n {\n query: z\n .string()\n .optional()\n .describe(\n \"Подстрока для поиска в имени иконки (регистронезависимая). Напр. 'plus' или 'arrow'.\",\n ),\n size: z\n .number()\n .int()\n .positive()\n .optional()\n .describe(\"Размер иконки в px (см. availableSizes в ответе для доступных значений).\"),\n limit: z\n .number()\n .int()\n .positive()\n .max(500)\n .optional()\n .describe(\"Максимум иконок в ответе. По умолчанию 100.\"),\n },\n async ({ query, size, limit }) => {\n if (icons.icons.length === 0) {\n return {\n content: [\n {\n type: \"text\",\n text: \"Список иконок пуст — сервер не смог загрузить bundle/icons.json. Проверь, что 'npm run fetch-icons' отработал на этапе сборки.\",\n },\n ],\n isError: true,\n };\n }\n\n const needle = query?.trim().toLowerCase() ?? \"\";\n const max = limit ?? 100;\n\n const matched = icons.icons.filter((ic) => {\n if (size !== undefined && ic.size !== size) return false;\n if (needle && !ic.name.toLowerCase().includes(needle)) return false;\n return true;\n });\n\n const truncated = matched.length > max;\n const page = truncated ? matched.slice(0, max) : matched;\n\n const payload = {\n package: `${icons.packageName}@${icons.packageVersion}`,\n totalInBundle: icons.icons.length,\n matched: matched.length,\n returned: page.length,\n truncated,\n availableSizes: availableIconSizes,\n icons: page,\n usage: \"import { IconName } from '@sberbusiness/icons-next'; <IconName />\",\n };\n\n return {\n content: [{ type: \"text\", text: JSON.stringify(payload, null, 2) }],\n };\n },\n );\n}\n","import { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { IconsBundle, Manifest, ParsedBundle, RawComponent } from \"../types/index.js\";\nimport { parseComponent } from \"./parseComponent.js\";\n\nconst EMPTY_BUNDLE: ParsedBundle = {\n schemaVersion: 1,\n triplexVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n components: [],\n guides: [],\n releaseNotes: [],\n};\n\nconst EMPTY_ICONS: IconsBundle = {\n schemaVersion: 1,\n packageName: \"@sberbusiness/icons-next\",\n packageVersion: \"0.0.0\",\n generatedAt: new Date(0).toISOString(),\n icons: [],\n};\n\n/**\n * Tsup bundles всю source в `dist/index.js`, поэтому относительный путь\n * src/parsers/loader.ts → bundle/... не совпадает с runtime-путём.\n * Идём вверх до ближайшего `package.json` — так корень пакета находится\n * и в dev (tsx/vitest из src/), и в prod (bundled dist/), и после npm-install.\n */\nfunction findPackageRoot(startDir: string): string {\n let dir = startDir;\n while (dir !== dirname(dir)) {\n if (existsSync(resolve(dir, \"package.json\"))) {\n return dir;\n }\n dir = dirname(dir);\n }\n throw new Error(`package.json not found above ${startDir}`);\n}\n\nconst PACKAGE_ROOT = findPackageRoot(dirname(fileURLToPath(import.meta.url)));\nconst BUNDLE_DIR = resolve(PACKAGE_ROOT, \"bundle\");\nconst MANIFEST_PATH = resolve(BUNDLE_DIR, \"manifest.json\");\nconst ICONS_PATH = resolve(BUNDLE_DIR, \"icons.json\");\n\nexport function loadIcons(): IconsBundle {\n try {\n return JSON.parse(readFileSync(ICONS_PATH, \"utf-8\")) as IconsBundle;\n } catch {\n console.error(`Failed to load icons from ${ICONS_PATH}. Run 'npm run fetch-icons' first.`);\n return EMPTY_ICONS;\n }\n}\n\nexport function loadBundle(): ParsedBundle {\n let manifest: Manifest;\n try {\n manifest = JSON.parse(readFileSync(MANIFEST_PATH, \"utf-8\")) as Manifest;\n } catch {\n console.error(\n `Failed to load manifest from ${MANIFEST_PATH}. Run 'npm run fetch-bundle' first.`,\n );\n return EMPTY_BUNDLE;\n }\n\n return {\n schemaVersion: manifest.schemaVersion,\n triplexVersion: manifest.triplexVersion,\n generatedAt: manifest.generatedAt,\n components: manifest.components.map((mc) => {\n const raw: RawComponent =\n mc.file !== null\n ? {\n name: mc.name,\n path: mc.path,\n raw: readFileSync(resolve(BUNDLE_DIR, mc.file), \"utf-8\"),\n fallback: null,\n }\n : {\n name: mc.name,\n path: mc.path,\n raw: null,\n fallback: {\n name: mc.name,\n storiesPath: mc.storiesPath ?? null,\n },\n };\n return parseComponent(raw);\n }),\n guides: manifest.guides.map((g) => ({\n topic: g.topic,\n path: g.path,\n raw: readFileSync(resolve(BUNDLE_DIR, g.file), \"utf-8\"),\n })),\n releaseNotes: manifest.releaseNotes.map((n) => ({\n version: n.version,\n path: n.path,\n raw: readFileSync(resolve(BUNDLE_DIR, n.file), \"utf-8\"),\n })),\n };\n}\n","import matter from \"gray-matter\";\nimport type { ComponentFrontmatter, ParsedComponent, RawComponent } from \"../types/index.js\";\n\nconst SECTION_HEADING_RE = /^##\\s+(.+?)\\s*$/;\n\nexport function parseComponent(raw: RawComponent): ParsedComponent {\n if (raw.raw === null) {\n const fallback = raw.fallback ?? { name: raw.name, storiesPath: null };\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: false,\n category: null,\n description: null,\n figma: { file: null, node: null },\n related: [],\n tokens: [],\n stories: fallback.storiesPath,\n sections: {},\n markdown: null,\n };\n }\n\n const parsed = matter(raw.raw);\n const fm = parsed.data as ComponentFrontmatter;\n const body = parsed.content;\n const sections = extractSections(body);\n\n return {\n name: raw.name,\n path: raw.path,\n ai_ready: true,\n category: fm.category ?? null,\n description: extractDescription(sections),\n figma: {\n file: nonEmpty(fm[\"figma-file\"]),\n node: nonEmpty(fm[\"figma-node\"]),\n },\n related: Array.isArray(fm.related) ? fm.related : [],\n tokens: Array.isArray(fm.tokens) ? fm.tokens : [],\n stories: fm.stories ?? null,\n sections,\n markdown: body,\n };\n}\n\nfunction extractSections(body: string): Record<string, string> {\n const sections: Record<string, string> = {};\n let currentTitle: string | null = null;\n let buffer: string[] = [];\n\n const flush = () => {\n if (currentTitle !== null) {\n sections[currentTitle] = buffer.join(\"\\n\").trim();\n }\n };\n\n for (const line of body.split(\"\\n\")) {\n const match = SECTION_HEADING_RE.exec(line);\n if (match) {\n flush();\n currentTitle = match[1];\n buffer = [];\n } else if (currentTitle !== null) {\n buffer.push(line);\n }\n }\n flush();\n return sections;\n}\n\nfunction extractDescription(sections: Record<string, string>): string | null {\n const purpose = sections[\"Назначение\"];\n if (!purpose) {\n return null;\n }\n const firstParagraph = purpose\n .split(/\\n\\s*\\n/)\n .map((p) => p.trim())\n .find((p) => p.length > 0);\n return firstParagraph ?? null;\n}\n\nfunction nonEmpty(value: string | undefined): string | null {\n if (typeof value !== \"string\") {\n return null;\n }\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n"],"mappings":"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","names":[]}
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "@sberbusiness/triplex-next-mcp-server",
3
+ "version": "0.24.0-beta1",
4
+ "description": "MCP-сервер для дизайн-системы Triplex. Предоставляет AI-агентам документацию компонентов, дизайн-токены и примеры использования.",
5
+ "author": "СберБизнес",
6
+ "license": "MIT",
7
+ "type": "module",
8
+ "bin": {
9
+ "triplex-mcp-server": "./dist/index.js"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
13
+ "files": [
14
+ "dist",
15
+ "bundle"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsup",
19
+ "dev": "tsup --watch",
20
+ "start": "node dist/index.js",
21
+ "fetch-bundle": "tsx scripts/fetch-bundle.ts",
22
+ "fetch-icons": "tsx scripts/fetch-icons.ts",
23
+ "inspect": "npx @modelcontextprotocol/inspector node dist/index.js",
24
+ "typecheck": "tsc --noEmit",
25
+ "lint": "eslint src/",
26
+ "format": "prettier --write .",
27
+ "format:check": "prettier --check .",
28
+ "check": "tsc --noEmit && eslint src/ && prettier --check . && vitest run",
29
+ "test": "vitest run",
30
+ "test:watch": "vitest"
31
+ },
32
+ "dependencies": {
33
+ "@modelcontextprotocol/sdk": "^1.12.1",
34
+ "gray-matter": "^4.0.3",
35
+ "zod": "^3.24.4"
36
+ },
37
+ "devDependencies": {
38
+ "@eslint/js": "^9.26.0",
39
+ "@types/node": "^22.15.3",
40
+ "eslint": "^9.26.0",
41
+ "prettier": "^3.5.3",
42
+ "tsup": "^8.4.0",
43
+ "tsx": "^4.21.0",
44
+ "typescript": "^6.0.2",
45
+ "typescript-eslint": "^8.31.1",
46
+ "vitest": "^3.1.2"
47
+ },
48
+ "engines": {
49
+ "node": ">=18"
50
+ }
51
+ }