mcp-prompt-optimizer 3.0.2 → 3.0.4

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
@@ -5,7 +5,7 @@
5
5
  * Production-grade with Bayesian optimization, AG-UI real-time features, enhanced network resilience,
6
6
  * development mode, and complete backend alignment
7
7
  *
8
- * Version: 2.2.0 - Aligned with FastAPI Backend production-v2.2.0-stable
8
+ * Version: 3.0.2 - Aligned with FastAPI Backend production-v2.2.0-stable
9
9
  */
10
10
 
11
11
  const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
@@ -14,6 +14,7 @@ const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontext
14
14
  const https = require('https');
15
15
  const CloudApiKeyManager = require('./lib/api-key-manager');
16
16
  const packageJson = require('./package.json');
17
+ const OPTIMIZATION_TEMPLATES = require('./lib/optimization-templates.json');
17
18
 
18
19
  const API_KEYS_PREFIX = '/api/v1/api-keys';
19
20
  const MCP_PREFIX = '/api/v1/mcp';
@@ -35,9 +36,6 @@ const ENDPOINTS = {
35
36
 
36
37
  /** Update (PATCH) */
37
38
  UPDATE: (id) => `${MCP_PREFIX}/templates/${id}`,
38
-
39
- /** Delete (DELETE) */
40
- DELETE: (id) => `${MCP_PREFIX}/templates/${id}`,
41
39
  },
42
40
 
43
41
  /** Search templates (GET) — MCP endpoint, API-key auth */
@@ -77,9 +75,9 @@ class MCPPromptOptimizer {
77
75
  this.developmentMode = false;
78
76
  this.requestTimeout = parseInt(process.env.OPTIMIZER_REQUEST_TIMEOUT) || 30000;
79
77
 
80
- // NEW: Feature flags aligned with backend
81
- this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION === 'true';
82
- this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES === 'true';
78
+ // Feature flags: enabled by default, set to 'false' to disable
79
+ this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION !== 'false';
80
+ this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES !== 'false';
83
81
 
84
82
  this.setupMCPHandlers();
85
83
  }
@@ -208,11 +206,16 @@ class MCPPromptOptimizer {
208
206
  type: "string",
209
207
  description: "Filter by optimization strategy used"
210
208
  },
211
- limit: {
212
- type: "number",
209
+ limit: {
210
+ type: "number",
213
211
  default: 5,
214
212
  description: "Number of templates to return (1-20)"
215
213
  },
214
+ page: {
215
+ type: "number",
216
+ default: 1,
217
+ description: "Page number for pagination (use with limit to access results beyond the first page)"
218
+ },
216
219
  sort_by: {
217
220
  type: "string",
218
221
  enum: ["created_at", "confidence_score", "usage_count", "title"],
@@ -228,6 +231,20 @@ class MCPPromptOptimizer {
228
231
  }
229
232
  }
230
233
  },
234
+ {
235
+ name: "list_recent_templates",
236
+ description: "šŸ“‹ List your most recently saved optimization templates, sorted by creation date.",
237
+ inputSchema: {
238
+ type: "object",
239
+ properties: {
240
+ limit: {
241
+ type: "number",
242
+ default: 10,
243
+ description: "Number of recent templates to return (1-20)"
244
+ }
245
+ }
246
+ }
247
+ },
231
248
  {
232
249
  name: "detect_ai_context",
233
250
  description: "🧠 Detects the AI context for a given prompt using advanced backend analysis.",
@@ -287,6 +304,7 @@ class MCPPromptOptimizer {
287
304
  case "optimize_prompt": return await this.handleOptimizePrompt(args);
288
305
  case "get_quota_status": return await this.handleGetQuotaStatus();
289
306
  case "search_templates": return await this.handleSearchTemplates(args);
307
+ case "list_recent_templates": return await this.handleListRecentTemplates(args);
290
308
  case "detect_ai_context": return await this.handleDetectAIContext(args);
291
309
  case "create_template": return await this.handleCreateTemplate(args);
292
310
  case "get_template": return await this.handleGetTemplate(args);
@@ -301,11 +319,185 @@ class MCPPromptOptimizer {
301
319
  });
302
320
  }
303
321
 
