@aleph-alpha/lib-mcp 2.0.0 → 2.1.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.
package/README.md CHANGED
@@ -1,17 +1,30 @@
1
1
  # @aleph-alpha/lib-mcp
2
2
 
3
- MCP (Model Context Protocol) Server for UI Library component discovery tools.
3
+ MCP (Model Context Protocol) Server for UI Library and ChatKit component discovery tools.
4
4
 
5
5
  ## Overview
6
6
 
7
- This package provides an MCP server that enables AI assistants (like Claude and Cursor) to discover and understand UI Library components. It offers tools to list available components and retrieve detailed documentation including props, examples, and usage guidance.
7
+ This package provides an MCP server that enables AI assistants (like Claude and Cursor) to discover and understand components from:
8
+
9
+ - [`@aleph-alpha/ui-library`](../ui-library) — `Ui*` components
10
+ - [`@aleph-alpha/chat-kit`](../chat-kit) — `Ck*` components
11
+
12
+ It offers tools to list available components and retrieve detailed documentation including props, examples, and usage guidance.
8
13
 
9
14
  ## Installation
10
15
 
16
+ Install `@aleph-alpha/lib-mcp` together with the component packages whose docs you want to query. UI Library is required; ChatKit is optional and only needed if you want `Ck*` component docs.
17
+
11
18
  ```bash
19
+ # UI Library only
12
20
  pnpm add @aleph-alpha/lib-mcp @aleph-alpha/ui-library
21
+
22
+ # UI Library + ChatKit
23
+ pnpm add @aleph-alpha/lib-mcp @aleph-alpha/ui-library @aleph-alpha/chat-kit
13
24
  ```
14
25
 
26
+ > ChatKit docs require `@aleph-alpha/chat-kit` to publish its `src/` directory (component `types.ts` and `*.stories.ts` files). If `get_chat_kit_docs` returns "Could not find chat-kit source directory", upgrade `@aleph-alpha/chat-kit` to a version that includes `src/` in its published files.
27
+
15
28
  ## Usage
16
29
 
17
30
  ### Configure MCP Server
@@ -24,6 +37,9 @@ npx @aleph-alpha/lib-mcp mcp-install
24
37
 
25
38
  # For both Claude Code and Cursor
26
39
  npx @aleph-alpha/lib-mcp mcp-install --cursor
40
+
41
+ # For VS Code
42
+ npx @aleph-alpha/lib-mcp mcp-install --vscode
27
43
  ```
28
44
 
29
45
  After installation, restart your IDE to activate the MCP tools.
@@ -32,9 +48,11 @@ After installation, restart your IDE to activate the MCP tools.
32
48
 
33
49
  Once configured, the following tools are available to your AI assistant:
34
50
 
35
- #### `list_components`
51
+ #### UI Library tools
52
+
53
+ ##### `list_components`
36
54
 
37
- Lists all available UI components. Supports optional filtering by name, category, or description.
55
+ Lists all available UI Library components. Supports optional filtering by name, category, or description.
38
56
 
39
57
  ```
40
58
  list_components
@@ -42,9 +60,9 @@ list_components --filter="button"
42
60
  list_components --filter="form"
43
61
  ```
44
62
 
45
- #### `get_component_docs`
63
+ ##### `get_component_docs`
46
64
 
47
- Retrieves full documentation for a specific component including:
65
+ Retrieves full documentation for a specific UI Library component including:
48
66
 
49
67
  - Component description
50
68
  - Props with types, defaults, and descriptions
@@ -57,6 +75,45 @@ get_component_docs UiButton
57
75
  get_component_docs Button # "Ui" prefix is optional
58
76
  ```
59
77
 
