@appscreenshotstudio/mcp 0.3.0 → 0.4.0
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 +25 -19
- package/dist/index.js +95 -8
- package/package.json +1 -1
- package/skills/appscreenshotstudio/SKILL.md +10 -2
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.
|
|
@@ -136,27 +154,15 @@ Show all supported device specs. No API call needed.
|
|
|
136
154
|
|
|
137
155
|
**Free.**
|
|
138
156
|
|
|
139
|
-
##
|
|
140
|
-
|
|
141
|
-
MCP prompts are pre-defined workflows your agent can follow.
|
|
142
|
-
|
|
143
|
-
### `create-app-screenshots`
|
|
157
|
+
## Claude Code Skill
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
| Argument | Default | Description |
|
|
148
|
-
|---|---|---|
|
|
149
|
-
| `platform` | ios | "ios", "android", or "both" |
|
|
150
|
-
| `extra_instructions` | none | Additional instructions like "use dark theme" |
|
|
159
|
+
The MCP server auto-installs a Claude Code skill on first startup. The skill teaches Claude a structured research-first workflow for better screenshot results. You can also install it manually:
|
|
151
160
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
161
|
+
```bash
|
|
162
|
+
npx @appscreenshotstudio/mcp install-skill
|
|
163
|
+
```
|
|
155
164
|
|
|
156
|
-
|
|
157
|
-
|---|---|---|
|
|
158
|
-
| `project_id` | Yes | Project ID to improve |
|
|
159
|
-
| `focus` | No | What to focus on: "headlines", "colors", "story flow", etc. |
|
|
165
|
+
Once installed, use `/appscreenshotstudio` in Claude Code or just ask "generate App Store screenshots for my app".
|
|
160
166
|
|
|
161
167
|
## Supported Devices
|
|
162
168
|
|
|
@@ -183,7 +189,7 @@ The AI generates professional screenshots using:
|
|
|
183
189
|
1. **Research** — Agent calls `prepare-screenshot-brief`, then searches your codebase for app name, features, colors, screens, and audience
|
|
184
190
|
2. **Generate** — Agent calls `generate-screenshots` with `codebase_context` for app-specific designs
|
|
185
191
|
3. **Iterate** — Agent calls `edit-screenshots` to refine (codebase context carries over automatically)
|
|
186
|
-
4. **Upload** —
|
|
192
|
+
4. **Upload** — Agent calls `upload-screenshots` with local file paths to fill device mockups
|
|
187
193
|
5. **Export** — Agent calls `render-screenshots` or click "Download All" in the web app
|
|
188
194
|
|
|
189
195
|
## 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';
|
|
@@ -124,7 +124,7 @@ function buildDesignMessage(input) {
|
|
|
124
124
|
// ─── MCP Server ─────────────────────────────────────────────────────────────────
|
|
125
125
|
const server = new McpServer({
|
|
126
126
|
name: 'appscreenshotstudio',
|
|
127
|
-
version: '0.
|
|
127
|
+
version: '0.4.0',
|
|
128
128
|
});
|
|
129
129
|
// Tool 1: generate-screenshots
|
|
130
130
|
server.registerTool('generate-screenshots', {
|
|
@@ -244,9 +244,9 @@ Costs 5 credits per generation.`,
|
|
|
244
244
|
`Credits remaining: ${creditsRemaining}`,
|
|
245
245
|
'',
|
|
246
246
|
'Next steps:',
|
|
247
|
-
'1.
|
|
248
|
-
'2.
|
|
249
|
-
'3.
|
|
247
|
+
'1. Use upload-screenshots to add your app screenshots into the device frames',
|
|
248
|
+
'2. Use render-screenshots to export final PNGs',
|
|
249
|
+
'3. Or open the project URL in a browser to preview and adjust',
|
|
250
250
|
'',
|
|
251
251
|
chatData.suggestions?.length
|
|
252
252
|
? `Suggestions: ${chatData.suggestions.join(', ')}`
|
|
@@ -355,7 +355,7 @@ Example edit messages:
|
|
|
355
355
|
// Tool 3: render-screenshots
|
|
356
356
|
server.registerTool('render-screenshots', {
|
|
357
357
|
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
|
|
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 upload-screenshots first.',
|
|
359
359
|
inputSchema: z.object({
|
|
360
360
|
project_id: z.string().describe('Project ID to render'),
|
|
361
361
|
}),
|
|
@@ -730,6 +730,94 @@ This tool helps you gather the right information so generate-screenshots produce
|
|
|
730
730
|
}],
|
|
731
731
|
};
|
|
732
732
|
});
|
|
733
|
+
// Tool 8: upload-screenshots
|
|
734
|
+
server.registerTool('upload-screenshots', {
|
|
735
|
+
title: 'Upload App Screenshots',
|
|
736
|
+
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.
|
|
737
|
+
|
|
738
|
+
Reads files from your local filesystem, converts them to base64, and sets them on the device mockup elements in the specified cards.
|
|
739
|
+
|
|
740
|
+
Free — no credit cost. The screenshots are placed into the device frames that were created by generate-screenshots.
|
|
741
|
+
|
|
742
|
+
Workflow:
|
|
743
|
+
1. generate-screenshots → creates project with empty device frames
|
|
744
|
+
2. upload-screenshots → fills the device frames with your actual app UI
|
|
745
|
+
3. render-screenshots → exports final PNGs at App Store dimensions
|
|
746
|
+
|
|
747
|
+
Tips:
|
|
748
|
+
- Take screenshots from the iOS Simulator (Cmd+S) or Android emulator
|
|
749
|
+
- Use PNG format for best quality
|
|
750
|
+
- Screenshots are automatically fitted into the device frame
|
|
751
|
+
- You can upload different screenshots to different cards`,
|
|
752
|
+
inputSchema: z.object({
|
|
753
|
+
project_id: z.string().describe('Project ID from a previous generate-screenshots call'),
|
|
754
|
+
screenshots: z.array(z.object({
|
|
755
|
+
file_path: z.string().describe('Absolute path to a screenshot file on the local filesystem (PNG, JPG, or WEBP)'),
|
|
756
|
+
card_index: z.number().int().min(0).describe('Which card to place this screenshot on (0-based)'),
|
|
757
|
+
})).min(1).max(10)
|
|
758
|
+
.describe('Array of screenshots to upload, each mapped to a specific card index'),
|
|
759
|
+
}),
|
|
760
|
+
}, async ({ project_id, screenshots }) => {
|
|
761
|
+
// Read local files and convert to base64
|
|
762
|
+
const screenshotData = [];
|
|
763
|
+
const errors = [];
|
|
764
|
+
for (const { file_path, card_index } of screenshots) {
|
|
765
|
+
try {
|
|
766
|
+
if (!existsSync(file_path)) {
|
|
767
|
+
errors.push(`File not found: ${file_path}`);
|
|
768
|
+
continue;
|
|
769
|
+
}
|
|
770
|
+
const buffer = readFileSync(file_path);
|
|
771
|
+
const ext = file_path.toLowerCase().split('.').pop();
|
|
772
|
+
const mimeType = ext === 'jpg' || ext === 'jpeg' ? 'image/jpeg'
|
|
773
|
+
: ext === 'webp' ? 'image/webp'
|
|
774
|
+
: 'image/png';
|
|
775
|
+
const base64 = `data:${mimeType};base64,${buffer.toString('base64')}`;
|
|
776
|
+
screenshotData.push({ card_index, image_base64: base64 });
|
|
777
|
+
}
|
|
778
|
+
catch (err) {
|
|
779
|
+
errors.push(`Failed to read ${file_path}: ${err instanceof Error ? err.message : String(err)}`);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (screenshotData.length === 0) {
|
|
783
|
+
return {
|
|
784
|
+
content: [{
|
|
785
|
+
type: 'text',
|
|
786
|
+
text: `No screenshots could be read.\n\nErrors:\n${errors.join('\n')}`,
|
|
787
|
+
}],
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
// Upload to API
|
|
791
|
+
const res = await apiCall('POST', `/api/v1/projects/${project_id}/upload-screenshots`, {
|
|
792
|
+
screenshots: screenshotData,
|
|
793
|
+
});
|
|
794
|
+
if (!res.ok) {
|
|
795
|
+
return {
|
|
796
|
+
content: [{
|
|
797
|
+
type: 'text',
|
|
798
|
+
text: `Upload failed: ${JSON.stringify(res.data)}${errors.length ? `\n\nFile read errors:\n${errors.join('\n')}` : ''}`,
|
|
799
|
+
}],
|
|
800
|
+
};
|
|
801
|
+
}
|
|
802
|
+
const data = res.data.data;
|
|
803
|
+
const lines = [
|
|
804
|
+
`Uploaded ${data.uploaded} screenshot${data.uploaded !== 1 ? 's' : ''} into device mockups.`,
|
|
805
|
+
'',
|
|
806
|
+
];
|
|
807
|
+
for (const r of data.results) {
|
|
808
|
+
lines.push(` Card ${r.card_index + 1}: ${r.success ? 'OK' : r.error}`);
|
|
809
|
+
}
|
|
810
|
+
if (errors.length) {
|
|
811
|
+
lines.push('', 'File read warnings:', ...errors.map(e => ` ${e}`));
|
|
812
|
+
}
|
|
813
|
+
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');
|
|
814
|
+
return {
|
|
815
|
+
content: [{
|
|
816
|
+
type: 'text',
|
|
817
|
+
text: lines.join('\n'),
|
|
818
|
+
}],
|
|
819
|
+
};
|
|
820
|
+
});
|
|
733
821
|
// ─── Start server ───────────────────────────────────────────────────────────────
|
|
734
822
|
function autoInstallSkill() {
|
|
735
823
|
try {
|
|
@@ -737,11 +825,10 @@ function autoInstallSkill() {
|
|
|
737
825
|
const src = join(__dir, '..', 'skills', 'appscreenshotstudio', 'SKILL.md');
|
|
738
826
|
const destDir = join(homedir(), '.claude', 'skills', 'appscreenshotstudio');
|
|
739
827
|
const dest = join(destDir, 'SKILL.md');
|
|
740
|
-
if (!existsSync(src)
|
|
828
|
+
if (!existsSync(src))
|
|
741
829
|
return;
|
|
742
830
|
mkdirSync(destDir, { recursive: true });
|
|
743
831
|
copyFileSync(src, dest);
|
|
744
|
-
console.error('Installed Claude Code skill to ~/.claude/skills/appscreenshotstudio/');
|
|
745
832
|
}
|
|
746
833
|
catch {
|
|
747
834
|
// Silent fail — skill install is optional
|
package/package.json
CHANGED
|
@@ -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:
|
|
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
|
|
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 |
|