@diffui.mcp/install 0.2.0 → 0.2.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 +10 -3
- package/launcher.mjs +8 -0
- package/package.json +1 -1
- package/skill/SKILL.md +37 -42
package/README.md
CHANGED
|
@@ -9,11 +9,18 @@ Thin Node launcher for the diffui MCP server. Cursor (and other MCP hosts) run:
|
|
|
9
9
|
"args": ["-y", "@diffui.mcp/install@latest"],
|
|
10
10
|
"env": {
|
|
11
11
|
"DIFFUI_API_BASE": "https://diffui.ai",
|
|
12
|
-
"DIFFUI_API_KEY": "dui_..."
|
|
12
|
+
"DIFFUI_API_KEY": "dui_...",
|
|
13
|
+
"npm_config_prefix": "",
|
|
14
|
+
"NPM_CONFIG_PREFIX": "",
|
|
15
|
+
"PATH": "/opt/homebrew/bin:/opt/homebrew/opt/node@22/bin:/opt/homebrew/opt/node@20/bin:/usr/local/bin:/usr/bin:/bin"
|
|
13
16
|
}
|
|
14
17
|
}
|
|
15
18
|
```
|
|
16
19
|
|
|
20
|
+
Cursor injects `npm_config_prefix` inside its app bundle (`…/Cursor.app/…/resources/lib`).
|
|
21
|
+
That path does not exist, so `npx` fails with `ENOENT` unless those vars are cleared.
|
|
22
|
+
The diffui install deeplink sets empty prefix values and prepends common system paths to `PATH`.
|
|
23
|
+
|
|
17
24
|
On first start, the launcher:
|
|
18
25
|
|
|
19
26
|
1. Copies the bundled design-first skill to `~/.cursor/skills/diffui/SKILL.md` (updates when
|
|
@@ -69,5 +76,5 @@ npm link
|
|
|
69
76
|
|
|
70
77
|
## Cursor deeplink
|
|
71
78
|
|
|
72
|
-
The diffui app builds install links with `command: npx
|
|
73
|
-
`args: ["-y", "@diffui.mcp/install@latest"]
|
|
79
|
+
The diffui app builds install links with `command: npx`,
|
|
80
|
+
`args: ["-y", "@diffui.mcp/install@latest"]`, npm prefix overrides, and env for API base and key.
|
package/launcher.mjs
CHANGED
|
@@ -27,6 +27,14 @@ import { pipeline } from "node:stream/promises";
|
|
|
27
27
|
import { get as httpsGet } from "node:https";
|
|
28
28
|
import { get as httpGet } from "node:http";
|
|
29
29
|
|
|
30
|
+
// Cursor MCP may inherit npm prefix inside the app bundle; drop it before any child spawns.
|
|
31
|
+
for (const key of ["npm_config_prefix", "NPM_CONFIG_PREFIX"]) {
|
|
32
|
+
const value = process.env[key];
|
|
33
|
+
if (value && /Cursor\.app/i.test(value)) {
|
|
34
|
+
delete process.env[key];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
30
38
|
const launcherDir = dirname(fileURLToPath(import.meta.url));
|
|
31
39
|
const base = String(process.env.DIFFUI_API_BASE || "https://diffui.ai").replace(/\/+$/, "");
|
|
32
40
|
const dest = join(homedir(), ".diffui", "bin", "diffui-mcp");
|
package/package.json
CHANGED
package/skill/SKILL.md
CHANGED
|
@@ -15,8 +15,7 @@ description: >-
|
|
|
15
15
|
# Diffui designer
|
|
16
16
|
|
|
17
17
|
You orchestrate diffui (an AI design-generation canvas) through its **MCP tools**.
|
|
18
|
-
The user sees
|
|
19
|
-
in their browser. Follow this choreography.
|
|
18
|
+
The user sees all option images inline in the tool result. Follow this choreography.
|
|
20
19
|
|
|
21
20
|
## When this skill applies (required)
|
|
22
21
|
|
|
@@ -32,7 +31,7 @@ Treat these as the same class of request:
|
|
|
32
31
|
|
|
33
32
|
**Two phases — never merge them:**
|
|
34
33
|
|
|
35
|
-
1. **Design (diffui MCP)** — `create_project` →
|
|
34
|
+
1. **Design (diffui MCP)** — `create_project` →
|
|
36
35
|
`generate_options` → pick/iterate → (optional `generate_page` for multi-page) →
|
|
37
36
|
`create_build_link`.
|
|
38
37
|
2. **Implementation (code)** — write HTML/CSS/JS only **after** phase 1, following
|
|
@@ -50,7 +49,9 @@ calls for a one-page request.
|
|
|
50
49
|
|
|
51
50
|
**After `generate_options`:**
|
|
52
51
|
|
|
53
|
-
- Present options as Option A–D with
|
|
52
|
+
- Present options as **Option A–D** with short visual descriptions only
|
|
53
|
+
- Do NOT include imageIds, UUIDs, or other internal metadata in user-facing text
|
|
54
|
+
- Keep the imageId ledger from the assistant-only tool result block in your reasoning
|
|
54
55
|
- User present → ask which to build
|
|
55
56
|
- User said "surprise me" / full trust → pick the strongest fit and say why
|
|
56
57
|
- User unavailable mid-run → wait; do not proceed to code without a pick
|
|
@@ -59,8 +60,10 @@ calls for a one-page request.
|
|
|
59
60
|
install usually includes credentials. If any tool returns not-authenticated, call
|
|
60
61
|
`authenticate` once, then retry. Do not silently fall back to hand-designed UI.
|
|
61
62
|
|
|
62
|
-
**Prompt writing:** Turn the user's request into a visual design prompt
|
|
63
|
-
sections, layout, color/mood).
|
|
63
|
+
**Prompt writing:** Turn the user's request into a visual design prompt for
|
|
64
|
+
`generate_options` (audience, tone, sections, layout, color/mood). For
|
|
65
|
+
`generate_page`, use the shortest prompt that fits — page name plus any
|
|
66
|
+
user-requested specifics only.
|
|
64
67
|
|
|
65
68
|
**Do not:**
|
|
66
69
|
|
|
@@ -84,9 +87,9 @@ one sentence.
|
|
|
84
87
|
|
|
85
88
|
## 0. Setup
|
|
86
89
|
|
|
87
|
-
1. For a new design session, call `create_project
|
|
88
|
-
|
|
89
|
-
|
|
90
|
+
1. For a new design session, call `create_project`. Reuse the same `project_id` for the
|
|
91
|
+
whole session. Do **not** call `open_canvas` by default — inline tool images are enough
|
|
92
|
+
inside Cursor/Claude/Codex. Only open the browser canvas if the user asks to watch there.
|
|
90
93
|
2. **Auth only on error.** Do not proactively call `whoami`. If a tool fails with
|
|
91
94
|
not-authenticated, call `authenticate` — a browser window opens for one-click
|
|
92
95
|
connect, or pass an API key from diffui → Settings → API as `api_key`. Then
|
|
@@ -98,10 +101,9 @@ When the user describes a design they want:
|
|
|
98
101
|
|
|
99
102
|
- Call `generate_options` with `count: 4` and **no** `brand_id` (a fresh
|
|
100
103
|
canvas auto-diversifies styles across the options, which is what you want).
|
|
101
|
-
-
|
|
102
|
-
`option → imageId`
|
|
103
|
-
|
|
104
|
-
reasoning.
|
|
104
|
+
- The tool returns all four images inline plus an assistant-only ledger JSON.
|
|
105
|
+
Keep the `option → imageId` mapping in your reasoning — never paste ids into
|
|
106
|
+
user-facing messages.
|
|
105
107
|
- Offer three paths: pick one, see more options (`generate_options` again,
|
|
106
108
|
passing the same `prompt_node_id` to append), or mix elements of options
|
|
107
109
|
(see "Generating with inputs").
|
|
@@ -109,27 +111,21 @@ When the user describes a design they want:
|
|
|
109
111
|
## 2. Generating with inputs
|
|
110
112
|
|
|
111
113
|
`generate_with_inputs` handles any request where existing images should
|
|
112
|
-
shape the result.
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
matching @screenshot's visual style."
|
|
128
|
-
|
|
129
|
-
Keep spatial phrases tied to their labels ("the header from @option-4",
|
|
130
|
-
"@logo in the top right") — diffui resolves positions per named reference.
|
|
131
|
-
Present the results as new numbered options and update your ledger. Use
|
|
132
|
-
`upload_reference` first when a file will be reused across several
|
|
114
|
+
shape the result. Canvas-generated options (`image_id`) are wired from the
|
|
115
|
+
original prompt stack — never re-uploaded. Only `file_path` / `asset_id`
|
|
116
|
+
add new nodes.
|
|
117
|
+
|
|
118
|
+
Use `@label` in the prompt **only when combining specific parts** across
|
|
119
|
+
inputs. Otherwise keep the prompt short and omit `@` mentions — diffui
|
|
120
|
+
preserves style from the wired reference automatically.
|
|
121
|
+
|
|
122
|
+
Examples:
|
|
123
|
+
|
|
124
|
+
- **Combine options** — `inputs: [{image_id: <opt1>, label: "option-1"}, {image_id: <opt2>, label: "option-2"}]`, prompt "Use the header from @option-1 and the footer from @option-2."
|
|
125
|
+
- **Local file** — `inputs: [{file_path: "/path/to/logo.png", label: "logo"}]`, prompt "Landing page with @logo in the top right of the header."
|
|
126
|
+
- **Uploaded asset** — `inputs: [{asset_id: <id>, label: "screenshot"}]`, prompt "Settings page matching @screenshot's visual style."
|
|
127
|
+
|
|
128
|
+
Use `upload_reference` first when a file will be reused across several
|
|
133
129
|
generations; pass `file_path` directly for one-offs.
|
|
134
130
|
|
|
135
131
|
## 3. Chosen option → build out the rest of the site
|
|
@@ -143,11 +139,10 @@ option's imageId (from your ledger) is the only handle you need. Immediately:
|
|
|
143
139
|
build. Add any obvious page the design implies but the nav omits (a cart /
|
|
144
140
|
checkout behind a cart icon, a sign-up behind a "Get started" button). List
|
|
145
141
|
the pages you inferred and confirm or adjust with the user before generating.
|
|
146
|
-
2. **Generate
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
page's own content and layout).
|
|
142
|
+
2. **Generate all pages in one parallel call.** Call `generate_pages` with `input_image_id` set to the
|
|
143
|
+
**chosen option's imageId** and a `pages` array — one entry per screen with a short prompt
|
|
144
|
+
(e.g. `{name: "Features", prompt: "Create the features page"}`). Do **not** call `generate_page`
|
|
145
|
+
repeatedly in a loop; that runs sequentially and is much slower.
|
|
151
146
|
3. **Track page name → imageId** in your ledger as each page returns. No lock
|
|
152
147
|
step is involved; the imageId is the durable handle for brands and the build.
|
|
153
148
|
|
|
@@ -213,9 +208,9 @@ When the design flow feels complete (pages generated, user satisfied), ask:
|
|
|
213
208
|
|
|
214
209
|
- **Design before code.** If you have not called `generate_options` this session,
|
|
215
210
|
you are not allowed to create webpage files yet.
|
|
216
|
-
-
|
|
217
|
-
- Keep a running ledger of option
|
|
218
|
-
|
|
211
|
+
- All option images are returned inline by the tool — rely on those, not the browser canvas.
|
|
212
|
+
- Keep a running ledger of option letters → imageIds → page names in your reasoning only;
|
|
213
|
+
never restate UUIDs to the user.
|
|
219
214
|
- Generations block for the whole render (up to a few minutes) and stream
|
|
220
215
|
progress updates. A quiet call is working, not stuck — **never re-issue a
|
|
221
216
|
generation to "retry" a slow one.** A duplicate run desyncs the canvas and
|