@synergy-design-system/mcp 3.6.0 → 3.8.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 +30 -0
- package/README.md +207 -18
- package/dist/middleware/index.d.ts +1 -0
- package/dist/middleware/index.js +1 -0
- package/dist/middleware/logging.d.ts +5 -5
- package/dist/middleware/logging.js +72 -0
- package/dist/prompts/component-rules.d.ts +2 -0
- package/dist/prompts/component-rules.js +36 -0
- package/dist/prompts/index.d.ts +1 -0
- package/dist/prompts/index.js +1 -0
- package/dist/resources/index.d.ts +1 -0
- package/dist/resources/index.js +1 -0
- package/dist/resources/intent-categories-list.d.ts +7 -0
- package/dist/resources/intent-categories-list.js +25 -0
- package/dist/server.js +23 -6
- package/dist/tools/component-info.js +5 -2
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/intent-categories-list.d.ts +6 -0
- package/dist/tools/intent-categories-list.js +26 -0
- package/dist/tools/intent-component-guide.d.ts +6 -0
- package/dist/tools/intent-component-guide.js +33 -0
- package/dist/tools/intent-component-validate.d.ts +6 -0
- package/dist/tools/intent-component-validate.js +169 -0
- package/dist/tools/intent-options.d.ts +6 -0
- package/dist/tools/intent-options.js +48 -0
- package/dist/tools/intent-task-recommendations.d.ts +6 -0
- package/dist/tools/intent-task-recommendations.js +54 -0
- package/dist/types/prompt-response.d.ts +14 -0
- package/dist/types/prompt-response.js +1 -0
- package/dist/utilities/config.d.ts +74 -1
- package/dist/utilities/config.js +123 -1
- package/dist/utilities/index.d.ts +1 -0
- package/dist/utilities/index.js +1 -0
- package/dist/utilities/intent.d.ts +27 -0
- package/dist/utilities/intent.js +26 -0
- package/dist/utilities/metadata.d.ts +16 -0
- package/dist/utilities/metadata.js +109 -14
- package/package.json +2 -2
package/dist/tools/index.js
CHANGED
|
@@ -7,6 +7,11 @@ export * from './davinci-migration-info.js';
|
|
|
7
7
|
export * from './davinci-migration-list.js';
|
|
8
8
|
export * from './migration-info.js';
|
|
9
9
|
export * from './migration-list.js';
|
|
10
|
+
export * from './intent-categories-list.js';
|
|
11
|
+
export * from './intent-component-guide.js';
|
|
12
|
+
export * from './intent-component-validate.js';
|
|
13
|
+
export * from './intent-task-recommendations.js';
|
|
14
|
+
export * from './intent-options.js';
|
|
10
15
|
export * from './setup.js';
|
|
11
16
|
export * from './styles-info.js';
|
|
12
17
|
export * from './styles-list.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Lists available intent categories from the experimental intent policy layer.
|
|
4
|
+
* @param server The MCP server instance used for tool registration.
|
|
5
|
+
*/
|
|
6
|
+
export declare const intentCategoriesListTool: (server: McpServer) => void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { experimental_listIntentCategories as listIntentCategories, } from '@synergy-design-system/metadata';
|
|
3
|
+
import { INTENT_DEFAULT_PHASES, createToolAnnotations, getRuntimeConfig, getToolRule, intentPhaseSchema, toolHandler, } from '../utilities/index.js';
|
|
4
|
+
/**
|
|
5
|
+
* Lists available intent categories from the experimental intent policy layer.
|
|
6
|
+
* @param server The MCP server instance used for tool registration.
|
|
7
|
+
*/
|
|
8
|
+
export const intentCategoriesListTool = (server) => {
|
|
9
|
+
server.registerTool('intent-categories-list', {
|
|
10
|
+
annotations: createToolAnnotations(),
|
|
11
|
+
description: 'List available intent categories in the intent policy layer.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
includePhases: z.array(intentPhaseSchema).optional().describe('Optional phase filter. Defaults to ["experimental"].'),
|
|
14
|
+
},
|
|
15
|
+
title: 'Intent categories list',
|
|
16
|
+
}, toolHandler('intent-categories-list', async ({ includePhases, }) => {
|
|
17
|
+
const toolDefaults = getRuntimeConfig().tools.intentCategoriesList;
|
|
18
|
+
const aiRules = await getToolRule('intent-categories-list');
|
|
19
|
+
const response = await listIntentCategories({}, { includePhases: includePhases ?? toolDefaults.includePhases ?? [...INTENT_DEFAULT_PHASES] });
|
|
20
|
+
if (!response.data) {
|
|
21
|
+
const message = response.errors?.[0]?.message ?? 'No intent categories found.';
|
|
22
|
+
return [aiRules, message];
|
|
23
|
+
}
|
|
24
|
+
return [aiRules, response.data];
|
|
25
|
+
}));
|
|
26
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns intent-focused usage guidance for a component.
|
|
4
|
+
* @param server The MCP server instance used for tool registration.
|
|
5
|
+
*/
|
|
6
|
+
export declare const intentComponentGuideTool: (server: McpServer) => void;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { experimental_getComponentGuide as getComponentGuide, } from '@synergy-design-system/metadata';
|
|
3
|
+
import { INTENT_DEFAULT_FRAMEWORK, INTENT_DEFAULT_PHASES, createToolAnnotations, getRuntimeConfig, getToolRule, intentFrameworkSchema, intentPhaseSchema, toolHandler, } from '../utilities/index.js';
|
|
4
|
+
const frameworkSchema = intentFrameworkSchema;
|
|
5
|
+
/**
|
|
6
|
+
* Returns intent-focused usage guidance for a component.
|
|
7
|
+
* @param server The MCP server instance used for tool registration.
|
|
8
|
+
*/
|
|
9
|
+
export const intentComponentGuideTool = (server) => {
|
|
10
|
+
server.registerTool('intent-component-guide', {
|
|
11
|
+
annotations: createToolAnnotations(),
|
|
12
|
+
description: 'Answer the question: What can I do with this component in the intent system?',
|
|
13
|
+
inputSchema: {
|
|
14
|
+
component: z.string().startsWith('syn-').describe('Component tag name, for example syn-button.'),
|
|
15
|
+
framework: frameworkSchema.optional().describe('Target framework profile. Defaults to vanilla.'),
|
|
16
|
+
includePhases: z.array(intentPhaseSchema).optional().describe('Optional phase filter. Defaults to ["experimental"].'),
|
|
17
|
+
},
|
|
18
|
+
title: 'Intent component guide',
|
|
19
|
+
}, toolHandler('intent-component-guide', async ({ component, framework, includePhases, }) => {
|
|
20
|
+
const toolDefaults = getRuntimeConfig().tools.intentComponentGuide;
|
|
21
|
+
const aiRules = await getToolRule('intent-component-guide');
|
|
22
|
+
const response = await getComponentGuide({
|
|
23
|
+
component,
|
|
24
|
+
framework: framework ?? toolDefaults.framework ?? INTENT_DEFAULT_FRAMEWORK,
|
|
25
|
+
includePhases: includePhases ?? toolDefaults.includePhases ?? [...INTENT_DEFAULT_PHASES],
|
|
26
|
+
});
|
|
27
|
+
if (!response.data) {
|
|
28
|
+
const message = response.errors?.[0]?.message ?? `No intent guide found for component ${component}.`;
|
|
29
|
+
return [aiRules, message];
|
|
30
|
+
}
|
|
31
|
+
return [aiRules, response.data];
|
|
32
|
+
}));
|
|
33
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Validates whether a component usage matches intent rules.
|
|
4
|
+
* @param server The MCP server instance used for tool registration.
|
|
5
|
+
*/
|
|
6
|
+
export declare const intentComponentValidateTool: (server: McpServer) => void;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { experimental_validateComponent as validateComponent, } from '@synergy-design-system/metadata';
|
|
3
|
+
import { INTENT_DEFAULT_FRAMEWORK, INTENT_DEFAULT_PHASES, createToolAnnotations, getRuntimeConfig, getToolRule, intentFrameworkSchema, intentPhaseSchema, toolHandler, } from '../utilities/index.js';
|
|
4
|
+
const frameworkSchema = intentFrameworkSchema;
|
|
5
|
+
const parsePrimitiveValue = (rawValue, isBinding) => {
|
|
6
|
+
if (rawValue === undefined) {
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
const value = rawValue.trim();
|
|
10
|
+
if (value === 'true') {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
if (value === 'false') {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (value === 'null') {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (isBinding && /^-?\d+(\.\d+)?$/.test(value)) {
|
|
20
|
+
return Number(value);
|
|
21
|
+
}
|
|
22
|
+
return value;
|
|
23
|
+
};
|
|
24
|
+
const parseAttribute = (match) => {
|
|
25
|
+
const rawName = match[1] ?? '';
|
|
26
|
+
const rawValue = match[2] ?? match[3] ?? match[4];
|
|
27
|
+
const shouldSkip = rawName.startsWith('(')
|
|
28
|
+
|| rawName.startsWith('#')
|
|
29
|
+
|| rawName.startsWith('*')
|
|
30
|
+
|| rawName.startsWith('@');
|
|
31
|
+
const bracketBinding = rawName.startsWith('[') && rawName.endsWith(']');
|
|
32
|
+
const withoutBrackets = bracketBinding ? rawName.slice(1, -1) : rawName;
|
|
33
|
+
const normalizedName = withoutBrackets.startsWith('attr.')
|
|
34
|
+
? withoutBrackets.slice(5)
|
|
35
|
+
: withoutBrackets;
|
|
36
|
+
return {
|
|
37
|
+
isBinding: bracketBinding,
|
|
38
|
+
name: normalizedName,
|
|
39
|
+
rawValue,
|
|
40
|
+
shouldSkip,
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const parseAttributes = (source) => {
|
|
44
|
+
const attrPattern = /([^\s=/>]+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'=<>`]+)))?/g;
|
|
45
|
+
const matches = Array.from(source.matchAll(attrPattern));
|
|
46
|
+
const reduced = matches.reduce((acc, match) => {
|
|
47
|
+
const parsed = parseAttribute(match);
|
|
48
|
+
if (parsed.shouldSkip) {
|
|
49
|
+
return acc;
|
|
50
|
+
}
|
|
51
|
+
if (parsed.name === 'class') {
|
|
52
|
+
if (parsed.rawValue) {
|
|
53
|
+
acc.classes.push(...parsed.rawValue.split(/\s+/).filter(Boolean));
|
|
54
|
+
}
|
|
55
|
+
return acc;
|
|
56
|
+
}
|
|
57
|
+
if (parsed.name === 'role') {
|
|
58
|
+
acc.role = parsed.rawValue ?? 'true';
|
|
59
|
+
return acc;
|
|
60
|
+
}
|
|
61
|
+
if (parsed.name === 'slot') {
|
|
62
|
+
acc.slot = parsed.rawValue ?? 'true';
|
|
63
|
+
return acc;
|
|
64
|
+
}
|
|
65
|
+
acc.props[parsed.name] = parsePrimitiveValue(parsed.rawValue, parsed.isBinding);
|
|
66
|
+
return acc;
|
|
67
|
+
}, {
|
|
68
|
+
classes: [],
|
|
69
|
+
props: {},
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
...(reduced.classes.length > 0 ? { classes: Array.from(new Set(reduced.classes)) } : {}),
|
|
73
|
+
...(Object.keys(reduced.props).length > 0 ? { props: reduced.props } : {}),
|
|
74
|
+
...(reduced.role ? { role: reduced.role } : {}),
|
|
75
|
+
...(reduced.slot ? { slot: reduced.slot } : {}),
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
const findFirstNodeByComponent = (nodes, component) => {
|
|
79
|
+
const directMatch = nodes.find((node) => node.component === component);
|
|
80
|
+
if (directMatch) {
|
|
81
|
+
return directMatch;
|
|
82
|
+
}
|
|
83
|
+
return nodes
|
|
84
|
+
.map((node) => (node.children && node.children.length > 0 ? findFirstNodeByComponent(node.children, component) : undefined))
|
|
85
|
+
.find((node) => Boolean(node));
|
|
86
|
+
};
|
|
87
|
+
const parseMarkupToStructure = (markup) => {
|
|
88
|
+
const tokenPattern = /<!--[\s\S]*?-->|<\/?[a-zA-Z][\w:-]*\b[^>]*\/?>|[^<]+/g;
|
|
89
|
+
const root = { children: [], component: '__root__' };
|
|
90
|
+
const stack = [root];
|
|
91
|
+
const tokens = markup.match(tokenPattern) ?? [];
|
|
92
|
+
tokens.forEach((token) => {
|
|
93
|
+
const currentParent = stack[stack.length - 1];
|
|
94
|
+
if (token && !token.startsWith('<!--') && token.startsWith('</')) {
|
|
95
|
+
const closeName = token.slice(2, -1).trim().toLowerCase();
|
|
96
|
+
while (stack.length > 1) {
|
|
97
|
+
const top = stack.pop();
|
|
98
|
+
if (top?.component.toLowerCase() === closeName) {
|
|
99
|
+
break;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (token && !token.startsWith('<!--') && token.startsWith('<')) {
|
|
104
|
+
const openMatch = token.match(/^<([a-zA-Z][\w:-]*)([^>]*)\/?>(?:\s*)$/);
|
|
105
|
+
if (openMatch) {
|
|
106
|
+
const tagName = (openMatch[1] ?? '').toLowerCase();
|
|
107
|
+
const attrSource = openMatch[2] ?? '';
|
|
108
|
+
const isSelfClosing = token.endsWith('/>');
|
|
109
|
+
const node = {
|
|
110
|
+
component: tagName,
|
|
111
|
+
...parseAttributes(attrSource),
|
|
112
|
+
};
|
|
113
|
+
currentParent.children = currentParent.children ?? [];
|
|
114
|
+
currentParent.children.push(node);
|
|
115
|
+
if (!isSelfClosing) {
|
|
116
|
+
stack.push(node);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (token && !token.startsWith('<!--')) {
|
|
121
|
+
const normalizedText = token.replace(/\s+/g, ' ').trim();
|
|
122
|
+
if (!normalizedText) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
currentParent.children = currentParent.children ?? [];
|
|
126
|
+
currentParent.children.push({ component: 'text', text: normalizedText });
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return root.children ?? [];
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Validates whether a component usage matches intent rules.
|
|
133
|
+
* @param server The MCP server instance used for tool registration.
|
|
134
|
+
*/
|
|
135
|
+
export const intentComponentValidateTool = (server) => {
|
|
136
|
+
server.registerTool('intent-component-validate', {
|
|
137
|
+
annotations: createToolAnnotations(),
|
|
138
|
+
description: 'Answer the question: Do I use a component correctly for a specific intent?',
|
|
139
|
+
inputSchema: {
|
|
140
|
+
component: z.string().startsWith('syn-').describe('Component tag name, for example syn-button.'),
|
|
141
|
+
framework: frameworkSchema.optional().describe('Target framework profile. Defaults to vanilla.'),
|
|
142
|
+
includePhases: z.array(intentPhaseSchema).optional().describe('Optional phase filter. Defaults to ["experimental"].'),
|
|
143
|
+
intent: z.string().min(1).describe('Intent ID, for example action.submit.'),
|
|
144
|
+
markup: z.string().min(1).describe('Template or markup source. The tool auto-derives structure for validation from this content.'),
|
|
145
|
+
},
|
|
146
|
+
title: 'Intent component validate',
|
|
147
|
+
}, toolHandler('intent-component-validate', async ({ component, framework, includePhases, intent, markup, }) => {
|
|
148
|
+
const { tools } = getRuntimeConfig();
|
|
149
|
+
const aiRules = await getToolRule('intent-component-validate');
|
|
150
|
+
const parsedNodes = parseMarkupToStructure(markup);
|
|
151
|
+
const normalizedStructure = findFirstNodeByComponent(parsedNodes, component)
|
|
152
|
+
?? {
|
|
153
|
+
children: parsedNodes,
|
|
154
|
+
component,
|
|
155
|
+
};
|
|
156
|
+
const response = await validateComponent({
|
|
157
|
+
component,
|
|
158
|
+
framework: framework ?? tools.intentComponentValidate.framework ?? INTENT_DEFAULT_FRAMEWORK,
|
|
159
|
+
includePhases: includePhases ?? tools.intentComponentValidate.includePhases ?? [...INTENT_DEFAULT_PHASES],
|
|
160
|
+
intent,
|
|
161
|
+
structure: normalizedStructure,
|
|
162
|
+
});
|
|
163
|
+
if (!response.data) {
|
|
164
|
+
const message = response.errors?.[0]?.message ?? `No validation result available for component ${component}.`;
|
|
165
|
+
return [aiRules, message];
|
|
166
|
+
}
|
|
167
|
+
return [aiRules, response.data];
|
|
168
|
+
}));
|
|
169
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Returns renderable target options for a specific intent.
|
|
4
|
+
* @param server The MCP server instance used for tool registration.
|
|
5
|
+
*/
|
|
6
|
+
export declare const intentOptionsTool: (server: McpServer) => void;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { experimental_getIntentOptions as getIntentOptions, } from '@synergy-design-system/metadata';
|
|
3
|
+
import { INTENT_DEFAULT_FRAMEWORK, INTENT_DEFAULT_PHASES, createToolAnnotations, getRuntimeConfig, getToolRule, intentFrameworkSchema, intentPhaseSchema, toolHandler, } from '../utilities/index.js';
|
|
4
|
+
const frameworkSchema = intentFrameworkSchema;
|
|
5
|
+
/**
|
|
6
|
+
* Returns renderable target options for a specific intent.
|
|
7
|
+
* @param server The MCP server instance used for tool registration.
|
|
8
|
+
*/
|
|
9
|
+
export const intentOptionsTool = (server) => {
|
|
10
|
+
server.registerTool('intent-options', {
|
|
11
|
+
annotations: createToolAnnotations(),
|
|
12
|
+
description: 'Answer the question: What are my renderable options for a specific intent?',
|
|
13
|
+
inputSchema: {
|
|
14
|
+
content: z.string().optional().describe('Optional content used in preview snippets.'),
|
|
15
|
+
framework: frameworkSchema.optional().describe('Target framework profile. Defaults to vanilla.'),
|
|
16
|
+
includeDiagnostics: z.boolean().optional().describe('Include non-renderable candidates for diagnostics.'),
|
|
17
|
+
includePhases: z.array(intentPhaseSchema).optional().describe('Optional phase filter. Defaults to ["experimental"].'),
|
|
18
|
+
intentId: z
|
|
19
|
+
.string()
|
|
20
|
+
.min(1)
|
|
21
|
+
.describe('Intent ID to resolve, for example action.submit. Can be obtained by calling intent-categories-list tool.'),
|
|
22
|
+
maxAlternatives: z
|
|
23
|
+
.number()
|
|
24
|
+
.int()
|
|
25
|
+
.min(1)
|
|
26
|
+
.max(20)
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Maximum number of alternatives.'),
|
|
29
|
+
},
|
|
30
|
+
title: 'Intent options',
|
|
31
|
+
}, toolHandler('intent-options', async ({ content, framework, includeDiagnostics, includePhases, intentId, maxAlternatives, }) => {
|
|
32
|
+
const { tools } = getRuntimeConfig();
|
|
33
|
+
const aiRules = await getToolRule('intent-options');
|
|
34
|
+
const response = await getIntentOptions({
|
|
35
|
+
content,
|
|
36
|
+
framework: framework ?? tools.intentOptions.framework ?? INTENT_DEFAULT_FRAMEWORK,
|
|
37
|
+
includeDiagnostics: includeDiagnostics ?? tools.intentOptions.includeDiagnostics,
|
|
38
|
+
includePhases: includePhases ?? tools.intentOptions.includePhases ?? [...INTENT_DEFAULT_PHASES],
|
|
39
|
+
intentId,
|
|
40
|
+
maxAlternatives: maxAlternatives ?? tools.intentOptions.maxAlternatives,
|
|
41
|
+
});
|
|
42
|
+
if (!response.data) {
|
|
43
|
+
const message = response.errors?.[0]?.message ?? `No intent options found for ${intentId}.`;
|
|
44
|
+
return [aiRules, message];
|
|
45
|
+
}
|
|
46
|
+
return [aiRules, response.data];
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
/**
|
|
3
|
+
* Recommends components for a task represented by an intent ID.
|
|
4
|
+
* @param server The MCP server instance used for tool registration.
|
|
5
|
+
*/
|
|
6
|
+
export declare const intentTaskRecommendationsTool: (server: McpServer) => void;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { experimental_findComponentsForTask as findComponentsForTask, } from '@synergy-design-system/metadata';
|
|
3
|
+
import { INTENT_DEFAULT_FRAMEWORK, INTENT_DEFAULT_PHASES, createToolAnnotations, getRuntimeConfig, getToolRule, intentFrameworkSchema, intentPhaseSchema, toolHandler, } from '../utilities/index.js';
|
|
4
|
+
const frameworkSchema = intentFrameworkSchema;
|
|
5
|
+
/**
|
|
6
|
+
* Recommends components for a task represented by an intent ID.
|
|
7
|
+
* @param server The MCP server instance used for tool registration.
|
|
8
|
+
*/
|
|
9
|
+
export const intentTaskRecommendationsTool = (server) => {
|
|
10
|
+
server.registerTool('intent-task-recommendations', {
|
|
11
|
+
annotations: createToolAnnotations(),
|
|
12
|
+
description: 'Answer the question: What does Synergy provide for a specific task intent?',
|
|
13
|
+
inputSchema: {
|
|
14
|
+
avoidTargets: z.array(z.string()).optional().describe('Optional target IDs to avoid.'),
|
|
15
|
+
content: z.string().optional().describe('Optional content used in render snippets.'),
|
|
16
|
+
framework: frameworkSchema.optional().describe('Target framework profile. Defaults to vanilla.'),
|
|
17
|
+
includePhases: z.array(intentPhaseSchema).optional().describe('Optional phase filter. Defaults to ["experimental"].'),
|
|
18
|
+
maxAlternatives: z
|
|
19
|
+
.number()
|
|
20
|
+
.int()
|
|
21
|
+
.min(1)
|
|
22
|
+
.max(20)
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Maximum number of alternatives.'),
|
|
25
|
+
preferredTargets: z.array(z.string()).optional().describe('Optional preferred target IDs for ranking.'),
|
|
26
|
+
taskId: z
|
|
27
|
+
.string()
|
|
28
|
+
.min(1)
|
|
29
|
+
.describe('Intent ID representing the task, for example action.submit. Can be obtained by calling intent-categories-list tool.'),
|
|
30
|
+
},
|
|
31
|
+
title: 'Intent task recommendations',
|
|
32
|
+
}, toolHandler('intent-task-recommendations', async ({ avoidTargets, content, framework, includePhases, maxAlternatives, preferredTargets, taskId, }) => {
|
|
33
|
+
const { tools } = getRuntimeConfig();
|
|
34
|
+
const aiRules = await getToolRule('intent-task-recommendations');
|
|
35
|
+
const hasConstraints = Boolean((preferredTargets && preferredTargets.length > 0)
|
|
36
|
+
|| (avoidTargets && avoidTargets.length > 0));
|
|
37
|
+
const response = await findComponentsForTask({
|
|
38
|
+
constraints: hasConstraints ? {
|
|
39
|
+
avoidTargets,
|
|
40
|
+
preferredTargets,
|
|
41
|
+
} : undefined,
|
|
42
|
+
content,
|
|
43
|
+
framework: framework ?? tools.intentTaskRecommendations.framework ?? INTENT_DEFAULT_FRAMEWORK,
|
|
44
|
+
includePhases: includePhases ?? tools.intentTaskRecommendations.includePhases ?? [...INTENT_DEFAULT_PHASES],
|
|
45
|
+
maxAlternatives: maxAlternatives ?? tools.intentTaskRecommendations.maxAlternatives,
|
|
46
|
+
taskId,
|
|
47
|
+
});
|
|
48
|
+
if (!response.data) {
|
|
49
|
+
const message = response.errors?.[0]?.message ?? `No recommendations found for task ${taskId}.`;
|
|
50
|
+
return [aiRules, message];
|
|
51
|
+
}
|
|
52
|
+
return [aiRules, response.data];
|
|
53
|
+
}));
|
|
54
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PromptResponse type from MCP SDK representing a prompt response.
|
|
3
|
+
* Contains description and messages for the prompt result.
|
|
4
|
+
*/
|
|
5
|
+
export type PromptResponse = {
|
|
6
|
+
description: string;
|
|
7
|
+
messages: Array<{
|
|
8
|
+
content: {
|
|
9
|
+
text: string;
|
|
10
|
+
type: 'text';
|
|
11
|
+
};
|
|
12
|
+
role: 'user' | 'assistant';
|
|
13
|
+
}>;
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -8,6 +8,7 @@ export declare const McpRuntimeConfigSchema: z.ZodObject<{
|
|
|
8
8
|
none: "none";
|
|
9
9
|
toon: "toon";
|
|
10
10
|
}>>;
|
|
11
|
+
experimentalFeatures: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodBoolean>>;
|
|
11
12
|
host: z.ZodDefault<z.ZodString>;
|
|
12
13
|
includeAiRules: z.ZodDefault<z.ZodBoolean>;
|
|
13
14
|
interface: z.ZodDefault<z.ZodEnum<{
|
|
@@ -45,14 +46,15 @@ export declare const McpRuntimeConfigSchema: z.ZodObject<{
|
|
|
45
46
|
componentInfo: z.ZodDefault<z.ZodObject<{
|
|
46
47
|
framework: z.ZodDefault<z.ZodEnum<{
|
|
47
48
|
angular: "angular";
|
|
48
|
-
react: "react";
|
|
49
49
|
vue: "vue";
|
|
50
50
|
vanilla: "vanilla";
|
|
51
|
+
react: "react";
|
|
51
52
|
}>>;
|
|
52
53
|
layer: z.ZodDefault<z.ZodEnum<{
|
|
53
54
|
full: "full";
|
|
54
55
|
examples: "examples";
|
|
55
56
|
interface: "interface";
|
|
57
|
+
rules: "rules";
|
|
56
58
|
}>>;
|
|
57
59
|
}, z.core.$strip>>;
|
|
58
60
|
davinciMigrationInfo: z.ZodDefault<z.ZodObject<{
|
|
@@ -67,6 +69,77 @@ export declare const McpRuntimeConfigSchema: z.ZodObject<{
|
|
|
67
69
|
"dashboard-elements": "dashboard-elements";
|
|
68
70
|
}>>;
|
|
69
71
|
}, z.core.$strip>>;
|
|
72
|
+
intentCategoriesList: z.ZodDefault<z.ZodObject<{
|
|
73
|
+
includePhases: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
74
|
+
stable: "stable";
|
|
75
|
+
deprecated: "deprecated";
|
|
76
|
+
experimental: "experimental";
|
|
77
|
+
preview: "preview";
|
|
78
|
+
}>>>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
80
|
+
intentComponentGuide: z.ZodDefault<z.ZodObject<{
|
|
81
|
+
framework: z.ZodDefault<z.ZodEnum<{
|
|
82
|
+
"react-wrapper": "react-wrapper";
|
|
83
|
+
"react-web-components": "react-web-components";
|
|
84
|
+
angular: "angular";
|
|
85
|
+
vue: "vue";
|
|
86
|
+
vanilla: "vanilla";
|
|
87
|
+
}>>;
|
|
88
|
+
includePhases: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
89
|
+
stable: "stable";
|
|
90
|
+
deprecated: "deprecated";
|
|
91
|
+
experimental: "experimental";
|
|
92
|
+
preview: "preview";
|
|
93
|
+
}>>>;
|
|
94
|
+
}, z.core.$strip>>;
|
|
95
|
+
intentComponentValidate: z.ZodDefault<z.ZodObject<{
|
|
96
|
+
framework: z.ZodDefault<z.ZodEnum<{
|
|
97
|
+
"react-wrapper": "react-wrapper";
|
|
98
|
+
"react-web-components": "react-web-components";
|
|
99
|
+
angular: "angular";
|
|
100
|
+
vue: "vue";
|
|
101
|
+
vanilla: "vanilla";
|
|
102
|
+
}>>;
|
|
103
|
+
includePhases: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
104
|
+
stable: "stable";
|
|
105
|
+
deprecated: "deprecated";
|
|
106
|
+
experimental: "experimental";
|
|
107
|
+
preview: "preview";
|
|
108
|
+
}>>>;
|
|
109
|
+
}, z.core.$strip>>;
|
|
110
|
+
intentOptions: z.ZodDefault<z.ZodObject<{
|
|
111
|
+
framework: z.ZodDefault<z.ZodEnum<{
|
|
112
|
+
"react-wrapper": "react-wrapper";
|
|
113
|
+
"react-web-components": "react-web-components";
|
|
114
|
+
angular: "angular";
|
|
115
|
+
vue: "vue";
|
|
116
|
+
vanilla: "vanilla";
|
|
117
|
+
}>>;
|
|
118
|
+
includeDiagnostics: z.ZodDefault<z.ZodBoolean>;
|
|
119
|
+
includePhases: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
120
|
+
stable: "stable";
|
|
121
|
+
deprecated: "deprecated";
|
|
122
|
+
experimental: "experimental";
|
|
123
|
+
preview: "preview";
|
|
124
|
+
}>>>;
|
|
125
|
+
maxAlternatives: z.ZodDefault<z.ZodNumber>;
|
|
126
|
+
}, z.core.$strip>>;
|
|
127
|
+
intentTaskRecommendations: z.ZodDefault<z.ZodObject<{
|
|
128
|
+
framework: z.ZodDefault<z.ZodEnum<{
|
|
129
|
+
"react-wrapper": "react-wrapper";
|
|
130
|
+
"react-web-components": "react-web-components";
|
|
131
|
+
angular: "angular";
|
|
132
|
+
vue: "vue";
|
|
133
|
+
vanilla: "vanilla";
|
|
134
|
+
}>>;
|
|
135
|
+
includePhases: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
136
|
+
stable: "stable";
|
|
137
|
+
deprecated: "deprecated";
|
|
138
|
+
experimental: "experimental";
|
|
139
|
+
preview: "preview";
|
|
140
|
+
}>>>;
|
|
141
|
+
maxAlternatives: z.ZodDefault<z.ZodNumber>;
|
|
142
|
+
}, z.core.$strip>>;
|
|
70
143
|
migrationInfo: z.ZodDefault<z.ZodObject<{
|
|
71
144
|
synergyPackage: z.ZodDefault<z.ZodEnum<{
|
|
72
145
|
components: "components";
|
package/dist/utilities/config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { INTENT_DEFAULT_FRAMEWORK, INTENT_DEFAULT_PHASES, INTENT_FRAMEWORK_VALUES, INTENT_PHASE_VALUES, } from './intent.js';
|
|
3
4
|
/**
|
|
4
5
|
* Zod schema for the synergy-mcp.json configuration file.
|
|
5
6
|
* All fields are optional and fall back to built-in defaults when absent.
|
|
@@ -12,6 +13,18 @@ export const McpRuntimeConfigSchema = z.object({
|
|
|
12
13
|
* @default 'none'
|
|
13
14
|
*/
|
|
14
15
|
compression: z.enum(['none', 'toon']).default('none'),
|
|
16
|
+
/**
|
|
17
|
+
* Experimental feature toggles.
|
|
18
|
+
*
|
|
19
|
+
* Tools or capabilities guarded by these flags are disabled unless
|
|
20
|
+
* explicitly enabled.
|
|
21
|
+
*
|
|
22
|
+
* Known keys:
|
|
23
|
+
* - intentTools: Enables experimental intent MCP tools.
|
|
24
|
+
*
|
|
25
|
+
* @default {}
|
|
26
|
+
*/
|
|
27
|
+
experimentalFeatures: z.record(z.string(), z.boolean()).default({}),
|
|
15
28
|
/**
|
|
16
29
|
* HTTP server host/interface when interface is 'http'.
|
|
17
30
|
* Use 127.0.0.1 for local-only access or 0.0.0.0 to listen on all IPv4 interfaces.
|
|
@@ -110,7 +123,7 @@ export const McpRuntimeConfigSchema = z.object({
|
|
|
110
123
|
* Default metadata layer when no layer is provided by the caller.
|
|
111
124
|
* @default 'interface'
|
|
112
125
|
*/
|
|
113
|
-
layer: z.enum(['full', 'examples', 'interface']).default('interface'),
|
|
126
|
+
layer: z.enum(['full', 'examples', 'interface', 'rules']).default('interface'),
|
|
114
127
|
}).default({ framework: 'vanilla', layer: 'interface' }),
|
|
115
128
|
davinciMigrationInfo: z.object({
|
|
116
129
|
/**
|
|
@@ -126,6 +139,101 @@ export const McpRuntimeConfigSchema = z.object({
|
|
|
126
139
|
*/
|
|
127
140
|
package: z.enum(['basic-elements', 'dashboard-elements']).default('basic-elements'),
|
|
128
141
|
}).default({ package: 'basic-elements' }),
|
|
142
|
+
intentCategoriesList: z.object({
|
|
143
|
+
/**
|
|
144
|
+
* Default intent phases when none are provided by the caller.
|
|
145
|
+
* @default ['experimental']
|
|
146
|
+
*/
|
|
147
|
+
includePhases: z.array(z.enum(INTENT_PHASE_VALUES)).default([...INTENT_DEFAULT_PHASES]),
|
|
148
|
+
}).default({ includePhases: [...INTENT_DEFAULT_PHASES] }),
|
|
149
|
+
intentComponentGuide: z.object({
|
|
150
|
+
/**
|
|
151
|
+
* Default framework when no framework is provided by the caller.
|
|
152
|
+
* @default 'vanilla'
|
|
153
|
+
*/
|
|
154
|
+
framework: z.enum(INTENT_FRAMEWORK_VALUES).default(INTENT_DEFAULT_FRAMEWORK),
|
|
155
|
+
/**
|
|
156
|
+
* Default intent phases when none are provided by the caller.
|
|
157
|
+
* @default ['experimental']
|
|
158
|
+
*/
|
|
159
|
+
includePhases: z.array(z.enum(INTENT_PHASE_VALUES)).default([...INTENT_DEFAULT_PHASES]),
|
|
160
|
+
}).default({
|
|
161
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
162
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
163
|
+
}),
|
|
164
|
+
intentComponentValidate: z.object({
|
|
165
|
+
/**
|
|
166
|
+
* Default framework when no framework is provided by the caller.
|
|
167
|
+
* @default 'vanilla'
|
|
168
|
+
*/
|
|
169
|
+
framework: z.enum(INTENT_FRAMEWORK_VALUES).default(INTENT_DEFAULT_FRAMEWORK),
|
|
170
|
+
/**
|
|
171
|
+
* Default intent phases when none are provided by the caller.
|
|
172
|
+
* @default ['experimental']
|
|
173
|
+
*/
|
|
174
|
+
includePhases: z.array(z.enum(INTENT_PHASE_VALUES)).default([...INTENT_DEFAULT_PHASES]),
|
|
175
|
+
}).default({
|
|
176
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
177
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
178
|
+
}),
|
|
179
|
+
intentOptions: z.object({
|
|
180
|
+
/**
|
|
181
|
+
* Default framework when no framework is provided by the caller.
|
|
182
|
+
* @default 'vanilla'
|
|
183
|
+
*/
|
|
184
|
+
framework: z.enum(INTENT_FRAMEWORK_VALUES).default(INTENT_DEFAULT_FRAMEWORK),
|
|
185
|
+
/**
|
|
186
|
+
* Include non-renderable candidates by default.
|
|
187
|
+
* @default false
|
|
188
|
+
*/
|
|
189
|
+
includeDiagnostics: z.boolean().default(false),
|
|
190
|
+
/**
|
|
191
|
+
* Default intent phases when none are provided by the caller.
|
|
192
|
+
* @default ['experimental']
|
|
193
|
+
*/
|
|
194
|
+
includePhases: z.array(z.enum(INTENT_PHASE_VALUES)).default([...INTENT_DEFAULT_PHASES]),
|
|
195
|
+
/**
|
|
196
|
+
* Default maximum number of alternatives.
|
|
197
|
+
* @default 5
|
|
198
|
+
*/
|
|
199
|
+
maxAlternatives: z
|
|
200
|
+
.number()
|
|
201
|
+
.int()
|
|
202
|
+
.min(1)
|
|
203
|
+
.max(20)
|
|
204
|
+
.default(5),
|
|
205
|
+
}).default({
|
|
206
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
207
|
+
includeDiagnostics: false,
|
|
208
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
209
|
+
maxAlternatives: 5,
|
|
210
|
+
}),
|
|
211
|
+
intentTaskRecommendations: z.object({
|
|
212
|
+
/**
|
|
213
|
+
* Default framework when no framework is provided by the caller.
|
|
214
|
+
* @default 'vanilla'
|
|
215
|
+
*/
|
|
216
|
+
framework: z.enum(INTENT_FRAMEWORK_VALUES).default(INTENT_DEFAULT_FRAMEWORK),
|
|
217
|
+
/**
|
|
218
|
+
* Default intent phases when none are provided by the caller.
|
|
219
|
+
* @default ['experimental']
|
|
220
|
+
*/
|
|
221
|
+
includePhases: z.array(z.enum(INTENT_PHASE_VALUES)).default([...INTENT_DEFAULT_PHASES]),
|
|
222
|
+
/**
|
|
223
|
+
* Default maximum number of alternatives.
|
|
224
|
+
* @default 5
|
|
225
|
+
*/
|
|
226
|
+
maxAlternatives: z
|
|
227
|
+
.number()
|
|
228
|
+
.int()
|
|
229
|
+
.min(1)
|
|
230
|
+
.max(20)
|
|
231
|
+
.default(5),
|
|
232
|
+
}).default({
|
|
233
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
234
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
235
|
+
maxAlternatives: 5,
|
|
236
|
+
}),
|
|
129
237
|
migrationInfo: z.object({
|
|
130
238
|
/**
|
|
131
239
|
* Default Synergy package when none is provided by the caller.
|
|
@@ -159,6 +267,20 @@ export const McpRuntimeConfigSchema = z.object({
|
|
|
159
267
|
componentInfo: { framework: 'vanilla', layer: 'full' },
|
|
160
268
|
davinciMigrationInfo: { package: 'basic-elements' },
|
|
161
269
|
davinciMigrationList: { package: 'basic-elements' },
|
|
270
|
+
intentCategoriesList: { includePhases: [...INTENT_DEFAULT_PHASES] },
|
|
271
|
+
intentComponentGuide: { framework: INTENT_DEFAULT_FRAMEWORK, includePhases: [...INTENT_DEFAULT_PHASES] },
|
|
272
|
+
intentComponentValidate: { framework: INTENT_DEFAULT_FRAMEWORK, includePhases: [...INTENT_DEFAULT_PHASES] },
|
|
273
|
+
intentOptions: {
|
|
274
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
275
|
+
includeDiagnostics: false,
|
|
276
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
277
|
+
maxAlternatives: 5,
|
|
278
|
+
},
|
|
279
|
+
intentTaskRecommendations: {
|
|
280
|
+
framework: INTENT_DEFAULT_FRAMEWORK,
|
|
281
|
+
includePhases: [...INTENT_DEFAULT_PHASES],
|
|
282
|
+
maxAlternatives: 5,
|
|
283
|
+
},
|
|
162
284
|
migrationInfo: { synergyPackage: 'components' },
|
|
163
285
|
migrationList: { synergyPackage: 'components' },
|
|
164
286
|
setup: { includeLimitations: true },
|