webcake-landing-mcp 1.0.1 → 1.0.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 +26 -0
- package/dist/index.js +14 -0
- package/dist/install.js +395 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,32 @@ Or run the latest from GitHub (npx clones + builds via the `prepare` script on t
|
|
|
92
92
|
npx -y github:vuluu2k/webcake-landing-mcp
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
### Auto-configure your IDE (`install` subcommand)
|
|
96
|
+
|
|
97
|
+
`npx` only **runs** the server — unlike `install.sh`/`install.ps1`, it does not write the MCP
|
|
98
|
+
config into your IDE. The bundled `install` subcommand does that step for you, no clone needed:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Interactive — asks for env + which IDE(s) step by step
|
|
102
|
+
npx -y webcake-landing-mcp install
|
|
103
|
+
|
|
104
|
+
# Non-interactive — configure every supported IDE at once
|
|
105
|
+
npx -y webcake-landing-mcp install --ide all --jwt <your-jwt> --api-base http://localhost:5800
|
|
106
|
+
|
|
107
|
+
# Just one IDE
|
|
108
|
+
npx -y webcake-landing-mcp install --ide cursor --jwt <your-jwt>
|
|
109
|
+
|
|
110
|
+
# Remove the server from every IDE config
|
|
111
|
+
npx -y webcake-landing-mcp uninstall
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
It writes a `webcake-landing` entry (using the `npx` launch form below) into the right config file
|
|
115
|
+
for each target: `claude-desktop`, `claude-code`, `cursor`, `windsurf`, `augment` (VS Code), `codex`,
|
|
116
|
+
or `all`. Flags: `--ide`, `--api-base`, `--jwt`, `--org-id`, `--host`, `--app-base`, `--npx`/`--local`,
|
|
117
|
+
`-y`. Run `npx -y webcake-landing-mcp --help` for the full list.
|
|
118
|
+
|
|
119
|
+
### Manual config
|
|
120
|
+
|
|
95
121
|
The MCP config is the same as the local one, but `command`/`args` point at `npx` instead of a built file:
|
|
96
122
|
|
|
97
123
|
```json
|
package/dist/index.js
CHANGED
|
@@ -233,6 +233,20 @@ server.tool("update_page", "Overwrite an EXISTING page's source with an edited t
|
|
|
233
233
|
return text({ updated: outcome.ok, ...outcome, warnings: result.warnings });
|
|
234
234
|
});
|
|
235
235
|
async function main() {
|
|
236
|
+
// Subcommand dispatch: `webcake-landing-mcp install|uninstall` runs the
|
|
237
|
+
// bundled IDE installer instead of starting the MCP server. Default (no
|
|
238
|
+
// subcommand) starts the stdio server as usual.
|
|
239
|
+
const sub = process.argv[2];
|
|
240
|
+
if (sub === "install" || sub === "uninstall" || sub === "--help" || sub === "-h") {
|
|
241
|
+
const { runInstaller } = await import("./install.js");
|
|
242
|
+
const rest = sub === "uninstall"
|
|
243
|
+
? ["--uninstall", ...process.argv.slice(3)]
|
|
244
|
+
: sub === "--help" || sub === "-h"
|
|
245
|
+
? ["--help"]
|
|
246
|
+
: process.argv.slice(3);
|
|
247
|
+
await runInstaller(rest);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
236
250
|
const transport = new StdioServerTransport();
|
|
237
251
|
await server.connect(transport);
|
|
238
252
|
// stderr only — stdout is the MCP channel.
|
package/dist/install.js
ADDED
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Self-installer for webcake-landing-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Runs when the server is invoked as `webcake-landing-mcp install` (e.g. via
|
|
5
|
+
* `npx -y webcake-landing-mcp install`). It collects env config and writes the
|
|
6
|
+
* MCP server block into each selected IDE/agent config file — the same job the
|
|
7
|
+
* standalone install.sh / install.ps1 do, but bundled so npx users don't need
|
|
8
|
+
* to clone anything.
|
|
9
|
+
*
|
|
10
|
+
* Two modes:
|
|
11
|
+
* - Interactive (a TTY and no --ide flag): asks step by step.
|
|
12
|
+
* - Flag-driven (--ide present, or no TTY): non-interactive.
|
|
13
|
+
*
|
|
14
|
+
* The launch command written into configs is `npx -y webcake-landing-mcp` when
|
|
15
|
+
* this installer itself was run via npx (path-independent), or
|
|
16
|
+
* `node <abs path>/dist/index.js` when run from a local clone. Override with
|
|
17
|
+
* --npx / --local.
|
|
18
|
+
*/
|
|
19
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { homedir, platform } from "node:os";
|
|
21
|
+
import { dirname, join } from "node:path";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { spawnSync } from "node:child_process";
|
|
24
|
+
import { createInterface } from "node:readline";
|
|
25
|
+
const NAME = "webcake-landing";
|
|
26
|
+
const PKG = "webcake-landing-mcp";
|
|
27
|
+
const HOME = homedir();
|
|
28
|
+
const PLAT = platform(); // 'darwin' | 'linux' | 'win32'
|
|
29
|
+
const APPDATA = process.env.APPDATA || join(HOME, "AppData", "Roaming");
|
|
30
|
+
const c = {
|
|
31
|
+
reset: "\x1b[0m",
|
|
32
|
+
bold: "\x1b[1m",
|
|
33
|
+
red: "\x1b[31m",
|
|
34
|
+
green: "\x1b[32m",
|
|
35
|
+
yellow: "\x1b[33m",
|
|
36
|
+
cyan: "\x1b[36m",
|
|
37
|
+
gray: "\x1b[90m",
|
|
38
|
+
};
|
|
39
|
+
const log = (m = "", color = "") => console.log(`${color}${m}${c.reset}`);
|
|
40
|
+
const info = (m) => log(` ${c.cyan}›${c.reset} ${m}`);
|
|
41
|
+
const ok = (m) => log(` ${c.green}✓${c.reset} ${m}`);
|
|
42
|
+
const warn = (m) => log(` ${c.yellow}!${c.reset} ${m}`);
|
|
43
|
+
// ── arg parsing ──────────────────────────────────────────────────────────────
|
|
44
|
+
function parseArgs(argv) {
|
|
45
|
+
const o = { yes: false, uninstall: false };
|
|
46
|
+
const val = (a, i) => a.includes("=") ? a.slice(a.indexOf("=") + 1) : argv[++i];
|
|
47
|
+
for (let i = 0; i < argv.length; i++) {
|
|
48
|
+
const a = argv[i];
|
|
49
|
+
const next = () => (a.includes("=") ? a.slice(a.indexOf("=") + 1) : argv[++i]);
|
|
50
|
+
if (a === "--uninstall" || a === "uninstall")
|
|
51
|
+
o.uninstall = true;
|
|
52
|
+
else if (a === "-y" || a === "--yes")
|
|
53
|
+
o.yes = true;
|
|
54
|
+
else if (a === "--npx")
|
|
55
|
+
o.npx = true;
|
|
56
|
+
else if (a === "--local")
|
|
57
|
+
o.local = true;
|
|
58
|
+
else if (a.startsWith("--ide"))
|
|
59
|
+
o.ide = next();
|
|
60
|
+
else if (a.startsWith("--api-base"))
|
|
61
|
+
o.apiBase = next();
|
|
62
|
+
else if (a.startsWith("--jwt") || a.startsWith("--token"))
|
|
63
|
+
o.jwt = next();
|
|
64
|
+
else if (a.startsWith("--org-id") || a.startsWith("--org"))
|
|
65
|
+
o.orgId = next();
|
|
66
|
+
else if (a.startsWith("--host"))
|
|
67
|
+
o.host = next();
|
|
68
|
+
else if (a.startsWith("--app-base"))
|
|
69
|
+
o.appBase = next();
|
|
70
|
+
else if (a === "--help" || a === "-h")
|
|
71
|
+
o.ide = "__help__";
|
|
72
|
+
void val;
|
|
73
|
+
}
|
|
74
|
+
return o;
|
|
75
|
+
}
|
|
76
|
+
// ── readline prompt ──────────────────────────────────────────────────────────
|
|
77
|
+
function ask(question) {
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
80
|
+
rl.question(question, (answer) => {
|
|
81
|
+
rl.close();
|
|
82
|
+
resolve(answer.trim());
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// ── launch command (npx vs local node) ───────────────────────────────────────
|
|
87
|
+
function resolveLaunch(o) {
|
|
88
|
+
const self = fileURLToPath(import.meta.url); // .../dist/install.js
|
|
89
|
+
const ranViaNpx = self.includes(`${"/"}_npx${"/"}`) || self.includes("\\_npx\\");
|
|
90
|
+
const useLocal = o.local ?? (!o.npx && !ranViaNpx);
|
|
91
|
+
if (useLocal) {
|
|
92
|
+
const indexPath = join(dirname(self), "index.js");
|
|
93
|
+
return { command: process.execPath, args: [indexPath] };
|
|
94
|
+
}
|
|
95
|
+
return { command: "npx", args: ["-y", PKG] };
|
|
96
|
+
}
|
|
97
|
+
// ── JSON config (Claude Desktop, Claude Code, Cursor, Windsurf, VS Code) ──────
|
|
98
|
+
function mergeJson(file, launch, env) {
|
|
99
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
100
|
+
let cfg = {};
|
|
101
|
+
if (existsSync(file)) {
|
|
102
|
+
const raw = readFileSync(file, "utf8").trim();
|
|
103
|
+
if (raw) {
|
|
104
|
+
try {
|
|
105
|
+
cfg = JSON.parse(raw);
|
|
106
|
+
}
|
|
107
|
+
catch (e) {
|
|
108
|
+
warn(`Skip ${file} (invalid JSON: ${e.message})`);
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (typeof cfg.mcpServers !== "object" || !cfg.mcpServers)
|
|
114
|
+
cfg.mcpServers = {};
|
|
115
|
+
cfg.mcpServers[NAME] = {
|
|
116
|
+
command: launch.command,
|
|
117
|
+
args: launch.args,
|
|
118
|
+
...(Object.keys(env).length ? { env } : {}),
|
|
119
|
+
};
|
|
120
|
+
writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n");
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
// ── TOML config (Codex) ──────────────────────────────────────────────────────
|
|
124
|
+
function configureCodex(launch, env) {
|
|
125
|
+
const dir = join(HOME, ".codex");
|
|
126
|
+
const cfg = join(dir, "config.toml");
|
|
127
|
+
mkdirSync(dir, { recursive: true });
|
|
128
|
+
const argsToml = launch.args.map((a) => `"${a}"`).join(", ");
|
|
129
|
+
const envParts = Object.entries(env)
|
|
130
|
+
.map(([k, v]) => `"${k}" = "${v}"`)
|
|
131
|
+
.join(", ");
|
|
132
|
+
const envLine = envParts ? `env = { ${envParts} }\n` : "";
|
|
133
|
+
const block = `\n[mcp_servers.${NAME}]\ncommand = "${launch.command}"\nargs = [${argsToml}]\n${envLine}`;
|
|
134
|
+
let content = existsSync(cfg) ? readFileSync(cfg, "utf8") : "# Webcake Landing MCP\n";
|
|
135
|
+
content = content.replace(new RegExp(`\\n?\\[mcp_servers\\.${NAME}\\][\\s\\S]*?(?=\\n\\[|$)`), "");
|
|
136
|
+
content = content.trimEnd() + "\n" + block;
|
|
137
|
+
writeFileSync(cfg, content);
|
|
138
|
+
}
|
|
139
|
+
// ── IDE config-file locations ────────────────────────────────────────────────
|
|
140
|
+
function claudeDesktopPath() {
|
|
141
|
+
if (PLAT === "win32")
|
|
142
|
+
return join(APPDATA, "Claude", "claude_desktop_config.json");
|
|
143
|
+
const mac = join(HOME, "Library", "Application Support", "Claude");
|
|
144
|
+
const dir = existsSync(mac) ? mac : join(HOME, ".config", "Claude");
|
|
145
|
+
return join(dir, "claude_desktop_config.json");
|
|
146
|
+
}
|
|
147
|
+
function vscodeUserPath() {
|
|
148
|
+
if (PLAT === "win32")
|
|
149
|
+
return join(APPDATA, "Code", "User", "mcp.json");
|
|
150
|
+
const mac = join(HOME, "Library", "Application Support", "Code", "User");
|
|
151
|
+
if (existsSync(mac))
|
|
152
|
+
return join(mac, "mcp.json");
|
|
153
|
+
const lin = join(HOME, ".config", "Code", "User");
|
|
154
|
+
if (existsSync(lin))
|
|
155
|
+
return join(lin, "mcp.json");
|
|
156
|
+
return join(HOME, ".vscode", "mcp.json");
|
|
157
|
+
}
|
|
158
|
+
const cursorPath = () => join(HOME, ".cursor", "mcp.json");
|
|
159
|
+
const windsurfPath = () => join(HOME, ".codeium", "windsurf", "mcp_config.json");
|
|
160
|
+
const claudeJsonPath = () => join(HOME, ".claude.json");
|
|
161
|
+
function hasClaudeCli() {
|
|
162
|
+
const probe = spawnSync(PLAT === "win32" ? "where" : "which", ["claude"], {
|
|
163
|
+
stdio: "ignore",
|
|
164
|
+
});
|
|
165
|
+
return probe.status === 0;
|
|
166
|
+
}
|
|
167
|
+
// ── per-IDE configure ────────────────────────────────────────────────────────
|
|
168
|
+
function configureClaudeCode(launch, env) {
|
|
169
|
+
info("Claude Code…");
|
|
170
|
+
if (hasClaudeCli()) {
|
|
171
|
+
spawnSync("claude", ["mcp", "remove", NAME], { stdio: "ignore" });
|
|
172
|
+
const envFlags = Object.entries(env).flatMap(([k, v]) => ["-e", `${k}=${v}`]);
|
|
173
|
+
const r = spawnSync("claude", ["mcp", "add", NAME, ...envFlags, "--", launch.command, ...launch.args], { stdio: "inherit" });
|
|
174
|
+
if (r.status === 0) {
|
|
175
|
+
ok("Claude Code configured via CLI — verify: claude mcp list");
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
warn("claude CLI failed — falling back to ~/.claude.json");
|
|
179
|
+
}
|
|
180
|
+
if (mergeJson(claudeJsonPath(), launch, env))
|
|
181
|
+
ok(`Claude Code configured (${claudeJsonPath()})`);
|
|
182
|
+
}
|
|
183
|
+
function configureClaudeDesktop(launch, env) {
|
|
184
|
+
info("Claude Desktop…");
|
|
185
|
+
if (mergeJson(claudeDesktopPath(), launch, env)) {
|
|
186
|
+
ok(`Claude Desktop configured (${claudeDesktopPath()})`);
|
|
187
|
+
warn("Restart Claude Desktop to load the server.");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function configureCursor(launch, env) {
|
|
191
|
+
info("Cursor…");
|
|
192
|
+
if (mergeJson(cursorPath(), launch, env))
|
|
193
|
+
ok(`Cursor configured (${cursorPath()})`);
|
|
194
|
+
}
|
|
195
|
+
function configureWindsurf(launch, env) {
|
|
196
|
+
info("Windsurf…");
|
|
197
|
+
if (mergeJson(windsurfPath(), launch, env))
|
|
198
|
+
ok(`Windsurf configured (${windsurfPath()})`);
|
|
199
|
+
}
|
|
200
|
+
function configureAugment(launch, env) {
|
|
201
|
+
info("Augment / VS Code…");
|
|
202
|
+
if (mergeJson(vscodeUserPath(), launch, env))
|
|
203
|
+
ok(`VS Code configured (${vscodeUserPath()})`);
|
|
204
|
+
}
|
|
205
|
+
function configureCodexIde(launch, env) {
|
|
206
|
+
info("Codex…");
|
|
207
|
+
configureCodex(launch, env);
|
|
208
|
+
ok(`Codex configured (${join(HOME, ".codex", "config.toml")}) — restart Codex.`);
|
|
209
|
+
}
|
|
210
|
+
const IDE_ALIASES = {
|
|
211
|
+
"claude-desktop": "claude-desktop",
|
|
212
|
+
desktop: "claude-desktop",
|
|
213
|
+
"claude-code": "claude-code",
|
|
214
|
+
claude: "claude-code",
|
|
215
|
+
code: "claude-code",
|
|
216
|
+
cursor: "cursor",
|
|
217
|
+
windsurf: "windsurf",
|
|
218
|
+
augment: "augment",
|
|
219
|
+
vscode: "augment",
|
|
220
|
+
codex: "codex",
|
|
221
|
+
all: "all",
|
|
222
|
+
};
|
|
223
|
+
function runConfigure(ides, launch, env) {
|
|
224
|
+
const set = new Set(ides);
|
|
225
|
+
if (set.has("all")) {
|
|
226
|
+
configureClaudeDesktop(launch, env);
|
|
227
|
+
configureClaudeCode(launch, env);
|
|
228
|
+
configureCursor(launch, env);
|
|
229
|
+
configureWindsurf(launch, env);
|
|
230
|
+
configureAugment(launch, env);
|
|
231
|
+
configureCodexIde(launch, env);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
for (const id of set) {
|
|
235
|
+
if (id === "claude-desktop")
|
|
236
|
+
configureClaudeDesktop(launch, env);
|
|
237
|
+
else if (id === "claude-code")
|
|
238
|
+
configureClaudeCode(launch, env);
|
|
239
|
+
else if (id === "cursor")
|
|
240
|
+
configureCursor(launch, env);
|
|
241
|
+
else if (id === "windsurf")
|
|
242
|
+
configureWindsurf(launch, env);
|
|
243
|
+
else if (id === "augment")
|
|
244
|
+
configureAugment(launch, env);
|
|
245
|
+
else if (id === "codex")
|
|
246
|
+
configureCodexIde(launch, env);
|
|
247
|
+
else
|
|
248
|
+
warn(`Unknown IDE: ${id}`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// ── uninstall ────────────────────────────────────────────────────────────────
|
|
252
|
+
function removeFromJson(file) {
|
|
253
|
+
if (!existsSync(file))
|
|
254
|
+
return;
|
|
255
|
+
try {
|
|
256
|
+
const cfg = JSON.parse(readFileSync(file, "utf8"));
|
|
257
|
+
if (cfg.mcpServers && cfg.mcpServers[NAME]) {
|
|
258
|
+
delete cfg.mcpServers[NAME];
|
|
259
|
+
writeFileSync(file, JSON.stringify(cfg, null, 2) + "\n");
|
|
260
|
+
ok(`Cleaned ${file}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
/* ignore unparseable files */
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function uninstall() {
|
|
268
|
+
log(`\n${c.bold}Uninstalling ${PKG}${c.reset}\n`);
|
|
269
|
+
if (hasClaudeCli())
|
|
270
|
+
spawnSync("claude", ["mcp", "remove", NAME], { stdio: "ignore" });
|
|
271
|
+
[
|
|
272
|
+
claudeJsonPath(),
|
|
273
|
+
claudeDesktopPath(),
|
|
274
|
+
join(HOME, ".config", "Claude", "claude_desktop_config.json"),
|
|
275
|
+
cursorPath(),
|
|
276
|
+
windsurfPath(),
|
|
277
|
+
vscodeUserPath(),
|
|
278
|
+
].forEach(removeFromJson);
|
|
279
|
+
const codex = join(HOME, ".codex", "config.toml");
|
|
280
|
+
if (existsSync(codex)) {
|
|
281
|
+
let content = readFileSync(codex, "utf8");
|
|
282
|
+
content = content.replace(new RegExp(`\\n?\\[mcp_servers\\.${NAME}\\][\\s\\S]*?(?=\\n\\[|$)`), "");
|
|
283
|
+
writeFileSync(codex, content.trimEnd() + "\n");
|
|
284
|
+
ok("Cleaned Codex config.toml");
|
|
285
|
+
}
|
|
286
|
+
log(`\n${c.green}Done. Restart your IDE.${c.reset}\n`);
|
|
287
|
+
}
|
|
288
|
+
function printHelp() {
|
|
289
|
+
log(`
|
|
290
|
+
${c.bold}webcake-landing-mcp install${c.reset} — configure the MCP server in your IDE(s)
|
|
291
|
+
|
|
292
|
+
${c.bold}Usage${c.reset}
|
|
293
|
+
npx -y ${PKG} install # interactive (asks step by step)
|
|
294
|
+
npx -y ${PKG} install --ide all # non-interactive, all IDEs
|
|
295
|
+
npx -y ${PKG} install --ide claude-code --jwt <JWT> --api-base http://localhost:5800
|
|
296
|
+
npx -y ${PKG} uninstall # remove from every IDE config
|
|
297
|
+
|
|
298
|
+
${c.bold}Flags${c.reset}
|
|
299
|
+
--ide <list> comma list: claude-desktop, claude-code, cursor, windsurf, augment, codex, all
|
|
300
|
+
--api-base <url> WEBCAKE_API_BASE (default http://localhost:5800)
|
|
301
|
+
--jwt <token> WEBCAKE_JWT (account token; optional, needed to persist)
|
|
302
|
+
--org-id <id> WEBCAKE_ORG_ID (optional)
|
|
303
|
+
--host <host> WEBCAKE_HOST (optional)
|
|
304
|
+
--app-base <url> WEBCAKE_APP_BASE (optional)
|
|
305
|
+
--npx | --local force the launch command form (default: auto-detect)
|
|
306
|
+
-y, --yes accept defaults, skip confirmations
|
|
307
|
+
--uninstall remove the server from all IDE configs
|
|
308
|
+
`);
|
|
309
|
+
}
|
|
310
|
+
// ── main ─────────────────────────────────────────────────────────────────────
|
|
311
|
+
export async function runInstaller(argv) {
|
|
312
|
+
const o = parseArgs(argv);
|
|
313
|
+
if (o.ide === "__help__")
|
|
314
|
+
return printHelp();
|
|
315
|
+
if (o.uninstall)
|
|
316
|
+
return uninstall();
|
|
317
|
+
log(`\n${c.cyan}${c.bold}Webcake Landing MCP — installer${c.reset}`);
|
|
318
|
+
log(`${c.gray}Build & edit Webcake landing pages from a prompt. 12 tools.${c.reset}`);
|
|
319
|
+
const interactive = !o.ide && process.stdin.isTTY && process.stdout.isTTY;
|
|
320
|
+
// 1) env
|
|
321
|
+
const env = {};
|
|
322
|
+
let apiBase = o.apiBase ?? process.env.WEBCAKE_API_BASE ?? "";
|
|
323
|
+
let jwt = o.jwt ?? process.env.WEBCAKE_JWT ?? "";
|
|
324
|
+
let orgId = o.orgId ?? process.env.WEBCAKE_ORG_ID ?? "";
|
|
325
|
+
const host = o.host ?? process.env.WEBCAKE_HOST ?? "";
|
|
326
|
+
const appBase = o.appBase ?? process.env.WEBCAKE_APP_BASE ?? "";
|
|
327
|
+
if (interactive) {
|
|
328
|
+
log(`\n${c.bold}1) Config${c.reset} ${c.gray}(Enter to skip — reference tools work with no creds)${c.reset}`);
|
|
329
|
+
apiBase =
|
|
330
|
+
(await ask(` WEBCAKE_API_BASE [${apiBase || "http://localhost:5800"}]: `)) ||
|
|
331
|
+
apiBase ||
|
|
332
|
+
"http://localhost:5800";
|
|
333
|
+
jwt = (await ask(` WEBCAKE_JWT (account token, optional): `)) || jwt;
|
|
334
|
+
orgId = (await ask(` WEBCAKE_ORG_ID (optional): `)) || orgId;
|
|
335
|
+
}
|
|
336
|
+
else if (!apiBase) {
|
|
337
|
+
apiBase = "http://localhost:5800";
|
|
338
|
+
}
|
|
339
|
+
if (apiBase)
|
|
340
|
+
env.WEBCAKE_API_BASE = apiBase;
|
|
341
|
+
if (jwt)
|
|
342
|
+
env.WEBCAKE_JWT = jwt;
|
|
343
|
+
if (orgId)
|
|
344
|
+
env.WEBCAKE_ORG_ID = orgId;
|
|
345
|
+
if (host)
|
|
346
|
+
env.WEBCAKE_HOST = host;
|
|
347
|
+
if (appBase)
|
|
348
|
+
env.WEBCAKE_APP_BASE = appBase;
|
|
349
|
+
// 2) which IDEs
|
|
350
|
+
let ides = [];
|
|
351
|
+
if (o.ide) {
|
|
352
|
+
ides = o.ide
|
|
353
|
+
.split(",")
|
|
354
|
+
.map((s) => IDE_ALIASES[s.trim().toLowerCase()])
|
|
355
|
+
.filter(Boolean);
|
|
356
|
+
}
|
|
357
|
+
else if (interactive) {
|
|
358
|
+
log(`\n${c.bold}2) Which IDE(s) to configure?${c.reset}`);
|
|
359
|
+
log(" 1) Claude Desktop 2) Claude Code (CLI) 3) Cursor");
|
|
360
|
+
log(" 4) Windsurf 5) Augment (VS Code) 6) Codex");
|
|
361
|
+
log(" 7) All 0) Skip");
|
|
362
|
+
const pick = await ask(" Select (comma-separated, e.g. 1,2): ");
|
|
363
|
+
const map = {
|
|
364
|
+
"1": "claude-desktop",
|
|
365
|
+
"2": "claude-code",
|
|
366
|
+
"3": "cursor",
|
|
367
|
+
"4": "windsurf",
|
|
368
|
+
"5": "augment",
|
|
369
|
+
"6": "codex",
|
|
370
|
+
"7": "all",
|
|
371
|
+
};
|
|
372
|
+
ides = pick
|
|
373
|
+
.split(",")
|
|
374
|
+
.map((s) => map[s.trim()])
|
|
375
|
+
.filter(Boolean);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
warn("No --ide given and not a TTY. Nothing to configure.");
|
|
379
|
+
printHelp();
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (!ides.length) {
|
|
383
|
+
warn("No IDE selected — skipping configuration.");
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
// 3) write
|
|
387
|
+
const launch = resolveLaunch(o);
|
|
388
|
+
log(`\n${c.bold}3) Writing config${c.reset} ${c.gray}(launch: ${launch.command} ${launch.args.join(" ")})${c.reset}`);
|
|
389
|
+
runConfigure(ides, launch, env);
|
|
390
|
+
// 4) summary
|
|
391
|
+
log(`\n${c.green}${c.bold}✓ Done.${c.reset}`);
|
|
392
|
+
log(` ${c.gray}API base : ${apiBase || "(unset)"}${c.reset}`);
|
|
393
|
+
log(` ${c.gray}JWT : ${jwt ? jwt.slice(0, 8) + "…" : "(unset — reference tools still work)"}${c.reset}`);
|
|
394
|
+
log(` Restart your IDE, then ask the AI: “Build a Webcake landing page”.\n`);
|
|
395
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "webcake-landing-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "MCP server exposing Webcake landing-page element schemas + AI usage hints, and persisting LLM-generated page sources to a Webcake backend.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|