78
+ #### ChatKit tools
79
+
80
+ Available when `@aleph-alpha/chat-kit` is installed alongside this package.
81
+
82
+ ##### `list_chat_kit_components`
83
+
84
+ Lists all available ChatKit (`Ck*`) components. Supports optional filtering by name, category, or description.
85
+
86
+ ```
87
+ list_chat_kit_components
88
+ list_chat_kit_components --filter="history"
89
+ list_chat_kit_components --filter="message"
90
+ ```
91
+
92
+ ##### `get_chat_kit_docs`
93
+
94
+ Retrieves full documentation for a specific ChatKit component, with the same shape as `get_component_docs`:
95
+
96
+ - Component description
97
+ - Props with types, defaults, and descriptions
98
+ - Sub-components (if applicable)
99
+ - Usage guidance
100
+ - Code examples
101
+
102
+ ```
103
+ get_chat_kit_docs CkHistory
104
+ get_chat_kit_docs History # "Ck" prefix is optional
105
+ ```
106
+
107
+ #### Setup tool
108
+
109
+ ##### `get_setup_guide`
110
+
111
+ Returns the setup and installation guide for integrating the UI library into a project (UnoCSS config, Vite config, required dependencies, and MCP setup instructions).
112
+
113
+ ```
114
+ get_setup_guide
115
+ ```
116
+
60
117
  ## Development
61
118
 
62
119
  ### Building
@@ -67,6 +124,8 @@ pnpm build
67
124
 
68
125
  ### Generating Component Metadata
69
126
 
127
+ Regenerates `components-meta.json` (UI Library) and `chat-kit-components-meta.json` (ChatKit) by scanning each package's source files.
128
+
70
129
  ```bash
71
130
  pnpm generate:component-meta
72
131
  ```
@@ -79,21 +138,23 @@ pnpm test
79
138
 
80
139
  ## How It Works
81
140
 
82
- The MCP server reads component metadata from:
141
+ The MCP server reads component metadata from each package's source layout:
83
142
 
84
143
  1. **`types.ts`**: Extracts props, their types, descriptions, and component-level JSDoc tags (`@category`, `@useCases`, `@keywords`, `@related`)
85
144
  2. **`*.stories.ts`**: Extracts code examples and usage guidance from Storybook stories
86
- 3. **`components-meta.json`**: Pre-generated metadata for faster lookups
145
+ 3. **`index.ts`**: Detects sub-component exports for the documented component
146
+ 4. **`components-meta.json` / `chat-kit-components-meta.json`**: Pre-generated metadata for faster lookups
147
+
148
+ UI Library components are read from `@aleph-alpha/ui-library/src/**`, and ChatKit components from `@aleph-alpha/chat-kit/src/components/**`. Both packages must publish their `src/` directory for docs to resolve when consumed from `node_modules`.
87
149
 
88
150
  ## CLI Commands
89
151
 
90
- | Command | Description |
91
- |---------|-------------|
92
- | `mcp-install` | Configure MCP server for IDE |
93
- | `serve` | Start the MCP server (used internally by IDE) |
94
- | `--help` | Show help message |
152
+ | Command | Description |
153
+ | ------------- | ----------------------------------------------------------------------- |
154
+ | `mcp-install` | Configure MCP server for IDE (`--cursor`, `--vscode` to add extra IDEs) |
155
+ | `serve` | Start the MCP server (used internally by IDE) |
156
+ | `--help` | Show help message |
95
157
 
96
158
  ## License
97
159
 
98
160
  Apache-2.0
99
-
@@ -526,7 +526,7 @@
526
526
  "WithRadioItems",
527
527
  "WithDestructiveAction",
528
528
  "WithSubmenu",
529
- "WithIconButton",
529
+ "WithIconTrigger",
530
530
  "WithSoftToggleTrigger",
531
531
  "WithSoftToggleTriggerAndText",
532
532
  "WithAvatarTrigger"
