mountly-mcp 4.0.2 → 4.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/GLOSSARY.md +37 -0
- package/README.md +75 -197
- package/dist/add-DAFMA4F3.js +263 -0
- package/dist/add-DAFMA4F3.js.map +1 -0
- package/dist/add.d.ts +13 -0
- package/dist/chunk-EOWAWZH2.js +34 -0
- package/dist/chunk-EOWAWZH2.js.map +1 -0
- package/dist/{chunk-UECZA34Q.js → chunk-OWAXBNZA.js} +10 -5
- package/dist/chunk-OWAXBNZA.js.map +1 -0
- package/dist/cli.js +96 -24
- package/dist/cli.js.map +1 -1
- package/dist/connect-server-P2UZ62YC.js +7 -0
- package/dist/create.js +43 -15
- package/dist/create.js.map +1 -1
- package/dist/dev/index.js +1 -1
- package/dist/doctor-B54H6CRN.js +122 -0
- package/dist/doctor-B54H6CRN.js.map +1 -0
- package/dist/doctor.d.ts +16 -0
- package/dist/errors-4ERW7HZB.js +11 -0
- package/dist/errors-4ERW7HZB.js.map +1 -0
- package/dist/errors.d.ts +25 -0
- package/package.json +9 -6
- package/templates/react/README.md.tmpl +83 -6
- package/templates/react/package.json.tmpl +2 -0
- package/templates/react/serve-stdio.mjs.tmpl +9 -0
- package/templates/react/server.mjs.tmpl +6 -1
- package/templates/react/src/view.tsx.tmpl +1 -1
- package/templates/svelte/README.md.tmpl +27 -4
- package/templates/svelte/package.json.tmpl +2 -0
- package/templates/svelte/serve-stdio.mjs.tmpl +5 -0
- package/templates/svelte/server.mjs.tmpl +6 -1
- package/templates/svelte/src/Dashboard.svelte.tmpl +1 -1
- package/templates/vanilla/README.md.tmpl +27 -11
- package/templates/vanilla/package.json.tmpl +2 -0
- package/templates/vanilla/serve-stdio.mjs.tmpl +5 -0
- package/templates/vanilla/server.mjs.tmpl +6 -1
- package/templates/vanilla/src/view.ts.tmpl +1 -1
- package/templates/vue/README.md.tmpl +27 -4
- package/templates/vue/package.json.tmpl +2 -0
- package/templates/vue/serve-stdio.mjs.tmpl +5 -0
- package/templates/vue/server.mjs.tmpl +6 -1
- package/templates/vue/src/Dashboard.vue.tmpl +1 -1
- package/dist/chunk-UECZA34Q.js.map +0 -1
- package/dist/connect-server-7L4HGKKL.js +0 -7
- /package/dist/{connect-server-7L4HGKKL.js.map → connect-server-P2UZ62YC.js.map} +0 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CLI_ERROR_CODES,
|
|
3
|
+
cliError
|
|
4
|
+
} from "./chunk-EOWAWZH2.js";
|
|
5
|
+
|
|
6
|
+
// src/doctor.ts
|
|
7
|
+
import { existsSync, readFileSync } from "fs";
|
|
8
|
+
import { createRequire } from "module";
|
|
9
|
+
import { resolve } from "path";
|
|
10
|
+
function nodeMajor() {
|
|
11
|
+
return Number(process.versions.node.split(".")[0] ?? 0);
|
|
12
|
+
}
|
|
13
|
+
function tryResolve(specifier, fromDir) {
|
|
14
|
+
try {
|
|
15
|
+
const require2 = createRequire(resolve(fromDir, "package.json"));
|
|
16
|
+
return require2.resolve(specifier);
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function runDoctor(cwd = process.cwd()) {
|
|
22
|
+
const checks = [];
|
|
23
|
+
const major = nodeMajor();
|
|
24
|
+
checks.push({
|
|
25
|
+
id: "node",
|
|
26
|
+
ok: major >= 20,
|
|
27
|
+
detail: major >= 20 ? `Node ${process.versions.node} (ok; 20+ required, 22+ recommended)` : `Node ${process.versions.node} is below 20. Upgrade Node, then re-run mountly-mcp doctor.`
|
|
28
|
+
});
|
|
29
|
+
const viteConfigCandidates = [
|
|
30
|
+
"vite.config.ts",
|
|
31
|
+
"vite.config.mts",
|
|
32
|
+
"vite.config.js",
|
|
33
|
+
"vite.config.mjs"
|
|
34
|
+
].map((name) => resolve(cwd, name));
|
|
35
|
+
const viteConfig = viteConfigCandidates.find((path) => existsSync(path));
|
|
36
|
+
checks.push({
|
|
37
|
+
id: "vite-config",
|
|
38
|
+
ok: Boolean(viteConfig),
|
|
39
|
+
detail: viteConfig ? `Found ${viteConfig}` : "No vite.config.* in this directory. Run from the View project, or: npx mountly-mcp create my-app --framework react"
|
|
40
|
+
});
|
|
41
|
+
if (viteConfig) {
|
|
42
|
+
const source = readFileSync(viteConfig, "utf8");
|
|
43
|
+
const hasPlugin = /mountlyMcpViews\s*\(/.test(source);
|
|
44
|
+
checks.push({
|
|
45
|
+
id: "vite-plugin",
|
|
46
|
+
ok: hasPlugin,
|
|
47
|
+
detail: hasPlugin ? "vite config imports mountlyMcpViews()" : `Add mountlyMcpViews() from "mountly-mcp/vite" to ${viteConfig}`
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
const manifest = resolve(cwd, "dist/mountly-mcp.manifest.json");
|
|
51
|
+
checks.push({
|
|
52
|
+
id: "manifest",
|
|
53
|
+
ok: existsSync(manifest),
|
|
54
|
+
detail: existsSync(manifest) ? `Found ${manifest}` : "No dist/mountly-mcp.manifest.json yet. Run: npx mountly-mcp build"
|
|
55
|
+
});
|
|
56
|
+
const playwright = tryResolve("playwright", cwd) ?? tryResolve("@playwright/test", cwd);
|
|
57
|
+
checks.push({
|
|
58
|
+
id: "playwright",
|
|
59
|
+
ok: Boolean(playwright),
|
|
60
|
+
detail: playwright ? `Playwright resolvable for verify --render (${playwright})` : "Playwright not installed. For CI render checks: pnpm add -D playwright && npx playwright install chromium"
|
|
61
|
+
});
|
|
62
|
+
const pkgPath = resolve(cwd, "package.json");
|
|
63
|
+
if (existsSync(pkgPath)) {
|
|
64
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
|
|
65
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
66
|
+
if (deps.react) {
|
|
67
|
+
const reactPath = tryResolve("react/package.json", cwd);
|
|
68
|
+
if (reactPath) {
|
|
69
|
+
const reactPkg = JSON.parse(readFileSync(reactPath, "utf8"));
|
|
70
|
+
const reactMajor = Number((reactPkg.version ?? "0").split(".")[0]);
|
|
71
|
+
checks.push({
|
|
72
|
+
id: "react",
|
|
73
|
+
ok: reactMajor >= 19,
|
|
74
|
+
detail: reactMajor >= 19 ? `React ${reactPkg.version} (ok)` : `React ${reactPkg.version} is below 19. mountly-mcp/react and mountly-react require React 19.`
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (deps.vite) {
|
|
79
|
+
const vitePath = tryResolve("vite/package.json", cwd);
|
|
80
|
+
if (vitePath) {
|
|
81
|
+
const vitePkg = JSON.parse(readFileSync(vitePath, "utf8"));
|
|
82
|
+
const viteMajor = Number((vitePkg.version ?? "0").split(".")[0]);
|
|
83
|
+
checks.push({
|
|
84
|
+
id: "vite",
|
|
85
|
+
ok: viteMajor >= 8,
|
|
86
|
+
detail: viteMajor >= 8 ? `Vite ${vitePkg.version} (ok)` : `Vite ${vitePkg.version} is below 8. mountly-mcp/vite is built and tested against Vite 8.`
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const hard = checks.filter((c) => c.id !== "manifest" && c.id !== "playwright");
|
|
92
|
+
const ok = hard.every((c) => c.ok);
|
|
93
|
+
return { ok, checks };
|
|
94
|
+
}
|
|
95
|
+
function formatDoctorReport(report) {
|
|
96
|
+
const lines = ["mountly-mcp doctor", ""];
|
|
97
|
+
for (const check of report.checks) {
|
|
98
|
+
lines.push(`${check.ok ? "ok" : "FAIL"} ${check.id.padEnd(14)} ${check.detail}`);
|
|
99
|
+
}
|
|
100
|
+
lines.push("");
|
|
101
|
+
lines.push(report.ok ? "Ready for mountly-mcp build / dev / verify." : "Fix FAIL items above.");
|
|
102
|
+
lines.push("");
|
|
103
|
+
return `${lines.join("\n")}
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
function doctorCommand(cwd = process.cwd()) {
|
|
107
|
+
const report = runDoctor(cwd);
|
|
108
|
+
process.stdout.write(formatDoctorReport(report));
|
|
109
|
+
if (!report.ok) {
|
|
110
|
+
throw cliError(
|
|
111
|
+
CLI_ERROR_CODES.DOCTOR_FAILED,
|
|
112
|
+
"one or more doctor checks failed",
|
|
113
|
+
"Fix the FAIL lines above, then re-run: mountly-mcp doctor"
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export {
|
|
118
|
+
doctorCommand,
|
|
119
|
+
formatDoctorReport,
|
|
120
|
+
runDoctor
|
|
121
|
+
};
|
|
122
|
+
//# sourceMappingURL=doctor-B54H6CRN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/doctor.ts"],"sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { CLI_ERROR_CODES, cliError } from \"./errors.js\";\n\nexport interface DoctorCheck {\n id: string;\n ok: boolean;\n detail: string;\n}\n\nexport interface DoctorReport {\n ok: boolean;\n checks: DoctorCheck[];\n}\n\nfunction nodeMajor(): number {\n return Number(process.versions.node.split(\".\")[0] ?? 0);\n}\n\nfunction tryResolve(specifier: string, fromDir: string): string | null {\n try {\n const require = createRequire(resolve(fromDir, \"package.json\"));\n return require.resolve(specifier);\n } catch {\n return null;\n }\n}\n\n/**\n * Check the local project for Mountly MCP readiness. Exits nonzero via the\n * CLI when `ok` is false.\n */\nexport function runDoctor(cwd = process.cwd()): DoctorReport {\n const checks: DoctorCheck[] = [];\n\n const major = nodeMajor();\n checks.push({\n id: \"node\",\n ok: major >= 20,\n detail:\n major >= 20\n ? `Node ${process.versions.node} (ok; 20+ required, 22+ recommended)`\n : `Node ${process.versions.node} is below 20. Upgrade Node, then re-run mountly-mcp doctor.`,\n });\n\n const viteConfigCandidates = [\n \"vite.config.ts\",\n \"vite.config.mts\",\n \"vite.config.js\",\n \"vite.config.mjs\",\n ].map((name) => resolve(cwd, name));\n const viteConfig = viteConfigCandidates.find((path) => existsSync(path));\n checks.push({\n id: \"vite-config\",\n ok: Boolean(viteConfig),\n detail: viteConfig\n ? `Found ${viteConfig}`\n : \"No vite.config.* in this directory. Run from the View project, or: npx mountly-mcp create my-app --framework react\",\n });\n\n if (viteConfig) {\n const source = readFileSync(viteConfig, \"utf8\");\n const hasPlugin = /mountlyMcpViews\\s*\\(/.test(source);\n checks.push({\n id: \"vite-plugin\",\n ok: hasPlugin,\n detail: hasPlugin\n ? \"vite config imports mountlyMcpViews()\"\n : `Add mountlyMcpViews() from \"mountly-mcp/vite\" to ${viteConfig}`,\n });\n }\n\n const manifest = resolve(cwd, \"dist/mountly-mcp.manifest.json\");\n checks.push({\n id: \"manifest\",\n ok: existsSync(manifest),\n detail: existsSync(manifest)\n ? `Found ${manifest}`\n : \"No dist/mountly-mcp.manifest.json yet. Run: npx mountly-mcp build\",\n });\n\n const playwright = tryResolve(\"playwright\", cwd) ?? tryResolve(\"@playwright/test\", cwd);\n checks.push({\n id: \"playwright\",\n ok: Boolean(playwright),\n detail: playwright\n ? `Playwright resolvable for verify --render (${playwright})`\n : \"Playwright not installed. For CI render checks: pnpm add -D playwright && npx playwright install chromium\",\n });\n\n const pkgPath = resolve(cwd, \"package.json\");\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as {\n dependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n const deps = { ...pkg.dependencies, ...pkg.devDependencies };\n if (deps.react) {\n const reactPath = tryResolve(\"react/package.json\", cwd);\n if (reactPath) {\n const reactPkg = JSON.parse(readFileSync(reactPath, \"utf8\")) as { version?: string };\n const reactMajor = Number((reactPkg.version ?? \"0\").split(\".\")[0]);\n checks.push({\n id: \"react\",\n ok: reactMajor >= 19,\n detail:\n reactMajor >= 19\n ? `React ${reactPkg.version} (ok)`\n : `React ${reactPkg.version} is below 19. mountly-mcp/react and mountly-react require React 19.`,\n });\n }\n }\n if (deps.vite) {\n const vitePath = tryResolve(\"vite/package.json\", cwd);\n if (vitePath) {\n const vitePkg = JSON.parse(readFileSync(vitePath, \"utf8\")) as { version?: string };\n const viteMajor = Number((vitePkg.version ?? \"0\").split(\".\")[0]);\n checks.push({\n id: \"vite\",\n ok: viteMajor >= 8,\n detail:\n viteMajor >= 8\n ? `Vite ${vitePkg.version} (ok)`\n : `Vite ${vitePkg.version} is below 8. mountly-mcp/vite is built and tested against Vite 8.`,\n });\n }\n }\n }\n\n // Manifest missing is advisory for a brand-new scaffold before first build.\n const hard = checks.filter((c) => c.id !== \"manifest\" && c.id !== \"playwright\");\n const ok = hard.every((c) => c.ok);\n\n return { ok, checks };\n}\n\nexport function formatDoctorReport(report: DoctorReport): string {\n const lines = [\"mountly-mcp doctor\", \"\"];\n for (const check of report.checks) {\n lines.push(`${check.ok ? \"ok\" : \"FAIL\"} ${check.id.padEnd(14)} ${check.detail}`);\n }\n lines.push(\"\");\n lines.push(report.ok ? \"Ready for mountly-mcp build / dev / verify.\" : \"Fix FAIL items above.\");\n lines.push(\"\");\n return `${lines.join(\"\\n\")}\\n`;\n}\n\nexport function doctorCommand(cwd = process.cwd()): void {\n const report = runDoctor(cwd);\n process.stdout.write(formatDoctorReport(report));\n if (!report.ok) {\n throw cliError(\n CLI_ERROR_CODES.DOCTOR_FAILED,\n \"one or more doctor checks failed\",\n \"Fix the FAIL lines above, then re-run: mountly-mcp doctor\",\n );\n }\n}\n"],"mappings":";;;;;;AAAA,SAAS,YAAY,oBAAoB;AACzC,SAAS,qBAAqB;AAC9B,SAAS,eAAe;AAcxB,SAAS,YAAoB;AAC3B,SAAO,OAAO,QAAQ,SAAS,KAAK,MAAM,GAAG,EAAE,CAAC,KAAK,CAAC;AACxD;AAEA,SAAS,WAAW,WAAmB,SAAgC;AACrE,MAAI;AACF,UAAMA,WAAU,cAAc,QAAQ,SAAS,cAAc,CAAC;AAC9D,WAAOA,SAAQ,QAAQ,SAAS;AAAA,EAClC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMO,SAAS,UAAU,MAAM,QAAQ,IAAI,GAAiB;AAC3D,QAAM,SAAwB,CAAC;AAE/B,QAAM,QAAQ,UAAU;AACxB,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,IAAI,SAAS;AAAA,IACb,QACE,SAAS,KACL,QAAQ,QAAQ,SAAS,IAAI,yCAC7B,QAAQ,QAAQ,SAAS,IAAI;AAAA,EACrC,CAAC;AAED,QAAM,uBAAuB;AAAA,IAC3B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,IAAI,CAAC,SAAS,QAAQ,KAAK,IAAI,CAAC;AAClC,QAAM,aAAa,qBAAqB,KAAK,CAAC,SAAS,WAAW,IAAI,CAAC;AACvE,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,IAAI,QAAQ,UAAU;AAAA,IACtB,QAAQ,aACJ,SAAS,UAAU,KACnB;AAAA,EACN,CAAC;AAED,MAAI,YAAY;AACd,UAAM,SAAS,aAAa,YAAY,MAAM;AAC9C,UAAM,YAAY,uBAAuB,KAAK,MAAM;AACpD,WAAO,KAAK;AAAA,MACV,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,QAAQ,YACJ,0CACA,oDAAoD,UAAU;AAAA,IACpE,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,QAAQ,KAAK,gCAAgC;AAC9D,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,IAAI,WAAW,QAAQ;AAAA,IACvB,QAAQ,WAAW,QAAQ,IACvB,SAAS,QAAQ,KACjB;AAAA,EACN,CAAC;AAED,QAAM,aAAa,WAAW,cAAc,GAAG,KAAK,WAAW,oBAAoB,GAAG;AACtF,SAAO,KAAK;AAAA,IACV,IAAI;AAAA,IACJ,IAAI,QAAQ,UAAU;AAAA,IACtB,QAAQ,aACJ,8CAA8C,UAAU,MACxD;AAAA,EACN,CAAC;AAED,QAAM,UAAU,QAAQ,KAAK,cAAc;AAC3C,MAAI,WAAW,OAAO,GAAG;AACvB,UAAM,MAAM,KAAK,MAAM,aAAa,SAAS,MAAM,CAAC;AAKpD,UAAM,OAAO,EAAE,GAAG,IAAI,cAAc,GAAG,IAAI,gBAAgB;AAC3D,QAAI,KAAK,OAAO;AACd,YAAM,YAAY,WAAW,sBAAsB,GAAG;AACtD,UAAI,WAAW;AACb,cAAM,WAAW,KAAK,MAAM,aAAa,WAAW,MAAM,CAAC;AAC3D,cAAM,aAAa,QAAQ,SAAS,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC;AACjE,eAAO,KAAK;AAAA,UACV,IAAI;AAAA,UACJ,IAAI,cAAc;AAAA,UAClB,QACE,cAAc,KACV,SAAS,SAAS,OAAO,UACzB,SAAS,SAAS,OAAO;AAAA,QACjC,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,KAAK,MAAM;AACb,YAAM,WAAW,WAAW,qBAAqB,GAAG;AACpD,UAAI,UAAU;AACZ,cAAM,UAAU,KAAK,MAAM,aAAa,UAAU,MAAM,CAAC;AACzD,cAAM,YAAY,QAAQ,QAAQ,WAAW,KAAK,MAAM,GAAG,EAAE,CAAC,CAAC;AAC/D,eAAO,KAAK;AAAA,UACV,IAAI;AAAA,UACJ,IAAI,aAAa;AAAA,UACjB,QACE,aAAa,IACT,QAAQ,QAAQ,OAAO,UACvB,QAAQ,QAAQ,OAAO;AAAA,QAC/B,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,QAAM,OAAO,OAAO,OAAO,CAAC,MAAM,EAAE,OAAO,cAAc,EAAE,OAAO,YAAY;AAC9E,QAAM,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,EAAE;AAEjC,SAAO,EAAE,IAAI,OAAO;AACtB;AAEO,SAAS,mBAAmB,QAA8B;AAC/D,QAAM,QAAQ,CAAC,sBAAsB,EAAE;AACvC,aAAW,SAAS,OAAO,QAAQ;AACjC,UAAM,KAAK,GAAG,MAAM,KAAK,OAAO,MAAM,KAAK,MAAM,GAAG,OAAO,EAAE,CAAC,IAAI,MAAM,MAAM,EAAE;AAAA,EAClF;AACA,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,OAAO,KAAK,gDAAgD,uBAAuB;AAC9F,QAAM,KAAK,EAAE;AACb,SAAO,GAAG,MAAM,KAAK,IAAI,CAAC;AAAA;AAC5B;AAEO,SAAS,cAAc,MAAM,QAAQ,IAAI,GAAS;AACvD,QAAM,SAAS,UAAU,GAAG;AAC5B,UAAQ,OAAO,MAAM,mBAAmB,MAAM,CAAC;AAC/C,MAAI,CAAC,OAAO,IAAI;AACd,UAAM;AAAA,MACJ,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;","names":["require"]}
|
package/dist/doctor.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface DoctorCheck {
|
|
2
|
+
id: string;
|
|
3
|
+
ok: boolean;
|
|
4
|
+
detail: string;
|
|
5
|
+
}
|
|
6
|
+
export interface DoctorReport {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
checks: DoctorCheck[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Check the local project for Mountly MCP readiness. Exits nonzero via the
|
|
12
|
+
* CLI when `ok` is false.
|
|
13
|
+
*/
|
|
14
|
+
export declare function runDoctor(cwd?: string): DoctorReport;
|
|
15
|
+
export declare function formatDoctorReport(report: DoctorReport): string;
|
|
16
|
+
export declare function doctorCommand(cwd?: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LLM-shaped CLI errors: a stable code plus the next command or file to open.
|
|
3
|
+
* Skills and agents should key off the `mountly-mcp/…` code prefix.
|
|
4
|
+
*/
|
|
5
|
+
export declare const CLI_ERROR_CODES: {
|
|
6
|
+
readonly MISSING_VITE_PLUGIN: "mountly-mcp/missing-vite-plugin";
|
|
7
|
+
readonly NO_VITE_CONFIG: "mountly-mcp/no-vite-config";
|
|
8
|
+
readonly UNKNOWN_VIEW: "mountly-mcp/unknown-view";
|
|
9
|
+
readonly MULTI_VIEW_NEEDS_APP: "mountly-mcp/multi-view-needs-app";
|
|
10
|
+
readonly INVALID_UI_URI: "mountly-mcp/invalid-ui-uri";
|
|
11
|
+
readonly BAD_SERVER_EXPORT: "mountly-mcp/bad-server-export";
|
|
12
|
+
readonly NO_TOOL_FOR_VIEW: "mountly-mcp/no-tool-for-view";
|
|
13
|
+
readonly UNKNOWN_OPTION: "mountly-mcp/unknown-option";
|
|
14
|
+
readonly UNKNOWN_COMMAND: "mountly-mcp/unknown-command";
|
|
15
|
+
readonly TARGET_EXISTS: "mountly-mcp/target-exists";
|
|
16
|
+
readonly MISSING_TEMPLATE: "mountly-mcp/missing-template";
|
|
17
|
+
readonly DOCTOR_FAILED: "mountly-mcp/doctor-failed";
|
|
18
|
+
};
|
|
19
|
+
export type CliErrorCode = (typeof CLI_ERROR_CODES)[keyof typeof CLI_ERROR_CODES];
|
|
20
|
+
export declare class MountlyMcpCliError extends Error {
|
|
21
|
+
readonly code: CliErrorCode;
|
|
22
|
+
readonly next: string;
|
|
23
|
+
constructor(code: CliErrorCode, message: string, next: string);
|
|
24
|
+
}
|
|
25
|
+
export declare function cliError(code: CliErrorCode, message: string, next: string): MountlyMcpCliError;
|
package/package.json
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mountly-mcp",
|
|
3
|
-
"version": "4.0
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "Build MCP Apps (SEP-1865) views from React, Vue or Svelte components — new or existing. One build emits the ui:// resource, its sidecar, and the MCP server wiring.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"chatgpt",
|
|
7
7
|
"claude",
|
|
8
8
|
"mcp",
|
|
9
9
|
"mcp-apps",
|
|
10
|
+
"mcp-apps-view",
|
|
10
11
|
"mcp-ui",
|
|
11
12
|
"mcp-view",
|
|
12
13
|
"model-context-protocol",
|
|
13
14
|
"react",
|
|
14
15
|
"sep-1865",
|
|
15
16
|
"svelte",
|
|
17
|
+
"ui-resource",
|
|
16
18
|
"vite-plugin",
|
|
17
19
|
"vue"
|
|
18
20
|
],
|
|
@@ -27,7 +29,8 @@
|
|
|
27
29
|
},
|
|
28
30
|
"files": [
|
|
29
31
|
"dist",
|
|
30
|
-
"templates"
|
|
32
|
+
"templates",
|
|
33
|
+
"GLOSSARY.md"
|
|
31
34
|
],
|
|
32
35
|
"type": "module",
|
|
33
36
|
"main": "./dist/index.js",
|
|
@@ -107,7 +110,7 @@
|
|
|
107
110
|
"dependencies": {
|
|
108
111
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
109
112
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
110
|
-
"mountly": "^1.0.
|
|
113
|
+
"mountly": "^1.0.1",
|
|
111
114
|
"mountly-react": "^2.1.0",
|
|
112
115
|
"zod": "^4.4.3"
|
|
113
116
|
},
|
|
@@ -125,8 +128,8 @@
|
|
|
125
128
|
"tsup": "^8.5.1",
|
|
126
129
|
"typescript": "^7.0.2",
|
|
127
130
|
"vite": "^8.1.5",
|
|
128
|
-
"mountly-
|
|
129
|
-
"mountly-
|
|
131
|
+
"mountly-vue": "^2.1.0",
|
|
132
|
+
"mountly-svelte": "^2.1.0"
|
|
130
133
|
},
|
|
131
134
|
"peerDependencies": {
|
|
132
135
|
"@json-render/core": "^0.20.0",
|
|
@@ -138,7 +141,7 @@
|
|
|
138
141
|
"playwright": ">=1.62.1",
|
|
139
142
|
"react": "^19",
|
|
140
143
|
"react-dom": "^19",
|
|
141
|
-
"vite": "^8
|
|
144
|
+
"vite": "^8"
|
|
142
145
|
},
|
|
143
146
|
"peerDependenciesMeta": {
|
|
144
147
|
"@json-render/core": {
|
|
@@ -2,14 +2,91 @@
|
|
|
2
2
|
|
|
3
3
|
MCP App scaffolded with `mountly-mcp create`.
|
|
4
4
|
|
|
5
|
+
## Runbook
|
|
6
|
+
|
|
5
7
|
```bash
|
|
6
8
|
pnpm install
|
|
7
|
-
pnpm dev
|
|
8
|
-
pnpm verify
|
|
9
|
+
pnpm dev # sandboxed AppBridge host on :5179 (uses --server ./server.mjs)
|
|
10
|
+
pnpm verify # static conformance
|
|
11
|
+
pnpm verify:render # + Chromium mount check (needs Playwright)
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| File | Role |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `src/view.tsx` | `createMcpView`: View entry; reads tool data via `useToolResult` |
|
|
17
|
+
| `server.mjs` | `registerMcpApps`: factory for `mountly-mcp dev --server` |
|
|
18
|
+
| `serve-stdio.mjs` | Stdio entry for Claude Desktop / VS Code / ChatGPT connectors |
|
|
19
|
+
| `mcp.fixtures.json` | Tool **arguments** when using `--server` |
|
|
20
|
+
| `vite.config.ts` | `mountlyMcpViews({ apps: [...] })` |
|
|
21
|
+
| `dist/mountly-mcp.manifest.json` | Build artifact (after `pnpm build` / first `dev`) |
|
|
22
|
+
|
|
23
|
+
Do not clone the Mountly monorepo for greenfield apps: this project is the canonical path.
|
|
24
|
+
|
|
25
|
+
## Open in a real host
|
|
26
|
+
|
|
27
|
+
`serve-stdio.mjs` is included. Build first (`pnpm build` or run `pnpm dev` once), then point the host at that entry.
|
|
28
|
+
|
|
29
|
+
Never write logs to **stdout** in a stdio server.
|
|
30
|
+
|
|
31
|
+
### Claude Desktop
|
|
32
|
+
|
|
33
|
+
`~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"{{slug}}": {
|
|
39
|
+
"command": "node",
|
|
40
|
+
"args": ["/ABSOLUTE/PATH/TO/{{name}}/serve-stdio.mjs"]
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### VS Code
|
|
47
|
+
|
|
48
|
+
`.vscode/mcp.json`:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
{
|
|
52
|
+
"servers": {
|
|
53
|
+
"{{slug}}": {
|
|
54
|
+
"type": "stdio",
|
|
55
|
+
"command": "node",
|
|
56
|
+
"args": ["${workspaceFolder}/serve-stdio.mjs"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
9
60
|
```
|
|
10
61
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
62
|
+
### ChatGPT
|
|
63
|
+
|
|
64
|
+
Use a connector / custom MCP that runs the same `serve-stdio.mjs` (or an HTTP transport your deployment owns). Mountly does not own OAuth or hosting.
|
|
65
|
+
|
|
66
|
+
## CI
|
|
67
|
+
|
|
68
|
+
```yaml
|
|
69
|
+
# .github/workflows/mcp-verify.yml
|
|
70
|
+
name: mcp-verify
|
|
71
|
+
on: [push, pull_request]
|
|
72
|
+
jobs:
|
|
73
|
+
verify:
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/checkout@v4
|
|
77
|
+
- uses: pnpm/action-setup@v4
|
|
78
|
+
- uses: actions/setup-node@v4
|
|
79
|
+
with: { node-version: 22, cache: pnpm }
|
|
80
|
+
- run: pnpm install
|
|
81
|
+
- run: pnpm exec mountly-mcp build
|
|
82
|
+
- run: pnpm exec playwright install chromium
|
|
83
|
+
- run: pnpm exec mountly-mcp verify --strict --render
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Add another View
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pnpm exec mountly-mcp add settings --framework react
|
|
90
|
+
```
|
|
14
91
|
|
|
15
|
-
|
|
92
|
+
Then register a tool with matching `resourceUri` in `server.mjs` via `registerMcpApps`.
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"dev": "mountly-mcp dev --server ./server.mjs",
|
|
9
9
|
"verify": "mountly-mcp verify",
|
|
10
10
|
"verify:strict": "mountly-mcp verify --strict",
|
|
11
|
+
"verify:render": "mountly-mcp verify --strict --render",
|
|
12
|
+
"doctor": "mountly-mcp doctor",
|
|
11
13
|
"typecheck": "tsc --noEmit"
|
|
12
14
|
},
|
|
13
15
|
"dependencies": {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
2
|
+
import createServer from "./server.mjs";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Stdio entry for Claude Desktop / VS Code / other MCP hosts.
|
|
6
|
+
* Never write logs to stdout: stdout is the JSON-RPC channel.
|
|
7
|
+
*/
|
|
8
|
+
const server = await createServer();
|
|
9
|
+
await server.connect(new StdioServerTransport());
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import { readMcpAppManifest } from "mountly-mcp/artifact";
|
|
3
4
|
import { registerMcpApps } from "mountly-mcp/server";
|
|
@@ -5,6 +6,10 @@ import { z } from "zod";
|
|
|
5
6
|
|
|
6
7
|
const URI = "{{uri}}";
|
|
7
8
|
|
|
9
|
+
// Resolved from this file, not the cwd: an MCP host spawns the process with a
|
|
10
|
+
// working directory of its own choosing.
|
|
11
|
+
const MANIFEST = fileURLToPath(new URL("./dist/mountly-mcp.manifest.json", import.meta.url));
|
|
12
|
+
|
|
8
13
|
function sampleCards() {
|
|
9
14
|
return [
|
|
10
15
|
{ label: "Requests", value: Math.floor(1200 + Math.random() * 200) },
|
|
@@ -20,7 +25,7 @@ export default async function createServer() {
|
|
|
20
25
|
{ capabilities: { tools: {}, resources: {} } },
|
|
21
26
|
);
|
|
22
27
|
|
|
23
|
-
const { artifacts } = await readMcpAppManifest(
|
|
28
|
+
const { artifacts } = await readMcpAppManifest(MANIFEST);
|
|
24
29
|
|
|
25
30
|
await registerMcpApps(server, {
|
|
26
31
|
views: artifacts.map((artifact) => ({ artifact })),
|
|
@@ -130,7 +130,7 @@ function Dashboard() {
|
|
|
130
130
|
<p className="eyebrow">MCP App · Mountly</p>
|
|
131
131
|
<h1>{title}</h1>
|
|
132
132
|
<p className="subtitle">
|
|
133
|
-
Built with <code>mountly-mcp</code
|
|
133
|
+
Built with <code>mountly-mcp</code>. Try Refresh to call an app-only tool.
|
|
134
134
|
</p>
|
|
135
135
|
<div className="grid">
|
|
136
136
|
{cards.length === 0
|
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
# {{name}}
|
|
2
2
|
|
|
3
|
-
MCP App scaffolded with `mountly-mcp create
|
|
3
|
+
MCP App scaffolded with `mountly-mcp create` (Svelte).
|
|
4
|
+
|
|
5
|
+
## Runbook
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
8
|
pnpm install
|
|
7
9
|
pnpm dev
|
|
8
10
|
pnpm verify
|
|
11
|
+
pnpm verify:render
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| File | Role |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `src/view.ts` | `createMcpView` entry |
|
|
17
|
+
| `src/Dashboard.svelte` | View UI: `toolResult` prop |
|
|
18
|
+
| `server.mjs` | `registerMcpApps` factory |
|
|
19
|
+
| `mcp.fixtures.json` | Tool args for `dev --server` |
|
|
20
|
+
|
|
21
|
+
## Open in a real host
|
|
22
|
+
|
|
23
|
+
`serve-stdio.mjs` is included. Point Claude Desktop or VS Code at that entry (stdio). ChatGPT: use your connector against the same process.
|
|
24
|
+
|
|
25
|
+
## CI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm exec mountly-mcp build
|
|
29
|
+
pnpm exec playwright install chromium
|
|
30
|
+
pnpm exec mountly-mcp verify --strict --render
|
|
9
31
|
```
|
|
10
32
|
|
|
11
|
-
|
|
12
|
-
- Server: `server.mjs` (`registerMcpApps`)
|
|
33
|
+
## Add another View
|
|
13
34
|
|
|
14
|
-
|
|
35
|
+
```bash
|
|
36
|
+
pnpm exec mountly-mcp add settings --framework svelte
|
|
37
|
+
```
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"dev": "mountly-mcp dev --server ./server.mjs",
|
|
9
9
|
"verify": "mountly-mcp verify",
|
|
10
10
|
"verify:strict": "mountly-mcp verify --strict",
|
|
11
|
+
"verify:render": "mountly-mcp verify --strict --render",
|
|
12
|
+
"doctor": "mountly-mcp doctor",
|
|
11
13
|
"typecheck": "svelte-check --tsconfig ./tsconfig.json"
|
|
12
14
|
},
|
|
13
15
|
"dependencies": {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import { readMcpAppManifest } from "mountly-mcp/artifact";
|
|
3
4
|
import { registerMcpApps } from "mountly-mcp/server";
|
|
@@ -5,6 +6,10 @@ import { z } from "zod";
|
|
|
5
6
|
|
|
6
7
|
const URI = "{{uri}}";
|
|
7
8
|
|
|
9
|
+
// Resolved from this file, not the cwd: an MCP host spawns the process with a
|
|
10
|
+
// working directory of its own choosing.
|
|
11
|
+
const MANIFEST = fileURLToPath(new URL("./dist/mountly-mcp.manifest.json", import.meta.url));
|
|
12
|
+
|
|
8
13
|
function sampleCards() {
|
|
9
14
|
return [
|
|
10
15
|
{ label: "Requests", value: Math.floor(1200 + Math.random() * 200) },
|
|
@@ -20,7 +25,7 @@ export default async function createServer() {
|
|
|
20
25
|
{ capabilities: { tools: {}, resources: {} } },
|
|
21
26
|
);
|
|
22
27
|
|
|
23
|
-
const { artifacts } = await readMcpAppManifest(
|
|
28
|
+
const { artifacts } = await readMcpAppManifest(MANIFEST);
|
|
24
29
|
|
|
25
30
|
await registerMcpApps(server, {
|
|
26
31
|
views: artifacts.map((artifact) => ({ artifact })),
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
<p class="eyebrow">MCP App · Mountly</p>
|
|
62
62
|
<h1>{title}</h1>
|
|
63
63
|
<p class="subtitle">
|
|
64
|
-
Built with <code>mountly-mcp</code
|
|
64
|
+
Built with <code>mountly-mcp</code>. Try Refresh to call an app-only tool.
|
|
65
65
|
</p>
|
|
66
66
|
<div class="grid">
|
|
67
67
|
{#if cards.length === 0}
|
|
@@ -1,20 +1,36 @@
|
|
|
1
1
|
# {{name}}
|
|
2
2
|
|
|
3
|
-
MCP App scaffolded with `mountly-mcp create
|
|
3
|
+
MCP App scaffolded with `mountly-mcp create` (vanilla: no framework).
|
|
4
|
+
|
|
5
|
+
## Runbook
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
8
|
pnpm install
|
|
7
|
-
pnpm dev
|
|
8
|
-
pnpm verify
|
|
9
|
+
pnpm dev
|
|
10
|
+
pnpm verify
|
|
11
|
+
pnpm verify:render
|
|
9
12
|
```
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
| File | Role |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `src/view.ts` | `publishMcpView`: `mount` / `update` / `unmount` |
|
|
17
|
+
| `server.mjs` | `registerMcpApps` factory |
|
|
18
|
+
| `mcp.fixtures.json` | Tool args for `dev --server` |
|
|
19
|
+
|
|
20
|
+
## Open in a real host
|
|
21
|
+
|
|
22
|
+
`serve-stdio.mjs` is included. Register that command in Claude Desktop / VS Code / ChatGPT.
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
`publishMcpView` takes the object directly. The bridge drives it exactly as it
|
|
17
|
-
drives a React, Vue or Svelte View. Add a framework later by swapping
|
|
18
|
-
`publishMcpView(...)` for that framework's `createMcpView(Component)`.
|
|
24
|
+
## CI
|
|
19
25
|
|
|
20
|
-
|
|
26
|
+
```bash
|
|
27
|
+
pnpm exec mountly-mcp build
|
|
28
|
+
pnpm exec playwright install chromium
|
|
29
|
+
pnpm exec mountly-mcp verify --strict --render
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Add another View
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
pnpm exec mountly-mcp add settings --framework vanilla
|
|
36
|
+
```
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"dev": "mountly-mcp dev --server ./server.mjs",
|
|
9
9
|
"verify": "mountly-mcp verify",
|
|
10
10
|
"verify:strict": "mountly-mcp verify --strict",
|
|
11
|
+
"verify:render": "mountly-mcp verify --strict --render",
|
|
12
|
+
"doctor": "mountly-mcp doctor",
|
|
11
13
|
"typecheck": "tsc --noEmit"
|
|
12
14
|
},
|
|
13
15
|
"dependencies": {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { fileURLToPath } from "node:url";
|
|
1
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
3
|
import { readMcpAppManifest } from "mountly-mcp/artifact";
|
|
3
4
|
import { registerMcpApps } from "mountly-mcp/server";
|
|
@@ -5,6 +6,10 @@ import { z } from "zod";
|
|
|
5
6
|
|
|
6
7
|
const URI = "{{uri}}";
|
|
7
8
|
|
|
9
|
+
// Resolved from this file, not the cwd: an MCP host spawns the process with a
|
|
10
|
+
// working directory of its own choosing.
|
|
11
|
+
const MANIFEST = fileURLToPath(new URL("./dist/mountly-mcp.manifest.json", import.meta.url));
|
|
12
|
+
|
|
8
13
|
function sampleCards() {
|
|
9
14
|
return [
|
|
10
15
|
{ label: "Requests", value: Math.floor(1200 + Math.random() * 200) },
|
|
@@ -20,7 +25,7 @@ export default async function createServer() {
|
|
|
20
25
|
{ capabilities: { tools: {}, resources: {} } },
|
|
21
26
|
);
|
|
22
27
|
|
|
23
|
-
const { artifacts } = await readMcpAppManifest(
|
|
28
|
+
const { artifacts } = await readMcpAppManifest(MANIFEST);
|
|
24
29
|
|
|
25
30
|
await registerMcpApps(server, {
|
|
26
31
|
views: artifacts.map((artifact) => ({ artifact })),
|
|
@@ -2,7 +2,7 @@ import { publishMcpView, type McpViewProps } from "mountly-mcp";
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* No framework, no adapter. A View is just `mount` / `update` / `unmount`, so
|
|
5
|
-
* `publishMcpView` takes this object directly
|
|
5
|
+
* `publishMcpView` takes this object directly. The bridge drives it exactly
|
|
6
6
|
* as it drives a React, Vue or Svelte View.
|
|
7
7
|
*/
|
|
8
8
|
|
|
@@ -1,14 +1,37 @@
|
|
|
1
1
|
# {{name}}
|
|
2
2
|
|
|
3
|
-
MCP App scaffolded with `mountly-mcp create
|
|
3
|
+
MCP App scaffolded with `mountly-mcp create` (Vue).
|
|
4
|
+
|
|
5
|
+
## Runbook
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
8
|
pnpm install
|
|
7
9
|
pnpm dev
|
|
8
10
|
pnpm verify
|
|
11
|
+
pnpm verify:render
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
| File | Role |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `src/view.ts` | `createMcpView` entry |
|
|
17
|
+
| `src/Dashboard.vue` | View UI: `useToolResult` |
|
|
18
|
+
| `server.mjs` | `registerMcpApps` factory |
|
|
19
|
+
| `mcp.fixtures.json` | Tool args for `dev --server` |
|
|
20
|
+
|
|
21
|
+
## Open in a real host
|
|
22
|
+
|
|
23
|
+
`serve-stdio.mjs` is included. Point Claude Desktop / VS Code at `node` + absolute path to that file (see the React scaffold README for JSON shapes). ChatGPT: use your connector against the same process.
|
|
24
|
+
|
|
25
|
+
## CI
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm exec mountly-mcp build
|
|
29
|
+
pnpm exec playwright install chromium
|
|
30
|
+
pnpm exec mountly-mcp verify --strict --render
|
|
9
31
|
```
|
|
10
32
|
|
|
11
|
-
|
|
12
|
-
- Server: `server.mjs` (`registerMcpApps`)
|
|
33
|
+
## Add another View
|
|
13
34
|
|
|
14
|
-
|
|
35
|
+
```bash
|
|
36
|
+
pnpm exec mountly-mcp add settings --framework vue
|
|
37
|
+
```
|
|
@@ -8,6 +8,8 @@
|
|
|
8
8
|
"dev": "mountly-mcp dev --server ./server.mjs",
|
|
9
9
|
"verify": "mountly-mcp verify",
|
|
10
10
|
"verify:strict": "mountly-mcp verify --strict",
|
|
11
|
+
"verify:render": "mountly-mcp verify --strict --render",
|
|
12
|
+
"doctor": "mountly-mcp doctor",
|
|
11
13
|
"typecheck": "vue-tsc --noEmit"
|
|
12
14
|
},
|
|
13
15
|
"dependencies": {
|