-
Notifications
You must be signed in to change notification settings - Fork 30
Expand file tree
/
Copy pathget-ui-building-instructions.ts
More file actions
82 lines (68 loc) · 2.66 KB
/
get-ui-building-instructions.ts
File metadata and controls
82 lines (68 loc) · 2.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import type { McpServer } from 'tmcp';
import { GET_STORY_URLS_TOOL_NAME } from './get-story-urls.ts';
import { collectTelemetry } from '../telemetry.ts';
import uiInstructionsTemplate from '../ui-building-instructions.md';
import { errorToMCPContent } from '../utils/errors.ts';
import type { AddonContext } from '../types.ts';
export const GET_UI_BUILDING_INSTRUCTIONS_TOOL_NAME =
'get-ui-building-instructions';
export async function addGetUIBuildingInstructionsTool(
server: McpServer<any, AddonContext>,
) {
server.tool(
{
name: GET_UI_BUILDING_INSTRUCTIONS_TOOL_NAME,
title: 'UI Component Building Instructions',
description: `Instructions on how to do UI component development.
ALWAYS call this tool before doing any UI/frontend/React/component development, including but not
limited to adding or updating new components, pages, screens or layouts.`,
enabled: () => server.ctx.custom?.toolsets?.dev ?? true,
},
async () => {
try {
const { options, disableTelemetry } = server.ctx.custom ?? {};
if (!options) {
throw new Error('Options are required in addon context');
}
if (!disableTelemetry) {
await collectTelemetry({
event: 'tool:getUIBuildingInstructions',
server,
toolset: 'dev',
});
}
const frameworkPreset = await options.presets.apply('framework');
const framework =
typeof frameworkPreset === 'string'
? frameworkPreset
: frameworkPreset?.name;
const renderer = frameworkToRendererMap[framework!];
const uiInstructions = uiInstructionsTemplate
.replace('{{FRAMEWORK}}', framework)
.replace('{{RENDERER}}', renderer ?? framework)
.replace('{{GET_STORY_URLS_TOOL_NAME}}', GET_STORY_URLS_TOOL_NAME);
return {
content: [{ type: 'text' as const, text: uiInstructions }],
};
} catch (error) {
return errorToMCPContent(error);
}
},
);
}
// TODO: this is a stupid map to maintain and it's not complete, but we can't easily get the current renderer name
const frameworkToRendererMap: Record<string, string> = {
'@storybook/react-vite': '@storybook/react',
'@storybook/react-webpack5': '@storybook/react',
'@storybook/nextjs': '@storybook/react',
'@storybook/nextjs-vite': '@storybook/react',
'@storybook/react-native-web-vite': '@storybook/react',
'@storybook/vue3-vite': '@storybook/vue3',
'@nuxtjs/storybook': '@storybook/vue3',
'@storybook/angular': '@storybook/angular',
'@storybook/svelte-vite': '@storybook/svelte',
'@storybook/sveltekit': '@storybook/svelte',
'@storybook/preact-vite': '@storybook/preact',
'@storybook/web-components-vite': '@storybook/web-components',
'@storybook/html-vite': '@storybook/html',
};