promptgraph-mcp 1.5.15 → 1.5.17

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.
Files changed (3) hide show
  1. package/index.js +66 -1
  2. package/marketplace.js +42 -0
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -8,7 +8,7 @@ import { startWatcher } from './watcher.js';
8
8
  import { promptConfig } from './config.js';
9
9
  import { importFromGitHub } from './github-import.js';
10
10
  import { detectPlatforms, PLATFORMS } from './platform.js';
11
- import { browseMarketplace, installSkill, publishSkill, getTopRated, recordUse, recordSuccess, recordFail } from './marketplace.js';
11
+ import { browseMarketplace, installSkill, publishSkill, getTopRated, recordUse, recordSuccess, recordFail, browseBundles, installBundle } from './marketplace.js';
12
12
 
13
13
  import { colors, banner, success, error, info, section, table } from './cli.js';
14
14
  import boxen from 'boxen';
@@ -83,6 +83,52 @@ if (args[0] === 'doctor') {
83
83
  process.exit(0);
84
84
  }
85
85
 
86
+ if (args[0] === 'marketplace' && (args[1] === 'bundles' || args[1] === 'bundle')) {
87
+ const { browseBundles } = await import('./marketplace.js');
88
+ const purple = chalk.hex('#7C3AED');
89
+ const spin = (await import('./cli.js')).spinner('Fetching bundles...');
90
+ spin.start();
91
+ const bundles = await browseBundles(1000);
92
+ spin.stop();
93
+ console.clear();
94
+
95
+ if (bundles?.error) { error(bundles.error); process.exit(1); }
96
+
97
+ console.log();
98
+ console.log(' ' + purple.bold('PromptGraph Bundles') + chalk.gray(' curated skill sets'));
99
+ console.log(' ' + chalk.gray(`${bundles.length} bundle${bundles.length === 1 ? '' : 's'}`));
100
+ console.log(' ' + chalk.gray('─'.repeat(54)));
101
+ console.log();
102
+
103
+ if (!bundles.length) {
104
+ info('No bundles yet.');
105
+ console.log(chalk.gray(' github.com/NeiP4n/promptgraph-registry\n'));
106
+ process.exit(0);
107
+ }
108
+
109
+ const wrapB = (t, w, ind) => {
110
+ const words = (t || '').split(/\s+/); const lines = []; let line = '';
111
+ for (const x of words) { if ((line + ' ' + x).trim().length > w) { lines.push(line.trim()); line = x; } else line += ' ' + x; }
112
+ if (line.trim()) lines.push(line.trim());
113
+ return lines.map(l => ind + chalk.gray(l)).join('\n');
114
+ };
115
+
116
+ bundles.forEach((b, i) => {
117
+ const stars = b.stars > 0 ? chalk.yellow('★ ' + b.stars) : chalk.gray('★ 0');
118
+ console.log(' ' + chalk.gray((i + 1) + '.') + ' ' + chalk.white.bold(b.id) + ' ' + stars + chalk.gray(' ' + (b.skills?.length || 0) + ' skills'));
119
+ console.log(wrapB(b.description, 64, ' '));
120
+ console.log(' ' + chalk.gray('includes: ') + chalk.gray((b.skills || []).join(', ')));
121
+ if (b.tags?.length) console.log(' ' + purple(b.tags.map(t => '#' + t).join(' ')));
122
+ console.log(' ' + chalk.gray('install: ') + chalk.cyan(`pg_bundle_install("${b.id}")`));
123
+ console.log();
124
+ });
125
+
126
+ console.log(' ' + chalk.gray('─'.repeat(54)));
127
+ console.log(' ' + chalk.gray('Installs all skills in the set. Run ') + chalk.cyan(`${bin} marketplace`) + chalk.gray(' for single skills.'));
128
+ console.log();
129
+ process.exit(0);
130
+ }
131
+
86
132
  if (args[0] === 'marketplace') {
87
133
  const { browseMarketplace } = await import('./marketplace.js');
88
134
  const PER_PAGE = 10;
@@ -92,6 +138,7 @@ if (args[0] === 'marketplace') {
92
138
  spin.start();
93
139
  const all = await browseMarketplace(1000);
94
140
  spin.stop();
141
+ console.clear();
95
142
 
96
143
  if (all?.error) {
97
144
  error(all.error);
@@ -150,6 +197,8 @@ if (args[0] === 'marketplace') {
150
197
  console.log(' ' + chalk.cyan('pg_marketplace_publish') + chalk.gray(' share your own ') + chalk.gray('(or /pg-publish <file>)'));
151
198
  console.log(' ' + chalk.cyan('pg_search') + chalk.gray(' find & apply any installed skill'));
152
199
  console.log();
200
+ console.log(' ' + chalk.gray('Browse curated sets: ') + chalk.cyan(`${bin} marketplace bundles`));
201
+ console.log();
153
202
  process.exit(0);
154
203
  }
155
204
 
@@ -315,6 +364,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
315
364
  required: ['file_path'],
316
365
  },
317
366
  },
367
+ {
368
+ name: 'pg_bundle_browse',
369
+ description: 'Browse curated bundles (sets of related skills) from the marketplace.',
370
+ inputSchema: { type: 'object', properties: { top_k: { type: 'number' } } },
371
+ },
372
+ {
373
+ name: 'pg_bundle_install',
374
+ description: 'Install all skills in a bundle by bundle id.',
375
+ inputSchema: {
376
+ type: 'object',
377
+ properties: { bundle_id: { type: 'string' } },
378
+ required: ['bundle_id'],
379
+ },
380
+ },
318
381
  ],
