@lando-labs/lando-ds-mcp 4.0.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/CHANGELOG.md +526 -0
- package/LICENSE +202 -0
- package/NOTICE +4 -0
- package/README.md +170 -0
- package/build/data/ds-meta.json +1 -0
- package/build/data/ds-meta.schema.json +282 -0
- package/build/data/ds-meta.verbose.json +1 -0
- package/build/data/icon-metadata.d.ts +64 -0
- package/build/data/icon-metadata.d.ts.map +1 -0
- package/build/data/icon-metadata.js +1128 -0
- package/build/data/icon-metadata.js.map +1 -0
- package/build/data/lucide-icon-names.d.ts +12 -0
- package/build/data/lucide-icon-names.d.ts.map +1 -0
- package/build/data/lucide-icon-names.js +1653 -0
- package/build/data/lucide-icon-names.js.map +1 -0
- package/build/data/lucide-icons.d.ts +41 -0
- package/build/data/lucide-icons.d.ts.map +1 -0
- package/build/data/lucide-icons.js +80 -0
- package/build/data/lucide-icons.js.map +1 -0
- package/build/data/rn-tokens-snapshot.d.ts +753 -0
- package/build/data/rn-tokens-snapshot.d.ts.map +1 -0
- package/build/data/rn-tokens-snapshot.js +286 -0
- package/build/data/rn-tokens-snapshot.js.map +1 -0
- package/build/index.d.ts +18 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +411 -0
- package/build/index.js.map +1 -0
- package/build/prompts/index.d.ts +16 -0
- package/build/prompts/index.d.ts.map +1 -0
- package/build/prompts/index.js +145 -0
- package/build/prompts/index.js.map +1 -0
- package/build/resources/code-examples.d.ts +6 -0
- package/build/resources/code-examples.d.ts.map +1 -0
- package/build/resources/code-examples.js +278 -0
- package/build/resources/code-examples.js.map +1 -0
- package/build/resources/design-tokens.d.ts +6 -0
- package/build/resources/design-tokens.d.ts.map +1 -0
- package/build/resources/design-tokens.js +128 -0
- package/build/resources/design-tokens.js.map +1 -0
- package/build/resources/index.d.ts +19 -0
- package/build/resources/index.d.ts.map +1 -0
- package/build/resources/index.js +80 -0
- package/build/resources/index.js.map +1 -0
- package/build/test.d.ts +12 -0
- package/build/test.d.ts.map +1 -0
- package/build/test.js +680 -0
- package/build/test.js.map +1 -0
- package/build/tools/compose-components.d.ts +40 -0
- package/build/tools/compose-components.d.ts.map +1 -0
- package/build/tools/compose-components.js +61 -0
- package/build/tools/compose-components.js.map +1 -0
- package/build/tools/get-animation-examples.d.ts +30 -0
- package/build/tools/get-animation-examples.d.ts.map +1 -0
- package/build/tools/get-animation-examples.js +484 -0
- package/build/tools/get-animation-examples.js.map +1 -0
- package/build/tools/get-component-capabilities.d.ts +43 -0
- package/build/tools/get-component-capabilities.d.ts.map +1 -0
- package/build/tools/get-component-capabilities.js +108 -0
- package/build/tools/get-component-capabilities.js.map +1 -0
- package/build/tools/get-component-props.d.ts +23 -0
- package/build/tools/get-component-props.d.ts.map +1 -0
- package/build/tools/get-component-props.js +46 -0
- package/build/tools/get-component-props.js.map +1 -0
- package/build/tools/get-component-reference.d.ts +25 -0
- package/build/tools/get-component-reference.d.ts.map +1 -0
- package/build/tools/get-component-reference.js +112 -0
- package/build/tools/get-component-reference.js.map +1 -0
- package/build/tools/get-component.d.ts +25 -0
- package/build/tools/get-component.d.ts.map +1 -0
- package/build/tools/get-component.js +60 -0
- package/build/tools/get-component.js.map +1 -0
- package/build/tools/get-composition-hints.d.ts +22 -0
- package/build/tools/get-composition-hints.d.ts.map +1 -0
- package/build/tools/get-composition-hints.js +39 -0
- package/build/tools/get-composition-hints.js.map +1 -0
- package/build/tools/get-design-tokens.d.ts +24 -0
- package/build/tools/get-design-tokens.d.ts.map +1 -0
- package/build/tools/get-design-tokens.js +96 -0
- package/build/tools/get-design-tokens.js.map +1 -0
- package/build/tools/get-ds-metadata.d.ts +16 -0
- package/build/tools/get-ds-metadata.d.ts.map +1 -0
- package/build/tools/get-ds-metadata.js +65 -0
- package/build/tools/get-ds-metadata.js.map +1 -0
- package/build/tools/get-hook.d.ts +19 -0
- package/build/tools/get-hook.d.ts.map +1 -0
- package/build/tools/get-hook.js +46 -0
- package/build/tools/get-hook.js.map +1 -0
- package/build/tools/get-theme-presets.d.ts +13 -0
- package/build/tools/get-theme-presets.d.ts.map +1 -0
- package/build/tools/get-theme-presets.js +41 -0
- package/build/tools/get-theme-presets.js.map +1 -0
- package/build/tools/list-components.d.ts +29 -0
- package/build/tools/list-components.d.ts.map +1 -0
- package/build/tools/list-components.js +88 -0
- package/build/tools/list-components.js.map +1 -0
- package/build/tools/list-hooks.d.ts +22 -0
- package/build/tools/list-hooks.d.ts.map +1 -0
- package/build/tools/list-hooks.js +80 -0
- package/build/tools/list-hooks.js.map +1 -0
- package/build/tools/list-icons.d.ts +28 -0
- package/build/tools/list-icons.d.ts.map +1 -0
- package/build/tools/list-icons.js +161 -0
- package/build/tools/list-icons.js.map +1 -0
- package/build/tools/platform-transform.d.ts +64 -0
- package/build/tools/platform-transform.d.ts.map +1 -0
- package/build/tools/platform-transform.js +117 -0
- package/build/tools/platform-transform.js.map +1 -0
- package/build/tools/platform.d.ts +76 -0
- package/build/tools/platform.d.ts.map +1 -0
- package/build/tools/platform.js +80 -0
- package/build/tools/platform.js.map +1 -0
- package/build/tools/search-icons.d.ts +28 -0
- package/build/tools/search-icons.d.ts.map +1 -0
- package/build/tools/search-icons.js +257 -0
- package/build/tools/search-icons.js.map +1 -0
- package/build/utils/error-envelope.d.ts +14 -0
- package/build/utils/error-envelope.d.ts.map +1 -0
- package/build/utils/error-envelope.js +35 -0
- package/build/utils/error-envelope.js.map +1 -0
- package/build/utils/icon-library.d.ts +17 -0
- package/build/utils/icon-library.d.ts.map +1 -0
- package/build/utils/icon-library.js +24 -0
- package/build/utils/icon-library.js.map +1 -0
- package/build/utils/jsx-safety.d.ts +47 -0
- package/build/utils/jsx-safety.d.ts.map +1 -0
- package/build/utils/jsx-safety.js +63 -0
- package/build/utils/jsx-safety.js.map +1 -0
- package/build/utils/meta-loader.d.ts +37 -0
- package/build/utils/meta-loader.d.ts.map +1 -0
- package/build/utils/meta-loader.js +114 -0
- package/build/utils/meta-loader.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-aware transformations for code-gen tools.
|
|
3
|
+
*
|
|
4
|
+
* Sprint 29, Lane G (#244): given a chunk of generated JSX + an import
|
|
5
|
+
* statement, produce the RN-flavored variant when `platform === 'react-native'`.
|
|
6
|
+
*
|
|
7
|
+
* Transformations applied for RN:
|
|
8
|
+
* - Import path: `@lando-labs/design-system` → `@lando-labs/design-system-native`
|
|
9
|
+
* - Event handlers:
|
|
10
|
+
* onClick → onPress
|
|
11
|
+
* onChange → onChangeText (only when the target is an Input/Textarea)
|
|
12
|
+
* - JSX tags:
|
|
13
|
+
* <div>...</div> → <View>...</View>
|
|
14
|
+
* <span>...</span> → <Text>...</Text>
|
|
15
|
+
* - Inline `style={{...}}` is left in place but annotated with a one-line
|
|
16
|
+
* comment hint that `StyleSheet.create` is preferred.
|
|
17
|
+
*
|
|
18
|
+
* The helpers here are intentionally regex-based: the inputs are short
|
|
19
|
+
* generated snippets where a parser would be overkill. The transformations
|
|
20
|
+
* are conservative — anything ambiguous is left alone (and warned about).
|
|
21
|
+
*/
|
|
22
|
+
/** Web import-path the metadata files emit. */
|
|
23
|
+
const WEB_IMPORT_PATH = '@lando-labs/design-system';
|
|
24
|
+
/** RN import-path the design system ships under. */
|
|
25
|
+
const RN_IMPORT_PATH = '@lando-labs/design-system-native';
|
|
26
|
+
/**
|
|
27
|
+
* Swap the web package name for the RN package name inside any import
|
|
28
|
+
* statement that targets the web DS. Other imports (`react`, `next/link`,
|
|
29
|
+
* `lucide-react`, etc.) pass through unchanged.
|
|
30
|
+
*
|
|
31
|
+
* Safe to call on input that may not contain an import statement — it's a
|
|
32
|
+
* no-op in that case.
|
|
33
|
+
*/
|
|
34
|
+
export function rewriteImportPath(snippet, platform) {
|
|
35
|
+
if (platform !== 'react-native')
|
|
36
|
+
return snippet;
|
|
37
|
+
// Match the package name only inside `from '...'` clauses so we don't
|
|
38
|
+
// accidentally swap occurrences in strings/comments.
|
|
39
|
+
return snippet.replace(new RegExp(`from\\s+(['"])${escapeForRegex(WEB_IMPORT_PATH)}\\1`, 'g'), `from $1${RN_IMPORT_PATH}$1`);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Rewrite a JSX snippet for RN.
|
|
43
|
+
*
|
|
44
|
+
* Returns both the transformed code and any warnings the caller may want
|
|
45
|
+
* to surface (e.g. the inline-style hint, ambiguous onChange usage on
|
|
46
|
+
* non-text elements, etc.).
|
|
47
|
+
*/
|
|
48
|
+
export function rewriteJsxForRn(jsx, options = {}) {
|
|
49
|
+
const warnings = [];
|
|
50
|
+
// Inline imports inside example bodies (e.g. the canned `Button as Next.js
|
|
51
|
+
// Link` example embeds its own `import { Button } from ...` line) must
|
|
52
|
+
// also flip to the RN package. We always force RN here because callers
|
|
53
|
+
// gate on platform before invoking this helper.
|
|
54
|
+
let out = rewriteImportPath(jsx, 'react-native');
|
|
55
|
+
// 1. JSX intrinsics. Keep these conservative — only swap exact tag names
|
|
56
|
+
// so we don't touch `<DivSomething>` etc.
|
|
57
|
+
out = out.replace(/<div(\s|>|\/>)/g, '<View$1');
|
|
58
|
+
out = out.replace(/<\/div>/g, '</View>');
|
|
59
|
+
out = out.replace(/<span(\s|>|\/>)/g, '<Text$1');
|
|
60
|
+
out = out.replace(/<\/span>/g, '</Text>');
|
|
61
|
+
// 2. onClick → onPress. Match `onClick=` (with `{` or `"` payload boundary
|
|
62
|
+
// to avoid touching strings like "onClickHandler" defined in props).
|
|
63
|
+
out = out.replace(/\bonClick=/g, 'onPress=');
|
|
64
|
+
// 3. onChange → onChangeText, only for text inputs. RN's onChange has a
|
|
65
|
+
// different signature for non-text controls (Switch, Select equivalent
|
|
66
|
+
// on RN), so we only rewrite for input/textarea targets — for anything
|
|
67
|
+
// else we leave onChange alone and emit a warning.
|
|
68
|
+
if (options.componentName === 'input' || options.componentName === 'textarea') {
|
|
69
|
+
out = out.replace(/\bonChange=/g, 'onChangeText=');
|
|
70
|
+
}
|
|
71
|
+
else if (/\bonChange=/.test(out)) {
|
|
72
|
+
warnings.push('onChange detected on a non-text component — RN consumers may need to remap this handler (e.g. onValueChange for Switch).');
|
|
73
|
+
}
|
|
74
|
+
// 4. Inline-style hint. If the snippet contains `style={{`, flag a hint
|
|
75
|
+
// about StyleSheet.create. We don't modify the snippet — both forms are
|
|
76
|
+
// valid in RN, the hint is informational.
|
|
77
|
+
if (/style=\{\{/.test(out)) {
|
|
78
|
+
warnings.push('Inline style={{ ... }} works on RN, but StyleSheet.create is preferred for performance + memoization.');
|
|
79
|
+
}
|
|
80
|
+
return { code: out, warnings };
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Convenience wrapper: apply both import + JSX rewrites to a full snippet
|
|
84
|
+
* (import statement + JSX), keeping the existing two-section format
|
|
85
|
+
* (`<import>\n\n<jsx>`) produced by `get_component` / `get_usage_example`.
|
|
86
|
+
*
|
|
87
|
+
* Splits on the first blank line; if none is found, the entire input is
|
|
88
|
+
* treated as JSX (no import to rewrite).
|
|
89
|
+
*/
|
|
90
|
+
export function rewriteSnippetForPlatform(snippet, platform, options = {}) {
|
|
91
|
+
if (platform !== 'react-native') {
|
|
92
|
+
return { code: snippet, warnings: [] };
|
|
93
|
+
}
|
|
94
|
+
const blankLine = snippet.indexOf('\n\n');
|
|
95
|
+
if (blankLine === -1) {
|
|
96
|
+
return rewriteJsxForRn(snippet, options);
|
|
97
|
+
}
|
|
98
|
+
const head = snippet.slice(0, blankLine);
|
|
99
|
+
const body = snippet.slice(blankLine + 2);
|
|
100
|
+
const rewrittenHead = rewriteImportPath(head, platform);
|
|
101
|
+
const { code: rewrittenBody, warnings } = rewriteJsxForRn(body, options);
|
|
102
|
+
return { code: `${rewrittenHead}\n\n${rewrittenBody}`, warnings };
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Format a list of warnings as a leading comment block. Returns an empty
|
|
106
|
+
* string if there are no warnings.
|
|
107
|
+
*/
|
|
108
|
+
export function formatWarningsHeader(warnings) {
|
|
109
|
+
if (warnings.length === 0)
|
|
110
|
+
return '';
|
|
111
|
+
const lines = warnings.map((w) => `// [RN] ${w}`).join('\n');
|
|
112
|
+
return `${lines}\n\n`;
|
|
113
|
+
}
|
|
114
|
+
function escapeForRegex(s) {
|
|
115
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
116
|
+
}
|
|
117
|
+
//# sourceMappingURL=platform-transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform-transform.js","sourceRoot":"","sources":["../../src/tools/platform-transform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared platform parameter definition for MCP tool schemas.
|
|
3
|
+
*
|
|
4
|
+
* Every tool accepts an optional `platform` field that controls import paths,
|
|
5
|
+
* output format, and component availability filtering. Defaulting to `'web'`
|
|
6
|
+
* keeps every existing AI consumer (that doesn't pass `platform`) on the
|
|
7
|
+
* exact same behavior we shipped before Sprint 29.
|
|
8
|
+
*
|
|
9
|
+
* Lanes G + H consume this parameter in their respective tools to render
|
|
10
|
+
* RN-flavored output (`@lando-labs/design-system-native` imports, RN
|
|
11
|
+
* StyleSheet snippets, etc.). The platform field is plumbed through every
|
|
12
|
+
* tool's Zod schema so future lanes only need to read `params.platform` —
|
|
13
|
+
* no schema migration required.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/**
|
|
17
|
+
* Target platforms the MCP server can produce output for.
|
|
18
|
+
*
|
|
19
|
+
* - `web` — `@lando-labs/design-system` (CSS variables, JSX with web imports)
|
|
20
|
+
* - `react-native` — `@lando-labs/design-system-native` (RN primitives, StyleSheet)
|
|
21
|
+
*/
|
|
22
|
+
export declare const platformValues: readonly ["web", "react-native"];
|
|
23
|
+
export type Platform = (typeof platformValues)[number];
|
|
24
|
+
/**
|
|
25
|
+
* Zod schema fragment for the `platform` parameter.
|
|
26
|
+
*
|
|
27
|
+
* Spread or merge this into every tool's input schema so the parameter is
|
|
28
|
+
* uniform across the entire server. The field is `.optional()` (no
|
|
29
|
+
* `.default()` on the Zod side) so `z.infer<typeof schema>` yields
|
|
30
|
+
* `platform?: 'web' | 'react-native'` — i.e. the parameter is truly optional
|
|
31
|
+
* for callers and existing test fixtures don't need to be updated.
|
|
32
|
+
*
|
|
33
|
+
* Handler-side defaulting: use `resolvePlatform(params.platform)` (below) to
|
|
34
|
+
* collapse `undefined` to `'web'`. Doing it this way preserves backwards
|
|
35
|
+
* compatibility for every existing AI consumer that doesn't pass the
|
|
36
|
+
* parameter, while keeping the public surface advertised in the JSON Schema
|
|
37
|
+
* (see `platformJsonSchema`) honest about the default.
|
|
38
|
+
*
|
|
39
|
+
* Usage:
|
|
40
|
+
*
|
|
41
|
+
* const mySchema = z.object({
|
|
42
|
+
* foo: z.string(),
|
|
43
|
+
* ...platformSchemaShape,
|
|
44
|
+
* })
|
|
45
|
+
*
|
|
46
|
+
* function myHandler(params: z.infer<typeof mySchema>) {
|
|
47
|
+
* const platform = resolvePlatform(params.platform) // 'web' if unset
|
|
48
|
+
* // ...
|
|
49
|
+
* }
|
|
50
|
+
*/
|
|
51
|
+
export declare const platformSchemaShape: {
|
|
52
|
+
readonly platform: z.ZodOptional<z.ZodEnum<["web", "react-native"]>>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Resolve an incoming `platform` field to a concrete `Platform`.
|
|
56
|
+
*
|
|
57
|
+
* Always falls back to `'web'` when undefined, mirroring the JSON Schema
|
|
58
|
+
* default we advertise to consumers.
|
|
59
|
+
*/
|
|
60
|
+
export declare function resolvePlatform(platform: Platform | undefined): Platform;
|
|
61
|
+
/**
|
|
62
|
+
* JSON Schema fragment for the `platform` parameter, suitable for embedding
|
|
63
|
+
* directly into the `inputSchema.properties` object that the MCP server
|
|
64
|
+
* advertises via `ListToolsRequestSchema`.
|
|
65
|
+
*
|
|
66
|
+
* Kept in sync with `platformSchemaShape` above — both must describe the
|
|
67
|
+
* same shape, since one is parsed (Zod) and the other is advertised (JSON
|
|
68
|
+
* Schema).
|
|
69
|
+
*/
|
|
70
|
+
export declare const platformJsonSchema: {
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
readonly enum: string[];
|
|
73
|
+
readonly default: "web";
|
|
74
|
+
readonly description: "Target platform. Controls import paths, output format, and component availability filtering.";
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../../src/tools/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,eAAO,MAAM,cAAc,kCAAmC,CAAA;AAE9D,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,cAAc,CAAC,CAAC,MAAM,CAAC,CAAA;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,mBAAmB;;CAOtB,CAAA;AAEV;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAExE;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;;mBAEM,MAAM,EAAE;;;CAInC,CAAA"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared platform parameter definition for MCP tool schemas.
|
|
3
|
+
*
|
|
4
|
+
* Every tool accepts an optional `platform` field that controls import paths,
|
|
5
|
+
* output format, and component availability filtering. Defaulting to `'web'`
|
|
6
|
+
* keeps every existing AI consumer (that doesn't pass `platform`) on the
|
|
7
|
+
* exact same behavior we shipped before Sprint 29.
|
|
8
|
+
*
|
|
9
|
+
* Lanes G + H consume this parameter in their respective tools to render
|
|
10
|
+
* RN-flavored output (`@lando-labs/design-system-native` imports, RN
|
|
11
|
+
* StyleSheet snippets, etc.). The platform field is plumbed through every
|
|
12
|
+
* tool's Zod schema so future lanes only need to read `params.platform` —
|
|
13
|
+
* no schema migration required.
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
/**
|
|
17
|
+
* Target platforms the MCP server can produce output for.
|
|
18
|
+
*
|
|
19
|
+
* - `web` — `@lando-labs/design-system` (CSS variables, JSX with web imports)
|
|
20
|
+
* - `react-native` — `@lando-labs/design-system-native` (RN primitives, StyleSheet)
|
|
21
|
+
*/
|
|
22
|
+
export const platformValues = ['web', 'react-native'];
|
|
23
|
+
/**
|
|
24
|
+
* Zod schema fragment for the `platform` parameter.
|
|
25
|
+
*
|
|
26
|
+
* Spread or merge this into every tool's input schema so the parameter is
|
|
27
|
+
* uniform across the entire server. The field is `.optional()` (no
|
|
28
|
+
* `.default()` on the Zod side) so `z.infer<typeof schema>` yields
|
|
29
|
+
* `platform?: 'web' | 'react-native'` — i.e. the parameter is truly optional
|
|
30
|
+
* for callers and existing test fixtures don't need to be updated.
|
|
31
|
+
*
|
|
32
|
+
* Handler-side defaulting: use `resolvePlatform(params.platform)` (below) to
|
|
33
|
+
* collapse `undefined` to `'web'`. Doing it this way preserves backwards
|
|
34
|
+
* compatibility for every existing AI consumer that doesn't pass the
|
|
35
|
+
* parameter, while keeping the public surface advertised in the JSON Schema
|
|
36
|
+
* (see `platformJsonSchema`) honest about the default.
|
|
37
|
+
*
|
|
38
|
+
* Usage:
|
|
39
|
+
*
|
|
40
|
+
* const mySchema = z.object({
|
|
41
|
+
* foo: z.string(),
|
|
42
|
+
* ...platformSchemaShape,
|
|
43
|
+
* })
|
|
44
|
+
*
|
|
45
|
+
* function myHandler(params: z.infer<typeof mySchema>) {
|
|
46
|
+
* const platform = resolvePlatform(params.platform) // 'web' if unset
|
|
47
|
+
* // ...
|
|
48
|
+
* }
|
|
49
|
+
*/
|
|
50
|
+
export const platformSchemaShape = {
|
|
51
|
+
platform: z
|
|
52
|
+
.enum(platformValues)
|
|
53
|
+
.optional()
|
|
54
|
+
.describe("Target platform. Controls import paths, output format, and component availability filtering. Defaults to 'web' for backwards compatibility."),
|
|
55
|
+
};
|
|
56
|
+
/**
|
|
57
|
+
* Resolve an incoming `platform` field to a concrete `Platform`.
|
|
58
|
+
*
|
|
59
|
+
* Always falls back to `'web'` when undefined, mirroring the JSON Schema
|
|
60
|
+
* default we advertise to consumers.
|
|
61
|
+
*/
|
|
62
|
+
export function resolvePlatform(platform) {
|
|
63
|
+
return platform ?? 'web';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* JSON Schema fragment for the `platform` parameter, suitable for embedding
|
|
67
|
+
* directly into the `inputSchema.properties` object that the MCP server
|
|
68
|
+
* advertises via `ListToolsRequestSchema`.
|
|
69
|
+
*
|
|
70
|
+
* Kept in sync with `platformSchemaShape` above — both must describe the
|
|
71
|
+
* same shape, since one is parsed (Zod) and the other is advertised (JSON
|
|
72
|
+
* Schema).
|
|
73
|
+
*/
|
|
74
|
+
export const platformJsonSchema = {
|
|
75
|
+
type: 'string',
|
|
76
|
+
enum: platformValues,
|
|
77
|
+
default: 'web',
|
|
78
|
+
description: "Target platform. Controls import paths, output format, and component availability filtering.",
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../../src/tools/platform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,KAAK,EAAE,cAAc,CAAU,CAAA;AAI9D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,QAAQ,EAAE,CAAC;SACR,IAAI,CAAC,cAAc,CAAC;SACpB,QAAQ,EAAE;SACV,QAAQ,CACP,6IAA6I,CAC9I;CACK,CAAA;AAEV;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,QAA8B;IAC5D,OAAO,QAAQ,IAAI,KAAK,CAAA;AAC1B,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,cAAqC;IAC3C,OAAO,EAAE,KAAK;IACd,WAAW,EACT,8FAA8F;CACxF,CAAA"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search_icons Tool — meta-backed sources, brand-neutral.
|
|
3
|
+
*
|
|
4
|
+
* Semantic search across DS-brand + Lucide-curated icons. Same source
|
|
5
|
+
* filter as list_icons ('ds-brand' | 'lucide-curated' | 'all'). Also
|
|
6
|
+
* spills over into the full Lucide library for additional matches that
|
|
7
|
+
* aren't in either curated set.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
export declare const searchIconsSchema: z.ZodObject<{
|
|
11
|
+
query: z.ZodString;
|
|
12
|
+
category: z.ZodOptional<z.ZodString>;
|
|
13
|
+
source: z.ZodOptional<z.ZodEnum<["ds-brand", "lucide-curated", "all"]>>;
|
|
14
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
15
|
+
}, "strip", z.ZodTypeAny, {
|
|
16
|
+
query: string;
|
|
17
|
+
category?: string | undefined;
|
|
18
|
+
source?: "all" | "ds-brand" | "lucide-curated" | undefined;
|
|
19
|
+
limit?: number | undefined;
|
|
20
|
+
}, {
|
|
21
|
+
query: string;
|
|
22
|
+
category?: string | undefined;
|
|
23
|
+
source?: "all" | "ds-brand" | "lucide-curated" | undefined;
|
|
24
|
+
limit?: number | undefined;
|
|
25
|
+
}>;
|
|
26
|
+
export type SearchIconsParams = z.infer<typeof searchIconsSchema>;
|
|
27
|
+
export declare function searchIcons(params: SearchIconsParams): Promise<string>;
|
|
28
|
+
//# sourceMappingURL=search-icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-icons.d.ts","sourceRoot":"","sources":["../../src/tools/search-icons.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AASvB,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;EAiB5B,CAAA;AAEF,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAA;AA6MjE,wBAAsB,WAAW,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB5E"}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search_icons Tool — meta-backed sources, brand-neutral.
|
|
3
|
+
*
|
|
4
|
+
* Semantic search across DS-brand + Lucide-curated icons. Same source
|
|
5
|
+
* filter as list_icons ('ds-brand' | 'lucide-curated' | 'all'). Also
|
|
6
|
+
* spills over into the full Lucide library for additional matches that
|
|
7
|
+
* aren't in either curated set.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { allIconMetadata, } from '../data/icon-metadata.js';
|
|
11
|
+
import { resolveLibraryInfo } from '../utils/icon-library.js';
|
|
12
|
+
import { searchLucideIconNames } from '../data/lucide-icons.js';
|
|
13
|
+
import { getLightMeta } from '../utils/meta-loader.js';
|
|
14
|
+
export const searchIconsSchema = z.object({
|
|
15
|
+
query: z
|
|
16
|
+
.string()
|
|
17
|
+
.max(8_000)
|
|
18
|
+
.describe('What you want to accomplish (e.g. "show user profile", "indicate success", "navigate home").'),
|
|
19
|
+
category: z.string().max(100).optional().describe('Optional: filter to this category.'),
|
|
20
|
+
source: z
|
|
21
|
+
.enum(['ds-brand', 'lucide-curated', 'all'])
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Icon source (default 'all')."),
|
|
24
|
+
limit: z
|
|
25
|
+
.number()
|
|
26
|
+
.int()
|
|
27
|
+
.min(1)
|
|
28
|
+
.max(200)
|
|
29
|
+
.optional()
|
|
30
|
+
.describe('Maximum curated matches to return (default: 10, max: 200).'),
|
|
31
|
+
});
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
// Purpose → icon-name mappings (brand-neutral)
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
const purposeMappings = {
|
|
36
|
+
'user profile': ['User', 'user', 'UserCircle'],
|
|
37
|
+
'account settings': ['User', 'Settings', 'settings'],
|
|
38
|
+
'user menu': ['UserCircle', 'User', 'user'],
|
|
39
|
+
'navigate home': ['Home', 'house'],
|
|
40
|
+
'go back': ['ArrowLeft', 'arrow-left', 'ChevronLeft', 'chevron-left'],
|
|
41
|
+
'go forward': ['ArrowRight', 'arrow-right', 'ChevronRight', 'chevron-right'],
|
|
42
|
+
'scroll up': ['ChevronUp', 'chevron-up', 'ArrowUp'],
|
|
43
|
+
'scroll down': ['ChevronDown', 'chevron-down', 'ArrowDown'],
|
|
44
|
+
navigate: ['ArrowRight', 'ChevronRight', 'arrow-right', 'chevron-right'],
|
|
45
|
+
'indicate success': ['CheckCircle', 'check', 'success', 'Check'],
|
|
46
|
+
'show error': ['XCircle', 'error', 'AlertCircle', 'X'],
|
|
47
|
+
'show warning': ['AlertTriangle', 'warning', 'AlertCircle'],
|
|
48
|
+
'show info': ['Info', 'info', 'AlertCircle'],
|
|
49
|
+
'loading state': ['Loader2', 'RefreshCw'],
|
|
50
|
+
loading: ['Loader2', 'RefreshCw'],
|
|
51
|
+
'edit content': ['Edit', 'edit', 'Pencil'],
|
|
52
|
+
'delete item': ['Trash2', 'trash', 'X'],
|
|
53
|
+
'download file': ['Download', 'download'],
|
|
54
|
+
'upload file': ['Upload', 'upload'],
|
|
55
|
+
'copy text': ['Copy', 'copy'],
|
|
56
|
+
search: ['Search', 'search'],
|
|
57
|
+
save: ['Save', 'save', 'Download'],
|
|
58
|
+
'close dialog': ['X', 'close', 'XCircle'],
|
|
59
|
+
'dismiss modal': ['X', 'close'],
|
|
60
|
+
'cancel action': ['X', 'close'],
|
|
61
|
+
'send message': ['Send', 'send', 'MessageSquare'],
|
|
62
|
+
chat: ['message', 'MessageSquare', 'MessageCircle'],
|
|
63
|
+
'user list': ['users', 'Users'],
|
|
64
|
+
email: ['Mail', 'send', 'Send'],
|
|
65
|
+
notification: ['Bell', 'AlertCircle'],
|
|
66
|
+
'file upload': ['Upload', 'upload', 'file'],
|
|
67
|
+
folder: ['folder', 'Folder'],
|
|
68
|
+
'image upload': ['image', 'Image', 'Upload'],
|
|
69
|
+
document: ['File', 'file', 'FileText'],
|
|
70
|
+
'open settings': ['Settings', 'settings', 'Sliders'],
|
|
71
|
+
configure: ['Settings', 'settings', 'Sliders'],
|
|
72
|
+
'open menu': ['Menu', 'menu', 'MoreVertical'],
|
|
73
|
+
'more options': ['MoreVertical', 'MoreHorizontal'],
|
|
74
|
+
'show date': ['calendar', 'Calendar'],
|
|
75
|
+
'show time': ['clock', 'Clock'],
|
|
76
|
+
'light mode': ['sun', 'Sun'],
|
|
77
|
+
'dark mode': ['moon', 'Moon'],
|
|
78
|
+
show: ['Eye', 'eye'],
|
|
79
|
+
hide: ['EyeOff', 'eye'],
|
|
80
|
+
visible: ['Eye', 'eye'],
|
|
81
|
+
secure: ['Lock', 'lock'],
|
|
82
|
+
lock: ['Lock', 'lock'],
|
|
83
|
+
unlock: ['Unlock', 'unlock'],
|
|
84
|
+
favorite: ['Star', 'star', 'Heart', 'heart'],
|
|
85
|
+
like: ['Heart', 'heart'],
|
|
86
|
+
bookmark: ['Bookmark', 'bookmark'],
|
|
87
|
+
refresh: ['RefreshCw', 'refresh'],
|
|
88
|
+
reload: ['RefreshCw', 'refresh'],
|
|
89
|
+
sync: ['RefreshCw', 'sync'],
|
|
90
|
+
expand: ['Maximize2', 'maximize', 'plus'],
|
|
91
|
+
collapse: ['Minimize2', 'minimize', 'minus'],
|
|
92
|
+
fullscreen: ['Maximize2', 'maximize'],
|
|
93
|
+
filter: ['Filter', 'filter', 'Sliders'],
|
|
94
|
+
sort: ['Filter', 'filter'],
|
|
95
|
+
'zoom in': ['ZoomIn', 'plus'],
|
|
96
|
+
'zoom out': ['ZoomOut', 'minus'],
|
|
97
|
+
'grid view': ['Grid', 'grid'],
|
|
98
|
+
'list view': ['List', 'list'],
|
|
99
|
+
play: ['Play', 'play'],
|
|
100
|
+
pause: ['Pause', 'pause'],
|
|
101
|
+
volume: ['Volume2', 'volume'],
|
|
102
|
+
ai: ['Sparkles', 'sparkles', 'Zap'],
|
|
103
|
+
magic: ['Sparkles', 'sparkles'],
|
|
104
|
+
fast: ['Zap', 'zap'],
|
|
105
|
+
power: ['Zap', 'zap'],
|
|
106
|
+
};
|
|
107
|
+
function dsBrandIcons() {
|
|
108
|
+
const registry = getLightMeta().icons.registry;
|
|
109
|
+
return Object.values(registry).map((entry) => ({
|
|
110
|
+
name: entry.name,
|
|
111
|
+
source: 'ds-brand',
|
|
112
|
+
category: entry.category,
|
|
113
|
+
description: `${entry.name} (DS brand icon)`,
|
|
114
|
+
tags: [entry.name, entry.category, entry.lucideName],
|
|
115
|
+
lucideName: entry.lucideName,
|
|
116
|
+
}));
|
|
117
|
+
}
|
|
118
|
+
function lucideCuratedIcons() {
|
|
119
|
+
return allIconMetadata
|
|
120
|
+
.filter((i) => i.source === 'lucide')
|
|
121
|
+
.map((i) => ({
|
|
122
|
+
name: i.name,
|
|
123
|
+
source: 'lucide-curated',
|
|
124
|
+
category: i.category,
|
|
125
|
+
description: i.description,
|
|
126
|
+
tags: i.tags,
|
|
127
|
+
lucideName: i.name,
|
|
128
|
+
commonUsage: i.commonUsage,
|
|
129
|
+
aliases: i.aliases,
|
|
130
|
+
}));
|
|
131
|
+
}
|
|
132
|
+
function collectIcons(source) {
|
|
133
|
+
if (source === 'ds-brand')
|
|
134
|
+
return dsBrandIcons();
|
|
135
|
+
if (source === 'lucide-curated')
|
|
136
|
+
return lucideCuratedIcons();
|
|
137
|
+
const brand = dsBrandIcons();
|
|
138
|
+
const brandNames = new Set(brand.map((i) => i.name));
|
|
139
|
+
const curated = lucideCuratedIcons().filter((i) => !brandNames.has(i.name));
|
|
140
|
+
return [...brand, ...curated];
|
|
141
|
+
}
|
|
142
|
+
// ---------------------------------------------------------------------------
|
|
143
|
+
// Ranking
|
|
144
|
+
// ---------------------------------------------------------------------------
|
|
145
|
+
function findByPurpose(pool, query, category) {
|
|
146
|
+
const q = query.toLowerCase();
|
|
147
|
+
const matches = new Set();
|
|
148
|
+
for (const [key, names] of Object.entries(purposeMappings)) {
|
|
149
|
+
if (q.includes(key) || key.includes(q)) {
|
|
150
|
+
for (const name of names) {
|
|
151
|
+
const hit = pool.find((i) => i.name === name || i.lucideName === name);
|
|
152
|
+
if (hit)
|
|
153
|
+
matches.add(hit);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const icon of pool) {
|
|
158
|
+
if (icon.name.toLowerCase().includes(q) ||
|
|
159
|
+
icon.tags.some((t) => q.includes(t.toLowerCase()) || t.toLowerCase().includes(q)) ||
|
|
160
|
+
icon.description.toLowerCase().includes(q) ||
|
|
161
|
+
icon.commonUsage?.toLowerCase().includes(q) ||
|
|
162
|
+
icon.aliases?.some((a) => q.includes(a.toLowerCase()))) {
|
|
163
|
+
matches.add(icon);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
let results = [...matches];
|
|
167
|
+
if (category)
|
|
168
|
+
results = results.filter((i) => i.category === category);
|
|
169
|
+
return results;
|
|
170
|
+
}
|
|
171
|
+
function score(icon, q, category) {
|
|
172
|
+
let s = 0;
|
|
173
|
+
const name = icon.name.toLowerCase();
|
|
174
|
+
if (name === q)
|
|
175
|
+
s += 100;
|
|
176
|
+
if (name.includes(q))
|
|
177
|
+
s += 50;
|
|
178
|
+
if (icon.tags.some((t) => t.toLowerCase() === q))
|
|
179
|
+
s += 80;
|
|
180
|
+
if (icon.tags.some((t) => t.toLowerCase().includes(q)))
|
|
181
|
+
s += 40;
|
|
182
|
+
if (icon.description.toLowerCase().includes(q))
|
|
183
|
+
s += 30;
|
|
184
|
+
if (icon.commonUsage?.toLowerCase().includes(q))
|
|
185
|
+
s += 60;
|
|
186
|
+
if (icon.aliases?.some((a) => a.toLowerCase() === q))
|
|
187
|
+
s += 70;
|
|
188
|
+
if (icon.aliases?.some((a) => a.toLowerCase().includes(q)))
|
|
189
|
+
s += 35;
|
|
190
|
+
if (category && icon.category === category)
|
|
191
|
+
s += 30;
|
|
192
|
+
// DS-brand icons get a small preference — they're the DS-canonical set.
|
|
193
|
+
if (icon.source === 'ds-brand')
|
|
194
|
+
s += 5;
|
|
195
|
+
return s;
|
|
196
|
+
}
|
|
197
|
+
// ---------------------------------------------------------------------------
|
|
198
|
+
// Handler
|
|
199
|
+
// ---------------------------------------------------------------------------
|
|
200
|
+
export async function searchIcons(params) {
|
|
201
|
+
const { query, category, limit } = params;
|
|
202
|
+
const source = params.source ?? 'all';
|
|
203
|
+
const safeLimit = limit ?? 10;
|
|
204
|
+
const pool = collectIcons(source);
|
|
205
|
+
const raw = findByPurpose(pool, query, category);
|
|
206
|
+
const q = query.toLowerCase();
|
|
207
|
+
const ranked = raw
|
|
208
|
+
.map((icon) => ({ icon, s: score(icon, q, category) }))
|
|
209
|
+
.sort((a, b) => b.s - a.s)
|
|
210
|
+
.map((entry) => entry.icon);
|
|
211
|
+
const results = ranked.slice(0, safeLimit);
|
|
212
|
+
const curatedNames = new Set(results.map((r) => r.name));
|
|
213
|
+
const lucideExtras = searchLucideIconNames(query)
|
|
214
|
+
.filter((name) => !curatedNames.has(name))
|
|
215
|
+
.slice(0, safeLimit);
|
|
216
|
+
const libraryInfo = resolveLibraryInfo();
|
|
217
|
+
return format(results, lucideExtras, query, category, source, libraryInfo);
|
|
218
|
+
}
|
|
219
|
+
function format(results, lucideExtras, query, category, source, libraryInfo) {
|
|
220
|
+
let out = '# Icon Search Results\n\n';
|
|
221
|
+
out += `**Query**: "${query}"\n`;
|
|
222
|
+
if (category)
|
|
223
|
+
out += `**Category**: ${category}\n`;
|
|
224
|
+
if (source !== 'all')
|
|
225
|
+
out += `**Source**: ${source}\n`;
|
|
226
|
+
out += `**Library**: \`${libraryInfo.libraryName}\`\n\n`;
|
|
227
|
+
if (results.length === 0 && lucideExtras.length === 0) {
|
|
228
|
+
out += 'No icons found. Try different keywords, or browse the full Lucide library: ';
|
|
229
|
+
out += `${libraryInfo.browseUrl}\n`;
|
|
230
|
+
return out;
|
|
231
|
+
}
|
|
232
|
+
if (results.length > 0) {
|
|
233
|
+
out += `## Recommended (${results.length})\n\n`;
|
|
234
|
+
results.forEach((icon, idx) => {
|
|
235
|
+
const rank = idx + 1;
|
|
236
|
+
out += `### ${rank}. **${icon.name}** _(${icon.source})_\n\n`;
|
|
237
|
+
out += `- Description: ${icon.description}\n`;
|
|
238
|
+
out += `- Category: ${icon.category}\n`;
|
|
239
|
+
if (icon.commonUsage)
|
|
240
|
+
out += `- Common usage: ${icon.commonUsage}\n`;
|
|
241
|
+
const lucideName = icon.lucideName ?? icon.name;
|
|
242
|
+
out += `\n\`\`\`tsx\nimport { ${lucideName} } from '${libraryInfo.libraryName}'\n\n`;
|
|
243
|
+
out += `<Icon size="md"><${lucideName} /></Icon>\n\`\`\`\n\n`;
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
if (lucideExtras.length > 0) {
|
|
247
|
+
out += `## Additional Lucide Matches (${lucideExtras.length})\n\n`;
|
|
248
|
+
out += `Names from the full Lucide library (not curated but supported via \`${libraryInfo.libraryName}\`):\n\n`;
|
|
249
|
+
lucideExtras.forEach((name) => {
|
|
250
|
+
out += `- **${name}** — \`import { ${name} } from '${libraryInfo.libraryName}'\`\n`;
|
|
251
|
+
});
|
|
252
|
+
out += '\n';
|
|
253
|
+
}
|
|
254
|
+
out += `---\n\nBrowse the full Lucide library (~${libraryInfo.totalIcons.toLocaleString()} icons): ${libraryInfo.browseUrl}\n`;
|
|
255
|
+
return out;
|
|
256
|
+
}
|
|
257
|
+
//# sourceMappingURL=search-icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-icons.js","sourceRoot":"","sources":["../../src/tools/search-icons.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error envelope (#15).
|
|
3
|
+
*
|
|
4
|
+
* Three-class classifier so the client gets useful errors for the things it
|
|
5
|
+
* can fix (validation, MCP-defined codes) and an opaque correlation ID for
|
|
6
|
+
* anything else. error.message is NEVER passed to the client because it may
|
|
7
|
+
* contain stack frames, ts-morph paths, or other filesystem disclosures.
|
|
8
|
+
* A levelled logger replaces console.error in Sprint 3 (#12).
|
|
9
|
+
*/
|
|
10
|
+
import { McpError } from '@modelcontextprotocol/sdk/types.js';
|
|
11
|
+
/** Reset the sequence — test-only. */
|
|
12
|
+
export declare function _resetErrorIdSeq(): void;
|
|
13
|
+
export declare function handleError(error: unknown, logger?: (message: string, error: unknown) => void): McpError;
|
|
14
|
+
//# sourceMappingURL=error-envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-envelope.d.ts","sourceRoot":"","sources":["../../src/utils/error-envelope.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,QAAQ,EAAa,MAAM,oCAAoC,CAAA;AAIxE,sCAAsC;AACtC,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAOD,wBAAgB,WAAW,CACzB,KAAK,EAAE,OAAO,EACd,MAAM,GAAE,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAwC,GACpF,QAAQ,CAeV"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error envelope (#15).
|
|
3
|
+
*
|
|
4
|
+
* Three-class classifier so the client gets useful errors for the things it
|
|
5
|
+
* can fix (validation, MCP-defined codes) and an opaque correlation ID for
|
|
6
|
+
* anything else. error.message is NEVER passed to the client because it may
|
|
7
|
+
* contain stack frames, ts-morph paths, or other filesystem disclosures.
|
|
8
|
+
* A levelled logger replaces console.error in Sprint 3 (#12).
|
|
9
|
+
*/
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
|
|
12
|
+
let errorIdSeq = 0;
|
|
13
|
+
/** Reset the sequence — test-only. */
|
|
14
|
+
export function _resetErrorIdSeq() {
|
|
15
|
+
errorIdSeq = 0;
|
|
16
|
+
}
|
|
17
|
+
function nextErrorId() {
|
|
18
|
+
errorIdSeq = (errorIdSeq + 1) >>> 0;
|
|
19
|
+
return errorIdSeq.toString(36).padStart(4, '0');
|
|
20
|
+
}
|
|
21
|
+
export function handleError(error, logger = (msg, e) => console.error(msg, e)) {
|
|
22
|
+
if (error instanceof McpError) {
|
|
23
|
+
return error;
|
|
24
|
+
}
|
|
25
|
+
if (error instanceof z.ZodError) {
|
|
26
|
+
const summary = error.errors
|
|
27
|
+
.map((e) => `${e.path.join('.') || '(root)'}: ${e.message}`)
|
|
28
|
+
.join('; ');
|
|
29
|
+
return new McpError(ErrorCode.InvalidParams, `Invalid arguments: ${summary}`);
|
|
30
|
+
}
|
|
31
|
+
const id = nextErrorId();
|
|
32
|
+
logger(`[mcp][error id=${id}]`, error);
|
|
33
|
+
return new McpError(ErrorCode.InternalError, `Internal error (id=${id})`);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=error-envelope.js.map
|