@appscreenshotstudio/mcp 0.3.1 → 0.4.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 CHANGED
@@ -98,6 +98,24 @@ Make changes to an existing project with natural language. Optionally target spe
98
98
 
99
99
  **Costs 5 credits.**
100
100
 
101
+ ### `upload-screenshots`
102
+
103
+ Upload local app screenshots (from Simulator, emulator, or screen captures) into the device mockups of an existing project. Reads files from your local filesystem and places them into the device frames.
104
+
105
+ | Parameter | Type | Required | Description |
106
+ |---|---|---|---|
107
+ | `project_id` | string | Yes | From a previous `generate-screenshots` call |
108
+ | `screenshots` | array | Yes | Array of `{ file_path, card_index }` — maps local files to cards |
109
+
110
+ Each item in `screenshots`:
111
+
112
+ | Field | Type | Description |
113
+ |---|---|---|
114
+ | `file_path` | string | Absolute path to a local PNG, JPG, or WEBP file |
115
+ | `card_index` | number | Which card to place this screenshot on (0-based) |
116
+
117
+ **Free.**
118
+
101
119
  ### `render-screenshots`
102
120
 
103
121
  Export to high-resolution PNGs. Returns download URLs.
@@ -153,7 +171,8 @@ Once installed, use `/appscreenshotstudio` in Claude Code or just ask "generate
153
171
  | `iphone-6.9` | iPhone 16 Pro Max | 1260x2736 | App Store |
154
172
  | `ipad-13` | iPad Pro 13" | 2064x2752 | App Store |
155
173
  | `android-phone` | Android Phone | 1080x2340 | Play Store |
156
- | `android-tablet-10` | Android Tablet 10" | 2560x1600 | Play Store |
174
+ | `android-tablet-10` | Android Tablet 7" | 1200x1920 | Play Store |
175
+ | `apple-watch-ultra` | Apple Watch Ultra 2 | 410x502 | App Store |
157
176
 
158
177
  ## Design Features
159
178
 
@@ -171,7 +190,7 @@ The AI generates professional screenshots using:
171
190
  1. **Research** — Agent calls `prepare-screenshot-brief`, then searches your codebase for app name, features, colors, screens, and audience
172
191
  2. **Generate** — Agent calls `generate-screenshots` with `codebase_context` for app-specific designs
173
192
  3. **Iterate** — Agent calls `edit-screenshots` to refine (codebase context carries over automatically)
174
- 4. **Upload** — Open the project URL, upload your actual app screenshots into the device mockups
193
+ 4. **Upload** — Agent calls `upload-screenshots` with local file paths to fill device mockups
175
194
  5. **Export** — Agent calls `render-screenshots` or click "Download All" in the web app
176
195
 
177
196
  ## Security
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { z } from 'zod';
5
- import { existsSync, mkdirSync, copyFileSync } from 'node:fs';
5
+ import { existsSync, mkdirSync, copyFileSync, readFileSync } from 'node:fs';
6
6
  import { join, dirname } from 'node:path';
7
7
  import { homedir } from 'node:os';
8
8
  import { fileURLToPath } from 'node:url';