319
382
  }));
320
383
 
@@ -340,6 +403,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
340
403
  case 'pg_marketplace_browse': result = await browseMarketplace(args.top_k || 20); break;
341
404
  case 'pg_marketplace_install': result = await installSkill(args.skill_id); break;
342
405
  case 'pg_marketplace_publish': result = await publishSkill(args.file_path); break;
406
+ case 'pg_bundle_browse': result = await browseBundles(args.top_k || 20); break;
407
+ case 'pg_bundle_install': result = await installBundle(args.bundle_id); break;
343
408
  default: throw new Error(`Unknown tool: ${name}`);
344
409
  }
345
410
  return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
package/marketplace.js CHANGED
@@ -71,6 +71,48 @@ export async function installSkill(skillId) {
71
71
  }
72
72
  }
73
73
 
74
+ export async function browseBundles(topK = 20) {
75
+ try {
76
+ const text = await fetchText(REGISTRY_URL);
77
+ const registry = JSON.parse(text);
78
+ const bundles = registry.bundles || [];
79
+ return bundles
80
+ .sort((a, b) => (b.stars || 0) - (a.stars || 0))
81
+ .slice(0, topK);
82
+ } catch (e) {
83
+ return { error: `Registry unavailable: ${e.message}` };
84
+ }
85
+ }
86
+
87
+ export async function installBundle(bundleId) {
88
+ try {
89
+ const text = await fetchText(REGISTRY_URL);
90
+ const registry = JSON.parse(text);
91
+ const bundle = (registry.bundles || []).find(b => b.id === bundleId);
92
+ if (!bundle) return { error: `Bundle "${bundleId}" not found in registry` };
93
+
94
+ fs.mkdirSync(SKILLS_DIR, { recursive: true });
95
+ const installed = [];
96
+ const failed = [];
97
+
98
+ for (const skillId of bundle.skills || []) {
99
+ const skill = registry.skills?.find(s => s.id === skillId);
100
+ if (!skill?.raw_url) { failed.push(skillId); continue; }
101
+ try {
102
+ const content = await fetchText(skill.raw_url);
103
+ fs.writeFileSync(path.join(SKILLS_DIR, `${skillId}.md`), content);
104
+ installed.push(skillId);
105
+ } catch {
106
+ failed.push(skillId);
107
+ }
108
+ }
109
+
110
+ return { success: true, bundle: bundle.name, installed, failed, dir: SKILLS_DIR };
111
+ } catch (e) {
112
+ return { error: e.message };
113
+ }
114
+ }
115
+
74
116
  export async function publishSkill(filePath) {
75
117
  if (!fs.existsSync(filePath)) return { error: `File not found: ${filePath}` };
76
118
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "promptgraph-mcp",
3
- "version": "1.5.15",
3
+ "version": "1.5.17",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {