viewgate-mcp 1.0.39 → 1.0.41
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/dist/index.js +70 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -249,12 +249,79 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
249
249
|
out.required = uniq(out.required);
|
|
250
250
|
return out;
|
|
251
251
|
};
|
|
252
|
-
const
|
|
252
|
+
const readJsonIfExists = async (p) => {
|
|
253
|
+
try {
|
|
254
|
+
const txt = await fsp.readFile(p, 'utf8');
|
|
255
|
+
return JSON.parse(txt);
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
const looksLikeFrontendPackageJson = (pkg) => {
|
|
262
|
+
const deps = { ...(pkg?.dependencies || {}), ...(pkg?.devDependencies || {}) };
|
|
263
|
+
const hasReact = typeof deps.react === 'string';
|
|
264
|
+
const hasViteOrNext = typeof deps.vite === 'string' || typeof deps.next === 'string';
|
|
265
|
+
return hasReact && hasViteOrNext;
|
|
266
|
+
};
|
|
267
|
+
const listSubdirs = async (dir) => {
|
|
268
|
+
try {
|
|
269
|
+
const entries = await fsp.readdir(dir, { withFileTypes: true });
|
|
270
|
+
return entries.filter((e) => e.isDirectory()).map((e) => path.join(dir, e.name));
|
|
271
|
+
}
|
|
272
|
+
catch {
|
|
273
|
+
return [];
|
|
274
|
+
}
|
|
275
|
+
};
|
|
276
|
+
const findFrontendRoot = async () => {
|
|
277
|
+
// In many MCP clients, INIT_CWD points to the directory where `npx viewgate-mcp` was launched.
|
|
278
|
+
const baseDir = process.env.VIEWGATE_WORKSPACE || process.env.INIT_CWD || process.cwd();
|
|
279
|
+
// Scan baseDir and one level deep for candidate frontends.
|
|
280
|
+
const candidates = [baseDir, ...(await listSubdirs(baseDir))];
|
|
281
|
+
const hits = [];
|
|
282
|
+
for (const c of candidates) {
|
|
283
|
+
const pkg = await readJsonIfExists(path.join(c, 'package.json'));
|
|
284
|
+
if (pkg && looksLikeFrontendPackageJson(pkg))
|
|
285
|
+
hits.push(c);
|
|
286
|
+
}
|
|
287
|
+
if (hits.length === 0)
|
|
288
|
+
return null;
|
|
289
|
+
if (hits.length === 1)
|
|
290
|
+
return hits[0];
|
|
291
|
+
// Prefer common names when multiple projects exist.
|
|
292
|
+
const preferred = hits.find((h) => {
|
|
293
|
+
const name = path.basename(h).toLowerCase();
|
|
294
|
+
return name === 'dashboard' || name === 'view-gate-dashboard' || name.includes('dashboard');
|
|
295
|
+
});
|
|
296
|
+
return preferred || hits[0];
|
|
297
|
+
};
|
|
298
|
+
const resolveComponentsDir = async () => {
|
|
299
|
+
const frontendRoot = await findFrontendRoot();
|
|
253
300
|
const cwd = process.cwd();
|
|
254
|
-
|
|
301
|
+
// Order matters: prefer src/components for SPA projects like Vite.
|
|
302
|
+
const rootsToTry = [
|
|
303
|
+
...(frontendRoot ? [frontendRoot] : []),
|
|
304
|
+
cwd,
|
|
305
|
+
];
|
|
306
|
+
for (const root of rootsToTry) {
|
|
307
|
+
const c1 = path.join(root, 'src', 'components');
|
|
308
|
+
if (fs.existsSync(c1))
|
|
309
|
+
return c1;
|
|
310
|
+
const c2 = path.join(root, 'components');
|
|
311
|
+
if (fs.existsSync(c2))
|
|
312
|
+
return c2;
|
|
313
|
+
}
|
|
314
|
+
// Fallback: create in src/components under detected frontendRoot if present.
|
|
315
|
+
if (frontendRoot)
|
|
316
|
+
return path.join(frontendRoot, 'src', 'components');
|
|
317
|
+
return path.join(cwd, 'components');
|
|
318
|
+
};
|
|
319
|
+
const writeComponentFile = async (componentType, model) => {
|
|
320
|
+
const componentsDir = await resolveComponentsDir();
|
|
255
321
|
await fsp.mkdir(componentsDir, { recursive: true });
|
|
256
322
|
const baseName = toPascalCase(componentType) || 'Component';
|
|
257
|
-
const
|
|
323
|
+
const projectRoot = path.dirname(componentsDir);
|
|
324
|
+
const hasTs = fs.existsSync(path.join(projectRoot, 'tsconfig.json'));
|
|
258
325
|
const ext = hasTs ? 'tsx' : 'jsx';
|
|
259
326
|
const fileBase = `${baseName}.${ext}`;
|
|
260
327
|
let filePath = path.join(componentsDir, fileBase);
|