@@ -28,11 +28,13 @@ if (args[0] === 'install-skill') {
28
28
  const API_BASE = process.env.APPSCREENSHOTSTUDIO_URL || 'https://appscreenshotstudio.com';
29
29
  const API_KEY = process.env.APPSCREENSHOTSTUDIO_API_KEY;
30
30
  // ─── Devices (mirrors lib/device-specs.ts) ─────────────────────────────────────
31
+ // ⚠️ Keep in sync: lib/device-specs.ts, mcp-server/README.md, docs/api page, docs/mcp page
31
32
  const DEVICES = [
32
33
  { id: 'iphone-6.9', name: 'iPhone 16 Pro Max', width: 1260, height: 2736, category: 'iphone', required: true },
33
34
  { id: 'ipad-13', name: 'iPad Pro 13"', width: 2064, height: 2752, category: 'ipad', required: true },
34
35
  { id: 'android-phone', name: 'Android Phone', width: 1080, height: 2340, category: 'android-phone', required: true },
35
- { id: 'android-tablet-10', name: 'Android Tablet 10"', width: 2560, height: 1600, category: 'android-tablet', required: true },
36
+ { id: 'android-tablet-10', name: 'Android Tablet 7"', width: 1200, height: 1920, category: 'android-tablet', required: true },
37
+ { id: 'apple-watch-ultra', name: 'Apple Watch Ultra 2', width: 410, height: 502, category: 'apple-watch', required: true },
36
38
  ];
37
39
  const VALID_DEVICE_IDS = DEVICES.map(d => d.id);
38
40
  // ─── API helper ─────────────────────────────────────────────────────────────────
@@ -124,7 +126,7 @@ function buildDesignMessage(input) {
124
126
  // ─── MCP Server ─────────────────────────────────────────────────────────────────
125
127
  const server = new McpServer({
126
128
  name: 'appscreenshotstudio',
127
- version: '0.3.1',
129
+ version: '0.4.0',
128
130
  });
129
131
  // Tool 1: generate-screenshots
130
132
  server.registerTool('generate-screenshots', {
@@ -244,9 +246,9 @@ Costs 5 credits per generation.`,
244
246
  `Credits remaining: ${creditsRemaining}`,
245
247
  '',
246
248
  'Next steps:',
247
- '1. Open the project URL in a browser',
248
- '2. Upload app screenshots into the device mockups',
249
- '3. Click "Download All" to export final PNGs',
249
+ '1. Use upload-screenshots to add your app screenshots into the device frames',
250
+ '2. Use render-screenshots to export final PNGs',
251
+ '3. Or open the project URL in a browser to preview and adjust',
250
252
  '',
251
253
  chatData.suggestions?.length
252
254
  ? `Suggestions: ${chatData.suggestions.join(', ')}`
@@ -355,7 +357,7 @@ Example edit messages:
355
357
  // Tool 3: render-screenshots
356
358
  server.registerTool('render-screenshots', {
357
359
  title: 'Render Screenshots to PNG',
358
- description: 'Export a screenshot project to high-resolution PNG files at exact App Store dimensions. Returns download URLs for each card. Free — no credit cost. Note: device mockups will show empty frames unless app screenshots have been uploaded via the web app first.',
360
+ description: 'Export a screenshot project to high-resolution PNG files at exact App Store dimensions. Returns download URLs for each card. Free — no credit cost. Note: device mockups will show empty frames unless app screenshots have been uploaded via upload-screenshots first.',
359
361
  inputSchema: z.object({
360
362
  project_id: z.string().describe('Project ID to render'),
361
363
  }),
@@ -690,7 +692,7 @@ This tool helps you gather the right information so generate-screenshots produce
690
692
  if (platform === 'android' || platform === 'both') {
691
693
  deviceTips.push('**Android (required for Play Store):**');
692
694
  deviceTips.push('- Android Phone (android-phone): 1080×2340 — REQUIRED');
693
- deviceTips.push('- Android Tablet 10" (android-tablet-10): 2560×1600 — optional');
695
+ deviceTips.push('- Android Tablet 7" (android-tablet-10): 1200×1920 — optional');
694
696
  deviceTips.push('');
695
697
  }
696
698
  // Schema reminder
@@ -730,6 +732,94 @@ This tool helps you gather the right information so generate-screenshots produce
730
732
  }],
731
733
  };
732
734
  });
735
+ // Tool 8: upload-screenshots
736
+ server.registerTool('upload-screenshots', {
737
+ title: 'Upload App Screenshots',
738
+ 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.
739
+
740
+ Reads files from your local filesystem, converts them to base64, and sets them on the device mockup elements in the specified cards.
741
+
742
+ Free — no credit cost. The screenshots are placed into the device frames that were created by generate-screenshots.
743
+
744
+ Workflow:
745
+ 1. generate-screenshots → creates project with empty device frames
746
+ 2. upload-screenshots → fills the device frames with your actual app UI
747
+ 3. render-screenshots → exports final PNGs at App Store dimensions
748
+
749
+ Tips:
750
+ - Take screenshots from the iOS Simulator (Cmd+S) or Android emulator
751
+ - Use PNG format for best quality
752
+ - Screenshots are automatically fitted into the device frame
753
+ - You can upload different screenshots to different cards`,
754
+ inputSchema: z.object({
755
+ project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
756
+ screenshots: z.array(z.object({
757
+ file_path: z.string().describe('Absolute path to a screenshot file on the local filesystem (PNG, JPG, or WEBP)'),
758
+ card_index: z.number().int().min(0).describe('Which card to place this screenshot on (0-based)'),
759
+ })).min(1).max(10)
760
+ .describe('Array of screenshots to upload, each mapped to a specific card index'),
761
+ }),
762
+ }, async ({ project_id, screenshots }) => {
763
+ // Read local files and convert to base64
764
+ const screenshotData = [];
765
+ const errors = [];
766
+ for (const { file_path, card_index } of screenshots) {
767
+ try {
768
+ if (!existsSync(file_path)) {
769
+ errors.push(`File not found: ${file_path}`);
770
+ continue;
771
+ }
772
+ const buffer = readFileSync(file_path);
773
+ const ext = file_path.toLowerCase().split('.').pop();
774
+ const mimeType = ext === 'jpg' || ext === 'jpeg' ? 'image/jpeg'
775
+ : ext === 'webp' ? 'image/webp'
776
+ : 'image/png';
777
+ const base64 = `data:${mimeType};base64,${buffer.toString('base64')}`;
778
+ screenshotData.push({ card_index, image_base64: base64 });
779
+ }
780
+ catch (err) {
781
+ errors.push(`Failed to read ${file_path}: ${err instanceof Error ? err.message : String(err)}`);
782
+ }
783
+ }
784
+ if (screenshotData.length === 0) {
785
+ return {
786
+ content: [{
787
+ type: 'text',
788
+ text: `No screenshots could be read.\n\nErrors:\n${errors.join('\n')}`,
789
+ }],
790
+ };
791
+ }
792
+ // Upload to API
793
+ const res = await apiCall('POST', `/api/v1/projects/${project_id}/upload-screenshots`, {
794
+ screenshots: screenshotData,
795
+ });
796
+ if (!res.ok) {
797
+ return {
798
+ content: [{
799
+ type: 'text',
800
+ text: `Upload failed: ${JSON.stringify(res.data)}${errors.length ? `\n\nFile read errors:\n${errors.join('\n')}` : ''}`,
801
+ }],
802
+ };
803
+ }
804
+ const data = res.data.data;
805
+ const lines = [
806
+ `Uploaded ${data.uploaded} screenshot${data.uploaded !== 1 ? 's' : ''} into device mockups.`,
807
+ '',
808
+ ];
809
+ for (const r of data.results) {
810
+ lines.push(` Card ${r.card_index + 1}: ${r.success ? 'OK' : r.error}`);
811
+ }
812
+ if (errors.length) {
813
+ lines.push('', 'File read warnings:', ...errors.map(e => ` ${e}`));
814
+ }
815
+ lines.push('', `Project URL: ${API_BASE}/builder/${project_id}`, '', 'Next steps:', '- Use render-screenshots to export final PNGs', '- Use edit-screenshots to adjust the design', '- Open the project URL to preview in the browser');
816
+ return {
817
+ content: [{
818
+ type: 'text',
819
+ text: lines.join('\n'),
820
+ }],
821
+ };
822
+ });
733
823
  // ─── Start server ───────────────────────────────────────────────────────────────
734
824
  function autoInstallSkill() {
735
825
  try {
@@ -737,11 +827,10 @@ function autoInstallSkill() {
737
827
  const src = join(__dir, '..', 'skills', 'appscreenshotstudio', 'SKILL.md');
738
828
  const destDir = join(homedir(), '.claude', 'skills', 'appscreenshotstudio');
739
829
  const dest = join(destDir, 'SKILL.md');
740
- if (!existsSync(src) || existsSync(dest))
830
+ if (!existsSync(src))
741
831
  return;
742
832
  mkdirSync(destDir, { recursive: true });
743
833
  copyFileSync(src, dest);
744
- console.error('Installed Claude Code skill to ~/.claude/skills/appscreenshotstudio/');
745
834
  }
746
835
  catch {
747
836
  // Silent fail — skill install is optional
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appscreenshotstudio/mcp",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "MCP server for generating App Store screenshots via AppScreenshotStudio",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -69,14 +69,21 @@ Call the `generate-screenshots` MCP tool with:
69
69
  - `story_flow`: `"auto"` (default), `"hero-intro"`, `"problem-solution"`, `"benefit-first"`, etc.
70
70
  - `codebase_context`: the full context object from Step 1
71
71
 
72
- ### Step 4: Review and Iterate
72
+ ### Step 4: Upload App Screenshots
73
+
74
+ If the user has actual app screenshots (from Simulator, emulator, or screen captures), upload them into the device frames using `upload-screenshots`:
75
+ - Takes local file paths and maps them to card indices
76
+ - Fills the empty device mockups with real app UI
77
+ - Free — no credit cost
78
+
79
+ ### Step 5: Review and Iterate
73
80
 
74
81
  Share the project URL and offer refinements using `edit-screenshots`:
75
82
  - "Want to change any headlines or colors?"
76
83
  - "Should I add a social proof card with ratings?"
77
84
  - "Want to try a different layout style?"
78
85
 
79
- ### Step 5: Export
86
+ ### Step 6: Export
80
87
 
81
88
  Call `render-screenshots` to export PNGs at exact App Store dimensions. This is free.
82
89
 
@@ -98,6 +105,7 @@ Headlines must pass the "one second test" — readable at thumbnail size.
98
105
  | generate-screenshots | 5 credits |
99
106
  | edit-screenshots | 5 credits |
100
107
  | generate-background | 6 credits |
108
+ | upload-screenshots | free |
101
109
  | render-screenshots | free |
102
110
  | prepare-screenshot-brief | free |
103
111
  | list-devices | free |