@@ -714,53 +714,7 @@
714
714
  "examples": [
715
715
  "Default",
716
716
  "Sizes",
717
- "InIconButton"
718
- ],
719
- "_autoGenerated": true
720
- },
721
- "UiIconButton": {
722
- "description": "A button that displays only an icon without text. Use for compact actions like close, edit, delete, or toolbar buttons. It is being merged into `UiButton` — use `UiButton` with an icon-only child and an `aria-label` instead (e.g. `<UiButton size=\"icon-sm\" aria-label=\"Close\"><UiIcon name=\"x\" /></UiButton>`).",
723
- "category": "Actions",
724
- "useCases": [
725
- "close button",
726
- "edit action",
727
- "toolbar button",
728
- "compact action"
729
- ],
730
- "keywords": [
731
- "iconbutton",
732
- "icon",
733
- "button",
734
- "action",
735
- "close",
736
- "edit",
737
- "delete"
738
- ],
739
- "related": [
740
- "UiButton",
741
- "UiIcon"
742
- ],
743
- "props": [
744
- "variant",
745
- "size",
746
- "asChild",
747
- "type",
748
- "disabled",
749
- "loading",
750
- "ariaLabel"
751
- ],
752
- "examples": [
753
- "Default",
754
- "Secondary",
755
- "Destructive",
756
- "Outline",
757
- "Ghost",
758
- "Link",
759
- "Loading",
760
- "Disabled",
761
- "AllVariants",
762
- "AllSizes",
763
- "AsChild"
717
+ "IconLibrary"
764
718
  ],
765
719
  "_autoGenerated": true
766
720
  },
@@ -1349,6 +1303,48 @@
1349
1303
  ],
1350
1304
  "_autoGenerated": true
1351
1305
  },
1306
+ "UiSnackbar": {
1307
+ "description": "Toast notification container (Sonner). Place once near the app root, then call `toast()` (or `toast.success()`, `toast.error()`, etc.) from anywhere to display a non-blocking notification.",
1308
+ "category": "Feedback",
1309
+ "useCases": [
1310
+ "success confirmation",
1311
+ "error notice",
1312
+ "undo action",
1313
+ "async progress",
1314
+ "background updates"
1315
+ ],
1316
+ "keywords": [
1317
+ "snackbar",
1318
+ "toast",
1319
+ "sonner",
1320
+ "notification",
1321
+ "alert",
1322
+ "message",
1323
+ "banner",
1324
+ "undo"
1325
+ ],
1326
+ "related": [
1327
+ "UiAlert",
1328
+ "UiAlertDialog"
1329
+ ],
1330
+ "props": [],
1331
+ "examples": [
1332
+ "SuccessHigh",
1333
+ "SuccessLow",
1334
+ "InfoHigh",
1335
+ "InfoLow",
1336
+ "WarningHigh",
1337
+ "WarningLow",
1338
+ "ErrorHigh",
1339
+ "ErrorLow",
1340
+ "AllVariants",
1341
+ "Default",
1342
+ "WithDescription",
1343
+ "PromiseSnackbar",
1344
+ "WithDialog"
1345
+ ],
1346
+ "_autoGenerated": true
1347
+ },
1352
1348
  "UiSpinner": {
1353
1349
  "description": "An animated loading indicator. Use while content is loading or an action is processing.",
1354
1350
  "category": "Feedback",
@@ -1681,7 +1677,7 @@
1681
1677
  ],