322
+ // ─── Rules-Based Optimization (offline / fallback tier) ─────────────────────
323
+
324
+ /**
325
+ * Select the best-matching template for a prompt using pattern scoring.
326
+ * Mirrors the backend's pattern-based fallback (no LLM required).
327
+ */
328
+ _matchTemplate(prompt, backendContext) {
329
+ const lc = prompt.toLowerCase();
330
+ let bestTemplate = null;
331
+ let bestScore = 0;
332
+ let fallbackName = null;
333
+
334
+ for (const [name, template] of Object.entries(OPTIMIZATION_TEMPLATES)) {
335
+ if (template.context !== backendContext) continue;
336
+ if (name.startsWith('fallback_')) { fallbackName = name; continue; }
337
+
338
+ let hits = 0;
339
+ for (const pattern of template.patterns) {
340
+ if (pattern === '.*') continue;
341
+ if (lc.includes(pattern.toLowerCase())) hits++;
342
+ }
343
+ if (hits === 0) continue;
344
+
345
+ // Confidence: 1 hit → 0.6, 2 hits → 0.75, 3+ hits → 0.9 (mirrors backend)
346
+ const patternConf = hits === 1 ? 0.6 : hits === 2 ? 0.75 : 0.9;
347
+ const score = patternConf + (template.priority || 1) / 100;
348
+
349
+ if (score > bestScore) { bestScore = score; bestTemplate = name; }
350
+ }
351
+
352
+ if (!bestTemplate) {
353
+ return { templateName: fallbackName || `fallback_${backendContext.toLowerCase()}`, matchConfidence: 0.3 };
354
+ }
355
+ return { templateName: bestTemplate, matchConfidence: bestScore };
356
+ }
357
+
358
+ /** Extract a user-defined role from the start of a prompt (e.g. "As a doctor, …"). */
359
+ _extractUserRole(request) {
360
+ const rolePatterns = [
361
+ /^['"]?(?:As a|You are a|My role is)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
362
+ /^['"]?(?:I am a|I'm a)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
363
+ ];
364
+ for (const re of rolePatterns) {
365
+ const m = request.match(re);
366
+ if (m) return m[1].trim();
367
+ }
368
+ return null;
369
+ }
370
+
371
+ /**
372
+ * Compile a template playbook into a user-facing prose prompt.
373
+ * Produces readable output instead of XML scaffolding, matching the
374
+ * result a backend LLM pass would generate from the same playbook.
375
+ */
376
+ _compilePlaybook(playbook, originalRequest) {
377
+ const parts = [];
378
+
379
+ parts.push(originalRequest.trim());
380
+ parts.push('');
381
+
382
+ const userFacingPrinciples = (playbook.principles || []).filter(p => {
383
+ const lc = p.toLowerCase();
384
+ return !lc.includes('scratchpad') &&
385
+ !lc.startsWith('first, think') &&
386
+ !/<[a-z]/i.test(p);
387
+ });
388
+
389
+ if (userFacingPrinciples.length > 0) {
390
+ parts.push('To address this effectively:');
391
+ for (const p of userFacingPrinciples) parts.push(`- ${p}`);
392
+ parts.push('');
393
+ }
394
+
395
+ if (playbook.output_format) {
396
+ parts.push(`*Response format: ${playbook.output_format}*`);
397
+ }
398
+
399
+ return parts.join('\n');
400
+ }
401
+
402
+ /**
403
+ * Enhance an image generation prompt by appending style-appropriate
404
+ * quality/composition boosters (mirrors backend _compile_image_prompt_fallback).
405
+ */
406
+ _compileImagePrompt(originalRequest) {
407
+ const text = originalRequest.trim();
408
+ const lc = text.toLowerCase();
409
+
410
+ const styles = {
411
+ photorealistic: ['photorealistic','realistic','photo','photograph','photography'],
412
+ '3d_render': ['3d','render','octane','unreal engine','blender','cinema 4d','ray tracing'],
413
+ cinematic: ['cinematic','movie','film','dramatic','epic'],
414
+ digital_art: ['digital art','concept art','digital illustration','cg','cgi'],
415
+ artistic: ['artistic','painting','watercolor','oil painting','impressionist'],
416
+ anime: ['anime','manga'],
417
+ vintage: ['vintage','retro','nostalgic'],
418
+ minimalist: ['minimalist','minimal','simple','clean'],
419
+ };
420
+
421
+ let detectedStyle = null;
422
+ for (const [style, kws] of Object.entries(styles)) {
423
+ if (kws.some(kw => lc.includes(kw))) { detectedStyle = style; break; }
424
+ }
425
+
426
+ const enhancements = [];
427
+ const hasQuality = ['high quality','8k','4k','hd','highly detailed','detailed'].some(t => lc.includes(t));
428
+ const hasLighting = ['lighting','light','shadow','illuminated','lit'].some(t => lc.includes(t));
429
+ const hasComposition = ['composition','rule of thirds','centered','framed'].some(t => lc.includes(t));
430
+
431
+ if (detectedStyle === 'photorealistic' && !hasQuality) {
432
+ enhancements.push('ultra realistic, sharp focus, professional photography');
433
+ } else if (detectedStyle === '3d_render' && !['octane','render'].some(t => lc.includes(t))) {
434
+ enhancements.push('high quality 3D render, volumetric lighting, ray traced shadows');
435
+ } else if (detectedStyle === 'cinematic' && !hasLighting) {
436
+ enhancements.push('cinematic lighting, dramatic atmosphere, film grain');
437
+ } else if (detectedStyle === 'digital_art' && !hasQuality) {
438
+ enhancements.push('highly detailed digital art, professional illustration');
439
+ } else if (detectedStyle === 'artistic' && !lc.includes('masterpiece')) {
440
+ enhancements.push('masterful technique, rich colors, artistic composition');
441
+ }
442
+
443
+ if (!hasLighting && detectedStyle !== 'minimalist') enhancements.push('dynamic lighting');
444
+ if (!hasComposition) enhancements.push('balanced composition');
445
+ if (!hasQuality) enhancements.push('high quality, 4K');
446
+
447
+ return enhancements.length > 0 ? `${text}, ${enhancements.join(', ')}` : text;
448
+ }
449
+
450
+ /**
451
+ * Core rules-based optimizer — no network, no LLM.
452
+ * Selects the best template by pattern matching, then compiles
453
+ * the playbook into a structured prompt. Confidence range: 0.35–0.55.
454
+ */
455
+ rulesBasedOptimize(prompt, aiContext, goals = []) {
456
+ const contextMap = {
457
+ code_generation: 'CODE_GENERATION',
458
+ llm_interaction: 'LLM_INTERACTION',
459
+ image_generation: 'IMAGE_GENERATION',
460
+ human_communication: 'HUMAN_COMMUNICATION',
461
+ api_automation: 'API_AUTOMATION',
462
+ technical_automation: 'TECHNICAL_AUTOMATION',
463
+ structured_output: 'STRUCTURED_OUTPUT',
464
+ creative_enhancement: 'CREATIVE_ENHANCEMENT',
465
+ creative_writing: 'CREATIVE_ENHANCEMENT',
466
+ general_assistant: 'LLM_INTERACTION',
467
+ };
468
+ const backendContext = contextMap[aiContext] || 'LLM_INTERACTION';
469
+
470
+ const { templateName, matchConfidence } = this._matchTemplate(prompt, backendContext);
471
+ const template = OPTIMIZATION_TEMPLATES[templateName];
472
+
473
+ const optimizedPrompt = backendContext === 'IMAGE_GENERATION'
474
+ ? this._compileImagePrompt(prompt)
475
+ : this._compilePlaybook(template.playbook, prompt);
476
+
477
+ // Honest confidence: rules-based tops out around 0.55
478
+ const confidence = parseFloat(Math.min(0.35 + matchConfidence * 0.2, 0.55).toFixed(2));
479
+
480
+ return {
481
+ optimized_prompt: optimizedPrompt,
482
+ confidence_score: confidence,
483
+ tier: 'rules',
484
+ template_used: templateName,
485
+ rules_based: true,
486
+ template_saved: false,
487
+ templates_found: [],
488
+ optimization_insights: null,
489
+ bayesian_insights: null,
490
+ };
491
+ }
492
+
493
+ // ─── End Rules-Based Optimization ────────────────────────────────────────────
494
+
304
495
  generateMockOptimization(prompt, goals, aiContext, enableBayesian = false) {
305
- const optimized_prompt = `Enhanced for ${aiContext}: ${prompt}`;
496
+ // Use real rules-based optimization instead of fake placeholder output
497
+ const rulesResult = this.rulesBasedOptimize(prompt, aiContext, goals);
306
498
  const baseResult = {
307
- optimized_prompt,
308
- confidence_score: 0.87,
499
+ ...rulesResult,
500
+ rules_based: false, // Show as normal optimized output in mock mode
309
501
  tier: 'explorer',
310
502
  mock_mode: true,
311
503
  template_saved: true,
@@ -381,7 +573,7 @@ class MCPPromptOptimizer {
381
573
  secondary_contexts: ['llm_interaction'],
382
574
  detected_parameters: [],
383
575
  mock_mode: true,
384
- reason: 'Running in development/fallback mode.'
576
+ reason: 'Backend unavailable — using local pattern matching as fallback.'
385
577
  };
386
578
  }
387
579
 
@@ -432,7 +624,7 @@ class MCPPromptOptimizer {
432
624
  if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout') || error.message.includes('Connection')) {
433
625
  const fallbackContext = args.ai_context || 'human_communication';
434
626
  const fallbackEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
435
- const fallbackResult = this.generateMockOptimization(args.prompt, args.goals || ['clarity'], fallbackContext, fallbackEnableBayesian);
627
+ const fallbackResult = this.rulesBasedOptimize(args.prompt, fallbackContext, args.goals || ['clarity']);
436
628
  fallbackResult.fallback_mode = true;
437
629
  fallbackResult.error_reason = error.message;
438
630
  const formatted = this.formatOptimizationResult(fallbackResult, { detectedContext: fallbackContext, enableBayesian: fallbackEnableBayesian });
@@ -451,7 +643,7 @@ class MCPPromptOptimizer {
451
643
  async handleSearchTemplates(args) {
452
644
  try {
453
645
  const params = new URLSearchParams({
454
- page: '1',
646
+ page: (args.page || 1).toString(),
455
647
  per_page: Math.min(args.limit || 5, 20).toString(),
456
648
  sort_by: args.sort_by || 'confidence_score',
457
649
  sort_order: args.sort_order || 'desc'
@@ -492,6 +684,49 @@ class MCPPromptOptimizer {
492
684
  }
493
685
  }
494
686
 
687
+ async handleListRecentTemplates(args) {
688
+ try {
689
+ const limit = Math.min(Math.max(args.limit || 10, 1), 20);
690
+ const params = new URLSearchParams({
691
+ page: '1',
692
+ per_page: limit.toString(),
693
+ sort_by: 'created_at',
694
+ sort_order: 'desc'
695
+ });
696
+
697
+ const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
698
+ const result = await this.callBackendAPI(endpoint, null, 'GET');
699
+
700
+ const templates = result.templates || [];
701
+ let output = `# šŸ“‹ Recent Templates\n\n`;
702
+ output += `Showing **${templates.length}** most recently saved template(s).\n\n`;
703
+
704
+ if (templates.length === 0) {
705
+ output += `šŸ“­ No templates found yet.\nRun \`optimize_prompt\` to start building your template library.\n`;
706
+ } else {
707
+ output += `## šŸ“‹ **Template Results**\n`;
708
+ templates.forEach((t, index) => {
709
+ const confidence = t.confidence_score ? `${(t.confidence_score * 100).toFixed(1)}%` : 'N/A';
710
+ const preview = t.optimized_prompt ? t.optimized_prompt.substring(0, 60) + '...' : 'Preview unavailable';
711
+ output += `### ${index + 1}. ${t.title}\n`;
712
+ output += `- **Confidence:** ${confidence}\n`;
713
+ output += `- **ID:** \`${t.id}\`\n`;
714
+ output += `- **Preview:** ${preview}\n`;
715
+ if (t.ai_context) output += `- **Context:** ${t.ai_context}\n`;
716
+ if (t.optimization_goals && t.optimization_goals.length) {
717
+ output += `- **Goals:** ${t.optimization_goals.join(', ')}\n`;
718
+ }
719
+ output += `\n`;
720
+ });
721
+ output += `šŸ’” Use \`get_template\` with an ID above to view the full optimized prompt.\n`;
722
+ }
723
+
724
+ return { content: [{ type: "text", text: output }] };
725
+ } catch (error) {
726
+ return { content: [{ type: "text", text: `āŒ Could not retrieve recent templates: ${error.message}` }] };
727
+ }
728
+ }
729
+
495
730
  async handleGetOptimizationInsights(args) {
496
731
  if (!this.bayesianOptimizationEnabled) {
497
732
  return { content: [{ type: "text", text: "🧠 Bayesian optimization features are not enabled. Set ENABLE_BAYESIAN_OPTIMIZATION=true to access advanced insights." }] };
@@ -607,6 +842,18 @@ class MCPPromptOptimizer {
607
842
  }
608
843
 
609
844
  async handleCreateTemplate(args) {
845
+ // Client-side validation before network call
846
+ const requiredStrings = ['title', 'original_prompt', 'optimized_prompt'];
847
+ for (const field of requiredStrings) {
848
+ if (!args[field] || typeof args[field] !== 'string' || args[field].trim() === '') {
849
+ return { content: [{ type: "text", text: `āŒ Missing required field: '${field}'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
850
+ }
851
+ }
852
+ if (args.confidence_score === undefined || args.confidence_score === null ||
853
+ typeof args.confidence_score !== 'number' || args.confidence_score < 0 || args.confidence_score > 1) {
854
+ return { content: [{ type: "text", text: `āŒ Missing required field: 'confidence_score'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
855
+ }
856
+
610
857
  try {
611
858
  const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.CREATE, args);
612
859
  let output = `# āœ… Template Created Successfully!\n\n`;
@@ -638,6 +885,10 @@ class MCPPromptOptimizer {
638
885
  output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n`;
639
886
  return { content: [{ type: "text", text: output }] };
640
887
  } catch (error) {
888
+ const msg = error.message || '';
889
+ if (msg.includes('404') || msg.toLowerCase().includes('not found')) {
890
+ throw new Error(`Template \`${args.template_id}\` not found. It may have been deleted or the ID is incorrect. Use \`search_templates\` to find available templates.`);
891
+ }
641
892
  throw new Error(`Failed to retrieve template: ${error.message}`);
642
893
  }
643
894
  }
@@ -736,8 +987,37 @@ class MCPPromptOptimizer {
736
987
  }
737
988
 
738
989
  formatOptimizationResult(result, context) {
739
- let output = `# šŸŽÆ Optimized Prompt\n\n${result.optimized_prompt}\n\n`;
740
- output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
990
+ let output;
991
+ if (result.rules_based) {
992
+ if (result.fallback_mode) {
993
+ output = `# šŸ”§ Rules-Based Optimization Applied\n\n`;
994
+ output += `āš ļø *Backend unreachable — your prompt has been structured using local rule templates (no LLM). `;
995
+ output += `Re-run when the backend is available for full LLM optimization.*\n\n`;
996
+ } else {
997
+ output = `# šŸ”§ Rules-Based Optimization Applied\n\n`;
998
+ output += `*API key not validated — optimized using local rule templates. `;
999
+ output += `Set \`MCP_API_KEY\` for full LLM optimization.*\n\n`;
1000
+ }
1001
+ output += `**Template:** \`${result.template_used || 'general'}\`\n\n`;
1002
+ output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1003
+ } else if (result.fallback_mode) {
1004
+ // Legacy path — should no longer be reached
1005
+ output = `# āš ļø Backend Unavailable — Prompt Not Optimized\n\n`;
1006
+ output += `**Issue:** ${result.error_reason}\n`;
1007
+ output += `The backend could not be reached. Your original prompt is returned below unmodified.\n\n`;
1008
+ output += `**Original Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1009
+ } else {
1010
+ output = `# šŸŽÆ Optimized Prompt\n\n${result.optimized_prompt}\n\n`;
1011
+ if (result.confidence_score < 0.25) {
1012
+ output += `> ā„¹ļø *Low confidence indicates the backend applied rules-based optimization (no LLM). `;
1013
+ output += `Ensure \`OPENROUTER_API_KEY\` is configured in the backend for full LLM enhancement.*\n\n`;
1014
+ }
1015
+ }
1016
+ if (result.rules_based) {
1017
+ output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}% *(rules-based — LLM optimization typically 70–95%)*\n`;
1018
+ } else {
1019
+ output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1020
+ }
741
1021
  output += `**AI Context:** ${context.detectedContext}\n`;
742
1022
 
743
1023
  if (result.template_saved) {
@@ -747,8 +1027,9 @@ class MCPPromptOptimizer {
747
1027
  if (result.templates_found?.length) {
748
1028
  output += `\nšŸ“‹ **Similar Templates Found**\nFound **${result.templates_found.length}** similar template(s):\n`;
749
1029
  result.templates_found.slice(0, 3).forEach(t => {
750
- output += `- ${t.title} (${(t.confidence_score * 100).toFixed(1)}% match)\n`;
1030
+ output += `- ${t.title} (${(t.confidence_score * 100).toFixed(1)}% match) — ID: \`${t.id}\`\n`;
751
1031
  });
1032
+ output += `\nšŸ’” Use \`get_template\` with any ID above to view the full optimized prompt.\n`;
752
1033
  }
753
1034
 
754
1035
  if (result.optimization_insights) {
@@ -796,12 +1077,10 @@ class MCPPromptOptimizer {
796
1077
  }
797
1078
  }
798
1079
 
799
- if (result.fallback_mode) {
800
- output += `\nāš ļø **Fallback Mode Active**\n**Issue:** ${result.error_reason}\n`;
1080
+ if (!result.fallback_mode) {
1081
+ output += `\nšŸ”— **Quick Actions**\n- Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n- Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
801
1082
  }
802
1083
 
803
- output += `\nšŸ”— **Quick Actions**\n- Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n- Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
804
-
805
1084
  return output;
806
1085
  }
807
1086
 
@@ -821,6 +1100,17 @@ class MCPPromptOptimizer {
821
1100
  else if (percentage >= 75) statusIcon = '🟔';
822
1101
 
823
1102
  output += `**Usage:** ${statusIcon} ${used}/${limit} (${percentage}%)\n`;
1103
+
1104
+ const remaining = limit - used;
1105
+ if (remaining <= 0) {
1106
+ output += `\nāŒ **Quota Exhausted** — You have no optimizations remaining this month.\n`;
1107
+ output += `Upgrade at https://promptoptimizer-blog.vercel.app/pricing\n`;
1108
+ output += `*(Quota resets at the start of your next billing cycle)*\n`;
1109
+ } else if (percentage >= 90) {
1110
+ output += `\nāš ļø **Critical** — ${remaining} optimization${remaining === 1 ? '' : 's'} remaining. Upgrade at https://promptoptimizer-blog.vercel.app/pricing\n`;
1111
+ } else if (percentage >= 75) {
1112
+ output += `\nāš ļø **Warning** — Approaching your monthly limit.\n`;
1113
+ }
824
1114
  }
825
1115
 
826
1116
  output += `\n## ✨ **Available Features**\n`;
@@ -865,10 +1155,12 @@ class MCPPromptOptimizer {
865
1155
 
866
1156
  if (!result.templates || result.templates.length === 0) {
867
1157
  output += `šŸ“­ **No Templates Found**\n`;
868
- if (originalArgs.query) {
869
- output += `Try searching with different keywords or remove filters.\n`;
1158
+ const hasActiveFilters = originalArgs.query || originalArgs.ai_context || originalArgs.sophistication_level || originalArgs.complexity_level;
1159
+ if (hasActiveFilters) {
1160
+ output += `No templates matched your filters. Try removing \`ai_context\` or \`query\` filters.\n`;
870
1161
  } else {
871
1162
  output += `You don't have any saved templates yet. Templates are automatically saved when optimization confidence is >70%.\n`;
1163
+ output += `Run \`optimize_prompt\` to start building your template library.\n`;
872
1164
  }
873
1165
  } else {
874
1166
  output += `## šŸ“‹ **Template Results**\n`;
@@ -488,7 +488,7 @@ class CloudApiKeyManager {
488
488
 
489
489
  try {
490
490
  // Step 1: Validate API key
491
- const validation = await this.validateApiKey();
491
+ let validation = await this.validateApiKey();
492
492
 
493
493
  // Step 2: Get comprehensive quota status
494
494
  const info = await this.getApiKeyInfo();