promptgraph-mcp 1.5.14 → 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 +73 -5
  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;
@@ -123,7 +168,7 @@ if (args[0] === 'marketplace') {
123
168
  console.log();
124
169
  console.log(' ' + purple.bold('PromptGraph Marketplace'));
125
170
  console.log(' ' + chalk.gray(`${all.length} skill${all.length === 1 ? '' : 's'} · page ${page}/${totalPages}`));
126
- console.log(' ' + chalk.gray('─'.repeat(50)));
171
+ console.log(' ' + chalk.gray('─'.repeat(54)));
127
172
  console.log();
128
173
 
129
174
  slice.forEach((s, i) => {
@@ -132,18 +177,25 @@ if (args[0] === 'marketplace') {
132
177
  console.log(' ' + num + ' ' + chalk.white.bold(s.id) + ' ' + stars);
133
178
  console.log(wrap(s.description, 64, ' '));
134
179
  if (s.tags?.length) console.log(' ' + purple(s.tags.map(t => '#' + t).join(' ')));
135
- console.log(' ' + chalk.gray('install: ') + chalk.cyan(`/pg-fetch ${s.id}`));
180
+ console.log(' ' + chalk.gray('install: ') + chalk.cyan(`pg_marketplace_install("${s.id}")`));
181
+ console.log(' ' + chalk.gray('use: ') + chalk.cyan(`pg_search("${s.id}")`) + chalk.gray(' → read the file'));
136
182
  console.log();
137
183
  });
138
184
 
139
- console.log(' ' + chalk.gray('─'.repeat(50)));
185
+ console.log(' ' + chalk.gray('─'.repeat(54)));
140
186
  if (totalPages > 1) {
141
187
  const nav = [];
142
188
  if (page > 1) nav.push(chalk.cyan(`${bin} marketplace ${page - 1}`) + chalk.gray(' ‹ prev'));
143
189
  if (page < totalPages) nav.push(chalk.gray('next › ') + chalk.cyan(`${bin} marketplace ${page + 1}`));
144
190
  console.log(' ' + nav.join(' '));
191
+ console.log();
145
192
  }
146
- console.log(' ' + chalk.gray('publish a skill: ') + chalk.cyan('/pg-publish <file.md>') + chalk.gray(' (via your AI assistant)'));
193
+ console.log(' ' + chalk.gray('These run through your AI assistant via the PromptGraph MCP server:'));
194
+ console.log(' ' + chalk.cyan('pg_marketplace_install') + chalk.gray(' install a skill ') + chalk.gray('(or /pg-fetch <id>)'));
195
+ console.log(' ' + chalk.cyan('pg_marketplace_publish') + chalk.gray(' share your own ') + chalk.gray('(or /pg-publish <file>)'));
196
+ console.log(' ' + chalk.cyan('pg_search') + chalk.gray(' find & apply any installed skill'));
197
+ console.log();
198
+ console.log(' ' + chalk.gray('Browse curated sets: ') + chalk.cyan(`${bin} marketplace bundles`));
147
199
  console.log();
148
200
  process.exit(0);
149
201
  }
@@ -310,6 +362,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
310
362
  required: ['file_path'],
311
363
  },
312
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
+ },
313
379
  ],
314
380
  }));
315
381
 
@@ -335,6 +401,8 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
335
401
  case 'pg_marketplace_browse': result = await browseMarketplace(args.top_k || 20); break;
336
402
  case 'pg_marketplace_install': result = await installSkill(args.skill_id); break;
337
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;
338
406
  default: throw new Error(`Unknown tool: ${name}`);
339
407
  }
340
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.14",
3
+ "version": "1.5.16",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "bin": {