1682
1678
  "examples": [
1683
1679
  "Default",
1684
- "WithIconButton",
1680
+ "WithIconTrigger",
1685
1681
  "InstantDelay",
1686
1682
  "LongDelay",
1687
1683
  "Disabled",
package/dist/cli.js CHANGED
@@ -21425,11 +21425,15 @@ function detectCategoryDirs() {
21425
21425
  return [];
21426
21426
  }
21427
21427
  const entries = fs4.readdirSync(srcPath, { withFileTypes: true });
21428
- return entries.filter((entry) => entry.isDirectory()).filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules").filter((entry) => {
21428
+ return entries.filter((entry) => entry.isDirectory()).filter(
21429
+ (entry) => !entry.name.startsWith(".") && entry.name !== "node_modules"
21430
+ ).filter((entry) => {
21429
21431
  try {
21430
21432
  const dirPath = path4.join(srcPath, entry.name);
21431
21433
  const subEntries = fs4.readdirSync(dirPath, { withFileTypes: true });
21432
- return subEntries.some((sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX));
21434
+ return subEntries.some(
21435
+ (sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX)
21436
+ );
21433
21437
  } catch {
21434
21438
  return false;
21435
21439
  }
@@ -21970,7 +21974,10 @@ function parseInterface2(content, interfaceName) {
21970
21974
  const propName = propMatch[2];
21971
21975
  const isOptional = !!propMatch[3];
21972
21976
  const typeStartIndex = propMatch.index + propMatch[0].length;
21973
- const { type: propType, endIndex } = extractType2(interfaceBody, typeStartIndex);
21977
+ const { type: propType, endIndex } = extractType2(
21978
+ interfaceBody,
21979
+ typeStartIndex
21980
+ );
21974
21981
  propStartRegex.lastIndex = endIndex + 1;
21975
21982
  const jsdoc = parseJSDoc2(jsdocComment);
21976
21983
  props.push({
@@ -21987,7 +21994,9 @@ function parseInterface2(content, interfaceName) {
21987
21994
  function extractComponentDescription2(content, interfaceName) {
21988
21995
  const lines = content.split("\n");
21989
21996
  const interfaceLineIndex = lines.findIndex(
21990
- (line) => line.match(new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+${interfaceName}`))
21997
+ (line) => line.match(
21998
+ new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+${interfaceName}`)
21999
+ )
21991
22000
  );
21992
22001
  if (interfaceLineIndex === -1) {
21993
22002
  return "";
@@ -22013,7 +22022,9 @@ function extractComponentDescription2(content, interfaceName) {
22013
22022
  return "";
22014
22023
  }
22015
22024
  function resolveUnionOrIntersectionProps2(content, typeName) {
22016
- const typeDefRegex = new RegExp(`export\\s+type\\s+${typeName}\\s*=\\s*([^;]+)`);
22025
+ const typeDefRegex = new RegExp(
22026
+ `export\\s+type\\s+${typeName}\\s*=\\s*([^;]+)`
22027
+ );
22017
22028
  const match = content.match(typeDefRegex);
22018
22029
  if (!match) return [];
22019
22030
  const referencedTypes = match[1].split(/[|&]/).map((t) => t.trim()).filter((t) => t.endsWith("Props"));
@@ -22041,7 +22052,9 @@ function readChatKitTypesFile(filePath, componentName) {
22041
22052
  return null;
22042
22053
  }
22043
22054
  const resolvedName = componentName || path9.basename(path9.dirname(filePath));
22044
- const exactRegex = new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+(${resolvedName}Props)\\b`);
22055
+ const exactRegex = new RegExp(
22056
+ `export\\s+${TYPE_OR_INTERFACE2}\\s+(${resolvedName}Props)\\b`
22057
+ );
22045
22058
  let propsInterfaceMatch = content.match(exactRegex);
22046
22059
  if (!propsInterfaceMatch) {
22047
22060
  const prefixRegex = new RegExp(
@@ -22307,7 +22320,9 @@ async function startServer() {
22307
22320
  server.tool(
22308
22321
  "list_chat_kit_components",
22309
22322
  "List all Chat Kit components. Optionally filter by name, category, or description.",
22310
- { filter: external_exports.string().optional().describe("Filter by name/category/description") },
22323
+ {
22324
+ filter: external_exports.string().optional().describe("Filter by name/category/description")
22325
+ },
22311
22326
  async ({ filter }) => {
22312
22327
  try {
22313
22328
  const components = listChatKitComponents(filter);
@@ -22322,7 +22337,10 @@ async function startServer() {
22322
22337
  },
22323
22338
  {}
22324
22339
  );
22325
- const sections = [`Found ${components.length} chat-kit component(s):`, ""];
22340
+ const sections = [
22341
+ `Found ${components.length} chat-kit component(s):`,
22342
+ ""
22343
+ ];
22326
22344
  Object.entries(grouped).forEach(([category, comps]) => {
22327
22345
  sections.push(`## ${category}`, "");
22328
22346
  comps.forEach((comp) => {
@@ -22339,11 +22357,14 @@ async function startServer() {
22339
22357
  server.tool(
22340
22358
  "get_chat_kit_docs",
22341
22359
  "Get full documentation for a Chat Kit component including props, examples, and usage.",
22342
- { componentName: external_exports.string().describe('Component name (e.g., "CkChatBubble" or "ChatBubble")') },
22360
+ {
22361
+ componentName: external_exports.string().describe('Component name (e.g., "CkChatBubble" or "ChatBubble")')
22362
+ },
22343
22363
  async ({ componentName }) => {
22344
22364
  try {
22345
22365
  const docs = getChatKitComponentDocs(componentName);
22346
- if (!docs) return error2(`Chat Kit component "${componentName}" not found.`);
22366
+ if (!docs)
22367
+ return error2(`Chat Kit component "${componentName}" not found.`);
22347
22368
  return text(formatComponentDocs(docs));
22348
22369
  } catch (e) {
22349
22370
  return handleError(e);
@@ -97,11 +97,15 @@ function detectCategoryDirs() {
97
97
  return [];
98
98
  }
99
99
  const entries = fs3.readdirSync(srcPath, { withFileTypes: true });
100
- return entries.filter((entry) => entry.isDirectory()).filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules").filter((entry) => {
100
+ return entries.filter((entry) => entry.isDirectory()).filter(
101
+ (entry) => !entry.name.startsWith(".") && entry.name !== "node_modules"
102
+ ).filter((entry) => {
101
103
  try {
102
104
  const dirPath = path2.join(srcPath, entry.name);
103
105
  const subEntries = fs3.readdirSync(dirPath, { withFileTypes: true });
104
- return subEntries.some((sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX));
106
+ return subEntries.some(
107
+ (sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX)
108
+ );
105
109
  } catch {
106
110
  return false;
107
111
  }
@@ -177,7 +181,10 @@ var __filename2 = fileURLToPath2(import.meta.url);
177
181
  var __dirname2 = path3.dirname(__filename2);
178
182
  var PACKAGE_ROOT = getPackageRoot();
179
183
  var OUTPUT_PATH = path3.join(PACKAGE_ROOT, "components-meta.json");
180
- var CHAT_KIT_OUTPUT_PATH = path3.join(PACKAGE_ROOT, "chat-kit-components-meta.json");
184
+ var CHAT_KIT_OUTPUT_PATH = path3.join(
185
+ PACKAGE_ROOT,
186
+ "chat-kit-components-meta.json"
187
+ );
181
188
  function extractJSDocTags(content, interfaceName) {
182
189
  const declarationRegex = new RegExp(
183
190
  `export\\s+(?:interface|type)\\s+${escapeRegex(interfaceName)}\\b`
@@ -265,13 +272,17 @@ function processComponent(componentDir, componentName) {
265
272
  typesContent = fs4.readFileSync(typesPath, "utf-8");
266
273
  }
267
274
  const escapedName = escapeRegex(componentName);
268
- const exactPropsRegex = new RegExp(`export\\s+(?:interface|type)\\s+(${escapedName}Props)\\b`);
275
+ const exactPropsRegex = new RegExp(
276
+ `export\\s+(?:interface|type)\\s+(${escapedName}Props)\\b`
277
+ );
269
278
  const exactMatch = typesContent.match(exactPropsRegex);
270
279
  const subComponentPropsRegex = new RegExp(
271
280
  `export\\s+(?:interface|type)\\s+(${escapedName}\\w*Props)\\b`
272
281
  );
273
282
  const subComponentMatch = typesContent.match(subComponentPropsRegex);
274
- const anyPropsMatch = typesContent.match(/export\s+(?:interface|type)\s+((?:Ui|Ck)\w+Props)/);
283
+ const anyPropsMatch = typesContent.match(
284
+ /export\s+(?:interface|type)\s+((?:Ui|Ck)\w+Props)/
285
+ );
275
286
  const interfaceName = exactMatch?.[1] || subComponentMatch?.[1] || anyPropsMatch?.[1] || `${componentName}Props`;
276
287
  const jsdocData = extractJSDocTags(typesContent, interfaceName);
277
288
  const nameKeywords = extractKeywordsFromName(componentName);
@@ -342,8 +353,12 @@ function scanChatKitComponents() {
342
353
  }
343
354
  function summarize(label, meta) {
344
355
  const total = Object.keys(meta).length;
345
- const withUseCases = Object.values(meta).filter((m) => m.useCases.length > 0).length;
346
- const withKeywords = Object.values(meta).filter((m) => m.keywords.length > 0).length;
356
+ const withUseCases = Object.values(meta).filter(
357
+ (m) => m.useCases.length > 0
358
+ ).length;
359
+ const withKeywords = Object.values(meta).filter(
360
+ (m) => m.keywords.length > 0
361
+ ).length;
347
362
  console.log(`
348
363
  ${label} summary:`);
349
364
  console.log(` Components with @useCases: ${withUseCases}/${total}`);
package/dist/server.js CHANGED
@@ -21313,11 +21313,15 @@ function detectCategoryDirs() {
21313
21313
  return [];
21314
21314
  }
21315
21315
  const entries = fs3.readdirSync(srcPath, { withFileTypes: true });
21316
- return entries.filter((entry) => entry.isDirectory()).filter((entry) => !entry.name.startsWith(".") && entry.name !== "node_modules").filter((entry) => {
21316
+ return entries.filter((entry) => entry.isDirectory()).filter(
21317
+ (entry) => !entry.name.startsWith(".") && entry.name !== "node_modules"
21318
+ ).filter((entry) => {
21317
21319
  try {
21318
21320
  const dirPath = path3.join(srcPath, entry.name);
21319
21321
  const subEntries = fs3.readdirSync(dirPath, { withFileTypes: true });
21320
- return subEntries.some((sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX));
21322
+ return subEntries.some(
21323
+ (sub) => sub.isDirectory() && sub.name.startsWith(COMPONENT_PREFIX)
21324
+ );
21321
21325
  } catch {
21322
21326
  return false;
21323
21327
  }
@@ -21858,7 +21862,10 @@ function parseInterface2(content, interfaceName) {
21858
21862
  const propName = propMatch[2];
21859
21863
  const isOptional = !!propMatch[3];
21860
21864
  const typeStartIndex = propMatch.index + propMatch[0].length;
21861
- const { type: propType, endIndex } = extractType2(interfaceBody, typeStartIndex);
21865
+ const { type: propType, endIndex } = extractType2(
21866
+ interfaceBody,
21867
+ typeStartIndex
21868
+ );
21862
21869
  propStartRegex.lastIndex = endIndex + 1;
21863
21870
  const jsdoc = parseJSDoc2(jsdocComment);
21864
21871
  props.push({
@@ -21875,7 +21882,9 @@ function parseInterface2(content, interfaceName) {
21875
21882
  function extractComponentDescription2(content, interfaceName) {
21876
21883
  const lines = content.split("\n");
21877
21884
  const interfaceLineIndex = lines.findIndex(
21878
- (line) => line.match(new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+${interfaceName}`))
21885
+ (line) => line.match(
21886
+ new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+${interfaceName}`)
21887
+ )
21879
21888
  );
21880
21889
  if (interfaceLineIndex === -1) {
21881
21890
  return "";
@@ -21901,7 +21910,9 @@ function extractComponentDescription2(content, interfaceName) {
21901
21910
  return "";
21902
21911
  }
21903
21912
  function resolveUnionOrIntersectionProps2(content, typeName) {
21904
- const typeDefRegex = new RegExp(`export\\s+type\\s+${typeName}\\s*=\\s*([^;]+)`);
21913
+ const typeDefRegex = new RegExp(
21914
+ `export\\s+type\\s+${typeName}\\s*=\\s*([^;]+)`
21915
+ );
21905
21916
  const match = content.match(typeDefRegex);
21906
21917
  if (!match) return [];
21907
21918
  const referencedTypes = match[1].split(/[|&]/).map((t) => t.trim()).filter((t) => t.endsWith("Props"));
@@ -21929,7 +21940,9 @@ function readChatKitTypesFile(filePath, componentName) {
21929
21940
  return null;
21930
21941
  }
21931
21942
  const resolvedName = componentName || path8.basename(path8.dirname(filePath));
21932
- const exactRegex = new RegExp(`export\\s+${TYPE_OR_INTERFACE2}\\s+(${resolvedName}Props)\\b`);
21943
+ const exactRegex = new RegExp(
21944
+ `export\\s+${TYPE_OR_INTERFACE2}\\s+(${resolvedName}Props)\\b`
21945
+ );
21933
21946
  let propsInterfaceMatch = content.match(exactRegex);
21934
21947
  if (!propsInterfaceMatch) {
21935
21948
  const prefixRegex = new RegExp(
@@ -22195,7 +22208,9 @@ async function startServer() {
22195
22208
  server.tool(
22196
22209
  "list_chat_kit_components",
22197
22210
  "List all Chat Kit components. Optionally filter by name, category, or description.",
22198
- { filter: external_exports.string().optional().describe("Filter by name/category/description") },
22211
+ {
22212
+ filter: external_exports.string().optional().describe("Filter by name/category/description")
22213
+ },
22199
22214
  async ({ filter }) => {
22200
22215
  try {
22201
22216
  const components = listChatKitComponents(filter);
@@ -22210,7 +22225,10 @@ async function startServer() {
22210
22225
  },
22211
22226
  {}
22212
22227
  );
22213
- const sections = [`Found ${components.length} chat-kit component(s):`, ""];
22228
+ const sections = [
22229
+ `Found ${components.length} chat-kit component(s):`,
22230
+ ""
22231
+ ];
22214
22232
  Object.entries(grouped).forEach(([category, comps]) => {
22215
22233
  sections.push(`## ${category}`, "");
22216
22234
  comps.forEach((comp) => {
@@ -22227,11 +22245,14 @@ async function startServer() {
22227
22245
  server.tool(
22228
22246
  "get_chat_kit_docs",
22229
22247
  "Get full documentation for a Chat Kit component including props, examples, and usage.",
22230
- { componentName: external_exports.string().describe('Component name (e.g., "CkChatBubble" or "ChatBubble")') },
22248
+ {
22249
+ componentName: external_exports.string().describe('Component name (e.g., "CkChatBubble" or "ChatBubble")')
22250
+ },
22231
22251
  async ({ componentName }) => {
22232
22252
  try {
22233
22253
  const docs = getChatKitComponentDocs(componentName);
22234
- if (!docs) return error2(`Chat Kit component "${componentName}" not found.`);
22254
+ if (!docs)
22255
+ return error2(`Chat Kit component "${componentName}" not found.`);
22235
22256
  return text(formatComponentDocs(docs));
22236
22257
  } catch (e) {
22237
22258
  return handleError(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aleph-alpha/lib-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "dist/server.js",
@@ -36,8 +36,8 @@
36
36
  "@aleph-alpha/tsconfig-frontend": "0.6.0"
37
37
  },
38
38
  "peerDependencies": {
39
- "@aleph-alpha/chat-kit": "1.0.0",
40
- "@aleph-alpha/ui-library": "2.0.0"
39
+ "@aleph-alpha/ui-library": "2.2.0",
40
+ "@aleph-alpha/chat-kit": "1.1.0"
41
41
  },
42
42
  "homepage": "https://docs.aleph-alpha.com",
43
43
  "scripts": {