promptgraph-mcp 1.5.15 → 1.5.16

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 +64 -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,51 @@ 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
+
94
+ if (bundles?.error) { error(bundles.error); process.exit(1); }
95
+
96
+ console.log();
97
+ console.log(' ' + purple.bold('PromptGraph Bundles') + chalk.gray(' curated skill sets'));
98
+ console.log(' ' + chalk.gray(`${bundles.length} bundle${bundles.length === 1 ? '' : 's'}`));
99
+ console.log(' ' + chalk.gray('─'.repeat(54)));
100
+ console.log();
101
+
102
+ if (!bundles.length) {
103
+ info('No bundles yet.');
104
+ console.log(chalk.gray(' github.com/NeiP4n/promptgraph-registry\n'));
105
+ process.exit(0);
106
+ }
107
+
108
+ const wrapB = (t, w, ind) => {
109
+ const words = (t || '').split(/\s+/); const lines = []; let line = '';
110
+ for (const x of words) { if ((line + ' ' + x).trim().length > w) { lines.push(line.trim()); line = x; } else line += ' ' + x; }
111
+ if (line.trim()) lines.push(line.trim());
112
+ return lines.map(l => ind + chalk.gray(l)).join('\n');
113
+ };
114
+
115
+ bundles.forEach((b, i) => {
116
+ const stars = b.stars > 0 ? chalk.yellow('★ ' + b.stars) : chalk.gray('★ 0');
117
+ console.log(' ' + chalk.gray((i + 1) + '.') + ' ' + chalk.white.bold(b.id) + ' ' + stars + chalk.gray(' ' + (b.skills?.length || 0) + ' skills'));
118
+ console.log(wrapB(b.description, 64, ' '));
119
+ console.log(' ' + chalk.gray('includes: ') + chalk.gray((b.skills || []).join(', ')));
120
+ if (b.tags?.length) console.log(' ' + purple(b.tags.map(t => '#' + t).join(' ')));
121
+ console.log(' ' + chalk.gray('install: ') + chalk.cyan(`pg_bundle_install("${b.id}")`));
122
+ console.log();
123
+ });
124
+
125
+ console.log(' ' + chalk.gray('─'.repeat(54)));
126
+ console.log(' ' + chalk.gray('Installs all skills in the set. Run ') + chalk.cyan(`${bin} marketplace`) + chalk.gray(' for single skills.'));
127
+ console.log();
128
+ process.exit(0);
129
+ }
130
+
86
131
  if (args[0] === 'marketplace') {
87
132
  const { browseMarketplace } = await import('./marketplace.js');
88
133
  const PER_PAGE = 10;
@@ -150,6 +195,8 @@ if (args[0] === 'marketplace') {
150
195
  console.log(' ' + chalk.cyan('pg_marketplace_publish') + chalk.gray(' share your own ') + chalk.gray('(or /pg-publish <file>)'));
151
196
  console.log(' ' + chalk.cyan('pg_search') + chalk.gray(' find & apply any installed skill'));
152
197
  console.log();
198
+ console.log(' ' + chalk.gray('Browse curated sets: ') + chalk.cyan(`${bin} marketplace bundles`));
199
+ console.log();
153
200
  process.exit(0);
154
201
  }
155
202
 
@@ -315,6 +362,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
315
362
  required: ['file_path'],
316
363
  },
317
364
  },
365
+ {
366
+ name: 'pg_bundle_browse',
367
+ description: 'Browse curated bundles (sets of related skills) from the marketplace.',
368
+ inputSchema: { type: 'object', properties: { top_k: { type: 'number' } } },
369
+ },
370
+ {
371
+ name: 'pg_bundle_install',
372
+ description: 'Install all skills in a bundle by bundle id.',
373
+ inputSchema: {
374
+ type: 'object',
375
+ properties: { bundle_id: { type: 'string' } },
376
+ required: ['bundle_id'],
377
+ },
378
+ },
318
379
  ],
319
380
  }));
320
381
 
@@ -340,6 +401,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
340
401
  case 'pg_marketplace_browse': result = await browseMarketplace(args.top_k || 20); break;
341
402
  case 'pg_marketplace_install': result = await installSkill(args.skill_id); break;
342
403
  case 'pg_marketplace_publish': result = await publishSkill(args.file_path); break;
404
+ case 'pg_bundle_browse': result = await browseBundles(args.top_k || 20); break;
405
+ case 'pg_bundle_install': result = await installBundle(args.bundle_id); break;
343
406
  default: throw new Error(`Unknown tool: ${name}`);
344
407
  }
345
408
  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.16",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {