shipshots-mcp 0.1.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/LICENSE +21 -0
- package/README.md +109 -0
- package/dist/api-client.d.ts +19 -0
- package/dist/api-client.d.ts.map +1 -0
- package/dist/api-client.js +126 -0
- package/dist/api-client.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +128 -0
- package/dist/cli.js.map +1 -0
- package/dist/defaults.d.ts +86 -0
- package/dist/defaults.d.ts.map +1 -0
- package/dist/defaults.js +360 -0
- package/dist/defaults.js.map +1 -0
- package/dist/design.d.ts +26 -0
- package/dist/design.d.ts.map +1 -0
- package/dist/design.js +63 -0
- package/dist/design.js.map +1 -0
- package/dist/helpers.d.ts +12 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +22 -0
- package/dist/helpers.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/batch.d.ts +4 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +253 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/duplicate.d.ts +4 -0
- package/dist/tools/duplicate.d.ts.map +1 -0
- package/dist/tools/duplicate.js +91 -0
- package/dist/tools/duplicate.js.map +1 -0
- package/dist/tools/export.d.ts +4 -0
- package/dist/tools/export.d.ts.map +1 -0
- package/dist/tools/export.js +67 -0
- package/dist/tools/export.js.map +1 -0
- package/dist/tools/layers.d.ts +4 -0
- package/dist/tools/layers.d.ts.map +1 -0
- package/dist/tools/layers.js +493 -0
- package/dist/tools/layers.js.map +1 -0
- package/dist/tools/project.d.ts +4 -0
- package/dist/tools/project.d.ts.map +1 -0
- package/dist/tools/project.js +190 -0
- package/dist/tools/project.js.map +1 -0
- package/dist/tools/screen.d.ts +4 -0
- package/dist/tools/screen.d.ts.map +1 -0
- package/dist/tools/screen.js +295 -0
- package/dist/tools/screen.js.map +1 -0
- package/dist/tools/video.d.ts +4 -0
- package/dist/tools/video.d.ts.map +1 -0
- package/dist/tools/video.js +144 -0
- package/dist/tools/video.js.map +1 -0
- package/dist/types.d.ts +163 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/package.json +41 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shipshots
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Shipshots MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server that lets Claude (or any MCP client) create App Store & Play Store screenshots programmatically via the [Shipshots](https://shipshots.app) API.
|
|
4
|
+
|
|
5
|
+
## Quick Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx shipshots-mcp init --token sb_your_token_here
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
This auto-configures your MCP client. It supports Claude Code, Claude Desktop, Cursor, and more.
|
|
12
|
+
|
|
13
|
+
Get your token at [shipshots.app/dashboard/setup](https://shipshots.app/dashboard/setup).
|
|
14
|
+
|
|
15
|
+
### Options
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npx shipshots-mcp init --token sb_... --client claude-code # .mcp.json in current dir
|
|
19
|
+
npx shipshots-mcp init --token sb_... --client claude-desktop # Claude Desktop config
|
|
20
|
+
npx shipshots-mcp init --token sb_... --client cursor # .cursor/mcp.json
|
|
21
|
+
npx shipshots-mcp init --token sb_... --client stdout # Print config to terminal
|
|
22
|
+
npx shipshots-mcp init --token sb_... --url http://localhost:3000 # Custom API URL
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Manual Setup
|
|
26
|
+
|
|
27
|
+
If you prefer to configure manually, add this to your MCP client's config:
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"mcpServers": {
|
|
32
|
+
"shipshots": {
|
|
33
|
+
"command": "npx",
|
|
34
|
+
"args": ["-y", "shipshots-mcp"],
|
|
35
|
+
"env": {
|
|
36
|
+
"SHIPSHOTS_API_URL": "https://shipshots.app",
|
|
37
|
+
"SHIPSHOTS_API_TOKEN": "sb_your_token_here"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Config file locations:**
|
|
45
|
+
- Claude Code: `.mcp.json` in your project
|
|
46
|
+
- Claude Desktop (macOS): `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
47
|
+
- Claude Desktop (Windows): `%APPDATA%/Claude/claude_desktop_config.json`
|
|
48
|
+
- Cursor: `.cursor/mcp.json` in your project
|
|
49
|
+
|
|
50
|
+
## Getting Your API Token
|
|
51
|
+
|
|
52
|
+
1. Sign in at [shipshots.app](https://shipshots.app)
|
|
53
|
+
2. Go to **Dashboard → Setup MCP** (or **Settings → MCP Tokens**)
|
|
54
|
+
3. Click **Create Token** and copy the `sb_`-prefixed token
|
|
55
|
+
|
|
56
|
+
## Available Tools
|
|
57
|
+
|
|
58
|
+
### Project Management
|
|
59
|
+
- **create_project** — Create a new project (optionally from a template)
|
|
60
|
+
- **get_project** — Fetch full project data
|
|
61
|
+
- **delete_project** — Delete a project
|
|
62
|
+
- **list_templates** — List available template presets
|
|
63
|
+
- **get_project_url** — Get the editor URL for a project
|
|
64
|
+
|
|
65
|
+
### Screen Management
|
|
66
|
+
- **add_screen** — Add a new screen to a project
|
|
67
|
+
- **update_screen** — Update screen background, name, dimensions
|
|
68
|
+
- **remove_screen** — Remove a screen
|
|
69
|
+
- **duplicate_screen** — Duplicate a screen with all layers
|
|
70
|
+
- **connect_screens** — Link screens into a panoramic strip
|
|
71
|
+
|
|
72
|
+
### Layer Management
|
|
73
|
+
- **add_text_layer** — Add styled text (auto-centered, smart defaults)
|
|
74
|
+
- **add_device_frame_layer** — Add iPhone/Android/iPad/MacBook mockup
|
|
75
|
+
- **add_image_layer** — Add an image from a URL
|
|
76
|
+
- **add_shape_layer** — Add rectangle, circle, or rounded rectangle
|
|
77
|
+
- **update_layer** — Update any layer property
|
|
78
|
+
- **remove_layer** — Remove a layer
|
|
79
|
+
- **duplicate_layer** — Duplicate a layer
|
|
80
|
+
- **reorder_layers** — Change layer z-order
|
|
81
|
+
- **upload_screenshot** — Upload a screenshot into a device frame
|
|
82
|
+
|
|
83
|
+
### Batch Operations
|
|
84
|
+
- **batch_add_layers** — Add multiple layers at once
|
|
85
|
+
- **batch_update_layers** — Update multiple layers at once
|
|
86
|
+
- **batch_remove_layers** — Remove multiple layers at once
|
|
87
|
+
|
|
88
|
+
### Video
|
|
89
|
+
- **update_video_config** — Set animation preset, duration, fps
|
|
90
|
+
- **list_video_presets** — List available animation presets
|
|
91
|
+
|
|
92
|
+
## Example Prompts
|
|
93
|
+
|
|
94
|
+
- "Create app store screenshots for my fitness app with 5 screens"
|
|
95
|
+
- "Add an iPhone mockup showing the home screen to the first screenshot"
|
|
96
|
+
- "Change the background color of screen 2 to a blue gradient"
|
|
97
|
+
- "Create a panoramic layout connecting screens 1, 2, and 3"
|
|
98
|
+
- "Upload this screenshot into the device frame on screen 1"
|
|
99
|
+
|
|
100
|
+
## Environment Variables
|
|
101
|
+
|
|
102
|
+
| Variable | Required | Description |
|
|
103
|
+
|----------|----------|-------------|
|
|
104
|
+
| `SHIPSHOTS_API_URL` | Yes | Shipshots instance URL (e.g., `https://shipshots.app`) |
|
|
105
|
+
| `SHIPSHOTS_API_TOKEN` | Yes | API token from Dashboard → Settings → MCP Tokens |
|
|
106
|
+
|
|
107
|
+
## License
|
|
108
|
+
|
|
109
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { CanvasProject } from "./types.js";
|
|
2
|
+
export declare class ApiClient {
|
|
3
|
+
private baseUrl;
|
|
4
|
+
private apiToken?;
|
|
5
|
+
constructor(baseUrl: string, apiToken?: string);
|
|
6
|
+
private get authHeaders();
|
|
7
|
+
createProject(name: string, data?: Partial<CanvasProject>, template?: string): Promise<{
|
|
8
|
+
id: string;
|
|
9
|
+
project: CanvasProject;
|
|
10
|
+
}>;
|
|
11
|
+
getProject(id: string): Promise<CanvasProject>;
|
|
12
|
+
updateProject(id: string, data: Partial<CanvasProject>): Promise<void>;
|
|
13
|
+
uploadImage(projectId: string, imageSource: string): Promise<{
|
|
14
|
+
url: string;
|
|
15
|
+
}>;
|
|
16
|
+
deleteProject(id: string): Promise<void>;
|
|
17
|
+
getProjectUrl(projectId: string): string;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=api-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAgBhD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,CAAS;gBAEd,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAS9C,OAAO,KAAK,WAAW,GAKtB;IAEK,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,EAC7B,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,aAAa,CAAA;KAAE,CAAC;IAU5C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAS9C,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,aAAa,CAAC,GAC3B,OAAO,CAAC,IAAI,CAAC;IASV,WAAW,CACf,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAyDrB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAGzC"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { extname } from "path";
|
|
3
|
+
/** Extract a clean error message from an API response. */
|
|
4
|
+
async function apiError(action, res) {
|
|
5
|
+
const text = await res.text();
|
|
6
|
+
// Try to extract the "error" field from JSON responses (e.g., 403 plan errors)
|
|
7
|
+
try {
|
|
8
|
+
const json = JSON.parse(text);
|
|
9
|
+
if (json.error)
|
|
10
|
+
return new Error(json.error);
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// Not JSON, use raw text
|
|
14
|
+
}
|
|
15
|
+
const truncated = text.length > 200 ? text.slice(0, 200) + "..." : text;
|
|
16
|
+
return new Error(`${action}: ${res.status} ${truncated}`);
|
|
17
|
+
}
|
|
18
|
+
export class ApiClient {
|
|
19
|
+
baseUrl;
|
|
20
|
+
apiToken;
|
|
21
|
+
constructor(baseUrl, apiToken) {
|
|
22
|
+
// Strip trailing slash
|
|
23
|
+
if (baseUrl.endsWith("/")) {
|
|
24
|
+
baseUrl = baseUrl.slice(0, -1);
|
|
25
|
+
}
|
|
26
|
+
this.baseUrl = baseUrl;
|
|
27
|
+
this.apiToken = apiToken;
|
|
28
|
+
}
|
|
29
|
+
get authHeaders() {
|
|
30
|
+
if (this.apiToken) {
|
|
31
|
+
return { Authorization: `Bearer ${this.apiToken}` };
|
|
32
|
+
}
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
async createProject(name, data, template) {
|
|
36
|
+
const res = await fetch(`${this.baseUrl}/api/projects`, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: { "Content-Type": "application/json", ...this.authHeaders },
|
|
39
|
+
body: JSON.stringify({ name, ...(data ? { data } : {}), ...(template ? { template } : {}) }),
|
|
40
|
+
});
|
|
41
|
+
if (!res.ok)
|
|
42
|
+
throw await apiError("Failed to create project", res);
|
|
43
|
+
return res.json();
|
|
44
|
+
}
|
|
45
|
+
async getProject(id) {
|
|
46
|
+
const res = await fetch(`${this.baseUrl}/api/projects/${id}`, {
|
|
47
|
+
headers: this.authHeaders,
|
|
48
|
+
});
|
|
49
|
+
if (!res.ok)
|
|
50
|
+
throw await apiError(`Failed to get project ${id}`, res);
|
|
51
|
+
const json = (await res.json());
|
|
52
|
+
return json.data;
|
|
53
|
+
}
|
|
54
|
+
async updateProject(id, data) {
|
|
55
|
+
const res = await fetch(`${this.baseUrl}/api/projects/${id}`, {
|
|
56
|
+
method: "PUT",
|
|
57
|
+
headers: { "Content-Type": "application/json", ...this.authHeaders },
|
|
58
|
+
body: JSON.stringify({ data }),
|
|
59
|
+
});
|
|
60
|
+
if (!res.ok)
|
|
61
|
+
throw await apiError(`Failed to update project ${id}`, res);
|
|
62
|
+
}
|
|
63
|
+
async uploadImage(projectId, imageSource) {
|
|
64
|
+
const mimeToExt = {
|
|
65
|
+
"image/png": "png",
|
|
66
|
+
"image/jpeg": "jpg",
|
|
67
|
+
"image/webp": "webp",
|
|
68
|
+
"image/gif": "gif",
|
|
69
|
+
};
|
|
70
|
+
const extToMime = {
|
|
71
|
+
png: "image/png",
|
|
72
|
+
jpg: "image/jpeg",
|
|
73
|
+
jpeg: "image/jpeg",
|
|
74
|
+
webp: "image/webp",
|
|
75
|
+
gif: "image/gif",
|
|
76
|
+
};
|
|
77
|
+
let blob;
|
|
78
|
+
let contentType;
|
|
79
|
+
let ext;
|
|
80
|
+
if (imageSource.startsWith("http://") || imageSource.startsWith("https://")) {
|
|
81
|
+
// Remote URL
|
|
82
|
+
const imageRes = await fetch(imageSource);
|
|
83
|
+
if (!imageRes.ok) {
|
|
84
|
+
throw new Error(`Failed to fetch image from ${imageSource}: ${imageRes.status}`);
|
|
85
|
+
}
|
|
86
|
+
blob = await imageRes.blob();
|
|
87
|
+
contentType = blob.type || "image/png";
|
|
88
|
+
ext = mimeToExt[contentType] || "png";
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
// Local file path
|
|
92
|
+
const allowedExtensions = ["png", "jpg", "jpeg", "webp", "gif"];
|
|
93
|
+
const fileExt = extname(imageSource).slice(1).toLowerCase();
|
|
94
|
+
if (!allowedExtensions.includes(fileExt)) {
|
|
95
|
+
throw new Error(`Unsupported file type: .${fileExt || "(none)"}. Allowed: ${allowedExtensions.join(", ")}`);
|
|
96
|
+
}
|
|
97
|
+
const buffer = readFileSync(imageSource);
|
|
98
|
+
contentType = extToMime[fileExt] || "image/png";
|
|
99
|
+
ext = fileExt || "png";
|
|
100
|
+
blob = new Blob([buffer], { type: contentType });
|
|
101
|
+
}
|
|
102
|
+
// Upload as FormData (matches API expectation)
|
|
103
|
+
const formData = new FormData();
|
|
104
|
+
formData.append("file", new File([blob], `screenshot.${ext}`, { type: contentType }));
|
|
105
|
+
const res = await fetch(`${this.baseUrl}/api/projects/${projectId}/images`, {
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: this.authHeaders,
|
|
108
|
+
body: formData,
|
|
109
|
+
});
|
|
110
|
+
if (!res.ok)
|
|
111
|
+
throw await apiError("Failed to upload image", res);
|
|
112
|
+
return res.json();
|
|
113
|
+
}
|
|
114
|
+
async deleteProject(id) {
|
|
115
|
+
const res = await fetch(`${this.baseUrl}/api/projects/${id}`, {
|
|
116
|
+
method: "DELETE",
|
|
117
|
+
headers: this.authHeaders,
|
|
118
|
+
});
|
|
119
|
+
if (!res.ok)
|
|
120
|
+
throw await apiError(`Failed to delete project ${id}`, res);
|
|
121
|
+
}
|
|
122
|
+
getProjectUrl(projectId) {
|
|
123
|
+
return `${this.baseUrl}/p/${projectId}`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=api-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA4FA,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAqD7C"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { homedir, platform } from "os";
|
|
4
|
+
import { createInterface } from "readline";
|
|
5
|
+
function parseArgs(argv) {
|
|
6
|
+
const args = {};
|
|
7
|
+
for (let i = 0; i < argv.length; i++) {
|
|
8
|
+
const arg = argv[i];
|
|
9
|
+
if (arg.startsWith("--") && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
|
|
10
|
+
args[arg.slice(2)] = argv[i + 1];
|
|
11
|
+
i++;
|
|
12
|
+
}
|
|
13
|
+
else if (arg.startsWith("--") && arg.includes("=")) {
|
|
14
|
+
const [key, val] = arg.slice(2).split("=", 2);
|
|
15
|
+
args[key] = val;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return args;
|
|
19
|
+
}
|
|
20
|
+
function prompt(question, choices) {
|
|
21
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
console.error(`\n${question}`);
|
|
24
|
+
choices.forEach((c, i) => console.error(` ${i + 1}) ${c}`));
|
|
25
|
+
rl.question("\nChoice (number): ", (answer) => {
|
|
26
|
+
rl.close();
|
|
27
|
+
const idx = parseInt(answer, 10) - 1;
|
|
28
|
+
resolve(choices[idx] ?? choices[0]);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function getConfigPath(client) {
|
|
33
|
+
switch (client) {
|
|
34
|
+
case "claude-code":
|
|
35
|
+
return join(process.cwd(), ".mcp.json");
|
|
36
|
+
case "cursor":
|
|
37
|
+
return join(process.cwd(), ".cursor", "mcp.json");
|
|
38
|
+
case "claude-desktop": {
|
|
39
|
+
const p = platform();
|
|
40
|
+
if (p === "darwin") {
|
|
41
|
+
return join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
|
|
42
|
+
}
|
|
43
|
+
if (p === "win32") {
|
|
44
|
+
return join(process.env.APPDATA || join(homedir(), "AppData", "Roaming"), "Claude", "claude_desktop_config.json");
|
|
45
|
+
}
|
|
46
|
+
// Linux
|
|
47
|
+
return join(homedir(), ".config", "Claude", "claude_desktop_config.json");
|
|
48
|
+
}
|
|
49
|
+
case "stdout":
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function buildConfig(token, url) {
|
|
54
|
+
return {
|
|
55
|
+
command: "npx",
|
|
56
|
+
args: ["-y", "shipshots-mcp"],
|
|
57
|
+
env: {
|
|
58
|
+
SHIPSHOTS_API_URL: url,
|
|
59
|
+
SHIPSHOTS_API_TOKEN: token,
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
function mergeConfig(existingContent, serverConfig) {
|
|
64
|
+
let existing;
|
|
65
|
+
try {
|
|
66
|
+
existing = JSON.parse(existingContent);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
existing = {};
|
|
70
|
+
}
|
|
71
|
+
const mcpServers = (existing.mcpServers ?? {});
|
|
72
|
+
mcpServers["shipshots"] = serverConfig;
|
|
73
|
+
existing.mcpServers = mcpServers;
|
|
74
|
+
return JSON.stringify(existing, null, 2);
|
|
75
|
+
}
|
|
76
|
+
const CLIENT_LABELS = {
|
|
77
|
+
"claude-code": "Claude Code (.mcp.json)",
|
|
78
|
+
"claude-desktop": "Claude Desktop",
|
|
79
|
+
"cursor": "Cursor (.cursor/mcp.json)",
|
|
80
|
+
"stdout": "Print to terminal (copy manually)",
|
|
81
|
+
};
|
|
82
|
+
const CLIENT_IDS = ["claude-code", "claude-desktop", "cursor", "stdout"];
|
|
83
|
+
export async function runInit() {
|
|
84
|
+
const args = parseArgs(process.argv.slice(3));
|
|
85
|
+
const token = args.token;
|
|
86
|
+
if (!token) {
|
|
87
|
+
console.error("Error: --token is required.\n");
|
|
88
|
+
console.error("Usage: shipshots-mcp init --token sb_your_token_here [--client claude-code|claude-desktop|cursor|stdout] [--url https://shipshots.app]");
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
if (!token.startsWith("sb_")) {
|
|
92
|
+
console.error("Error: token must start with 'sb_'. Check your token from the dashboard.\n");
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const url = args.url ?? "https://shipshots.app";
|
|
96
|
+
let client = args.client;
|
|
97
|
+
if (!client || !CLIENT_IDS.includes(client)) {
|
|
98
|
+
const choice = await prompt("Which MCP client do you want to configure?", CLIENT_IDS.map((id) => CLIENT_LABELS[id]));
|
|
99
|
+
client = CLIENT_IDS[CLIENT_IDS.findIndex((id) => CLIENT_LABELS[id] === choice)] ?? "claude-code";
|
|
100
|
+
}
|
|
101
|
+
const serverConfig = buildConfig(token, url);
|
|
102
|
+
if (client === "stdout") {
|
|
103
|
+
const fullConfig = { mcpServers: { shipshots: serverConfig } };
|
|
104
|
+
console.log(JSON.stringify(fullConfig, null, 2));
|
|
105
|
+
console.error("\nCopy this config into your MCP client's configuration file.");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const configPath = getConfigPath(client);
|
|
109
|
+
const dir = join(configPath, "..");
|
|
110
|
+
if (!existsSync(dir)) {
|
|
111
|
+
mkdirSync(dir, { recursive: true });
|
|
112
|
+
}
|
|
113
|
+
let content;
|
|
114
|
+
if (existsSync(configPath)) {
|
|
115
|
+
const existing = readFileSync(configPath, "utf-8");
|
|
116
|
+
content = mergeConfig(existing, serverConfig);
|
|
117
|
+
console.error(`Updated existing config: ${configPath}`);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
content = JSON.stringify({ mcpServers: { shipshots: serverConfig } }, null, 2);
|
|
121
|
+
console.error(`Created new config: ${configPath}`);
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(configPath, content + "\n");
|
|
124
|
+
console.error("\nShipshots MCP server configured successfully!");
|
|
125
|
+
console.error("Restart your MCP client to start using it.");
|
|
126
|
+
console.error('\nTry: "Create app store screenshots for my fitness app"');
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { DeviceType, Layer, TextLayer, DeviceFrameLayer, ImageLayer, ShapeLayer, BadgeLayer, ArrowLayer, LayerType } from "./types.js";
|
|
2
|
+
export declare const CANVAS_WIDTH = 1260;
|
|
3
|
+
export declare const CANVAS_HEIGHT = 2736;
|
|
4
|
+
export declare function deviceAspectRatio(type: DeviceType): number;
|
|
5
|
+
export declare function deviceSize(type: DeviceType, width: number): {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
};
|
|
9
|
+
/** Default position for a text layer — centered horizontally near the top. */
|
|
10
|
+
export declare function defaultTextPosition(): {
|
|
11
|
+
x: number;
|
|
12
|
+
y: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
/** Default position for a device frame — centered below text, fully visible. */
|
|
17
|
+
export declare function defaultDevicePosition(deviceType: DeviceType): {
|
|
18
|
+
x: number;
|
|
19
|
+
y: number;
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
23
|
+
/** Default position for an image layer — centered. */
|
|
24
|
+
export declare function defaultImagePosition(): {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
width: number;
|
|
28
|
+
height: number;
|
|
29
|
+
};
|
|
30
|
+
/** Default position for a shape layer — centered. */
|
|
31
|
+
export declare function defaultShapePosition(): {
|
|
32
|
+
x: number;
|
|
33
|
+
y: number;
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
};
|
|
37
|
+
export declare function defaultTextStyle(): Partial<TextLayer>;
|
|
38
|
+
/**
|
|
39
|
+
* Compute a position for a new layer that avoids overlapping existing layers.
|
|
40
|
+
* Offsets by 40px diagonally for each potential overlap.
|
|
41
|
+
*/
|
|
42
|
+
export declare function autoPosition(existingLayers: Layer[], newLayerType: LayerType): {
|
|
43
|
+
x: number;
|
|
44
|
+
y: number;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Returns white or black text color depending on the perceived brightness
|
|
48
|
+
* of the given hex background color.
|
|
49
|
+
*/
|
|
50
|
+
export declare function contrastColor(backgroundColor: string): string;
|
|
51
|
+
export declare function generateId(): string;
|
|
52
|
+
export declare function createTextLayer(overrides?: Partial<TextLayer>): TextLayer;
|
|
53
|
+
export declare function createDeviceLayer(overrides?: Partial<DeviceFrameLayer>): DeviceFrameLayer;
|
|
54
|
+
export declare function createImageLayer(overrides?: Partial<ImageLayer>): ImageLayer;
|
|
55
|
+
export declare function createShapeLayer(overrides?: Partial<ShapeLayer>): ShapeLayer;
|
|
56
|
+
/** Default position for a badge layer — centered horizontally near the top. */
|
|
57
|
+
export declare function defaultBadgePosition(): {
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
width: number;
|
|
61
|
+
height: number;
|
|
62
|
+
};
|
|
63
|
+
/** Default from/to for an arrow layer. */
|
|
64
|
+
export declare function defaultArrowEndpoints(): {
|
|
65
|
+
fromX: number;
|
|
66
|
+
fromY: number;
|
|
67
|
+
toX: number;
|
|
68
|
+
toY: number;
|
|
69
|
+
};
|
|
70
|
+
/** Compute bounding box from arrow endpoints. */
|
|
71
|
+
export declare function arrowBoundingBox(fromX: number, fromY: number, toX: number, toY: number, padding?: number): {
|
|
72
|
+
x: number;
|
|
73
|
+
y: number;
|
|
74
|
+
width: number;
|
|
75
|
+
height: number;
|
|
76
|
+
};
|
|
77
|
+
/** Default position for an arrow layer — derived from default endpoints. */
|
|
78
|
+
export declare function defaultArrowPosition(): {
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
width: number;
|
|
82
|
+
height: number;
|
|
83
|
+
};
|
|
84
|
+
export declare function createBadgeLayer(overrides?: Partial<BadgeLayer>): BadgeLayer;
|
|
85
|
+
export declare function createArrowLayer(overrides?: Partial<ArrowLayer>): ArrowLayer;
|
|
86
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"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"}
|