promptgraph-mcp 2.9.33 → 2.9.34

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/index.js CHANGED
@@ -299,7 +299,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
299
299
  case 'pg_marketplace_install': result = await installSkill(args.skill_id); break;
300
300
  case 'pg_marketplace_publish': result = await publishSkill(args.file_path); break;
301
301
  case 'pg_bundle_browse': result = await browseBundles(args.top_k || 20); break;
302
- case 'pg_bundle_install': result = await installBundle(args.bundle_id); break;
302
+ case 'pg_bundle_install': {
303
+ result = await installBundle(args.bundle_id);
304
+ if (result.toolsInstalled?.length) {
305
+ result.message = `Installed ${result.installed?.length || 0} skills + ${result.toolsInstalled.length} tool files`;
306
+ }
307
+ break;
308
+ }
303
309
  case 'pg_install_url': result = await installSkillFromUrl(args.url); break;
304
310
  case 'pg_bundle_publish': result = await publishBundle(args.bundle); break;
305
311
  case 'pg_config': {
package/marketplace.js CHANGED
@@ -397,26 +397,47 @@ async function _execRepoInstall(bundle) {
397
397
  }
398
398
 
399
399
  async function _execSkillsInstall(bundle, validSkills) {
400
- fs.mkdirSync(getSkillsDir(), { recursive: true });
400
+ const skillsDir = getSkillsDir();
401
+ fs.mkdirSync(skillsDir, { recursive: true });
401
402
  ensureMarketplaceSource();
402
403
  const installed = [];
403
404
  const failed = [];
405
+ const toolsInstalled = [];
404
406
  const delay = (ms) => new Promise(r => setTimeout(r, ms));
407
+
405
408
  for (const skillId of bundle.skills || []) {
406
409
  const skill = validSkills.find(s => s.id === skillId);
407
410
  if (!skill?.raw_url) { failed.push(skillId); continue; }
408
411
  try {
409
412
  if (installed.length > 0) await delay(300);
410
413
  const content = await fetchText(skill.raw_url);
411
- const dest = path.join(getSkillsDir(), `${skillId}.md`);
412
- const resolvedDest = path.resolve(dest);
413
- if (!resolvedDest.startsWith(path.resolve(getSkillsDir()))) { failed.push(skillId); continue; }
414
+ const dest = path.join(skillsDir, `${skillId}.md`);
415
+ if (!path.resolve(dest).startsWith(path.resolve(skillsDir))) { failed.push(skillId); continue; }
414
416
  const v = writeSkillAtomic(dest, content);
415
417
  if (!v.ok) { failed.push(skillId); continue; }
416
418
  installed.push(skillId);
417
419
  } catch { failed.push(skillId); }
418
420
  }
419
- return { success: true, bundle: bundle.name, installed, failed, dir: getSkillsDir() };
421
+
422
+ // Install tool files if bundle has them (scripts, .py, .sh, .js etc)
423
+ for (const tool of bundle.tool_files || []) {
424
+ if (!tool?.raw_url || !tool?.path) continue;
425
+ try {
426
+ await delay(200);
427
+ const content = await fetchText(tool.raw_url);
428
+ const dest = path.join(skillsDir, tool.path);
429
+ if (!path.resolve(dest).startsWith(path.resolve(skillsDir))) continue;
430
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
431
+ fs.writeFileSync(dest, content);
432
+ // Make executable on unix
433
+ if (process.platform !== 'win32') {
434
+ try { fs.chmodSync(dest, 0o755); } catch {}
435
+ }
436
+ toolsInstalled.push(tool.path);
437
+ } catch {}
438
+ }
439
+
440
+ return { success: true, bundle: bundle.name, installed, failed, toolsInstalled, dir: skillsDir, has_tools: bundle.has_tools || false };
420
441
  }
421
442
 
422
443
  export async function installBundle(bundleId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "2.9.33",
3
+ "version": "2.9.34",
4
4
  "files": [
5
5
  "*.js",
6
6
  "commands/",
package/tui.js CHANGED
@@ -50,7 +50,7 @@ function buildItems(skills, bundles) {
50
50
  items.push({ type: 'skill', id: s.id, name: s.name || s.id, description: s.description || '', category: s.category || 'Community', tags: s.tags || [], stars: s.stars || 0, code: s.code, created_at: s.created_at || null });
51
51
  }
52
52
  for (const b of bundles) {
53
- items.push({ type: 'bundle', id: b.id, name: b.name || b.id, description: b.description || '', category: b.category || 'Community', tags: b.tags || [], stars: b.stars || 0, skillCount: b.skillCount, repo_url: b.repo_url, skills: b.skills, created_at: b.created_at || null });
53
+ items.push({ type: 'bundle', id: b.id, name: b.name || b.id, description: b.description || '', category: b.category || 'Community', tags: b.tags || [], stars: b.stars || 0, skillCount: b.skillCount, repo_url: b.repo_url, skills: b.skills, has_tools: b.has_tools || false, created_at: b.created_at || null });
54
54
  }
55
55
  return items;
56
56
  }
@@ -162,12 +162,13 @@ function render(state, installedSet = new Set()) {
162
162
  const namePad = nameStr.padEnd(NAME_W);
163
163
  const nameCol = selected ? white.bold(namePad) : white(namePad);
164
164
  const installed = installedSet.has(item.id) || installedSet.has(item.code);
165
+ const toolsBadge = item.has_tools ? chalk.hex('#F59E0B')(' 🔧') : '';
165
166
  const extra = item.type === 'bundle'
166
167
  ? item.skillCount
167
- ? blue(((installed ? '' : '~') + item.skillCount + ' sk').padEnd(8))
168
+ ? blue(((installed ? '' : '~') + item.skillCount + ' sk').padEnd(8)) + toolsBadge
168
169
  : item.repo_url
169
- ? chalk.hex('#3B82F6')('↗ GitHub')
170
- : dim(((item.skills?.length || 0) + ' sk').padEnd(8))
170
+ ? chalk.hex('#3B82F6')('↗ GitHub') + toolsBadge
171
+ : dim(((item.skills?.length || 0) + ' sk').padEnd(8)) + toolsBadge
171
172
  : chalk.hex('#A78BFA')((item.code || '').padEnd(10));
172
173
  const desc = dim(truncate(item.description, Math.max(10, DESC_W)));
173
174
  const dateStr = item.created_at ? dim(item.created_at.slice(0, 7)) : ' ';