@promptingbox/mcp 0.2.0 → 0.3.0

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/README.md +73 -6
  2. package/dist/index.js +120 -61
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @promptingbox/mcp
2
2
 
3
- MCP (Model Context Protocol) server for [PromptingBox](https://www.promptingbox.com) — save prompts directly from Claude, Cursor, ChatGPT, and other MCP-compatible AI tools.
3
+ MCP (Model Context Protocol) server for [PromptingBox](https://www.promptingbox.com) — save, manage, and organize prompts directly from Claude, Cursor, ChatGPT, and other MCP-compatible AI tools.
4
4
 
5
5
  ## Setup
6
6
 
@@ -77,22 +77,89 @@ Restart Claude Desktop or Cursor for the MCP server to be detected.
77
77
 
78
78
  Once configured, you can say things like:
79
79
 
80
+ **Saving & retrieving prompts:**
80
81
  - "Save this prompt to pbox"
81
82
  - "Save this as 'Code Review Checklist' in my Work folder on pbox"
83
+ - "Get my prompt called 'Code Review'"
84
+ - "Search my pbox prompts for API"
82
85
  - "List my pbox prompts"
86
+
87
+ **Editing & managing prompts:**
88
+ - "Update the content of 'Code Review'"
89
+ - "Delete the prompt called 'Old Draft'"
90
+ - "Duplicate 'Code Review'"
91
+ - "Star my 'Code Review' prompt"
92
+
93
+ **Folders & tags:**
94
+ - "Create a folder called 'Work'"
95
+ - "Move 'Code Review' to my Work folder"
96
+ - "Delete my 'Old' folder"
97
+ - "Tag 'Code Review' with testing and automation"
83
98
  - "List my pbox folders"
84
99
  - "List my pbox tags"
85
- - "Move prompt [id] to my Work folder on pbox"
100
+
101
+ **Version history:**
102
+ - "Show version history for 'Code Review'"
103
+ - "Restore version 2 of 'Code Review'"
104
+
105
+ **Templates:**
106
+ - "Search pbox templates for email"
107
+ - "Save that template to my collection"
108
+
109
+ **Account:**
110
+ - "Which pbox account am I using?"
86
111
 
87
112
  ## Available Tools
88
113
 
114
+ ### Prompt Management
115
+
89
116
  | Tool | Description |
90
117
  |------|-------------|
91
118
  | `save_prompt` | Save a prompt with title, content, optional folder and tags |
92
- | `list_prompts` | List all your prompts with their current folder assignment |
93
- | `list_folders` | List your PromptingBox folders |
94
- | `list_tags` | List your PromptingBox tags |
95
- | `move_prompt_to_folder` | Move an existing prompt to a different folder by prompt ID |
119
+ | `get_prompt` | Get the full content and metadata of a prompt |
120
+ | `search_prompts` | Search prompts by title, content, tag, folder, or favorites |
121
+ | `update_prompt` | Update a prompt's title and/or content (auto-versions) |
122
+ | `delete_prompt` | Permanently delete a prompt and all its versions |
123
+ | `duplicate_prompt` | Create a copy of an existing prompt |
124
+ | `toggle_favorite` | Star or unstar a prompt |
125
+ | `list_prompts` | List all prompts grouped by folder |
126
+
127
+ ### Folder Management
128
+
129
+ | Tool | Description |
130
+ |------|-------------|
131
+ | `list_folders` | List all folders in your account |
132
+ | `create_folder` | Create a new folder (or return existing one) |
133
+ | `delete_folder` | Delete a folder (prompts move to root, not deleted) |
134
+ | `move_prompt_to_folder` | Move a prompt to a different folder |
135
+
136
+ ### Tag Management
137
+
138
+ | Tool | Description |
139
+ |------|-------------|
140
+ | `list_tags` | List all tags in your account |
141
+ | `add_tags` | Set tags on a prompt (replaces existing, auto-creates new tags) |
142
+ | `delete_tag` | Delete a tag from your account and all prompts |
143
+
144
+ ### Version History
145
+
146
+ | Tool | Description |
147
+ |------|-------------|
148
+ | `list_versions` | View all saved versions of a prompt |
149
+ | `restore_version` | Restore a prompt to a previous version |
150
+
151
+ ### Templates
152
+
153
+ | Tool | Description |
154
+ |------|-------------|
155
+ | `search_templates` | Browse and search the public template library |
156
+ | `use_template` | Save a public template to your collection |
157
+
158
+ ### Account
159
+
160
+ | Tool | Description |
161
+ |------|-------------|
162
+ | `whoami` | Show which PromptingBox account is connected |
96
163
 
97
164
  ## Environment Variables
98
165
 
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ if (!API_KEY) {
11
11
  process.exit(1);
12
12
  }
13
13
  const client = new PromptingBoxClient({ apiKey: API_KEY, baseUrl: BASE_URL });
14
+ const CURRENT_VERSION = '0.3.0';
14
15
  // Cache account info so we can surface it in every response
15
16
  let accountEmail = null;
16
17
  async function getAccountLabel() {
@@ -25,6 +26,60 @@ async function getAccountLabel() {
25
26
  return 'unknown (could not verify)';
26
27
  }
27
28
  }
29
+ // ── Version update check (once per process lifetime) ─────────────────────────
30
+ let updateNotice = null;
31
+ let updateChecked = false;
32
+ function isNewer(latest, current) {
33
+ const l = latest.split('.').map(Number);
34
+ const c = current.split('.').map(Number);
35
+ for (let i = 0; i < 3; i++) {
36
+ if ((l[i] ?? 0) > (c[i] ?? 0))
37
+ return true;
38
+ if ((l[i] ?? 0) < (c[i] ?? 0))
39
+ return false;
40
+ }
41
+ return false;
42
+ }
43
+ async function checkForUpdate() {
44
+ if (updateChecked)
45
+ return updateNotice;
46
+ updateChecked = true;
47
+ try {
48
+ const versionUrl = `${BASE_URL || 'https://www.promptingbox.com'}/api/mcp/version`;
49
+ const res = await fetch(versionUrl);
50
+ if (!res.ok)
51
+ return null;
52
+ const data = await res.json();
53
+ const latest = data.mcp;
54
+ if (!latest)
55
+ return null;
56
+ if (isNewer(latest, CURRENT_VERSION)) {
57
+ updateNotice = [
58
+ ``,
59
+ `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
60
+ ` New version available: v${CURRENT_VERSION} → v${latest}`,
61
+ ` Run: npm install -g @promptingbox/mcp`,
62
+ ` Changelog: https://www.promptingbox.com/docs/mcp`,
63
+ `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`,
64
+ ].join('\n');
65
+ }
66
+ return updateNotice;
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ }
72
+ /** Combined response suffix: account label + update notice (if available) */
73
+ async function getResponseSuffix() {
74
+ const [email, update] = await Promise.all([
75
+ getAccountLabel(),
76
+ checkForUpdate(),
77
+ ]);
78
+ let suffix = `🔑 Account: ${email}`;
79
+ if (update)
80
+ suffix += `\n${update}`;
81
+ return suffix;
82
+ }
28
83
  /** Resolve promptId from either explicit ID or title search */
29
84
  async function resolvePromptId(promptId, promptTitle) {
30
85
  if (promptId)
@@ -47,7 +102,7 @@ function errorResult(message) {
47
102
  }
48
103
  const server = new McpServer({
49
104
  name: 'promptingbox',
50
- version: '0.2.0',
105
+ version: CURRENT_VERSION,
51
106
  });
52
107
  const baseUrl = BASE_URL ?? 'https://www.promptingbox.com';
53
108
  // ── save_prompt ──────────────────────────────────────────────────────────────
@@ -58,9 +113,9 @@ server.tool('save_prompt', 'Save a prompt to the user\'s PromptingBox account. U
58
113
  tagNames: z.array(z.string()).optional().describe('Tag names to apply (created if they don\'t exist)'),
59
114
  }, async ({ title, content, folder, tagNames }) => {
60
115
  try {
61
- const [result, email] = await Promise.all([
116
+ const [result, suffix] = await Promise.all([
62
117
  client.savePrompt({ title, content, folder, tagNames }),
63
- getAccountLabel(),
118
+ getResponseSuffix(),
64
119
  ]);
65
120
  return {
66
121
  content: [
@@ -68,7 +123,7 @@ server.tool('save_prompt', 'Save a prompt to the user\'s PromptingBox account. U
68
123
  type: 'text',
69
124
  text: `Prompt saved to PromptingBox!\n\nTitle: ${result.title}\nID: ${result.id}\nURL: ${result.url}` +
70
125
  (result.folderId ? `\nFolder: ${folder}` : '') +
71
- `\n\n🔑 Account: ${email}`,
126
+ `\n\n${suffix}`,
72
127
  },
73
128
  ],
74
129
  };
@@ -87,9 +142,9 @@ server.tool('get_prompt', 'Get the full content of a single prompt from Promptin
87
142
  const resolved = await resolvePromptId(promptId, promptTitle);
88
143
  if ('error' in resolved)
89
144
  return errorResult(resolved.error);
90
- const [prompt, email] = await Promise.all([
145
+ const [prompt, suffix] = await Promise.all([
91
146
  client.getPrompt(resolved.id),
92
- getAccountLabel(),
147
+ getResponseSuffix(),
93
148
  ]);
94
149
  const tagList = prompt.tags.length > 0
95
150
  ? `Tags: ${prompt.tags.map((t) => t.name).join(', ')}`
@@ -102,7 +157,7 @@ server.tool('get_prompt', 'Get the full content of a single prompt from Promptin
102
157
  `${tagList}\n` +
103
158
  `Favorite: ${prompt.isFavorite ? 'Yes' : 'No'}\n` +
104
159
  `URL: ${baseUrl}/workspace/prompt/${prompt.id}\n\n` +
105
- `---\n\n${prompt.content}\n\n🔑 Account: ${email}`,
160
+ `---\n\n${prompt.content}\n\n${suffix}`,
106
161
  }],
107
162
  };
108
163
  }
@@ -119,20 +174,20 @@ server.tool('search_prompts', 'Search prompts in PromptingBox by title, content,
119
174
  favorites: z.boolean().optional().describe('Set to true to only show favorited prompts'),
120
175
  }, async ({ query, tag, folder, favorites }) => {
121
176
  try {
122
- const [results, email] = await Promise.all([
177
+ const [results, suffix] = await Promise.all([
123
178
  client.searchPrompts({ search: query, tag, folder, favorites }),
124
- getAccountLabel(),
179
+ getResponseSuffix(),
125
180
  ]);
126
181
  if (results.length === 0) {
127
182
  return {
128
- content: [{ type: 'text', text: `No prompts found matching your search.\n\n🔑 Account: ${email}` }],
183
+ content: [{ type: 'text', text: `No prompts found matching your search.\n\n${suffix}` }],
129
184
  };
130
185
  }
131
186
  const lines = results.map((p) => `- ${p.isFavorite ? '⭐ ' : ''}${p.title} (id: \`${p.id}\`)${p.folderName ? ` — 📁 ${p.folderName}` : ''}`);
132
187
  return {
133
188
  content: [{
134
189
  type: 'text',
135
- text: `Found ${results.length} prompt${results.length === 1 ? '' : 's'}:\n\n${lines.join('\n')}\n\n🔑 Account: ${email}`,
190
+ text: `Found ${results.length} prompt${results.length === 1 ? '' : 's'}:\n\n${lines.join('\n')}\n\n${suffix}`,
136
191
  }],
137
192
  };
138
193
  }
@@ -154,16 +209,16 @@ server.tool('update_prompt', 'Update the title and/or content of an existing pro
154
209
  const resolved = await resolvePromptId(promptId, promptTitle);
155
210
  if ('error' in resolved)
156
211
  return errorResult(resolved.error);
157
- const [result, email] = await Promise.all([
212
+ const [result, suffix] = await Promise.all([
158
213
  client.updatePrompt(resolved.id, { title, content }),
159
- getAccountLabel(),
214
+ getResponseSuffix(),
160
215
  ]);
161
216
  let text = `Prompt updated successfully!\nID: ${result.id}`;
162
217
  if (result.versionCreated) {
163
218
  text += `\nNew version created: v${result.newVersionNumber}`;
164
219
  }
165
220
  text += `\nURL: ${baseUrl}/workspace/prompt/${result.id}`;
166
- text += `\n\n🔑 Account: ${email}`;
221
+ text += `\n\n${suffix}`;
167
222
  return { content: [{ type: 'text', text }] };
168
223
  }
169
224
  catch (err) {
@@ -181,9 +236,9 @@ server.tool('delete_prompt', 'Permanently delete a prompt from PromptingBox. Thi
181
236
  if ('error' in resolved)
182
237
  return errorResult(resolved.error);
183
238
  await client.deletePrompt(resolved.id);
184
- const email = await getAccountLabel();
239
+ const suffix = await getResponseSuffix();
185
240
  return {
186
- content: [{ type: 'text', text: `Prompt deleted successfully.\n\n🔑 Account: ${email}` }],
241
+ content: [{ type: 'text', text: `Prompt deleted successfully.\n\n${suffix}` }],
187
242
  };
188
243
  }
189
244
  catch (err) {
@@ -200,14 +255,14 @@ server.tool('duplicate_prompt', 'Create a copy of an existing prompt. The copy g
200
255
  const resolved = await resolvePromptId(promptId, promptTitle);
201
256
  if ('error' in resolved)
202
257
  return errorResult(resolved.error);
203
- const [result, email] = await Promise.all([
258
+ const [result, suffix] = await Promise.all([
204
259
  client.duplicatePrompt(resolved.id),
205
- getAccountLabel(),
260
+ getResponseSuffix(),
206
261
  ]);
207
262
  return {
208
263
  content: [{
209
264
  type: 'text',
210
- text: `Prompt duplicated!\n\nTitle: ${result.title}\nID: ${result.id}\nURL: ${result.url}\n\n🔑 Account: ${email}`,
265
+ text: `Prompt duplicated!\n\nTitle: ${result.title}\nID: ${result.id}\nURL: ${result.url}\n\n${suffix}`,
211
266
  }],
212
267
  };
213
268
  }
@@ -227,10 +282,10 @@ server.tool('toggle_favorite', 'Star or unstar a prompt in PromptingBox.', {
227
282
  if ('error' in resolved)
228
283
  return errorResult(resolved.error);
229
284
  await client.toggleFavorite(resolved.id, isFavorite);
230
- const email = await getAccountLabel();
285
+ const suffix = await getResponseSuffix();
231
286
  const action = isFavorite ? 'favorited ⭐' : 'unfavorited';
232
287
  return {
233
- content: [{ type: 'text', text: `Prompt ${action}.\n\n🔑 Account: ${email}` }],
288
+ content: [{ type: 'text', text: `Prompt ${action}.\n\n${suffix}` }],
234
289
  };
235
290
  }
236
291
  catch (err) {
@@ -248,15 +303,15 @@ server.tool('add_tags', 'Set tags on a prompt (by tag name). This replaces all e
248
303
  const resolved = await resolvePromptId(promptId, promptTitle);
249
304
  if ('error' in resolved)
250
305
  return errorResult(resolved.error);
251
- const [result, email] = await Promise.all([
306
+ const [result, suffix] = await Promise.all([
252
307
  client.updatePromptTags(resolved.id, tagNames),
253
- getAccountLabel(),
308
+ getResponseSuffix(),
254
309
  ]);
255
310
  const tagList = result.tags.map((t) => t.name).join(', ');
256
311
  return {
257
312
  content: [{
258
313
  type: 'text',
259
- text: `Tags updated: ${tagList || '(no tags)'}.\n\n🔑 Account: ${email}`,
314
+ text: `Tags updated: ${tagList || '(no tags)'}.\n\n${suffix}`,
260
315
  }],
261
316
  };
262
317
  }
@@ -282,12 +337,12 @@ server.tool('delete_tag', 'Delete a tag entirely from PromptingBox. Removes it f
282
337
  return errorResult(`No tag found matching "${tagName}".`);
283
338
  resolvedId = matches[0].id;
284
339
  }
285
- const [result, email] = await Promise.all([
340
+ const [result, suffix] = await Promise.all([
286
341
  client.deleteTag(resolvedId),
287
- getAccountLabel(),
342
+ getResponseSuffix(),
288
343
  ]);
289
344
  return {
290
- content: [{ type: 'text', text: `Tag "${result.tagName}" deleted.\n\n🔑 Account: ${email}` }],
345
+ content: [{ type: 'text', text: `Tag "${result.tagName}" deleted.\n\n${suffix}` }],
291
346
  };
292
347
  }
293
348
  catch (err) {
@@ -300,15 +355,15 @@ server.tool('create_folder', 'Create a new folder in PromptingBox. If a folder w
300
355
  name: z.string().describe('The folder name to create'),
301
356
  }, async ({ name }) => {
302
357
  try {
303
- const [result, email] = await Promise.all([
358
+ const [result, suffix] = await Promise.all([
304
359
  client.createFolder(name),
305
- getAccountLabel(),
360
+ getResponseSuffix(),
306
361
  ]);
307
362
  const status = result.alreadyExisted ? 'already exists' : 'created';
308
363
  return {
309
364
  content: [{
310
365
  type: 'text',
311
- text: `Folder "${result.name}" ${status}.\nID: ${result.id}\n\n🔑 Account: ${email}`,
366
+ text: `Folder "${result.name}" ${status}.\nID: ${result.id}\n\n${suffix}`,
312
367
  }],
313
368
  };
314
369
  }
@@ -334,14 +389,14 @@ server.tool('delete_folder', 'Delete a folder from PromptingBox. Prompts in the
334
389
  return errorResult(`No folder found matching "${folderName}".`);
335
390
  resolvedId = matches[0].id;
336
391
  }
337
- const [result, email] = await Promise.all([
392
+ const [result, suffix] = await Promise.all([
338
393
  client.deleteFolder(resolvedId),
339
- getAccountLabel(),
394
+ getResponseSuffix(),
340
395
  ]);
341
396
  return {
342
397
  content: [{
343
398
  type: 'text',
344
- text: `Folder "${result.folderName}" deleted. Prompts moved to root.\n\n🔑 Account: ${email}`,
399
+ text: `Folder "${result.folderName}" deleted. Prompts moved to root.\n\n${suffix}`,
345
400
  }],
346
401
  };
347
402
  }
@@ -359,20 +414,20 @@ server.tool('list_versions', 'Get the version history for a prompt. Shows all sa
359
414
  const resolved = await resolvePromptId(promptId, promptTitle);
360
415
  if ('error' in resolved)
361
416
  return errorResult(resolved.error);
362
- const [versions, email] = await Promise.all([
417
+ const [versions, suffix] = await Promise.all([
363
418
  client.listVersions(resolved.id),
364
- getAccountLabel(),
419
+ getResponseSuffix(),
365
420
  ]);
366
421
  if (versions.length === 0) {
367
422
  return {
368
- content: [{ type: 'text', text: `No versions found.\n\n🔑 Account: ${email}` }],
423
+ content: [{ type: 'text', text: `No versions found.\n\n${suffix}` }],
369
424
  };
370
425
  }
371
426
  const lines = versions.map((v) => `- **v${v.versionNumber}** — ${v.versionNote ?? 'No note'} (${new Date(v.createdAt).toLocaleDateString()})`);
372
427
  return {
373
428
  content: [{
374
429
  type: 'text',
375
- text: `Version history (${versions.length} version${versions.length === 1 ? '' : 's'}):\n\n${lines.join('\n')}\n\n🔑 Account: ${email}`,
430
+ text: `Version history (${versions.length} version${versions.length === 1 ? '' : 's'}):\n\n${lines.join('\n')}\n\n${suffix}`,
376
431
  }],
377
432
  };
378
433
  }
@@ -391,14 +446,14 @@ server.tool('restore_version', 'Restore a prompt to a previous version. Creates
391
446
  const resolved = await resolvePromptId(promptId, promptTitle);
392
447
  if ('error' in resolved)
393
448
  return errorResult(resolved.error);
394
- const [result, email] = await Promise.all([
449
+ const [result, suffix] = await Promise.all([
395
450
  client.restoreVersion(resolved.id, versionNumber),
396
- getAccountLabel(),
451
+ getResponseSuffix(),
397
452
  ]);
398
453
  return {
399
454
  content: [{
400
455
  type: 'text',
401
- text: `Restored to version ${result.restoredVersion}. New version created: v${result.newVersionNumber}.\n\n🔑 Account: ${email}`,
456
+ text: `Restored to version ${result.restoredVersion}. New version created: v${result.newVersionNumber}.\n\n${suffix}`,
402
457
  }],
403
458
  };
404
459
  }
@@ -415,9 +470,10 @@ server.tool('search_templates', 'Browse and search the PromptingBox public templ
415
470
  }, async ({ query, category, limit }) => {
416
471
  try {
417
472
  const result = await client.searchTemplates({ search: query, category, limit });
473
+ const suffix = await getResponseSuffix();
418
474
  if (result.templates.length === 0) {
419
475
  return {
420
- content: [{ type: 'text', text: 'No templates found matching your search.' }],
476
+ content: [{ type: 'text', text: `No templates found matching your search.\n\n${suffix}` }],
421
477
  };
422
478
  }
423
479
  const lines = result.templates.map((t) => `- **${t.title}** (${t.category})${t.description ? ` — ${t.description}` : ''}\n ID: \`${t.id}\` | Used ${t.usageCount} times`);
@@ -426,7 +482,7 @@ server.tool('search_templates', 'Browse and search the PromptingBox public templ
426
482
  type: 'text',
427
483
  text: `Found ${result.pagination.total} template${result.pagination.total === 1 ? '' : 's'}` +
428
484
  `${result.pagination.hasMore ? ` (showing first ${result.templates.length})` : ''}:\n\n${lines.join('\n\n')}` +
429
- `\n\nUse \`use_template\` with the template ID to save one to your collection.`,
485
+ `\n\nUse \`use_template\` with the template ID to save one to your collection.\n\n${suffix}`,
430
486
  }],
431
487
  };
432
488
  }
@@ -440,14 +496,14 @@ server.tool('use_template', 'Save a public template to your PromptingBox collect
440
496
  templateId: z.string().describe('The template ID (from search_templates)'),
441
497
  }, async ({ templateId }) => {
442
498
  try {
443
- const [result, email] = await Promise.all([
499
+ const [result, suffix] = await Promise.all([
444
500
  client.useTemplate(templateId),
445
- getAccountLabel(),
501
+ getResponseSuffix(),
446
502
  ]);
447
503
  return {
448
504
  content: [{
449
505
  type: 'text',
450
- text: `Template saved to your collection!\n\nTitle: ${result.title}\nID: ${result.promptId}\nURL: ${result.url}\n\n🔑 Account: ${email}`,
506
+ text: `Template saved to your collection!\n\nTitle: ${result.title}\nID: ${result.promptId}\nURL: ${result.url}\n\n${suffix}`,
451
507
  }],
452
508
  };
453
509
  }
@@ -459,13 +515,16 @@ server.tool('use_template', 'Save a public template to your PromptingBox collect
459
515
  // ── whoami ──────────────────────────────────────────────────────────────────
460
516
  server.tool('whoami', 'Show which PromptingBox account is connected to this MCP server.', {}, async () => {
461
517
  try {
462
- const info = await client.getAccountInfo();
518
+ const [info, update] = await Promise.all([
519
+ client.getAccountInfo(),
520
+ checkForUpdate(),
521
+ ]);
463
522
  accountEmail = info.email; // refresh cache
523
+ let text = `Connected to PromptingBox as:\n\nEmail: ${info.email}\nName: ${info.name || '(not set)'}\nID: ${info.id}`;
524
+ if (update)
525
+ text += `\n\n${update}`;
464
526
  return {
465
- content: [{
466
- type: 'text',
467
- text: `Connected to PromptingBox as:\n\nEmail: ${info.email}\nName: ${info.name || '(not set)'}\nID: ${info.id}`,
468
- }],
527
+ content: [{ type: 'text', text }],
469
528
  };
470
529
  }
471
530
  catch (err) {
@@ -476,15 +535,15 @@ server.tool('whoami', 'Show which PromptingBox account is connected to this MCP
476
535
  // ── list_folders ─────────────────────────────────────────────────────────────
477
536
  server.tool('list_folders', 'List all folders in the user\'s PromptingBox account. Useful to know where to save a prompt.', {}, async () => {
478
537
  try {
479
- const [folders, email] = await Promise.all([client.listFolders(), getAccountLabel()]);
538
+ const [folders, suffix] = await Promise.all([client.listFolders(), getResponseSuffix()]);
480
539
  if (folders.length === 0) {
481
540
  return {
482
- content: [{ type: 'text', text: `No folders found. You can specify a folder name when saving and it will be created automatically.\n\n🔑 Account: ${email}` }],
541
+ content: [{ type: 'text', text: `No folders found. You can specify a folder name when saving and it will be created automatically.\n\n${suffix}` }],
483
542
  };
484
543
  }
485
544
  const list = folders.map((f) => `- ${f.name} (id: \`${f.id}\`)`).join('\n');
486
545
  return {
487
- content: [{ type: 'text', text: `Folders in PromptingBox:\n${list}\n\n🔑 Account: ${email}` }],
546
+ content: [{ type: 'text', text: `Folders in PromptingBox:\n${list}\n\n${suffix}` }],
488
547
  };
489
548
  }
490
549
  catch (err) {
@@ -495,10 +554,10 @@ server.tool('list_folders', 'List all folders in the user\'s PromptingBox accoun
495
554
  // ── list_prompts ─────────────────────────────────────────────────────────────
496
555
  server.tool('list_prompts', 'List all prompts in the user\'s PromptingBox account grouped by folder. Use this to see what prompts exist and where they are organized.', {}, async () => {
497
556
  try {
498
- const [prompts, email] = await Promise.all([client.listPrompts(), getAccountLabel()]);
557
+ const [prompts, suffix] = await Promise.all([client.listPrompts(), getResponseSuffix()]);
499
558
  if (prompts.length === 0) {
500
559
  return {
501
- content: [{ type: 'text', text: `No prompts found.\n\n🔑 Account: ${email}` }],
560
+ content: [{ type: 'text', text: `No prompts found.\n\n${suffix}` }],
502
561
  };
503
562
  }
504
563
  // Group by folder
@@ -526,7 +585,7 @@ server.tool('list_prompts', 'List all prompts in the user\'s PromptingBox accoun
526
585
  }
527
586
  lines.push('');
528
587
  }
529
- lines.push(`🔑 Account: ${email}`);
588
+ lines.push(suffix);
530
589
  return {
531
590
  content: [{ type: 'text', text: lines.join('\n').trimEnd() }],
532
591
  };
@@ -547,9 +606,9 @@ server.tool('move_prompt_to_folder', 'Move a prompt to a different folder. Provi
547
606
  if ('error' in resolved)
548
607
  return errorResult(resolved.error);
549
608
  await client.movePromptToFolder(resolved.id, folder);
550
- const email = await getAccountLabel();
609
+ const suffix = await getResponseSuffix();
551
610
  return {
552
- content: [{ type: 'text', text: `Moved prompt to folder "${folder}".\n\n🔑 Account: ${email}` }],
611
+ content: [{ type: 'text', text: `Moved prompt to folder "${folder}".\n\n${suffix}` }],
553
612
  };
554
613
  }
555
614
  catch (err) {
@@ -560,15 +619,15 @@ server.tool('move_prompt_to_folder', 'Move a prompt to a different folder. Provi
560
619
  // ── list_tags ────────────────────────────────────────────────────────────────
561
620
  server.tool('list_tags', 'List all tags in the user\'s PromptingBox account. Useful to know what tags are available when saving a prompt.', {}, async () => {
562
621
  try {
563
- const [tags, email] = await Promise.all([client.listTags(), getAccountLabel()]);
622
+ const [tags, suffix] = await Promise.all([client.listTags(), getResponseSuffix()]);
564
623
  if (tags.length === 0) {
565
624
  return {
566
- content: [{ type: 'text', text: `No tags found. You can specify tag names when saving and they will be created automatically.\n\n🔑 Account: ${email}` }],
625
+ content: [{ type: 'text', text: `No tags found. You can specify tag names when saving and they will be created automatically.\n\n${suffix}` }],
567
626
  };
568
627
  }
569
628
  const list = tags.map((t) => `- ${t.name} (id: \`${t.id}\`)`).join('\n');
570
629
  return {
571
- content: [{ type: 'text', text: `Tags in PromptingBox:\n${list}\n\n🔑 Account: ${email}` }],
630
+ content: [{ type: 'text', text: `Tags in PromptingBox:\n${list}\n\n${suffix}` }],
572
631
  };
573
632
  }
574
633
  catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptingbox/mcp",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "MCP server for PromptingBox — save prompts from Claude, Cursor, and ChatGPT",
5
5
  "license": "MIT",
6
6
  "type": "module",