@kvasar/google-stitch 0.1.21 → 0.1.23
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/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/skills/SKILL.md +19 -1
- package/src/tools/apply_design_system.ts +17 -53
- package/src/tools/create_design_system.ts +77 -129
- package/src/tools/edit_screens.ts +46 -4
- package/src/tools/generate_screen_from_text_tool.ts +105 -45
- package/src/tools/generate_variants.ts +81 -4
- package/src/tools/get_project.ts +11 -2
- package/src/tools/get_screen.ts +11 -34
- package/src/tools/update_design_system.ts +52 -4
package/openclaw.plugin.json
CHANGED
package/package.json
CHANGED
package/skills/SKILL.md
CHANGED
|
@@ -167,6 +167,22 @@ Returns:
|
|
|
167
167
|
- A visual list of generated screens in the project
|
|
168
168
|
- Each screen is rendered with title, prompt, device type, dimensions, and preview image/HTML when available
|
|
169
169
|
|
|
170
|
+
### Channel-specific link formatting
|
|
171
|
+
|
|
172
|
+
If the response contains URLs or downloadable resources and the channel is Telegram, always format links as clickable Markdown links.
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
Use this format:
|
|
177
|
+
|
|
178
|
+
[descriptive text](url)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
Example:
|
|
183
|
+
|
|
184
|
+
[View screen preview](https://example.com/screen.png)
|
|
185
|
+
|
|
170
186
|
---
|
|
171
187
|
|
|
172
188
|
### Screen editing
|
|
@@ -324,4 +340,6 @@ Focus on:
|
|
|
324
340
|
- realistic production UI
|
|
325
341
|
- startup / enterprise SaaS design
|
|
326
342
|
- scalable UX patterns
|
|
327
|
-
- modern component systems
|
|
343
|
+
- modern component systems
|
|
344
|
+
|
|
345
|
+
|
|
@@ -1,60 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
id: string;
|
|
3
|
-
sourceScreen: string;
|
|
4
|
-
};
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
};
|
|
3
|
+
const SelectedScreenInstanceSchema = Type.Object({
|
|
4
|
+
id: Type.String({ description: "Required. Screen instance ID (not source screen ID)." }),
|
|
5
|
+
sourceScreen: Type.String({ description: "Required. Resource name format: projects/{project}/screens/{screen}" })
|
|
6
|
+
});
|
|
11
7
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
8
|
+
const ApplyDesignSystemSchema = Type.Object({
|
|
9
|
+
projectId: Type.String({ description: "Required. Project ID without prefix." }),
|
|
10
|
+
selectedScreenInstances: Type.Array(SelectedScreenInstanceSchema, {
|
|
11
|
+
description: "Required. Screen instances to update from get_project."
|
|
12
|
+
}),
|
|
13
|
+
assetId: Type.String({ description: "Required. Design system asset ID without assets/ prefix." })
|
|
14
|
+
});
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
type: "object",
|
|
19
|
-
properties: {
|
|
20
|
-
projectId: {
|
|
21
|
-
type: "string",
|
|
22
|
-
description: "Required. Project ID without prefix."
|
|
23
|
-
},
|
|
24
|
-
selectedScreenInstances: {
|
|
25
|
-
type: "array",
|
|
26
|
-
description:
|
|
27
|
-
"Required. Screen instances to update from get_project.",
|
|
28
|
-
items: {
|
|
29
|
-
type: "object",
|
|
30
|
-
properties: {
|
|
31
|
-
id: {
|
|
32
|
-
type: "string",
|
|
33
|
-
description:
|
|
34
|
-
"Required. Screen instance ID (not source screen ID)."
|
|
35
|
-
},
|
|
36
|
-
sourceScreen: {
|
|
37
|
-
type: "string",
|
|
38
|
-
description:
|
|
39
|
-
"Required. Resource name format: projects/{project}/screens/{screen}"
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
required: ["id", "sourceScreen"]
|
|
43
|
-
}
|
|
44
|
-
},
|
|
45
|
-
assetId: {
|
|
46
|
-
type: "string",
|
|
47
|
-
description:
|
|
48
|
-
"Required. Design system asset ID without assets/ prefix."
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
required: [
|
|
52
|
-
"projectId",
|
|
53
|
-
"selectedScreenInstances",
|
|
54
|
-
"assetId"
|
|
55
|
-
]
|
|
56
|
-
},
|
|
16
|
+
type ApplyDesignSystemParams = Static<typeof ApplyDesignSystemSchema>;
|
|
57
17
|
|
|
18
|
+
export const applyDesignSystemTool = (client: any) => ({
|
|
19
|
+
name: "apply_design_system",
|
|
20
|
+
description: "Applies a design system asset to one or more screens, updating colors, fonts, and shapes",
|
|
21
|
+
parameters: ApplyDesignSystemSchema,
|
|
58
22
|
async execute(_: string, params: ApplyDesignSystemParams) {
|
|
59
23
|
return await client.request("apply_design_system", params);
|
|
60
24
|
}
|
|
@@ -1,141 +1,89 @@
|
|
|
1
|
-
|
|
2
|
-
| "COLOR_MODE_UNSPECIFIED"
|
|
3
|
-
| "LIGHT"
|
|
4
|
-
| "DARK";
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
5
2
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
const ColorMode = Type.Union([
|
|
4
|
+
Type.Literal("COLOR_MODE_UNSPECIFIED"),
|
|
5
|
+
Type.Literal("LIGHT"),
|
|
6
|
+
Type.Literal("DARK")
|
|
7
|
+
]);
|
|
11
8
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
const FontType = Type.Union([
|
|
10
|
+
Type.Literal("FONT_UNSPECIFIED"),
|
|
11
|
+
Type.Literal("INTER"),
|
|
12
|
+
Type.Literal("DM_SANS"),
|
|
13
|
+
Type.Literal("GEIST")
|
|
14
|
+
]);
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
| "FIDELITY"
|
|
27
|
-
| "CONTENT"
|
|
28
|
-
| "RAINBOW"
|
|
29
|
-
| "FRUIT_SALAD";
|
|
16
|
+
const Roundness = Type.Union([
|
|
17
|
+
Type.Literal("ROUNDNESS_UNSPECIFIED"),
|
|
18
|
+
Type.Literal("ROUND_FOUR"),
|
|
19
|
+
Type.Literal("ROUND_EIGHT"),
|
|
20
|
+
Type.Literal("ROUND_TWELVE"),
|
|
21
|
+
Type.Literal("ROUND_FULL")
|
|
22
|
+
]);
|
|
30
23
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
designMd?: string;
|
|
44
|
-
};
|
|
24
|
+
const ColorVariant = Type.Union([
|
|
25
|
+
Type.Literal("COLOR_VARIANT_UNSPECIFIED"),
|
|
26
|
+
Type.Literal("MONOCHROME"),
|
|
27
|
+
Type.Literal("NEUTRAL"),
|
|
28
|
+
Type.Literal("TONAL_SPOT"),
|
|
29
|
+
Type.Literal("VIBRANT"),
|
|
30
|
+
Type.Literal("EXPRESSIVE"),
|
|
31
|
+
Type.Literal("FIDELITY"),
|
|
32
|
+
Type.Literal("CONTENT"),
|
|
33
|
+
Type.Literal("RAINBOW"),
|
|
34
|
+
Type.Literal("FRUIT_SALAD")
|
|
35
|
+
]);
|
|
45
36
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
37
|
+
const DesignThemeSchema = Type.Object({
|
|
38
|
+
colorMode: Type.Union([Type.Literal("LIGHT"), Type.Literal("DARK")], {
|
|
39
|
+
description: "Color mode"
|
|
40
|
+
}),
|
|
41
|
+
headlineFont: Type.Union([Type.Literal("INTER"), Type.Literal("DM_SANS"), Type.Literal("GEIST")], {
|
|
42
|
+
description: "Headline font"
|
|
43
|
+
}),
|
|
44
|
+
bodyFont: Type.Union([Type.Literal("INTER"), Type.Literal("DM_SANS"), Type.Literal("GEIST")], {
|
|
45
|
+
description: "Body font"
|
|
46
|
+
}),
|
|
47
|
+
labelFont: Type.Optional(Type.Union([Type.Literal("INTER"), Type.Literal("DM_SANS"), Type.Literal("GEIST")], {
|
|
48
|
+
description: "Label font"
|
|
49
|
+
})),
|
|
50
|
+
roundness: Type.Union([
|
|
51
|
+
Type.Literal("ROUND_FOUR"),
|
|
52
|
+
Type.Literal("ROUND_EIGHT"),
|
|
53
|
+
Type.Literal("ROUND_TWELVE"),
|
|
54
|
+
Type.Literal("ROUND_FULL")
|
|
55
|
+
], {
|
|
56
|
+
description: "Roundness level"
|
|
57
|
+
}),
|
|
58
|
+
customColor: Type.String({ description: "Hex seed color" }),
|
|
59
|
+
colorVariant: Type.Optional(Type.Union([
|
|
60
|
+
Type.Literal("MONOCHROME"),
|
|
61
|
+
Type.Literal("NEUTRAL"),
|
|
62
|
+
Type.Literal("TONAL_SPOT"),
|
|
63
|
+
Type.Literal("VIBRANT"),
|
|
64
|
+
Type.Literal("EXPRESSIVE")
|
|
65
|
+
], {
|
|
66
|
+
description: "Color variant"
|
|
67
|
+
})),
|
|
68
|
+
designMd: Type.Optional(Type.String({ description: "Optional markdown design instructions" }))
|
|
69
|
+
});
|
|
50
70
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
};
|
|
71
|
+
const DesignSystemSchema = Type.Object({
|
|
72
|
+
displayName: Type.String({ description: "Required. Display name." }),
|
|
73
|
+
theme: DesignThemeSchema
|
|
74
|
+
});
|
|
55
75
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
76
|
+
const CreateDesignSystemSchema = Type.Object({
|
|
77
|
+
projectId: Type.Optional(Type.String({ description: "Optional. Project ID. If omitted, creates a global design asset." })),
|
|
78
|
+
designSystem: DesignSystemSchema
|
|
79
|
+
});
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
type: "object",
|
|
63
|
-
properties: {
|
|
64
|
-
projectId: {
|
|
65
|
-
type: "string",
|
|
66
|
-
description:
|
|
67
|
-
"Optional. Project ID. If omitted, creates a global design asset."
|
|
68
|
-
},
|
|
69
|
-
designSystem: {
|
|
70
|
-
type: "object",
|
|
71
|
-
description: "Required. Design system definition.",
|
|
72
|
-
properties: {
|
|
73
|
-
displayName: {
|
|
74
|
-
type: "string",
|
|
75
|
-
description: "Required. Display name."
|
|
76
|
-
},
|
|
77
|
-
theme: {
|
|
78
|
-
type: "object",
|
|
79
|
-
properties: {
|
|
80
|
-
colorMode: {
|
|
81
|
-
type: "string",
|
|
82
|
-
enum: ["LIGHT", "DARK"]
|
|
83
|
-
},
|
|
84
|
-
headlineFont: {
|
|
85
|
-
type: "string",
|
|
86
|
-
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
87
|
-
},
|
|
88
|
-
bodyFont: {
|
|
89
|
-
type: "string",
|
|
90
|
-
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
91
|
-
},
|
|
92
|
-
labelFont: {
|
|
93
|
-
type: "string",
|
|
94
|
-
enum: ["INTER", "DM_SANS", "GEIST"]
|
|
95
|
-
},
|
|
96
|
-
roundness: {
|
|
97
|
-
type: "string",
|
|
98
|
-
enum: [
|
|
99
|
-
"ROUND_FOUR",
|
|
100
|
-
"ROUND_EIGHT",
|
|
101
|
-
"ROUND_TWELVE",
|
|
102
|
-
"ROUND_FULL"
|
|
103
|
-
]
|
|
104
|
-
},
|
|
105
|
-
customColor: {
|
|
106
|
-
type: "string",
|
|
107
|
-
description: "Hex seed color"
|
|
108
|
-
},
|
|
109
|
-
colorVariant: {
|
|
110
|
-
type: "string",
|
|
111
|
-
enum: [
|
|
112
|
-
"MONOCHROME",
|
|
113
|
-
"NEUTRAL",
|
|
114
|
-
"TONAL_SPOT",
|
|
115
|
-
"VIBRANT",
|
|
116
|
-
"EXPRESSIVE"
|
|
117
|
-
]
|
|
118
|
-
},
|
|
119
|
-
designMd: {
|
|
120
|
-
type: "string",
|
|
121
|
-
description: "Optional markdown design instructions"
|
|
122
|
-
}
|
|
123
|
-
},
|
|
124
|
-
required: [
|
|
125
|
-
"colorMode",
|
|
126
|
-
"headlineFont",
|
|
127
|
-
"bodyFont",
|
|
128
|
-
"roundness",
|
|
129
|
-
"customColor"
|
|
130
|
-
]
|
|
131
|
-
}
|
|
132
|
-
},
|
|
133
|
-
required: ["displayName", "theme"]
|
|
134
|
-
}
|
|
135
|
-
},
|
|
136
|
-
required: ["designSystem"]
|
|
137
|
-
},
|
|
81
|
+
type CreateDesignSystemParams = Static<typeof CreateDesignSystemSchema>;
|
|
138
82
|
|
|
83
|
+
export const createDesignSystemTool = (client: any) => ({
|
|
84
|
+
name: "create_design_system",
|
|
85
|
+
description: "Creates a new design system with colors, typography, roundness, and theme tokens for a Stitch project",
|
|
86
|
+
parameters: CreateDesignSystemSchema,
|
|
139
87
|
async execute(_: string, params: CreateDesignSystemParams) {
|
|
140
88
|
return await client.request("create_design_system", params);
|
|
141
89
|
}
|
|
@@ -1,7 +1,49 @@
|
|
|
1
|
-
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
const EditScreensSchema = Type.Object({
|
|
4
|
+
projectId: Type.String({
|
|
5
|
+
description: "Required. Project ID without prefix.",
|
|
6
|
+
}),
|
|
7
|
+
|
|
8
|
+
selectedScreenIds: Type.Array(Type.String(), {
|
|
9
|
+
description:
|
|
10
|
+
"Required. Screen IDs to edit, without `screens/` prefix.",
|
|
11
|
+
minItems: 1,
|
|
12
|
+
}),
|
|
13
|
+
|
|
14
|
+
prompt: Type.String({
|
|
15
|
+
description: "Required. Edit instruction.",
|
|
16
|
+
}),
|
|
17
|
+
|
|
18
|
+
deviceType: Type.Optional(
|
|
19
|
+
Type.Union([
|
|
20
|
+
Type.Literal("DEVICE_TYPE_UNSPECIFIED"),
|
|
21
|
+
Type.Literal("MOBILE"),
|
|
22
|
+
Type.Literal("DESKTOP"),
|
|
23
|
+
Type.Literal("TABLET"),
|
|
24
|
+
Type.Literal("AGNOSTIC"),
|
|
25
|
+
])
|
|
26
|
+
),
|
|
27
|
+
|
|
28
|
+
modelId: Type.Optional(
|
|
29
|
+
Type.Union([
|
|
30
|
+
Type.Literal("MODEL_ID_UNSPECIFIED"),
|
|
31
|
+
Type.Literal("GEMINI_3_PRO"),
|
|
32
|
+
Type.Literal("GEMINI_3_FLASH"),
|
|
33
|
+
Type.Literal("GEMINI_3_1_PRO"),
|
|
34
|
+
])
|
|
35
|
+
),
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
type EditScreensParams = Static<typeof EditScreensSchema>;
|
|
39
|
+
|
|
40
|
+
export const editScreensTool = (client: any) => ({
|
|
2
41
|
name: "edit_screens",
|
|
3
|
-
description:
|
|
4
|
-
|
|
42
|
+
description:
|
|
43
|
+
"Edits existing screens using a text prompt. This process may take a few minutes.",
|
|
44
|
+
parameters: EditScreensSchema,
|
|
45
|
+
|
|
46
|
+
async execute(_: string, params: EditScreensParams) {
|
|
5
47
|
return await client.request?.("edit_screens", params);
|
|
6
48
|
},
|
|
7
|
-
});
|
|
49
|
+
});
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import fs from "node:fs";
|
|
7
7
|
import path from "node:path";
|
|
8
8
|
import os from "node:os";
|
|
9
|
-
import { Type } from "@sinclair/typebox";
|
|
9
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
type StitchFile = {
|
|
@@ -22,68 +22,75 @@ type SessionOutputComponent = {
|
|
|
22
22
|
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
type ScreenType = "SCREEN_TYPE_UNSPECIFIED" | "COMPONENT" | "LAYOUT" | "PAGE" | "FLOW";
|
|
26
|
+
type ScreenStatus = "SCREEN_STATUS_UNSPECIFIED" | "DRAFT" | "PUBLISHED" | "ARCHIVED";
|
|
27
|
+
type DisplayMode = "DISPLAY_MODE_UNSPECIFIED" | "LIGHT" | "DARK";
|
|
28
|
+
|
|
29
|
+
type DesignTheme = {
|
|
30
|
+
colorMode?: string;
|
|
31
|
+
headlineFont?: string;
|
|
32
|
+
bodyFont?: string;
|
|
33
|
+
labelFont?: string;
|
|
34
|
+
roundness?: string;
|
|
35
|
+
customColor?: string;
|
|
36
|
+
colorVariant?: string;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
type ScreenMetadata = {
|
|
40
|
+
agent?: string;
|
|
41
|
+
status?: ScreenStatus;
|
|
42
|
+
displayMode?: DisplayMode;
|
|
43
|
+
};
|
|
44
|
+
|
|
25
45
|
type StitchResponse = {
|
|
26
46
|
screen?: {
|
|
27
47
|
name?: string;
|
|
48
|
+
id?: string;
|
|
28
49
|
title?: string;
|
|
29
50
|
prompt?: string;
|
|
30
51
|
screenshot?: StitchFile;
|
|
31
52
|
htmlCode?: StitchFile;
|
|
53
|
+
figmaExport?: StitchFile;
|
|
54
|
+
theme?: DesignTheme;
|
|
32
55
|
deviceType?: DeviceType;
|
|
56
|
+
screenType?: ScreenType;
|
|
57
|
+
screenMetadata?: ScreenMetadata;
|
|
33
58
|
width?: string;
|
|
34
59
|
height?: string;
|
|
60
|
+
groupId?: string;
|
|
61
|
+
groupName?: string;
|
|
62
|
+
generatedBy?: string;
|
|
63
|
+
isCreatedByClient?: boolean;
|
|
35
64
|
};
|
|
36
65
|
output_components?: SessionOutputComponent[];
|
|
37
66
|
};
|
|
38
67
|
|
|
68
|
+
const GenerateScreenSchema = Type.Object({
|
|
69
|
+
projectId: Type.String({ description: "Required. Project ID without prefix." }),
|
|
70
|
+
prompt: Type.String({ description: "Natural language prompt describing the UI screen" }),
|
|
71
|
+
deviceType: Type.Optional(Type.Union([
|
|
72
|
+
Type.Literal("DEVICE_TYPE_UNSPECIFIED"),
|
|
73
|
+
Type.Literal("MOBILE"),
|
|
74
|
+
Type.Literal("DESKTOP"),
|
|
75
|
+
Type.Literal("TABLET"),
|
|
76
|
+
Type.Literal("AGNOSTIC")
|
|
77
|
+
])),
|
|
78
|
+
modelId: Type.Optional(Type.Union([
|
|
79
|
+
Type.Literal("MODEL_ID_UNSPECIFIED"),
|
|
80
|
+
Type.Literal("GEMINI_3_PRO"),
|
|
81
|
+
Type.Literal("GEMINI_3_FLASH"),
|
|
82
|
+
Type.Literal("GEMINI_3_1_PRO")
|
|
83
|
+
]))
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
type GenerateScreenParams = Static<typeof GenerateScreenSchema>;
|
|
87
|
+
|
|
39
88
|
export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
40
89
|
return {
|
|
41
90
|
name: "generate_screen_from_text",
|
|
42
91
|
description: "Generate a UI screen from a natural language prompt",
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
type: "object",
|
|
46
|
-
properties: {
|
|
47
|
-
projectId: {
|
|
48
|
-
type: "string",
|
|
49
|
-
description: "Required. Project ID without prefix."
|
|
50
|
-
},
|
|
51
|
-
prompt: {
|
|
52
|
-
type: "string",
|
|
53
|
-
description: "Describe the UI screen to generate"
|
|
54
|
-
},
|
|
55
|
-
deviceType: {
|
|
56
|
-
type: "string",
|
|
57
|
-
enum: [
|
|
58
|
-
"DEVICE_TYPE_UNSPECIFIED",
|
|
59
|
-
"MOBILE",
|
|
60
|
-
"DESKTOP",
|
|
61
|
-
"TABLET",
|
|
62
|
-
"AGNOSTIC"
|
|
63
|
-
]
|
|
64
|
-
},
|
|
65
|
-
modelId: {
|
|
66
|
-
type: "string",
|
|
67
|
-
enum: [
|
|
68
|
-
"MODEL_ID_UNSPECIFIED",
|
|
69
|
-
"GEMINI_3_PRO",
|
|
70
|
-
"GEMINI_3_FLASH",
|
|
71
|
-
"GEMINI_3_1_PRO"
|
|
72
|
-
]
|
|
73
|
-
}
|
|
74
|
-
},
|
|
75
|
-
required: ["projectId", "prompt"]
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
async execute(
|
|
79
|
-
_id: string,
|
|
80
|
-
params: {
|
|
81
|
-
projectId: string;
|
|
82
|
-
prompt: string;
|
|
83
|
-
deviceType?: DeviceType;
|
|
84
|
-
modelId?: ModelId;
|
|
85
|
-
}
|
|
86
|
-
) {
|
|
92
|
+
parameters: GenerateScreenSchema,
|
|
93
|
+
async execute(_id: string, params: GenerateScreenParams) {
|
|
87
94
|
const result = (await client.generateScreen(params)) as StitchResponse;
|
|
88
95
|
|
|
89
96
|
const screen = result.screen;
|
|
@@ -100,6 +107,45 @@ export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
|
100
107
|
|
|
101
108
|
const content: Array<{ type: string; [key: string]: any }> = [];
|
|
102
109
|
|
|
110
|
+
// Add screen metadata summary first
|
|
111
|
+
if (screen) {
|
|
112
|
+
const screenInfo = `
|
|
113
|
+
## Screen Generated Successfully
|
|
114
|
+
|
|
115
|
+
**Title:** ${screen.title || "Untitled"}
|
|
116
|
+
**Resource Name:** ${screen.name || "N/A"}
|
|
117
|
+
**ID:** ${screen.id || "N/A"}
|
|
118
|
+
**Device Type:** ${screen.deviceType || "N/A"}
|
|
119
|
+
**Screen Type:** ${screen.screenType || "N/A"}
|
|
120
|
+
**Dimensions:** ${screen.width || "N/A"} x ${screen.height || "N/A"}
|
|
121
|
+
**Generated By:** ${screen.generatedBy || "N/A"}
|
|
122
|
+
**Prompt:** ${screen.prompt || "N/A"}
|
|
123
|
+
|
|
124
|
+
**Metadata:**
|
|
125
|
+
- Agent: ${screen.screenMetadata?.agent || "N/A"}
|
|
126
|
+
- Status: ${screen.screenMetadata?.status || "N/A"}
|
|
127
|
+
- Display Mode: ${screen.screenMetadata?.displayMode || "N/A"}
|
|
128
|
+
|
|
129
|
+
**Group Info:**
|
|
130
|
+
- Group ID: ${screen.groupId || "N/A"}
|
|
131
|
+
- Group Name: ${screen.groupName || "N/A"}
|
|
132
|
+
|
|
133
|
+
**Theme:**
|
|
134
|
+
- Color Mode: ${screen.theme?.colorMode || "N/A"}
|
|
135
|
+
- Headline Font: ${screen.theme?.headlineFont || "N/A"}
|
|
136
|
+
- Body Font: ${screen.theme?.bodyFont || "N/A"}
|
|
137
|
+
- Roundness: ${screen.theme?.roundness || "N/A"}
|
|
138
|
+
- Color Variant: ${screen.theme?.colorVariant || "N/A"}
|
|
139
|
+
|
|
140
|
+
**Client Created:** ${screen.isCreatedByClient ? "Yes" : "No"}
|
|
141
|
+
`;
|
|
142
|
+
|
|
143
|
+
content.push({
|
|
144
|
+
type: "text",
|
|
145
|
+
text: screenInfo.trim()
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
103
149
|
if (modelText) {
|
|
104
150
|
content.push({
|
|
105
151
|
type: "text",
|
|
@@ -178,6 +224,7 @@ export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
|
178
224
|
<h3>${escapeHtml(
|
|
179
225
|
screen?.title || "Generated screen"
|
|
180
226
|
)}</h3>
|
|
227
|
+
<p>No HTML preview available</p>
|
|
181
228
|
</div>`;
|
|
182
229
|
}
|
|
183
230
|
|
|
@@ -186,6 +233,19 @@ export function generateScreenFromTextTool(client: StitchMCPClient) {
|
|
|
186
233
|
html
|
|
187
234
|
});
|
|
188
235
|
|
|
236
|
+
// Add Figma export info if available
|
|
237
|
+
if (screen?.figmaExport) {
|
|
238
|
+
const figmaInfo = `
|
|
239
|
+
**Figma Export Available:** ${screen.figmaExport.downloadUrl ? "Yes" : "No"}
|
|
240
|
+
${screen.figmaExport.name ? `**File Name:** ${screen.figmaExport.name}` : ""}
|
|
241
|
+
`;
|
|
242
|
+
|
|
243
|
+
content.push({
|
|
244
|
+
type: "text",
|
|
245
|
+
text: figmaInfo.trim()
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
189
249
|
if (suggestionText) {
|
|
190
250
|
content.push({
|
|
191
251
|
type: "text",
|
|
@@ -1,7 +1,84 @@
|
|
|
1
|
-
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
const VariantOptionsSchema = Type.Object({
|
|
4
|
+
variantCount: Type.Optional(
|
|
5
|
+
Type.Integer({
|
|
6
|
+
minimum: 1,
|
|
7
|
+
maximum: 5,
|
|
8
|
+
description: "Number of variants (1–5). Default: 3.",
|
|
9
|
+
})
|
|
10
|
+
),
|
|
11
|
+
|
|
12
|
+
creativeRange: Type.Optional(
|
|
13
|
+
Type.Union([
|
|
14
|
+
Type.Literal("CREATIVE_RANGE_UNSPECIFIED"),
|
|
15
|
+
Type.Literal("REFINE"),
|
|
16
|
+
Type.Literal("EXPLORE"),
|
|
17
|
+
Type.Literal("REIMAGINE"),
|
|
18
|
+
])
|
|
19
|
+
),
|
|
20
|
+
|
|
21
|
+
aspects: Type.Optional(
|
|
22
|
+
Type.Array(
|
|
23
|
+
Type.Union([
|
|
24
|
+
Type.Literal("VARIANT_ASPECT_UNSPECIFIED"),
|
|
25
|
+
Type.Literal("LAYOUT"),
|
|
26
|
+
Type.Literal("COLOR_SCHEME"),
|
|
27
|
+
Type.Literal("IMAGES"),
|
|
28
|
+
Type.Literal("TEXT_FONT"),
|
|
29
|
+
Type.Literal("TEXT_CONTENT"),
|
|
30
|
+
])
|
|
31
|
+
)
|
|
32
|
+
),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const GenerateVariantsSchema = Type.Object({
|
|
36
|
+
projectId: Type.String({
|
|
37
|
+
description: "Required. Project ID without prefix.",
|
|
38
|
+
}),
|
|
39
|
+
|
|
40
|
+
selectedScreenIds: Type.Array(Type.String(), {
|
|
41
|
+
description: "Required. Screen IDs to generate variants for.",
|
|
42
|
+
minItems: 1,
|
|
43
|
+
}),
|
|
44
|
+
|
|
45
|
+
prompt: Type.String({
|
|
46
|
+
description: "Required. Text guiding variant generation.",
|
|
47
|
+
}),
|
|
48
|
+
|
|
49
|
+
variantOptions: VariantOptionsSchema,
|
|
50
|
+
|
|
51
|
+
deviceType: Type.Optional(
|
|
52
|
+
Type.Union([
|
|
53
|
+
Type.Literal("DEVICE_TYPE_UNSPECIFIED"),
|
|
54
|
+
Type.Literal("MOBILE"),
|
|
55
|
+
Type.Literal("DESKTOP"),
|
|
56
|
+
Type.Literal("TABLET"),
|
|
57
|
+
Type.Literal("AGNOSTIC"),
|
|
58
|
+
])
|
|
59
|
+
),
|
|
60
|
+
|
|
61
|
+
modelId: Type.Optional(
|
|
62
|
+
Type.Union([
|
|
63
|
+
Type.Literal("MODEL_ID_UNSPECIFIED"),
|
|
64
|
+
// deprecated but still supported by API
|
|
65
|
+
Type.Literal("GEMINI_3_PRO"),
|
|
66
|
+
Type.Literal("GEMINI_3_FLASH"),
|
|
67
|
+
Type.Literal("GEMINI_3_1_PRO"),
|
|
68
|
+
])
|
|
69
|
+
),
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
type GenerateVariantsParams = Static<typeof GenerateVariantsSchema>;
|
|
73
|
+
|
|
74
|
+
export const generateVariantsTool = (client: any) => ({
|
|
2
75
|
name: "generate_variants",
|
|
3
|
-
description:
|
|
4
|
-
|
|
76
|
+
description:
|
|
77
|
+
"Generates design variants of existing screens based on selected screens and variant options.",
|
|
78
|
+
|
|
79
|
+
parameters: GenerateVariantsSchema,
|
|
80
|
+
|
|
81
|
+
async execute(_: string, params: GenerateVariantsParams) {
|
|
5
82
|
return await client.request?.("generate_variants", params);
|
|
6
83
|
},
|
|
7
|
-
});
|
|
84
|
+
});
|
package/src/tools/get_project.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
const GetProjectSchema = Type.Object({
|
|
4
|
+
// This tool appears to accept any parameters as per the API
|
|
5
|
+
});
|
|
6
|
+
|
|
7
|
+
type GetProjectParams = Static<typeof GetProjectSchema>;
|
|
8
|
+
|
|
9
|
+
export const getProjectTool = (client: any) => ({
|
|
2
10
|
name: "get_project",
|
|
3
11
|
description: "get project",
|
|
4
|
-
|
|
12
|
+
parameters: GetProjectSchema,
|
|
13
|
+
async execute(_: string, params: GetProjectParams) {
|
|
5
14
|
return await client.request?.("get_project", params);
|
|
6
15
|
},
|
|
7
16
|
});
|
package/src/tools/get_screen.ts
CHANGED
|
@@ -2,6 +2,7 @@ import { StitchMCPClient } from "../services/stitch-mcp-client.js";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
5
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
5
6
|
|
|
6
7
|
type StitchFile = {
|
|
7
8
|
name?: string;
|
|
@@ -27,11 +28,13 @@ type Screen = {
|
|
|
27
28
|
isCreatedByClient?: boolean;
|
|
28
29
|
};
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
name:
|
|
32
|
-
projectId:
|
|
33
|
-
screenId:
|
|
34
|
-
};
|
|
31
|
+
const GetScreenSchema = Type.Object({
|
|
32
|
+
name: Type.String({ description: "Required. Resource name. Format: projects/{project}/screens/{screen}" }),
|
|
33
|
+
projectId: Type.String({ description: "Required (deprecated). Project ID without prefix." }),
|
|
34
|
+
screenId: Type.String({ description: "Required (deprecated). Screen ID without prefix." })
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
type GetScreenParams = Static<typeof GetScreenSchema>;
|
|
35
38
|
|
|
36
39
|
type ContentItem = {
|
|
37
40
|
type: string;
|
|
@@ -40,35 +43,9 @@ type ContentItem = {
|
|
|
40
43
|
|
|
41
44
|
export const getScreenTool = (client: StitchMCPClient) => ({
|
|
42
45
|
name: "get_screen",
|
|
43
|
-
description:
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
parameters: {
|
|
47
|
-
type: "object",
|
|
48
|
-
properties: {
|
|
49
|
-
name: {
|
|
50
|
-
type: "string",
|
|
51
|
-
description:
|
|
52
|
-
"Required. Resource name. Format: projects/{project}/screens/{screen}"
|
|
53
|
-
},
|
|
54
|
-
projectId: {
|
|
55
|
-
type: "string",
|
|
56
|
-
description:
|
|
57
|
-
"Required (deprecated). Project ID without prefix."
|
|
58
|
-
},
|
|
59
|
-
screenId: {
|
|
60
|
-
type: "string",
|
|
61
|
-
description:
|
|
62
|
-
"Required (deprecated). Screen ID without prefix."
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
required: ["name", "projectId", "screenId"]
|
|
66
|
-
},
|
|
67
|
-
|
|
68
|
-
async execute(
|
|
69
|
-
_: string,
|
|
70
|
-
params: GetScreenParams
|
|
71
|
-
) {
|
|
46
|
+
description: "Retrieves and visually renders a specific screen within a Stitch project.",
|
|
47
|
+
parameters: GetScreenSchema,
|
|
48
|
+
async execute(_: string, params: GetScreenParams) {
|
|
72
49
|
const { name, projectId, screenId } = params;
|
|
73
50
|
|
|
74
51
|
if (!name || !projectId || !screenId) {
|
|
@@ -1,7 +1,55 @@
|
|
|
1
|
-
|
|
1
|
+
import { Type, Static } from "@sinclair/typebox";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Reusable nested theme schema
|
|
5
|
+
*/
|
|
6
|
+
const DesignThemeSchema = Type.Object({
|
|
7
|
+
name: Type.Optional(Type.String()),
|
|
8
|
+
primaryColor: Type.Optional(Type.String()),
|
|
9
|
+
secondaryColor: Type.Optional(Type.String()),
|
|
10
|
+
typography: Type.Optional(Type.String()),
|
|
11
|
+
spacing: Type.Optional(Type.String()),
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Main design system schema
|
|
16
|
+
*/
|
|
17
|
+
const DesignSystemSchema = Type.Object({
|
|
18
|
+
name: Type.Optional(Type.String()),
|
|
19
|
+
description: Type.Optional(Type.String()),
|
|
20
|
+
themes: Type.Optional(Type.Array(DesignThemeSchema)),
|
|
21
|
+
components: Type.Optional(Type.Array(Type.String())),
|
|
22
|
+
tokens: Type.Optional(Type.Record(Type.String(), Type.Any())),
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Update schema
|
|
27
|
+
*/
|
|
28
|
+
const UpdateDesignSystemSchema = Type.Object({
|
|
29
|
+
name: Type.String({
|
|
30
|
+
pattern: "^assets\\/[^\\/]+$",
|
|
31
|
+
description:
|
|
32
|
+
"Required. Resource name. Format: `assets/{asset}`.",
|
|
33
|
+
}),
|
|
34
|
+
|
|
35
|
+
projectId: Type.String({
|
|
36
|
+
description: "Required. Project ID without prefix.",
|
|
37
|
+
}),
|
|
38
|
+
|
|
39
|
+
designSystem: DesignSystemSchema,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
type UpdateDesignSystemParams = Static<typeof UpdateDesignSystemSchema>;
|
|
43
|
+
|
|
44
|
+
export const updateDesignSystemTool = (client: any) => ({
|
|
2
45
|
name: "update_design_system",
|
|
3
|
-
|
|
4
|
-
|
|
46
|
+
|
|
47
|
+
description:
|
|
48
|
+
"Updates an existing design system. Identifies the asset by its name field.",
|
|
49
|
+
|
|
50
|
+
parameters: UpdateDesignSystemSchema,
|
|
51
|
+
|
|
52
|
+
async execute(_: string, params: UpdateDesignSystemParams) {
|
|
5
53
|
return await client.request?.("update_design_system", params);
|
|
6
54
|
},
|
|
7
|
-
});
|
|
55
|
+
});
|