@appscreenshotstudio/mcp 0.8.0 → 0.8.2
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 +210 -150
- package/package.json +49 -49
- package/skills/appscreenshotstudio/SKILL.md +124 -119
package/dist/index.js
CHANGED
|
@@ -32,20 +32,27 @@ const API_KEY = process.env.APPSCREENSHOTSTUDIO_API_KEY;
|
|
|
32
32
|
// mcp-server/skills/appscreenshotstudio/SKILL.md (ships in the npm package, so it drifts unseen),
|
|
33
33
|
// public/api-docs.md (served raw at /api-docs.md, linked from nowhere, so it drifts unseen too)
|
|
34
34
|
// Enforced by `npm run test:device-specs`, which reads all six files.
|
|
35
|
+
// Hand-copied from lib/device-specs.ts because this package ships standalone.
|
|
36
|
+
// `required` means required to PUBLISH, and it is emitted to agents as
|
|
37
|
+
// "required for store submission", so a wrong flag here is a wrong instruction
|
|
38
|
+
// rather than a cosmetic slip. Keep it in step with the source file.
|
|
35
39
|
const DEVICES = [
|
|
36
40
|
{ id: 'iphone-6.9', name: 'iPhone 16 Pro Max', width: 1260, height: 2736, category: 'iphone', required: true },
|
|
37
41
|
{ id: 'iphone-6.3', name: 'iPhone 17 Pro', width: 1206, height: 2622, category: 'iphone', required: false },
|
|
38
42
|
{ id: 'ipad-13', name: 'iPad Pro 13"', width: 2064, height: 2752, category: 'ipad', required: true },
|
|
39
43
|
{ id: 'android-phone', name: 'Android Phone', width: 1080, height: 2340, category: 'android-phone', required: true },
|
|
40
44
|
{ id: 'pixel-11-pro', name: 'Google Pixel 11 Pro', width: 1280, height: 2856, category: 'android-phone', required: false },
|
|
41
|
-
{ id: '
|
|
45
|
+
{ id: 'galaxy-s26-ultra', name: 'Samsung Galaxy S26 Ultra', width: 1440, height: 3120, category: 'android-phone', required: false },
|
|
46
|
+
// Play Console requires 2 screenshots to publish; tablets are "can add", not
|
|
47
|
+
// "must provide". Was `true` until 2026-09-07. See lib/device-specs.ts.
|
|
48
|
+
{ id: 'android-tablet-10', name: 'Android Tablet 7"', width: 1200, height: 1920, category: 'android-tablet', required: false },
|
|
42
49
|
{ id: 'android-tablet-large', name: 'Android Tablet 10"', width: 1600, height: 2560, category: 'android-tablet', required: false },
|
|
43
50
|
{ id: 'apple-watch-ultra', name: 'Apple Watch Ultra 2', width: 410, height: 502, category: 'apple-watch', required: true },
|
|
44
51
|
];
|
|
45
52
|
const VALID_DEVICE_IDS = DEVICES.map(d => d.id);
|
|
46
53
|
// Aliases callers commonly pass instead of the canonical id: display-name
|
|
47
54
|
// derivations ("iPhone 16 Pro Max" -> iphone-16-pro-max) and legacy slugs.
|
|
48
|
-
// Mirrors MARKETING_TO_SPEC in lib/device-specs.ts
|
|
55
|
+
// Mirrors MARKETING_TO_SPEC in lib/device-specs.ts. Keep the two in sync.
|
|
49
56
|
const DEVICE_ALIASES = {
|
|
50
57
|
'iphone-16-pro': 'iphone-6.9',
|
|
51
58
|
'iphone-16-pro-max': 'iphone-6.9',
|
|
@@ -153,10 +160,10 @@ function buildDesignMessage(input, hasScreenshotImages = false) {
|
|
|
153
160
|
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
161
|
}
|
|
155
162
|
if (hasScreenshotImages) {
|
|
156
|
-
parts.push(`\nMy app screenshots are attached
|
|
163
|
+
parts.push(`\nMy app screenshots are attached, and they are placed into the device frames automatically.`);
|
|
157
164
|
}
|
|
158
165
|
else {
|
|
159
|
-
parts.push(`\nAll device mockups should have screenshotImage: null
|
|
166
|
+
parts.push(`\nAll device mockups should have screenshotImage: null. The developer will upload actual app screenshots later.`);
|
|
160
167
|
}
|
|
161
168
|
parts.push(`Please include projectMeta with brand colors, mood, appCategory, and a rich globalVisualTheme description.`);
|
|
162
169
|
return parts.join('\n');
|
|
@@ -191,49 +198,58 @@ const chatImagesSchema = z.array(z.object({
|
|
|
191
198
|
})).max(5).optional()
|
|
192
199
|
.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
200
|
// ─── MCP Server ─────────────────────────────────────────────────────────────────
|
|
201
|
+
// Read from package.json rather than a literal. This is the version a client
|
|
202
|
+
// sees in the MCP handshake, and a hand-synced literal silently sat at 0.6.1
|
|
203
|
+
// through the 0.6.2 release, then at 0.6.3 through 0.7.0 and 0.8.0. A comment
|
|
204
|
+
// asking the next person to remember has now failed twice, so stop asking.
|
|
205
|
+
const PKG_VERSION = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf-8')).version;
|
|
194
206
|
const server = new McpServer({
|
|
195
207
|
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',
|
|
208
|
+
version: PKG_VERSION,
|
|
199
209
|
});
|
|
200
210
|
// Tool 1: generate-screenshots
|
|
201
211
|
server.registerTool('generate-screenshots', {
|
|
202
212
|
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
|
-
|
|
213
|
+
annotations: {
|
|
214
|
+
// Creates a new project; never overwrites an existing one.
|
|
215
|
+
readOnlyHint: false,
|
|
216
|
+
destructiveHint: false,
|
|
217
|
+
openWorldHint: false,
|
|
218
|
+
},
|
|
219
|
+
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.
|
|
220
|
+
|
|
221
|
+
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.
|
|
222
|
+
|
|
223
|
+
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.
|
|
224
|
+
|
|
225
|
+
10 layout types available per card:
|
|
226
|
+
- text-top-device-bottom: headline top, flat device bottom (feature/educate)
|
|
227
|
+
- text-top-device-tilted: headline left, tilted device right (or mirrored)
|
|
228
|
+
- device-hero: headline + large centered device, product-forward
|
|
229
|
+
- social-proof: stars + quote + laurel stat, no device (testimonial-led)
|
|
230
|
+
- review-clip: rating-statement headline + stars + quote + bottom-clipped device
|
|
231
|
+
- screen-hero: top-clipped device + centered headline + optional trust stat
|
|
232
|
+
- lifestyle-hero: full-bleed photo background + text overlay (no device)
|
|
233
|
+
- stats-hero: giant centered stat(s), no device, numbers-led
|
|
234
|
+
- metric-badge: centered device + chunky "achievement card" floating over its screen
|
|
235
|
+
- annotated-feature: tilted device + side callout chip linked by a connector line
|
|
236
|
+
|
|
237
|
+
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.
|
|
238
|
+
|
|
239
|
+
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.
|
|
240
|
+
|
|
241
|
+
Design features:
|
|
242
|
+
- Rich text with per-word color, weight, italic, underline, highlight pills, gradient fills, stroke outlines, and emoji
|
|
243
|
+
- Device perspective variants: flat, left-15/30, right-15/30, isometric, top-down, landscape
|
|
244
|
+
- 77 decorative shapes across 13 categories (nature, weather, celebration, social, tech, health, food, travel, abstract, finance, education, pets, emoji), plus 17 core geometric shapes
|
|
245
|
+
- Laurel stats: wing-left + wing-right shapes flanking a hero number
|
|
246
|
+
|
|
247
|
+
App Store 60/40 rule enforced: minimum 60% of cards must show a device mockup, maximum 40% can be marketing-only.
|
|
248
|
+
|
|
233
249
|
Costs 5 credits per generation.`,
|
|
234
250
|
inputSchema: z.object({
|
|
235
251
|
app_name: z.string().describe('Name of the app'),
|
|
236
|
-
app_description: z.string().describe('What the app does
|
|
252
|
+
app_description: z.string().describe('What the app does, in 1-3 sentences'),
|
|
237
253
|
features: z.array(z.string()).max(10).optional()
|
|
238
254
|
.describe('Key features in order of importance. The first 2-3 will be highlighted most prominently.'),
|
|
239
255
|
brand_colors: z.object({
|
|
@@ -242,7 +258,7 @@ Costs 5 credits per generation.`,
|
|
|
242
258
|
accent: z.string().optional().describe('Accent color as hex'),
|
|
243
259
|
}).optional().describe('Brand colors to use in the design'),
|
|
244
260
|
mood: z.string().optional()
|
|
245
|
-
.describe('Design mood
|
|
261
|
+
.describe('Design mood, e.g. "energetic", "calm", "minimal", "bold", "professional", "playful"'),
|
|
246
262
|
device_id: z.string().default('iphone-6.9')
|
|
247
263
|
.describe(`Target device. Options: ${VALID_DEVICE_IDS.join(', ')}. Default: iphone-6.9 (iPhone 16 Pro Max)`),
|
|
248
264
|
count: z.number().min(3).max(10).default(5)
|
|
@@ -251,27 +267,27 @@ Costs 5 credits per generation.`,
|
|
|
251
267
|
.describe('Narrative structure for the screenshots. "auto" lets the AI choose the best flow.'),
|
|
252
268
|
codebase_context: z.object({
|
|
253
269
|
readme_summary: z.string().optional()
|
|
254
|
-
.describe('Summary of the app from README or docs
|
|
270
|
+
.describe('Summary of the app from README or docs: what does it do and why?'),
|
|
255
271
|
key_screens: z.array(z.string()).max(15).optional()
|
|
256
|
-
.describe('Main screens/views in the app
|
|
272
|
+
.describe('Main screens/views in the app, e.g. "Dashboard with activity feed", "Settings with theme toggle"'),
|
|
257
273
|
color_tokens: z.record(z.string()).optional()
|
|
258
|
-
.describe('Brand/theme colors found in code
|
|
274
|
+
.describe('Brand/theme colors found in code, e.g. {"primary": "#7C3AED", "background": "#0F172A"}'),
|
|
259
275
|
target_audience: z.string().optional()
|
|
260
|
-
.describe('Who the app is for
|
|
276
|
+
.describe('Who the app is for, e.g. "busy professionals who want to track habits"'),
|
|
261
277
|
app_category: z.string().optional()
|
|
262
|
-
.describe('App category
|
|
278
|
+
.describe('App category, e.g. fitness, finance, social, productivity, food, travel, health, education'),
|
|
263
279
|
competitive_edge: z.string().optional()
|
|
264
280
|
.describe('What makes this app unique vs competitors'),
|
|
265
281
|
app_store_description: z.string().optional()
|
|
266
282
|
.describe('Existing App Store/Play Store description if found in the codebase'),
|
|
267
283
|
tech_stack: z.string().optional()
|
|
268
|
-
.describe('Tech stack
|
|
284
|
+
.describe('Tech stack, e.g. "React Native", "SwiftUI", "Flutter". Useful for developer-tool apps.'),
|
|
269
285
|
ui_style: z.string().optional()
|
|
270
|
-
.describe('UI style observations
|
|
286
|
+
.describe('UI style observations, e.g. "dark mode with neon accents", "clean minimal with lots of whitespace"'),
|
|
271
287
|
primary_user_flow: z.string().optional()
|
|
272
|
-
.describe('The main user journey
|
|
288
|
+
.describe('The main user journey, e.g. "Sign up → Create project → Invite team → Track progress"'),
|
|
273
289
|
}).optional()
|
|
274
|
-
.describe('Context gathered from researching the app codebase. Dramatically improves screenshot quality
|
|
290
|
+
.describe('Context gathered from researching the app codebase. Dramatically improves screenshot quality. The more detail here, the better the output.'),
|
|
275
291
|
images: chatImagesSchema,
|
|
276
292
|
}),
|
|
277
293
|
}, async (input) => {
|
|
@@ -346,48 +362,54 @@ Costs 5 credits per generation.`,
|
|
|
346
362
|
// Tool 2: edit-screenshots
|
|
347
363
|
server.registerTool('edit-screenshots', {
|
|
348
364
|
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
|
-
- "
|
|
365
|
+
annotations: {
|
|
366
|
+
// Rewrites cards in place, so a bad edit costs the previous design.
|
|
367
|
+
readOnlyHint: false,
|
|
368
|
+
destructiveHint: true,
|
|
369
|
+
openWorldHint: false,
|
|
370
|
+
},
|
|
371
|
+
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.
|
|
372
|
+
|
|
373
|
+
What you can change:
|
|
374
|
+
- Text: headlines, subtitles, badge text, font size, font family (Inter, Poppins, Montserrat, DM Sans, Space Grotesk, etc.)
|
|
375
|
+
- Text styling: per-word color, bold, italic, underline, highlight pills (colored background behind words), gradient text, text stroke outlines
|
|
376
|
+
- 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.
|
|
377
|
+
- 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.
|
|
378
|
+
- 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.
|
|
379
|
+
- Layout params: deviceScale (small/medium/large), deviceSide (left/right), textPosition (above/below), textAlign (left/center)
|
|
380
|
+
- Device mockups: perspective variants (flat, left-15, right-15, left-30, right-30, isometric, top-down, landscape-left, landscape-right), 2D rotation, resize, reposition
|
|
381
|
+
- 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.
|
|
382
|
+
- Switch devices: "make this for Apple Watch" / "duplicate for Android tablet" clones the project at the target device's canvas size
|
|
383
|
+
- Add/remove cards: add a social proof card, remove card 3, add a marketing title card
|
|
384
|
+
- Compound fields (auto-positioned): statRow, laurelStat, pressBanner, starRating, quote, credential, guarantee
|
|
385
|
+
- 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.
|
|
386
|
+
- Panoramic element spans: stretch a foreground image, device-mockup, or shape across adjacent cards ("pano the device across cards 1-2")
|
|
387
|
+
- Floating elements: add/edit badges, star ratings
|
|
388
|
+
- Shapes: glow orbs, waves, blobs, rounded rectangles, circles, custom SVG paths
|
|
389
|
+
- 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
|
|
390
|
+
- Backgrounds: solid, subtle-gradient, rich-gradient, photo (Pexels), or ai-generated; change gradient colors/angle; set a backgroundPrompt for AI-generated
|
|
391
|
+
- Style: shadows, opacity, border radius, rotation, blur
|
|
392
|
+
|
|
393
|
+
What isn't supported (the AI will flag these in unsupportedAsks):
|
|
394
|
+
- 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.
|
|
395
|
+
- Uploading a specific user-supplied screenshot into a mockup: use upload-screenshots tool first, then reference the uploaded project.
|
|
396
|
+
|
|
397
|
+
Example edit messages:
|
|
398
|
+
- "Make the headlines larger and use Bebas Neue font"
|
|
399
|
+
- "Change the color scheme to blue (#2563EB) across all cards"
|
|
400
|
+
- "Add a social proof card with 5 stars and a testimonial quote"
|
|
401
|
+
- "Tilt the phone on card 2 to the left"
|
|
402
|
+
- "Pano the background photo across cards 1-3"
|
|
403
|
+
- "Stretch the device on card 1 across into card 2"
|
|
404
|
+
- "Make this project for Apple Watch"
|
|
405
|
+
- "Recolor the iPhone frame to gold across all cards"
|
|
406
|
+
- "Replace card 3 with a CTA card saying Download Free"
|
|
407
|
+
- "Switch card 2 to device-hero layout with statRow showing our three key metrics"
|
|
408
|
+
- "Add decorative leaf and sparkle shapes scattered in the background"
|
|
387
409
|
- "Make 'Every' underlined and italic in the headline"`,
|
|
388
410
|
inputSchema: z.object({
|
|
389
411
|
project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
|
|
390
|
-
message: z.string().describe('What to change
|
|
412
|
+
message: z.string().describe('What to change, in natural language'),
|
|
391
413
|
card_indices: z.array(z.number().int().min(0)).max(10).optional()
|
|
392
414
|
.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
415
|
codebase_context: z.object({
|
|
@@ -464,6 +486,13 @@ Example edit messages:
|
|
|
464
486
|
// Tool 3: render-screenshots
|
|
465
487
|
server.registerTool('render-screenshots', {
|
|
466
488
|
title: 'Render Screenshots to PNG',
|
|
489
|
+
annotations: {
|
|
490
|
+
// Re-rendering the same project state yields the same PNGs.
|
|
491
|
+
readOnlyHint: false,
|
|
492
|
+
destructiveHint: false,
|
|
493
|
+
idempotentHint: true,
|
|
494
|
+
openWorldHint: false,
|
|
495
|
+
},
|
|
467
496
|
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
497
|
inputSchema: z.object({
|
|
469
498
|
project_id: z.string().describe('Project ID to render'),
|
|
@@ -511,10 +540,15 @@ server.registerTool('render-screenshots', {
|
|
|
511
540
|
// Tool 4: list-devices
|
|
512
541
|
server.registerTool('list-devices', {
|
|
513
542
|
title: 'List Supported Devices',
|
|
543
|
+
annotations: {
|
|
544
|
+
// Reads a local constant; makes no API call at all.
|
|
545
|
+
readOnlyHint: true,
|
|
546
|
+
openWorldHint: false,
|
|
547
|
+
},
|
|
514
548
|
description: 'Show all supported device specs for App Store and Play Store screenshots. Use the device ID when generating screenshots.',
|
|
515
549
|
inputSchema: z.object({}),
|
|
516
550
|
}, async () => {
|
|
517
|
-
const lines = DEVICES.map(d => `${d.id}
|
|
551
|
+
const lines = DEVICES.map(d => `${d.id}: ${d.name} (${d.width}×${d.height}, ${d.category}${d.required ? ', required for store submission' : ''})`);
|
|
518
552
|
return {
|
|
519
553
|
content: [{
|
|
520
554
|
type: 'text',
|
|
@@ -532,14 +566,18 @@ server.registerTool('list-devices', {
|
|
|
532
566
|
// Tool 5: get-project
|
|
533
567
|
server.registerTool('get-project', {
|
|
534
568
|
title: 'Get Project Details',
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
-
|
|
569
|
+
annotations: {
|
|
570
|
+
readOnlyHint: true,
|
|
571
|
+
openWorldHint: false,
|
|
572
|
+
},
|
|
573
|
+
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.
|
|
574
|
+
|
|
575
|
+
Returns the canvas state with:
|
|
576
|
+
- cards[]: each card has an id, elements array, and optional background settings
|
|
577
|
+
- Each element has: type (text, device-mockup, shape, badge, image, star-rating), position (x, y), size (width, height), zIndex, and type-specific properties
|
|
578
|
+
- Text elements: fontFamily, fontSize, fontWeight, color, segments (for multi-color text with per-word color, bold, italic, underline, highlightColor)
|
|
579
|
+
- 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)
|
|
580
|
+
- 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
581
|
- projectMeta: globalVisualTheme, brandColors, mood, appCategory`,
|
|
544
582
|
inputSchema: z.object({
|
|
545
583
|
project_id: z.string().describe('Project ID to inspect'),
|
|
@@ -560,7 +598,7 @@ Returns the canvas state with:
|
|
|
560
598
|
typeCounts[t] = (typeCounts[t] || 0) + 1;
|
|
561
599
|
}
|
|
562
600
|
const typeStr = Object.entries(typeCounts).map(([t, c]) => `${c} ${t}`).join(', ');
|
|
563
|
-
return ` Card ${i} (${card.id}): ${card.elements.length} elements
|
|
601
|
+
return ` Card ${i} (${card.id}): ${card.elements.length} elements: ${typeStr}`;
|
|
564
602
|
}) || [];
|
|
565
603
|
return {
|
|
566
604
|
content: [{
|
|
@@ -584,19 +622,25 @@ Returns the canvas state with:
|
|
|
584
622
|
// Tool 6: generate-background
|
|
585
623
|
server.registerTool('generate-background', {
|
|
586
624
|
title: 'Generate AI Background',
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
625
|
+
annotations: {
|
|
626
|
+
// Replaces the card's existing background.
|
|
627
|
+
readOnlyHint: false,
|
|
628
|
+
destructiveHint: true,
|
|
629
|
+
openWorldHint: false,
|
|
630
|
+
},
|
|
631
|
+
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.
|
|
632
|
+
|
|
633
|
+
Good prompts describe mood, lighting, and color, not objects or text:
|
|
634
|
+
- "Deep purple nebula with soft pink and blue light rays"
|
|
635
|
+
- "Warm sunset gradient with golden bokeh particles"
|
|
636
|
+
- "Dark moody atmosphere with teal and emerald glow"
|
|
637
|
+
- "Clean minimal white-to-light-gray gradient with subtle noise texture"
|
|
638
|
+
|
|
595
639
|
The generated image is cropped to exact device dimensions and set as the card's background.`,
|
|
596
640
|
inputSchema: z.object({
|
|
597
641
|
project_id: z.string().describe('Project ID'),
|
|
598
642
|
card_index: z.number().describe('Card index (0-based) to apply the background to'),
|
|
599
|
-
prompt: z.string().describe('Background description
|
|
643
|
+
prompt: z.string().describe('Background description: describe mood, lighting, colors, textures. Do NOT include text, devices, or UI elements.'),
|
|
600
644
|
}),
|
|
601
645
|
}, async ({ project_id, card_index, prompt }) => {
|
|
602
646
|
const res = await apiCall('POST', `/api/v1/projects/${project_id}/generate-background`, {
|
|
@@ -623,17 +667,23 @@ The generated image is cropped to exact device dimensions and set as the card's
|
|
|
623
667
|
// Tool 7: generate-panoramic-background
|
|
624
668
|
server.registerTool('generate-panoramic-background', {
|
|
625
669
|
title: 'Generate Panoramic Background',
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
-
|
|
636
|
-
-
|
|
670
|
+
annotations: {
|
|
671
|
+
// Replaces the background on every card in the span.
|
|
672
|
+
readOnlyHint: false,
|
|
673
|
+
destructiveHint: true,
|
|
674
|
+
openWorldHint: false,
|
|
675
|
+
},
|
|
676
|
+
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.
|
|
677
|
+
|
|
678
|
+
Two image sources:
|
|
679
|
+
- prompt: AI-generated via Gemini. Costs 6 credits.
|
|
680
|
+
- pexels_query: stock landscape photo from Pexels. Free.
|
|
681
|
+
|
|
682
|
+
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.
|
|
683
|
+
|
|
684
|
+
Good prompts describe a continuous scene, not objects or text:
|
|
685
|
+
- "Misty mountain range at dawn, soft pink-to-blue gradient sky"
|
|
686
|
+
- "Calm ocean horizon at golden hour with gentle waves"
|
|
637
687
|
- "Abstract flowing emerald and teal silk waves"`,
|
|
638
688
|
inputSchema: z.object({
|
|
639
689
|
project_id: z.string().describe('Project ID'),
|
|
@@ -671,16 +721,20 @@ Good prompts describe a continuous scene, not objects or text:
|
|
|
671
721
|
// Tool 8: prepare-screenshot-brief
|
|
672
722
|
server.registerTool('prepare-screenshot-brief', {
|
|
673
723
|
title: 'Prepare Screenshot Brief',
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
724
|
+
annotations: {
|
|
725
|
+
readOnlyHint: true,
|
|
726
|
+
openWorldHint: false,
|
|
727
|
+
},
|
|
728
|
+
description: `Get a category playbook and repo-research checklist to prepare for screenshot generation. Call this BEFORE generate-screenshots. Free (no credits).
|
|
729
|
+
|
|
730
|
+
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).
|
|
731
|
+
|
|
732
|
+
Returns:
|
|
733
|
+
- A category playbook (frame-1 hooks + layout + arc + mood) for the app_category
|
|
734
|
+
- A category-specific repo research focus (what to grep this app for)
|
|
735
|
+
- A generic codebase research checklist (file patterns per tech stack)
|
|
736
|
+
- Headline tips + the codebase_context schema to fill in
|
|
737
|
+
|
|
684
738
|
The more you gather here, the better generate-screenshots does on the first try.`,
|
|
685
739
|
inputSchema: z.object({
|
|
686
740
|
app_category: z.string().optional()
|
|
@@ -690,7 +744,7 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
690
744
|
}),
|
|
691
745
|
}, async ({ app_category, platform }) => {
|
|
692
746
|
const checklist = [
|
|
693
|
-
'# Screenshot Brief
|
|
747
|
+
'# Screenshot Brief: Research Checklist',
|
|
694
748
|
'',
|
|
695
749
|
'Search the codebase for each of these before calling generate-screenshots.',
|
|
696
750
|
'The more you find, the better the screenshots will be.',
|
|
@@ -796,7 +850,7 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
796
850
|
'- Lead with USER BENEFIT, not feature name: "Never forget a task" > "Task Management"',
|
|
797
851
|
'- Use power words: Track, Save, Build, Discover, Master, Simplify, Automate',
|
|
798
852
|
'- Include numbers when possible: "3x faster", "10K+ recipes", "Save 2hrs/week"',
|
|
799
|
-
'- First 3 screenshots matter most
|
|
853
|
+
'- First 3 screenshots matter most: App Store shows them in search results',
|
|
800
854
|
'- Hero card headline = your one-sentence pitch. Make it count.',
|
|
801
855
|
'- Keep headlines under 6 words. Subtitle can add detail.',
|
|
802
856
|
];
|
|
@@ -810,15 +864,15 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
810
864
|
];
|
|
811
865
|
if (platform === 'ios' || platform === 'both') {
|
|
812
866
|
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
|
|
867
|
+
deviceTips.push('- iPhone 16 Pro Max (iphone-6.9): 1260×2736: REQUIRED');
|
|
868
|
+
deviceTips.push('- iPad Pro 13" (ipad-13): 2064×2752: REQUIRED');
|
|
815
869
|
deviceTips.push('');
|
|
816
870
|
}
|
|
817
871
|
if (platform === 'android' || platform === 'both') {
|
|
818
872
|
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
|
|
873
|
+
deviceTips.push('- Android Phone (android-phone): 1080×2340: REQUIRED');
|
|
874
|
+
deviceTips.push('- Android Tablet 7" (android-tablet-10): 1200×1920: REQUIRED');
|
|
875
|
+
deviceTips.push('- Android Tablet 10" (android-tablet-large): 1600×2560: second large-screen slot');
|
|
822
876
|
deviceTips.push('');
|
|
823
877
|
}
|
|
824
878
|
// Schema reminder
|
|
@@ -861,21 +915,27 @@ The more you gather here, the better generate-screenshots does on the first try.
|
|
|
861
915
|
// Tool 9: upload-screenshots
|
|
862
916
|
server.registerTool('upload-screenshots', {
|
|
863
917
|
title: 'Upload App Screenshots',
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
-
|
|
878
|
-
-
|
|
918
|
+
annotations: {
|
|
919
|
+
// Overwrites whatever image the device frames already held.
|
|
920
|
+
readOnlyHint: false,
|
|
921
|
+
destructiveHint: true,
|
|
922
|
+
openWorldHint: false,
|
|
923
|
+
},
|
|
924
|
+
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.
|
|
925
|
+
|
|
926
|
+
Reads files from your local filesystem, converts them to base64, and sets them on the device mockup elements in the specified cards.
|
|
927
|
+
|
|
928
|
+
Free: no credit cost. The screenshots are placed into the device frames that were created by generate-screenshots.
|
|
929
|
+
|
|
930
|
+
Workflow:
|
|
931
|
+
1. generate-screenshots → creates project with empty device frames
|
|
932
|
+
2. upload-screenshots → fills the device frames with your actual app UI
|
|
933
|
+
3. render-screenshots → exports final PNGs at App Store dimensions
|
|
934
|
+
|
|
935
|
+
Tips:
|
|
936
|
+
- Take screenshots from the iOS Simulator (Cmd+S) or Android emulator
|
|
937
|
+
- Use PNG format for best quality
|
|
938
|
+
- Screenshots are automatically fitted into the device frame
|
|
879
939
|
- You can upload different screenshots to different cards`,
|
|
880
940
|
inputSchema: z.object({
|
|
881
941
|
project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
|
|
@@ -959,7 +1019,7 @@ function autoInstallSkill() {
|
|
|
959
1019
|
copyFileSync(src, dest);
|
|
960
1020
|
}
|
|
961
1021
|
catch {
|
|
962
|
-
// Silent fail
|
|
1022
|
+
// Silent fail: skill install is optional
|
|
963
1023
|
}
|
|
964
1024
|
}
|
|
965
1025
|
async function main() {
|