@appscreenshotstudio/mcp 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +272 -228
- package/dist/index.js +203 -149
- package/package.json +49 -49
- package/skills/appscreenshotstudio/SKILL.md +124 -119
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ const DEVICES = [
|
|
|
38
38
|
{ id: 'ipad-13', name: 'iPad Pro 13"', width: 2064, height: 2752, category: 'ipad', required: true },
|
|
39
39
|
{ id: 'android-phone', name: 'Android Phone', width: 1080, height: 2340, category: 'android-phone', required: true },
|
|
40
40
|
{ id: 'pixel-11-pro', name: 'Google Pixel 11 Pro', width: 1280, height: 2856, category: 'android-phone', required: false },
|
|
41
|
+
{ id: 'galaxy-s26-ultra', name: 'Samsung Galaxy S26 Ultra', width: 1440, height: 3120, category: 'android-phone', required: false },
|
|
41
42
|
{ id: 'android-tablet-10', name: 'Android Tablet 7"', width: 1200, height: 1920, category: 'android-tablet', required: true },
|
|
42
43
|
{ id: 'android-tablet-large', name: 'Android Tablet 10"', width: 1600, height: 2560, category: 'android-tablet', required: false },
|
|
43
44
|
{ id: 'apple-watch-ultra', name: 'Apple Watch Ultra 2', width: 410, height: 502, category: 'apple-watch', required: true },
|
|
@@ -45,7 +46,7 @@ const DEVICES = [
|
|
|
45
46
|
const VALID_DEVICE_IDS = DEVICES.map(d => d.id);
|
|
46
47
|
// Aliases callers commonly pass instead of the canonical id: display-name
|
|
47
48
|
// derivations ("iPhone 16 Pro Max" -> iphone-16-pro-max) and legacy slugs.
|
|
48
|
-
// Mirrors MARKETING_TO_SPEC in lib/device-specs.ts
|
|
49
|
+
// Mirrors MARKETING_TO_SPEC in lib/device-specs.ts. Keep the two in sync.
|
|
49
50
|
const DEVICE_ALIASES = {
|
|
50
51
|
'iphone-16-pro': 'iphone-6.9',
|
|
51
52
|
'iphone-16-pro-max': 'iphone-6.9',
|
|
@@ -153,10 +154,10 @@ function buildDesignMessage(input, hasScreenshotImages = false) {
|
|
|
153
154
|
parts.push('\nUse the research context above to create screenshots that accurately represent this specific app. Headlines, features, and visual style should reflect what the app actually does and looks like.');
|
|
154
155
|
}
|
|
155
156
|
if (hasScreenshotImages) {
|
|
156
|
-
parts.push(`\nMy app screenshots are attached
|
|
157
|
+
parts.push(`\nMy app screenshots are attached, and they are placed into the device frames automatically.`);
|
|
157
158
|
}
|
|
158
159
|
else {
|
|
159
|
-
parts.push(`\nAll device mockups should have screenshotImage: null
|
|
160
|
+
parts.push(`\nAll device mockups should have screenshotImage: null. The developer will upload actual app screenshots later.`);
|
|
160
161
|
}
|
|
161
162
|
parts.push(`Please include projectMeta with brand colors, mood, appCategory, and a rich globalVisualTheme description.`);
|
|
162
163
|
return parts.join('\n');
|
|
@@ -191,49 +192,58 @@ const chatImagesSchema = z.array(z.object({
|
|
|
191
192
|
})).max(5).optional()
|
|
192
193
|
.describe('Images to attach to this generation. App screenshots land inside the device frames automatically; a mascot gets placed around the phones; a reference only informs the design. All survive later edits and regenerations.');
|
|
193
194
|
// ─── MCP Server ─────────────────────────────────────────────────────────────────
|
|
195
|
+
// Read from package.json rather than a literal. This is the version a client
|
|
196
|
+
// sees in the MCP handshake, and a hand-synced literal silently sat at 0.6.1
|
|
197
|
+
// through the 0.6.2 release, then at 0.6.3 through 0.7.0 and 0.8.0. A comment
|
|
198
|
+
// asking the next person to remember has now failed twice, so stop asking.
|
|
199
|
+
const PKG_VERSION = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf-8')).version;
|
|
194
200
|
const server = new McpServer({
|
|
195
201
|
name: 'appscreenshotstudio',
|
|
196
|
-
|
|
197
|
-
// MCP handshake, and it silently sat at 0.6.1 through the 0.6.2 release.
|
|
198
|
-
version: '0.6.3',
|
|
202
|
+
version: PKG_VERSION,
|
|
199
203
|
});
|
|
200
204
|
// Tool 1: generate-screenshots
|
|
201
205
|
server.registerTool('generate-screenshots', {
|
|
202
206
|
title: 'Generate App Store Screenshots',
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
-
|
|
228
|
-
|
|
229
|
-
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
207
|
+
annotations: {
|
|
208
|
+
// Creates a new project; never overwrites an existing one.
|
|
209
|
+
readOnlyHint: false,
|
|
210
|
+
destructiveHint: false,
|
|
211
|
+
openWorldHint: false,
|
|
212
|
+
},
|
|
213
|
+
description: `Create a complete set of App Store screenshot designs for an app. Attach real app screenshots via the images param and they are placed inside the device frames automatically; attach a mascot/character image (kind: "mascot", transparent PNG) and it gets placed around the phones. Returns a project URL where the developer can preview, refine, and export final PNGs.
|
|
214
|
+
|
|
215
|
+
IMPORTANT: Before calling this tool, research the user's codebase to populate the codebase_context parameter. Search for: package.json/README (app name & description), theme/color config files (brand colors), route definitions (key screens), marketing copy (value proposition), and App Store metadata. The more context you provide, the better the screenshots will be. Call prepare-screenshot-brief first if you need a research checklist.
|
|
216
|
+
|
|
217
|
+
The AI picks a narrative arc that fits the app's sell angle (trust-first for finance/health, visual-first for creative/lifestyle, problem-first for pain-relief apps, numbers-led for SaaS/analytics, community-first for social, feature-forward for multi-mode apps) and assigns a job to each card: HOOK → EDUCATE → PROVE → CONVERT.
|
|
218
|
+
|
|
219
|
+
10 layout types available per card:
|
|
220
|
+
- text-top-device-bottom: headline top, flat device bottom (feature/educate)
|
|
221
|
+
- text-top-device-tilted: headline left, tilted device right (or mirrored)
|
|
222
|
+
- device-hero: headline + large centered device, product-forward
|
|
223
|
+
- social-proof: stars + quote + laurel stat, no device (testimonial-led)
|
|
224
|
+
- review-clip: rating-statement headline + stars + quote + bottom-clipped device
|
|
225
|
+
- screen-hero: top-clipped device + centered headline + optional trust stat
|
|
226
|
+
- lifestyle-hero: full-bleed photo background + text overlay (no device)
|
|
227
|
+
- stats-hero: giant centered stat(s), no device, numbers-led
|
|
228
|
+
- metric-badge: centered device + chunky "achievement card" floating over its screen
|
|
229
|
+
- annotated-feature: tilted device + side callout chip linked by a connector line
|
|
230
|
+
|
|
231
|
+
Each card can carry auto-positioned compound fields: statRow, laurelStat, pressBanner, starRating, quote, credential ("FDIC insured"-style trust pills), guarantee ("Cancel anytime"-style risk-reversal pills). Trust signals are opt-in: supply the real number, quote or press name, or the card ships clean rather than inventing one.
|
|
232
|
+
|
|
233
|
+
Panoramic backgrounds slice one wide AI-generated or Pexels image across multiple cards for cohesion. Panoramic element spans stretch a foreground image or device across adjacent cards. Note: if the design comes back with a panoramic background, the chat only tags the cards; call generate-panoramic-background afterwards to actually create and slice the wide image.
|
|
234
|
+
|
|
235
|
+
Design features:
|
|
236
|
+
- Rich text with per-word color, weight, italic, underline, highlight pills, gradient fills, stroke outlines, and emoji
|
|
237
|
+
- Device perspective variants: flat, left-15/30, right-15/30, isometric, top-down, landscape
|
|
238
|
+
- 77 decorative shapes across 13 categories (nature, weather, celebration, social, tech, health, food, travel, abstract, finance, education, pets, emoji), plus 17 core geometric shapes
|
|
239
|
+
- Laurel stats: wing-left + wing-right shapes flanking a hero number
|
|
240
|
+
|
|
241
|
+
App Store 60/40 rule enforced: minimum 60% of cards must show a device mockup, maximum 40% can be marketing-only.
|
|
242
|
+
|
|
233
243
|
Costs 5 credits per generation.`,
|
|
234
244
|
inputSchema: z.object({
|
|
235
245
|
app_name: z.string().describe('Name of the app'),
|
|
236
|
-
app_description: z.string().describe('What the app does
|
|
246
|
+
app_description: z.string().describe('What the app does, in 1-3 sentences'),
|
|
237
247
|
features: z.array(z.string()).max(10).optional()
|
|
238
248
|
.describe('Key features in order of importance. The first 2-3 will be highlighted most prominently.'),
|
|
239
249
|
brand_colors: z.object({
|
|
@@ -242,7 +252,7 @@ Costs 5 credits per generation.`,
|
|
|
242
252
|
accent: z.string().optional().describe('Accent color as hex'),
|
|
243
253
|
}).optional().describe('Brand colors to use in the design'),
|
|
244
254
|
mood: z.string().optional()
|
|
245
|
-
.describe('Design mood
|
|
255
|
+
.describe('Design mood, e.g. "energetic", "calm", "minimal", "bold", "professional", "playful"'),
|
|
246
256
|
device_id: z.string().default('iphone-6.9')
|
|
247
257
|
.describe(`Target device. Options: ${VALID_DEVICE_IDS.join(', ')}. Default: iphone-6.9 (iPhone 16 Pro Max)`),
|
|
248
258
|
count: z.number().min(3).max(10).default(5)
|
|
@@ -251,27 +261,27 @@ Costs 5 credits per generation.`,
|
|
|
251
261
|
.describe('Narrative structure for the screenshots. "auto" lets the AI choose the best flow.'),
|
|
252
262
|
codebase_context: z.object({
|
|
253
263
|
readme_summary: z.string().optional()
|
|
254
|
-
.describe('Summary of the app from README or docs
|
|
264
|
+
.describe('Summary of the app from README or docs: what does it do and why?'),
|
|
255
265
|
key_screens: z.array(z.string()).max(15).optional()
|
|
256
|
-
.describe('Main screens/views in the app
|
|
266
|
+
.describe('Main screens/views in the app, e.g. "Dashboard with activity feed", "Settings with theme toggle"'),
|
|
257
267
|
color_tokens: z.record(z.string()).optional()
|
|
258
|
-
.describe('Brand/theme colors found in code
|
|
268
|
+
.describe('Brand/theme colors found in code, e.g. {"primary": "#7C3AED", "background": "#0F172A"}'),
|
|
259
269
|
target_audience: z.string().optional()
|
|
260
|
-
.describe('Who the app is for
|
|
270
|
+
.describe('Who the app is for, e.g. "busy professionals who want to track habits"'),
|
|
261
271
|
app_category: z.string().optional()
|
|
262
|
-
.describe('App category
|
|
272
|
+
.describe('App category, e.g. fitness, finance, social, productivity, food, travel, health, education'),
|
|
263
273
|
competitive_edge: z.string().optional()
|
|
264
274
|
.describe('What makes this app unique vs competitors'),
|
|
265
275
|
app_store_description: z.string().optional()
|
|
266
276
|
.describe('Existing App Store/Play Store description if found in the codebase'),
|
|
267
277
|
tech_stack: z.string().optional()
|
|
268
|
-
.describe('Tech stack
|
|
278
|
+
.describe('Tech stack, e.g. "React Native", "SwiftUI", "Flutter". Useful for developer-tool apps.'),
|
|
269
279
|
ui_style: z.string().optional()
|
|
270
|
-
.describe('UI style observations
|
|
280
|
+
.describe('UI style observations, e.g. "dark mode with neon accents", "clean minimal with lots of whitespace"'),
|
|
271
281
|
primary_user_flow: z.string().optional()
|
|
272
|
-
.describe('The main user journey
|
|
282
|
+
.describe('The main user journey, e.g. "Sign up → Create project → Invite team → Track progress"'),
|
|
273
283
|
}).optional()
|
|
274
|
-
.describe('Context gathered from researching the app codebase. Dramatically improves screenshot quality
|
|
284
|
+
.describe('Context gathered from researching the app codebase. Dramatically improves screenshot quality. The more detail here, the better the output.'),
|
|
275
285
|
images: chatImagesSchema,
|
|
276
286
|
}),
|
|
277
287
|
}, async (input) => {
|
|
@@ -346,48 +356,54 @@ Costs 5 credits per generation.`,
|
|
|
346
356
|
// Tool 2: edit-screenshots
|
|
347
357
|
server.registerTool('edit-screenshots', {
|
|
348
358
|
title: 'Edit Screenshot Designs',
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
-
|
|
359
|
-
-
|
|
360
|
-
-
|
|
361
|
-
-
|
|
362
|
-
-
|
|
363
|
-
-
|
|
364
|
-
-
|
|
365
|
-
-
|
|
366
|
-
-
|
|
367
|
-
-
|
|
368
|
-
-
|
|
369
|
-
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
-
|
|
373
|
-
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
-
|
|
379
|
-
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
- "Make
|
|
383
|
-
- "
|
|
384
|
-
- "
|
|
385
|
-
- "
|
|
386
|
-
- "
|
|
359
|
+
annotations: {
|
|
360
|
+
// Rewrites cards in place, so a bad edit costs the previous design.
|
|
361
|
+
readOnlyHint: false,
|
|
362
|
+
destructiveHint: true,
|
|
363
|
+
openWorldHint: false,
|
|
364
|
+
},
|
|
365
|
+
description: `Make changes to an existing screenshot project. Use natural language to describe what you want to change. Costs 5 credits per edit. You can also attach images: app screenshots fill the device frames of regenerated cards, a mascot (kind: "mascot") gets placed around the phones.
|
|
366
|
+
|
|
367
|
+
What you can change:
|
|
368
|
+
- Text: headlines, subtitles, badge text, font size, font family (Inter, Poppins, Montserrat, DM Sans, Space Grotesk, etc.)
|
|
369
|
+
- Text styling: per-word color, bold, italic, underline, highlight pills (colored background behind words), gradient text, text stroke outlines
|
|
370
|
+
- Colors: brand palette, gradient backgrounds, accent colors, text colors. A set can rotate MULTIPLE accents card by card ("pink, then coral, then brick") and each card keeps its own highlight colour.
|
|
371
|
+
- Background textures (ask for one explicitly, they are never added on their own): diagonal-stripe, crosshatch, checkerboard, zigzag, hairline-grid, dot-grid, waves, grain, radial-rays, concentric-circles. Kept subtle by design so they cannot affect headline contrast. Tiled textures run continuously across the whole set; radial-rays and concentric-circles can be centred on the middle of the set so the pattern fans out across every card.
|
|
372
|
+
- Layouts (10 types): text-top-device-bottom, text-top-device-tilted, device-hero, social-proof, review-clip, screen-hero, lifestyle-hero, stats-hero, metric-badge, annotated-feature. The AI picks a narrative arc (HOOK → EDUCATE → PROVE → CONVERT) across the set.
|
|
373
|
+
- Layout params: deviceScale (small/medium/large), deviceSide (left/right), textPosition (above/below), textAlign (left/center)
|
|
374
|
+
- Device mockups: perspective variants (flat, left-15, right-15, left-30, right-30, isometric, top-down, landscape-left, landscape-right), 2D rotation, resize, reposition
|
|
375
|
+
- Frame color: recolor the device frame: "natural" (default), "black", "white", "gold". Examples: "make the iPhone gold", "black titanium finish", "white iPhone". Requires Growth plan or higher.
|
|
376
|
+
- Switch devices: "make this for Apple Watch" / "duplicate for Android tablet" clones the project at the target device's canvas size
|
|
377
|
+
- Add/remove cards: add a social proof card, remove card 3, add a marketing title card
|
|
378
|
+
- Compound fields (auto-positioned): statRow, laurelStat, pressBanner, starRating, quote, credential, guarantee
|
|
379
|
+
- Panoramic backgrounds: one wide AI or Pexels image sliced across multiple cards ("pano the background across cards 1-3"). The edit only tags the cards; call generate-panoramic-background afterwards to create and slice the wide image.
|
|
380
|
+
- Panoramic element spans: stretch a foreground image, device-mockup, or shape across adjacent cards ("pano the device across cards 1-2")
|
|
381
|
+
- Floating elements: add/edit badges, star ratings
|
|
382
|
+
- Shapes: glow orbs, waves, blobs, rounded rectangles, circles, custom SVG paths
|
|
383
|
+
- Decorative shapes: 77 library shapes: leaf, flower, cloud, sparkle, heart, rocket, trophy, crown, coffee-cup, airplane, dollar-sign, paw-print, wing-left/wing-right (for laurels), and many more
|
|
384
|
+
- Backgrounds: solid, subtle-gradient, rich-gradient, photo (Pexels), or ai-generated; change gradient colors/angle; set a backgroundPrompt for AI-generated
|
|
385
|
+
- Style: shadows, opacity, border radius, rotation, blur
|
|
386
|
+
|
|
387
|
+
What isn't supported (the AI will flag these in unsupportedAsks):
|
|
388
|
+
- Multiple devices side-by-side in a single card (e.g. iPhone + Watch in one scene). Each card renders one device. Use the duplicate-for-device workflow instead, or split across cards.
|
|
389
|
+
- Uploading a specific user-supplied screenshot into a mockup: use upload-screenshots tool first, then reference the uploaded project.
|
|
390
|
+
|
|
391
|
+
Example edit messages:
|
|
392
|
+
- "Make the headlines larger and use Bebas Neue font"
|
|
393
|
+
- "Change the color scheme to blue (#2563EB) across all cards"
|
|
394
|
+
- "Add a social proof card with 5 stars and a testimonial quote"
|
|
395
|
+
- "Tilt the phone on card 2 to the left"
|
|
396
|
+
- "Pano the background photo across cards 1-3"
|
|
397
|
+
- "Stretch the device on card 1 across into card 2"
|
|
398
|
+
- "Make this project for Apple Watch"
|
|
399
|
+
- "Recolor the iPhone frame to gold across all cards"
|
|
400
|
+
- "Replace card 3 with a CTA card saying Download Free"
|
|
401
|
+
- "Switch card 2 to device-hero layout with statRow showing our three key metrics"
|
|
402
|
+
- "Add decorative leaf and sparkle shapes scattered in the background"
|
|
387
403
|
- "Make 'Every' underlined and italic in the headline"`,
|
|
388
404
|
inputSchema: z.object({
|
|
389
405
|
project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
|
|
390
|
-
message: z.string().describe('What to change
|
|
406
|
+
message: z.string().describe('What to change, in natural language'),
|
|
391
407
|
card_indices: z.array(z.number().int().min(0)).max(10).optional()
|
|
392
408
|
.describe('Target specific cards by index (0-based). e.g. [0] for card 1, [2,3] for cards 3-4. Max 10 indices. Omit to apply changes to all cards.'),
|
|
393
409
|
codebase_context: z.object({
|
|
@@ -464,6 +480,13 @@ Example edit messages:
|
|
|
464
480
|
// Tool 3: render-screenshots
|
|
465
481
|
server.registerTool('render-screenshots', {
|
|
466
482
|
title: 'Render Screenshots to PNG',
|
|
483
|
+
annotations: {
|
|
484
|
+
// Re-rendering the same project state yields the same PNGs.
|
|
485
|
+
readOnlyHint: false,
|
|
486
|
+
destructiveHint: false,
|
|
487
|
+
idempotentHint: true,
|
|
488
|
+
openWorldHint: false,
|
|
489
|
+
},
|
|
467
490
|
description: 'Export a screenshot project to high-resolution PNG files at exact App Store dimensions. Returns download URLs for each card; URLs stay valid for 7 days, so save the PNGs to disk promptly (re-rendering is free if a URL has expired). Free (no credit cost). Rendering blocks until the PNGs are ready: expect roughly 20-40s for iPhone sets and 60-120s for iPad (the larger canvas renders slower), so allow up to ~2 minutes before treating it as failed. Note: device mockups will show empty frames unless app screenshots have been uploaded via upload-screenshots first.',
|
|
468
491
|
inputSchema: z.object({
|
|
469
492
|
project_id: z.string().describe('Project ID to render'),
|
|
@@ -511,10 +534,15 @@ server.registerTool('render-screenshots', {
|
|
|
511
534
|
// Tool 4: list-devices
|
|
512
535
|
server.registerTool('list-devices', {
|
|
513
536
|
title: 'List Supported Devices',
|
|
537
|
+
annotations: {
|
|
538
|
+
// Reads a local constant; makes no API call at all.
|
|
539
|
+
readOnlyHint: true,
|
|
540
|
+
openWorldHint: false,
|
|
541
|
+
},
|
|
514
542
|
description: 'Show all supported device specs for App Store and Play Store screenshots. Use the device ID when generating screenshots.',
|
|
515
543
|
inputSchema: z.object({}),
|
|
516
544
|
}, async () => {
|
|
517
|
-
const lines = DEVICES.map(d => `${d.id}
|
|
545
|
+
const lines = DEVICES.map(d => `${d.id}: ${d.name} (${d.width}×${d.height}, ${d.category}${d.required ? ', required for store submission' : ''})`);
|
|
518
546
|
return {
|
|
519
547
|
content: [{
|
|
520
548
|
type: 'text',
|
|
@@ -532,14 +560,18 @@ server.registerTool('list-devices', {
|
|
|
532
560
|
// Tool 5: get-project
|
|
533
561
|
server.registerTool('get-project', {
|
|
534
562
|
title: 'Get Project Details',
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
-
|
|
563
|
+
annotations: {
|
|
564
|
+
readOnlyHint: true,
|
|
565
|
+
openWorldHint: false,
|
|
566
|
+
},
|
|
567
|
+
description: `Retrieve the full state of a screenshot project, including all cards and their elements. Use this to inspect what was generated before making edits. Free: no credit cost.
|
|
568
|
+
|
|
569
|
+
Returns the canvas state with:
|
|
570
|
+
- cards[]: each card has an id, elements array, and optional background settings
|
|
571
|
+
- Each element has: type (text, device-mockup, shape, badge, image, star-rating), position (x, y), size (width, height), zIndex, and type-specific properties
|
|
572
|
+
- Text elements: fontFamily, fontSize, fontWeight, color, segments (for multi-color text with per-word color, bold, italic, underline, highlightColor)
|
|
573
|
+
- Device mockups: perspectiveVariant (flat, left-15, right-15, left-30, right-30, isometric, top-down, landscape-left, landscape-right), screenshotImage (null if no upload), frameStyle (realistic | none), showIsland (false hides the Dynamic Island pill; Apple accepts screenshots either way)
|
|
574
|
+
- Shapes: 94 shape types (17 core + 77 decorative across 13 categories): core shapes (circle, rectangle, rounded-rect, blob, wave, triangle, diamond, hexagon, ring, star, wing-left, wing-right, etc.) plus decorative library shapes (leaf, flower, cloud, sparkle, heart, rocket, trophy, crown, coffee-cup, airplane, dollar-sign, paw-print, and many more)
|
|
543
575
|
- projectMeta: globalVisualTheme, brandColors, mood, appCategory`,
|
|
544
576
|
inputSchema: z.object({
|
|
545
577
|
project_id: z.string().describe('Project ID to inspect'),
|
|
@@ -560,7 +592,7 @@ Returns the canvas state with:
|
|
|
560
592
|
typeCounts[t] = (typeCounts[t] || 0) + 1;
|
|
561
593
|
}
|
|
562
594
|
const typeStr = Object.entries(typeCounts).map(([t, c]) => `${c} ${t}`).join(', ');
|
|
563
|
-
return ` Card ${i} (${card.id}): ${card.elements.length} elements
|
|
595
|
+
return ` Card ${i} (${card.id}): ${card.elements.length} elements: ${typeStr}`;
|
|
564
596
|
}) || [];
|
|
565
597
|
return {
|
|
566
598
|
content: [{
|
|
@@ -584,19 +616,25 @@ Returns the canvas state with:
|
|
|
584
616
|
// Tool 6: generate-background
|
|
585
617
|
server.registerTool('generate-background', {
|
|
586
618
|
title: 'Generate AI Background',
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
619
|
+
annotations: {
|
|
620
|
+
// Replaces the card's existing background.
|
|
621
|
+
readOnlyHint: false,
|
|
622
|
+
destructiveHint: true,
|
|
623
|
+
openWorldHint: false,
|
|
624
|
+
},
|
|
625
|
+
description: `Generate an AI background image for a specific card using Gemini. The background is generated based on a text prompt and applied directly to the card. Costs 6 credits.
|
|
626
|
+
|
|
627
|
+
Good prompts describe mood, lighting, and color, not objects or text:
|
|
628
|
+
- "Deep purple nebula with soft pink and blue light rays"
|
|
629
|
+
- "Warm sunset gradient with golden bokeh particles"
|
|
630
|
+
- "Dark moody atmosphere with teal and emerald glow"
|
|
631
|
+
- "Clean minimal white-to-light-gray gradient with subtle noise texture"
|
|
632
|
+
|
|
595
633
|
The generated image is cropped to exact device dimensions and set as the card's background.`,
|
|
596
634
|
inputSchema: z.object({
|
|
597
635
|
project_id: z.string().describe('Project ID'),
|
|
598
636
|
card_index: z.number().describe('Card index (0-based) to apply the background to'),
|
|
599
|
-
prompt: z.string().describe('Background description
|
|
637
|
+
prompt: z.string().describe('Background description: describe mood, lighting, colors, textures. Do NOT include text, devices, or UI elements.'),
|
|
600
638
|
}),
|
|
601
639
|
}, async ({ project_id, card_index, prompt }) => {
|
|
602
640
|
const res = await apiCall('POST', `/api/v1/projects/${project_id}/generate-background`, {
|
|
@@ -623,17 +661,23 @@ The generated image is cropped to exact device dimensions and set as the card's
|
|
|
623
661
|
// Tool 7: generate-panoramic-background
|
|
624
662
|
server.registerTool('generate-panoramic-background', {
|
|
625
663
|
title: 'Generate Panoramic Background',
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
-
|
|
636
|
-
-
|
|
664
|
+
annotations: {
|
|
665
|
+
// Replaces the background on every card in the span.
|
|
666
|
+
readOnlyHint: false,
|
|
667
|
+
destructiveHint: true,
|
|
668
|
+
openWorldHint: false,
|
|
669
|
+
},
|
|
670
|
+
description: `Generate one wide background image and slice it across multiple cards so they read as a continuous scene when the App Store gallery scrolls. The store gallery gap is accounted for, so slices line up after Apple's gutter.
|
|
671
|
+
|
|
672
|
+
Two image sources:
|
|
673
|
+
- prompt: AI-generated via Gemini. Costs 6 credits.
|
|
674
|
+
- pexels_query: stock landscape photo from Pexels. Free.
|
|
675
|
+
|
|
676
|
+
If you omit both, the tool fulfills a panoramic the chat already set up: when generate-screenshots or edit-screenshots returns a design with a panoramic background (e.g. after "pano the background across cards 1-3"), the cards are tagged but the wide image isn't created yet. Calling this tool with just the project_id picks up that pending panoramic and generates it.
|
|
677
|
+
|
|
678
|
+
Good prompts describe a continuous scene, not objects or text:
|
|
679
|
+
- "Misty mountain range at dawn, soft pink-to-blue gradient sky"
|
|
680
|
+
- "Calm ocean horizon at golden hour with gentle waves"
|
|
637
681
|
- "Abstract flowing emerald and teal silk waves"`,
|
|
638
682
|
inputSchema: z.object({
|
|
639
683
|
project_id: z.string().describe('Project ID'),
|
|
@@ -671,16 +715,20 @@ Good prompts describe a continuous scene, not objects or text:
|
|
|
671
715
|
// Tool 8: prepare-screenshot-brief
|
|
672
716
|
server.registerTool('prepare-screenshot-brief', {
|
|
673
717
|
title: 'Prepare Screenshot Brief',
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
718
|
+
annotations: {
|
|
719
|
+
readOnlyHint: true,
|
|
720
|
+
openWorldHint: false,
|
|
721
|
+
},
|
|
722
|
+
description: `Get a category playbook and repo-research checklist to prepare for screenshot generation. Call this BEFORE generate-screenshots. Free (no credits).
|
|
723
|
+
|
|
724
|
+
Pass app_category to get category-specific guidance pulled live from AppScreenshotStudio: the frame-1 hook playbook (default layout, what to avoid, caption patterns), the recommended story_flow and mood, and the exact facts to dig out of THIS app's repo for its category (e.g. security and compliance signals for finance, real gameplay art for games, the outcome for fitness).
|
|
725
|
+
|
|
726
|
+
Returns:
|
|
727
|
+
- A category playbook (frame-1 hooks + layout + arc + mood) for the app_category
|
|
728
|
+
- A category-specific repo research focus (what to grep this app for)
|
|
729
|
+
- A generic codebase research checklist (file patterns per tech stack)
|
|
730
|
+
- Headline tips + the codebase_context schema to fill in
|
|
731
|
+
|
|
684
732
|
The more you gather here, the better generate-screenshots does on the first try.`,
|
|
685
733
|
inputSchema: z.object({
|
|
686
734
|
app_category: z.string().optional()
|
|
@@ -690,7 +738,7 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
690
738
|
}),
|
|
691
739
|
}, async ({ app_category, platform }) => {
|
|
692
740
|
const checklist = [
|
|
693
|
-
'# Screenshot Brief
|
|
741
|
+
'# Screenshot Brief: Research Checklist',
|
|
694
742
|
'',
|
|
695
743
|
'Search the codebase for each of these before calling generate-screenshots.',
|
|
696
744
|
'The more you find, the better the screenshots will be.',
|
|
@@ -796,7 +844,7 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
796
844
|
'- Lead with USER BENEFIT, not feature name: "Never forget a task" > "Task Management"',
|
|
797
845
|
'- Use power words: Track, Save, Build, Discover, Master, Simplify, Automate',
|
|
798
846
|
'- Include numbers when possible: "3x faster", "10K+ recipes", "Save 2hrs/week"',
|
|
799
|
-
'- First 3 screenshots matter most
|
|
847
|
+
'- First 3 screenshots matter most: App Store shows them in search results',
|
|
800
848
|
'- Hero card headline = your one-sentence pitch. Make it count.',
|
|
801
849
|
'- Keep headlines under 6 words. Subtitle can add detail.',
|
|
802
850
|
];
|
|
@@ -810,15 +858,15 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
810
858
|
];
|
|
811
859
|
if (platform === 'ios' || platform === 'both') {
|
|
812
860
|
deviceTips.push('**iOS (required for App Store):**');
|
|
813
|
-
deviceTips.push('- iPhone 16 Pro Max (iphone-6.9): 1260×2736
|
|
814
|
-
deviceTips.push('- iPad Pro 13" (ipad-13): 2064×2752
|
|
861
|
+
deviceTips.push('- iPhone 16 Pro Max (iphone-6.9): 1260×2736: REQUIRED');
|
|
862
|
+
deviceTips.push('- iPad Pro 13" (ipad-13): 2064×2752: REQUIRED');
|
|
815
863
|
deviceTips.push('');
|
|
816
864
|
}
|
|
817
865
|
if (platform === 'android' || platform === 'both') {
|
|
818
866
|
deviceTips.push('**Android (required for Play Store):**');
|
|
819
|
-
deviceTips.push('- Android Phone (android-phone): 1080×2340
|
|
820
|
-
deviceTips.push('- Android Tablet 7" (android-tablet-10): 1200×1920
|
|
821
|
-
deviceTips.push('- Android Tablet 10" (android-tablet-large): 1600×2560
|
|
867
|
+
deviceTips.push('- Android Phone (android-phone): 1080×2340: REQUIRED');
|
|
868
|
+
deviceTips.push('- Android Tablet 7" (android-tablet-10): 1200×1920: REQUIRED');
|
|
869
|
+
deviceTips.push('- Android Tablet 10" (android-tablet-large): 1600×2560: second large-screen slot');
|
|
822
870
|
deviceTips.push('');
|
|
823
871
|
}
|
|
824
872
|
// Schema reminder
|
|
@@ -861,21 +909,27 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
861
909
|
// Tool 9: upload-screenshots
|
|
862
910
|
server.registerTool('upload-screenshots', {
|
|
863
911
|
title: 'Upload App Screenshots',
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
-
|
|
878
|
-
-
|
|
912
|
+
annotations: {
|
|
913
|
+
// Overwrites whatever image the device frames already held.
|
|
914
|
+
readOnlyHint: false,
|
|
915
|
+
destructiveHint: true,
|
|
916
|
+
openWorldHint: false,
|
|
917
|
+
},
|
|
918
|
+
description: `Upload local app screenshots (from Simulator, emulator, or screen captures) into the device mockups of an existing project. This lets you add real app UI into the device frames without leaving the terminal.
|
|
919
|
+
|
|
920
|
+
Reads files from your local filesystem, converts them to base64, and sets them on the device mockup elements in the specified cards.
|
|
921
|
+
|
|
922
|
+
Free: no credit cost. The screenshots are placed into the device frames that were created by generate-screenshots.
|
|
923
|
+
|
|
924
|
+
Workflow:
|
|
925
|
+
1. generate-screenshots → creates project with empty device frames
|
|
926
|
+
2. upload-screenshots → fills the device frames with your actual app UI
|
|
927
|
+
3. render-screenshots → exports final PNGs at App Store dimensions
|
|
928
|
+
|
|
929
|
+
Tips:
|
|
930
|
+
- Take screenshots from the iOS Simulator (Cmd+S) or Android emulator
|
|
931
|
+
- Use PNG format for best quality
|
|
932
|
+
- Screenshots are automatically fitted into the device frame
|
|
879
933
|
- You can upload different screenshots to different cards`,
|
|
880
934
|
inputSchema: z.object({
|
|
881
935
|
project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
|
|
@@ -959,7 +1013,7 @@ function autoInstallSkill() {
|
|
|
959
1013
|
copyFileSync(src, dest);
|
|
960
1014
|
}
|
|
961
1015
|
catch {
|
|
962
|
-
// Silent fail
|
|
1016
|
+
// Silent fail: skill install is optional
|
|
963
1017
|
}
|
|
964
1018
|
}
|
|
965
1019
|
async function main() {
|