mcp-prompt-optimizer 3.7.0 → 3.7.2

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
@@ -1,1989 +1,1995 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * MCP Prompt Optimizer - Professional Cloud-Based MCP Server
5
- * Production-grade with Bayesian optimization, AG-UI real-time features, enhanced network resilience,
6
- * development mode, and complete backend alignment
7
- *
8
- * Version: 3.2.0 - add delete_template tool (15 tools total)
9
- */
10
-
11
- const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
12
- const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
13
- const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
14
- const https = require('https');
15
- const CloudApiKeyManager = require('./lib/api-key-manager');
16
- const packageJson = require('./package.json');
17
- const OPTIMIZATION_TEMPLATES = require('./lib/optimization-templates.json');
18
-
19
- const API_KEYS_PREFIX = '/api/v1/api-keys';
20
- const MCP_PREFIX = '/api/v1/mcp';
21
-
22
- const ENDPOINTS = {
23
- /** Detect AI context (POST) — MCP endpoint, API-key auth */
24
- DETECT_CONTEXT: `${MCP_PREFIX}/detect-context`,
25
-
26
- /** Prompt optimization (POST) — MCP endpoint, API-key auth */
27
- OPTIMIZE: `${MCP_PREFIX}/optimize`,
28
-
29
- /** CRUD on templates — MCP endpoints, API-key auth */
30
- TEMPLATE: {
31
- /** Create (POST) */
32
- CREATE: `${MCP_PREFIX}/templates`,
33
-
34
- /** Read (GET) */
35
- GET: (id) => `${MCP_PREFIX}/templates/${id}`,
36
-
37
- /** Update (PATCH) */
38
- UPDATE: (id) => `${MCP_PREFIX}/templates/${id}`,
39
-
40
- /** Delete (DELETE) */
41
- DELETE: (id) => `${MCP_PREFIX}/templates/${id}`,
42
- },
43
-
44
- /** Search templates (GET) — MCP endpoint, API-key auth */
45
- SEARCH_TEMPLATES: `${MCP_PREFIX}/templates`,
46
-
47
- /** Quota status (GET) — MCP endpoint, API-key auth */
48
- QUOTA_STATUS: `${MCP_PREFIX}/quota-status`,
49
-
50
- /** Validate API key (POST) — standard api-keys router */
51
- VALIDATE_KEY: `${API_KEYS_PREFIX}/validate`,
52
-
53
- /** Bayesian insights (GET) */
54
- ANALYTICS_BAYESIAN_INSIGHTS:
55
- '/api/v1/analytics/bayesian-insights',
56
-
57
- /** AG‑UI status (GET) */
58
- AGUI_STATUS: '/api/status',
59
-
60
- /** Context Engineer (CE) endpoints */
61
- CE: {
62
- SOP: '/api/v1/context-engineer/sop',
63
- GENERATE_SKILL_PACKAGE: '/api/v1/context-engineer/generate-skill-package',
64
- SESSION: (id) => `/api/v1/context-engineer/sessions/${id}`,
65
- TRANSFORM: '/api/v1/context-engineer/transform',
66
- QUOTA: '/api/v1/context-engineer/quota',
67
- HARNESS_BUNDLE: '/api/v1/context-engineer/harness-bundle',
68
- SOP_EXPLORE: '/api/v1/context-engineer/sop-explore',
69
- SOP_BLEND: '/api/v1/context-engineer/sop-blend',
70
- },
71
- };
72
-
73
- const DEPLOY_TARGET_ENUM = [
74
- "claude_code", "claude_desktop", "cursor", "copilot",
75
- "windsurf", "cline", "zed", "replit", "openai_agents", "ollama",
76
- "amazon_q", "aider", "continue_dev", "crewai"
77
- ];
78
-
79
- class MCPPromptOptimizer {
80
- constructor() {
81
- this.server = new Server(
82
- {
83
- name: "mcp-prompt-optimizer",
84
- version: packageJson.version,
85
- },
86
- {
87
- capabilities: {
88
- tools: {},
89
- },
90
- }
91
- );
92
-
93
- this.backendUrl = process.env.OPTIMIZER_BACKEND_URL || 'https://p01--project-optimizer--fvmrdk8m9k9j.code.run';
94
- this.apiKey = process.env.OPTIMIZER_API_KEY;
95
- // SECURITY: Development mode removed - all environments require backend validation
96
- this.developmentMode = false;
97
- this.requestTimeout = parseInt(process.env.OPTIMIZER_REQUEST_TIMEOUT) || 30000;
98
-
99
- // Feature flags: enabled by default, set to 'false' to disable
100
- this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION !== 'false';
101
- this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES !== 'false';
102
-
103
- this.setupMCPHandlers();
104
- }
105
-
106
- setupMCPHandlers() {
107
- this.server.setRequestHandler(ListToolsRequestSchema, async () => {
108
- const baseTools = [
109
- {
110
- name: "optimize_prompt",
111
- description: "🎯 Professional AI-powered prompt optimization with intelligent context detection, Bayesian optimization, template auto-save, and comprehensive optimization insights",
112
- inputSchema: {
113
- type: "object",
114
- properties: {
115
- prompt: {
116
- type: "string",
117
- description: "The prompt text to optimize"
118
- },
119
- goals: {
120
- type: "array",
121
- items: { type: "string" },
122
- description: "Optimization goals (e.g., 'clarity', 'conciseness', 'creativity', 'technical_accuracy', 'analytical_depth', 'creative_enhancement')",
123
- default: ["clarity"]
124
- },
125
- ai_context: {
126
- type: "string",
127
- enum: [
128
- "human_communication", "llm_interaction", "image_generation", "technical_automation",
129
- "structured_output", "code_generation", "api_automation", "data_analysis",
130
- "creative_writing", "business_strategy", "technical_strategy", "academic_research",
131
- "legal_compliance", "medical_healthcare", "educational_content"
132
- ],
133
- description: "The context for the AI's task (auto-detected if not specified with enhanced detection)"
134
- },
135
- enable_bayesian: {
136
- type: "boolean",
137
- description: "Enable Bayesian optimization features for parameter tuning (if available)",
138
- default: true
139
- },
140
- value_hierarchy: {
141
- type: "array",
142
- description: "Ordered list of values/constraints the optimizer must respect. NON_NEGOTIABLE entries force LLM-tier routing and inject hard constraints into the system prompt. Example: [{label:'NON_NEGOTIABLE',description:'Never suggest removing error handling'},{label:'HIGH',description:'Preserve technical terminology'}]",
143
- items: {
144
- type: "object",
145
- properties: {
146
- label: {
147
- type: "string",
148
- enum: ["NON_NEGOTIABLE", "HIGH", "MEDIUM", "LOW"],
149
- description: "Priority level for this constraint"
150
- },
151
- description: {
152
- type: "string",
153
- description: "The value or constraint to enforce during optimization"
154
- }
155
- },
156
- required: ["label", "description"]
157
- }
158
- },
159
- intent_frame: {
160
- type: "object",
161
- description: "Question Method intent framing — steers optimization toward a specific angle, excludes off-topic territory, and defines what success looks like. Any non-null field floors routing to HYBRID tier minimum.",
162
- properties: {
163
- perspective: {
164
- type: "string",
165
- description: "The angle or thesis to optimize from (e.g. 'growth is a retention problem, not an acquisition problem'). Gives the optimizer a north-star direction."
166
- },
167
- out_of_scope: {
168
- type: "array",
169
- items: { type: "string" },
170
- description: "Topics, approaches, or angles to explicitly exclude from optimization (e.g. ['pricing strategy', 'acquisition channels'])."
171
- },
172
- success_definition: {
173
- type: "string",
174
- description: "Narrative description of what a successful optimized output achieves (e.g. 'reader understands why churn drives flat revenue even with user growth')."
175
- }
176
- }
177
- }
178
- },
179
- required: ["prompt"]
180
- }
181
- },
182
- {
183
- name: "get_quota_status",
184
- description: "📊 Check subscription status, quota usage, and account information with detailed insights and Bayesian optimization metrics",
185
- inputSchema: { type: "object", properties: {}, additionalProperties: false }
186
- },
187
- {
188
- name: "create_template",
189
- description: "➕ Create a new optimization template.",
190
- inputSchema: {
191
- type: "object",
192
- properties: {
193
- title: { type: "string", description: "Title of the template" },
194
- description: { type: "string", description: "Description of the template" },
195
- original_prompt: { type: "string", description: "The original prompt text" },
196
- optimized_prompt: { type: "string", description: "The optimized prompt text" },
197
- optimization_goals: { type: "array", items: { type: "string" }, description: "Goals for this optimization (e.g., 'clarity', 'conciseness', 'creativity', 'technical_accuracy', 'analytical_depth', 'creative_enhancement')" },
198
- confidence_score: { type: "number", description: "Confidence score of the optimization (0.0-1.0)" },
199
- model_used: { type: "string", description: "Model used for optimization" },
200
- optimization_tier: { type: "string", description: "Tier of optimization (e.g., rules, llm, hybrid)" },
201
- ai_context_detected: { type: "string", description: "Detected AI context (e.g., code_generation, image_generation)" },
202
- is_public: { type: "boolean", default: false, description: "Whether the template is public" },
203
- tags: { type: "array", items: { type: "string" }, description: "Tags for the template" }
204
- },
205
- required: ["title", "original_prompt", "optimized_prompt", "confidence_score"]
206
- }
207
- },
208
- {
209
- name: "get_template",
210
- description: "🔍 Retrieve a specific template by its ID.",
211
- inputSchema: {
212
- type: "object",
213
- properties: {
214
- template_id: { type: "string", description: "The ID of the template to retrieve" }
215
- },
216
- required: ["template_id"]
217
- }
218
- },
219
- {
220
- name: "update_template",
221
- description: "✏️ Update an existing optimization template.",
222
- inputSchema: {
223
- type: "object",
224
- properties: {
225
- template_id: { type: "string", description: "The ID of the template to update" },
226
- title: { type: "string", description: "New title for the template" },
227
- description: { type: "string", description: "New description for the template" },
228
- original_prompt: { type: "string", description: "New original prompt text" },
229
- optimized_prompt: { type: "string", description: "New optimized prompt text" },
230
- optimization_goals: { type: "array", items: { type: "string" }, description: "New optimization goals" },
231
- confidence_score: { type: "number", description: "New confidence score (0.0-1.0)" },
232
- model_used: { type: "string", description: "New model used for optimization" },
233
- optimization_tier: { type: "string", description: "New tier of optimization" },
234
- ai_context_detected: { type: "string", description: "New detected AI context" },
235
- is_public: { type: "boolean", description: "Whether the template is public" },
236
- tags: { type: "array", items: { type: "string" }, description: "New tags for the template" }
237
- },
238
- required: ["template_id"]
239
- }
240
- },
241
- {
242
- name: "delete_template",
243
- description: "🗑️ Delete a saved optimization template by ID.",
244
- inputSchema: {
245
- type: "object",
246
- properties: {
247
- template_id: { type: "string", description: "The ID of the template to delete" }
248
- },
249
- required: ["template_id"]
250
- }
251
- },
252
- {
253
- name: "search_templates",
254
- description: "🔍 Search your saved template library with AI-aware filtering, context-based search, and sophisticated template matching",
255
- inputSchema: {
256
- type: "object",
257
- properties: {
258
- query: {
259
- type: "string",
260
- description: "Search term to filter templates by content or title"
261
- },
262
- ai_context: {
263
- type: "string",
264
- enum: ["human_communication", "llm_interaction", "image_generation", "technical_automation", "structured_output", "code_generation", "api_automation"],
265
- description: "Filter templates by AI context type"
266
- },
267
- sophistication_level: {
268
- type: "string",
269
- enum: ["basic", "intermediate", "advanced", "expert"],
270
- description: "Filter by template sophistication level"
271
- },
272
- complexity_level: {
273
- type: "string",
274
- enum: ["simple", "moderate", "complex", "very_complex"],
275
- description: "Filter by template complexity level"
276
- },
277
- optimization_strategy: {
278
- type: "string",
279
- description: "Filter by optimization strategy used"
280
- },
281
- limit: {
282
- type: "number",
283
- default: 5,
284
- description: "Number of templates to return (1-20)"
285
- },
286
- page: {
287
- type: "number",
288
- default: 1,
289
- description: "Page number for pagination (use with limit to access results beyond the first page)"
290
- },
291
- sort_by: {
292
- type: "string",
293
- enum: ["created_at", "confidence_score", "usage_count", "title"],
294
- default: "confidence_score",
295
- description: "Sort templates by field"
296
- },
297
- sort_order: {
298
- type: "string",
299
- enum: ["asc", "desc"],
300
- default: "desc",
301
- description: "Sort order"
302
- }
303
- }
304
- }
305
- },
306
- {
307
- name: "list_recent_templates",
308
- description: "📋 List your most recently saved optimization templates, sorted by creation date.",
309
- inputSchema: {
310
- type: "object",
311
- properties: {
312
- limit: {
313
- type: "number",
314
- default: 10,
315
- description: "Number of recent templates to return (1-20)"
316
- }
317
- }
318
- }
319
- },
320
- {
321
- name: "detect_ai_context",
322
- description: "🧠 Detects the AI context for a given prompt using advanced backend analysis.",
323
- inputSchema: {
324
- type: "object",
325
- properties: {
326
- prompt: {
327
- type: "string",
328
- description: "The prompt text for which to detect the AI context"
329
- }
330
- },
331
- required: ["prompt"]
332
- }
333
- },
334
- {
335
- name: "generate_agent_sop",
336
- description: "Generate a structured SOP document for an AI agent from a goal description.",
337
- inputSchema: {
338
- type: "object",
339
- properties: {
340
- goal: { type: "string", description: "What the agent should accomplish" },
341
- context: { type: "string", description: "Additional context (optional)" },
342
- model_id: { type: "string", description: "Model to use (optional)" },
343
- intent_frame: {
344
- type: "object",
345
- description: "Optional IntentFrame to sharpen SOP scope and success criteria.",
346
- properties: {
347
- perspective: { type: "string", description: "The agent role or viewpoint (e.g. DevOps engineer)." },
348
- out_of_scope: { type: "string", description: "What is explicitly excluded from this workflow." },
349
- success_definition: { type: "string", description: "Measurable criteria that define success." }
350
- },
351
- additionalProperties: false
352
- }
353
- },
354
- required: ["goal"]
355
- }
356
- },
357
- {
358
- name: "generate_skill_package",
359
- description: "Generate a complete skill package (SOP + SKILL.md + examples + helper.py) for an AI agent. Takes 30-120 seconds (async).",
360
- inputSchema: {
361
- type: "object",
362
- properties: {
363
- goal: { type: "string", description: "What the agent should accomplish" },
364
- format: { type: "string", enum: ["knowledge_doc", "agent_spec"], description: "Output format" },
365
- model_id: { type: "string", description: "Model to use (optional)" }
366
- },
367
- required: ["goal"]
368
- }
369
- },
370
- {
371
- name: "transform_for_framework",
372
- description: "Transform a SOP into native code for LangChain, AutoGen, or Claude Code.",
373
- inputSchema: {
374
- type: "object",
375
- properties: {
376
- sop_content: { type: "string", description: "SOP content to transform" },
377
- goal: { type: "string", description: "What the agent should accomplish" },
378
- framework: { type: "string", enum: ["langchain_tool", "autogen_agent", "claude_skill"], description: "Target framework" }
379
- },
380
- required: ["sop_content", "goal", "framework"]
381
- }
382
- },
383
- {
384
- name: "get_ce_quota_status",
385
- description: "Check your Context Engineer credit balance and available workflow types.",
386
- inputSchema: { type: "object", properties: {}, additionalProperties: false }
387
- },
388
- {
389
- name: "generate_harness_bundle",
390
- description: (
391
- "Generate a deployment-ready Agentic Harness ZIP bundle for a specific platform. "
392
- + "Returns a confirmation message when the bundle is queued. "
393
- + "Explorer+ required for non-default deploy targets."
394
- ),
395
- inputSchema: {
396
- type: "object",
397
- properties: {
398
- goal: {
399
- type: "string",
400
- description: "The workflow goal the harness is built for."
401
- },
402
- deploy_target: {
403
- oneOf: [
404
- {
405
- type: "string",
406
- enum: DEPLOY_TARGET_ENUM,
407
- description: "Single deploy target."
408
- },
409
- {
410
- type: "array",
411
- minItems: 1,
412
- items: {
413
- type: "string",
414
- enum: DEPLOY_TARGET_ENUM
415
- },
416
- description: "Multiple deploy targets simultaneously (Creator+ required)."
417
- }
418
- ],
419
- description: (
420
- "Target deployment platform(s). Single string (Explorer+) or array (Creator+). "
421
- + "amazon_q, aider, continue_dev, crewai require Creator+. "
422
- + "Default: claude_code."
423
- )
424
- },
425
- session_id: {
426
- type: "string",
427
- description: "Optional: session ID from a prior generate_skill_package call to reuse SOP."
428
- },
429
- sop_content: {
430
- type: "string",
431
- description: "The SOP content to base the harness on (required if no session_id)."
432
- }
433
- },
434
- required: ["goal"]
435
- }
436
- },
437
- {
438
- name: "explore_sop_approaches",
439
- description: (
440
- "Generate 3 parallel SOP variants (process-oriented, decision-tree, role-based) for comparison before committing. " +
441
- "Returns exploration_html (self-contained comparison grid), variants array, and a recommended variant. " +
442
- "Innovator tier required. " +
443
- "Optionally provide blend_description to skip comparison and receive a single blended SOP instead."
444
- ),
445
- inputSchema: {
446
- type: "object",
447
- properties: {
448
- goal: {
449
- type: "string",
450
- description: "The workflow goal to generate SOP variants for"
451
- },
452
- context: {
453
- type: "string",
454
- description: "Optional background context or documentation excerpt"
455
- },
456
- blend_description: {
457
- type: "string",
458
- description: "Optional: if provided, skips variant comparison and blends all 3 into one SOP using this description"
459
- },
460
- perspective: { type: "string", description: "Agent role or viewpoint (IntentFrame)" },
461
- out_of_scope: { type: "string", description: "What is explicitly excluded (IntentFrame)" },
462
- success_definition: { type: "string", description: "Measurable success criteria (IntentFrame)" },
463
- },
464
- required: ["goal"],
465
- additionalProperties: false
466
- }
467
- },
468
- ];
469
-
470
- // Add advanced tools if Bayesian optimization is enabled
471
- if (this.bayesianOptimizationEnabled) {
472
- baseTools.push({
473
- name: "get_optimization_insights",
474
- description: "🧠 Get advanced Bayesian optimization insights, performance analytics, and parameter tuning recommendations",
475
- inputSchema: {
476
- type: "object",
477
- properties: {
478
- analysis_depth: {
479
- type: "string",
480
- enum: ["basic", "detailed", "comprehensive"],
481
- default: "detailed",
482
- description: "Depth of analysis to provide"
483
- },
484
- include_recommendations: {
485
- type: "boolean",
486
- default: true,
487
- description: "Include optimization recommendations"
488
- }
489
- }
490
- }
491
- });
492
- }
493
-
494
- // Add AG-UI tools if enabled
495
- if (this.aguiFeatures) {
496
- baseTools.push({
497
- name: "get_real_time_status",
498
- description: "⚡ Get real-time optimization status, AG-UI capabilities, and streaming optimization availability",
499
- inputSchema: { type: "object", properties: {}, additionalProperties: false }
500
- });
501
- }
502
-
503
- return { tools: baseTools };
504
- });
505
-
506
- this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
507
- const { name, arguments: args } = request.params;
508
- try {
509
- switch (name) {
510
- case "optimize_prompt": return await this.handleOptimizePrompt(args);
511
- case "get_quota_status": return await this.handleGetQuotaStatus();
512
- case "search_templates": return await this.handleSearchTemplates(args);
513
- case "list_recent_templates": return await this.handleListRecentTemplates(args);
514
- case "detect_ai_context": return await this.handleDetectAIContext(args);
515
- case "create_template": return await this.handleCreateTemplate(args);
516
- case "get_template": return await this.handleGetTemplate(args);
517
- case "update_template": return await this.handleUpdateTemplate(args);
518
- case "delete_template": return await this.handleDeleteTemplate(args);
519
- case "get_optimization_insights": return await this.handleGetOptimizationInsights(args);
520
- case "get_real_time_status": return await this.handleGetRealTimeStatus();
521
- case "generate_agent_sop": return await this.handleGenerateAgentSop(args);
522
- case "generate_skill_package": return await this.handleGenerateSkillPackage(args);
523
- case "transform_for_framework": return await this.handleTransformForFramework(args);
524
- case "get_ce_quota_status": return await this.handleGetCEQuotaStatus();
525
- case "generate_harness_bundle": return await this.handleGenerateHarnessBundle(args);
526
- case "explore_sop_approaches": return await this.handleExploreSopApproaches(args);
527
- default: throw new Error(`Unknown tool: ${name}`);
528
- }
529
- } catch (error) {
530
- throw new Error(`Tool execution failed: ${error.message}`);
531
- }
532
- });
533
- }
534
-
535
- // ─── Rules-Based Optimization (offline / fallback tier) ─────────────────────
536
-
537
- /**
538
- * Select the best-matching template for a prompt using pattern scoring.
539
- * Mirrors the backend's pattern-based fallback (no LLM required).
540
- */
541
- _matchTemplate(prompt, backendContext) {
542
- const lc = prompt.toLowerCase();
543
- let bestTemplate = null;
544
- let bestScore = 0;
545
- let fallbackName = null;
546
-
547
- for (const [name, template] of Object.entries(OPTIMIZATION_TEMPLATES)) {
548
- if (template.context !== backendContext) continue;
549
- if (name.startsWith('fallback_')) { fallbackName = name; continue; }
550
-
551
- let hits = 0;
552
- for (const pattern of template.patterns) {
553
- if (pattern === '.*') continue;
554
- if (lc.includes(pattern.toLowerCase())) hits++;
555
- }
556
- if (hits === 0) continue;
557
-
558
- // Confidence: 1 hit → 0.6, 2 hits → 0.75, 3+ hits → 0.9 (mirrors backend)
559
- const patternConf = hits === 1 ? 0.6 : hits === 2 ? 0.75 : 0.9;
560
- const score = patternConf + (template.priority || 1) / 100;
561
-
562
- if (score > bestScore) { bestScore = score; bestTemplate = name; }
563
- }
564
-
565
- if (!bestTemplate) {
566
- return { templateName: fallbackName || `fallback_${backendContext.toLowerCase()}`, matchConfidence: 0.3 };
567
- }
568
- return { templateName: bestTemplate, matchConfidence: bestScore };
569
- }
570
-
571
- /** Extract a user-defined role from the start of a prompt (e.g. "As a doctor, …"). */
572
- _extractUserRole(request) {
573
- const rolePatterns = [
574
- /^['"]?(?:As a|You are a|My role is)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
575
- /^['"]?(?:I am a|I'm a)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
576
- ];
577
- for (const re of rolePatterns) {
578
- const m = request.match(re);
579
- if (m) return m[1].trim();
580
- }
581
- return null;
582
- }
583
-
584
- /**
585
- * Compile a template playbook into a user-facing prose prompt.
586
- * Produces readable output instead of XML scaffolding, matching the
587
- * result a backend LLM pass would generate from the same playbook.
588
- */
589
- _compilePlaybook(playbook, originalRequest) {
590
- const parts = [];
591
-
592
- parts.push(originalRequest.trim());
593
- parts.push('');
594
-
595
- const userFacingPrinciples = (playbook.principles || []).filter(p => {
596
- const lc = p.toLowerCase();
597
- return !lc.includes('scratchpad') &&
598
- !lc.startsWith('first, think') &&
599
- !/<[a-z]/i.test(p);
600
- });
601
-
602
- if (userFacingPrinciples.length > 0) {
603
- parts.push('To address this effectively:');
604
- for (const p of userFacingPrinciples) parts.push(`- ${p}`);
605
- parts.push('');
606
- }
607
-
608
- if (playbook.output_format) {
609
- parts.push(`*Response format: ${playbook.output_format}*`);
610
- }
611
-
612
- return parts.join('\n');
613
- }
614
-
615
- /**
616
- * Enhance an image generation prompt by appending style-appropriate
617
- * quality/composition boosters (mirrors backend _compile_image_prompt_fallback).
618
- */
619
- _compileImagePrompt(originalRequest) {
620
- const text = originalRequest.trim();
621
- const lc = text.toLowerCase();
622
-
623
- const styles = {
624
- photorealistic: ['photorealistic','realistic','photo','photograph','photography'],
625
- '3d_render': ['3d','render','octane','unreal engine','blender','cinema 4d','ray tracing'],
626
- cinematic: ['cinematic','movie','film','dramatic','epic'],
627
- digital_art: ['digital art','concept art','digital illustration','cg','cgi'],
628
- artistic: ['artistic','painting','watercolor','oil painting','impressionist'],
629
- anime: ['anime','manga'],
630
- vintage: ['vintage','retro','nostalgic'],
631
- minimalist: ['minimalist','minimal','simple','clean'],
632
- };
633
-
634
- let detectedStyle = null;
635
- for (const [style, kws] of Object.entries(styles)) {
636
- if (kws.some(kw => lc.includes(kw))) { detectedStyle = style; break; }
637
- }
638
-
639
- const enhancements = [];
640
- const hasQuality = ['high quality','8k','4k','hd','highly detailed','detailed'].some(t => lc.includes(t));
641
- const hasLighting = ['lighting','light','shadow','illuminated','lit'].some(t => lc.includes(t));
642
- const hasComposition = ['composition','rule of thirds','centered','framed'].some(t => lc.includes(t));
643
-
644
- if (detectedStyle === 'photorealistic' && !hasQuality) {
645
- enhancements.push('ultra realistic, sharp focus, professional photography');
646
- } else if (detectedStyle === '3d_render' && !['octane','render'].some(t => lc.includes(t))) {
647
- enhancements.push('high quality 3D render, volumetric lighting, ray traced shadows');
648
- } else if (detectedStyle === 'cinematic' && !hasLighting) {
649
- enhancements.push('cinematic lighting, dramatic atmosphere, film grain');
650
- } else if (detectedStyle === 'digital_art' && !hasQuality) {
651
- enhancements.push('highly detailed digital art, professional illustration');
652
- } else if (detectedStyle === 'artistic' && !lc.includes('masterpiece')) {
653
- enhancements.push('masterful technique, rich colors, artistic composition');
654
- }
655
-
656
- if (!hasLighting && detectedStyle !== 'minimalist') enhancements.push('dynamic lighting');
657
- if (!hasComposition) enhancements.push('balanced composition');
658
- if (!hasQuality) enhancements.push('high quality, 4K');
659
-
660
- return enhancements.length > 0 ? `${text}, ${enhancements.join(', ')}` : text;
661
- }
662
-
663
- /**
664
- * Core rules-based optimizer — no network, no LLM.
665
- * Selects the best template by pattern matching, then compiles
666
- * the playbook into a structured prompt. Confidence range: 0.35–0.55.
667
- */
668
- rulesBasedOptimize(prompt, aiContext, goals = []) {
669
- const contextMap = {
670
- code_generation: 'CODE_GENERATION',
671
- llm_interaction: 'LLM_INTERACTION',
672
- image_generation: 'IMAGE_GENERATION',
673
- human_communication: 'HUMAN_COMMUNICATION',
674
- api_automation: 'API_AUTOMATION',
675
- technical_automation: 'TECHNICAL_AUTOMATION',
676
- structured_output: 'STRUCTURED_OUTPUT',
677
- creative_enhancement: 'CREATIVE_ENHANCEMENT',
678
- creative_writing: 'CREATIVE_ENHANCEMENT',
679
- general_assistant: 'LLM_INTERACTION',
680
- };
681
- const backendContext = contextMap[aiContext] || 'LLM_INTERACTION';
682
-
683
- const { templateName, matchConfidence } = this._matchTemplate(prompt, backendContext);
684
- const template = OPTIMIZATION_TEMPLATES[templateName];
685
-
686
- const optimizedPrompt = backendContext === 'IMAGE_GENERATION'
687
- ? this._compileImagePrompt(prompt)
688
- : this._compilePlaybook(template.playbook, prompt);
689
-
690
- // Honest confidence: rules-based tops out around 0.55
691
- const confidence = parseFloat(Math.min(0.35 + matchConfidence * 0.2, 0.55).toFixed(2));
692
-
693
- return {
694
- optimized_prompt: optimizedPrompt,
695
- confidence_score: confidence,
696
- tier: 'rules',
697
- template_used: templateName,
698
- rules_based: true,
699
- template_saved: false,
700
- templates_found: [],
701
- optimization_insights: null,
702
- bayesian_insights: null,
703
- };
704
- }
705
-
706
- // ─── End Rules-Based Optimization ────────────────────────────────────────────
707
-
708
- generateMockOptimization(prompt, goals, aiContext, enableBayesian = false) {
709
- // Use real rules-based optimization instead of fake placeholder output
710
- const rulesResult = this.rulesBasedOptimize(prompt, aiContext, goals);
711
- const baseResult = {
712
- ...rulesResult,
713
- rules_based: false, // Show as normal optimized output in mock mode
714
- tier: 'free',
715
- mock_mode: true,
716
- template_saved: true,
717
- template_id: 'test-template-123',
718
- templates_found: [{ title: 'Similar Template 1', confidence_score: 0.85, id: 'tmpl-1' }],
719
- optimization_insights: {
720
- improvement_metrics: {
721
- clarity_improvement: 0.25,
722
- specificity_improvement: 0.20,
723
- length_optimization: 0.15,
724
- context_alignment: 0.30
725
- },
726
- user_patterns: {
727
- optimization_confidence: '87.0%',
728
- prompt_complexity: 'intermediate',
729
- ai_context: aiContext
730
- },
731
- recommendations: [
732
- `Context detected as ${aiContext}`,
733
- 'Enhanced goal optimization applied',
734
- 'Template auto-save threshold met'
735
- ]
736
- }
737
- };
738
-
739
- // Add Bayesian optimization insights if enabled
740
- if (enableBayesian && this.bayesianOptimizationEnabled) {
741
- baseResult.bayesian_insights = {
742
- parameter_optimization: {
743
- temperature_adjustment: '+0.1',
744
- context_weight: '+0.15',
745
- goal_prioritization: 'clarity > specificity > engagement'
746
- },
747
- performance_prediction: {
748
- expected_improvement: '12-18%',
749
- confidence_interval: '85-95%',
750
- optimization_strategy: 'gradient_boost_context'
751
- },
752
- next_optimization_recommendation: {
753
- suggested_goals: ['analytical_depth', 'creative_enhancement'],
754
- estimated_improvement: '8-12%'
755
- }
756
- };
757
- }
758
-
759
- return baseResult;
760
- }
761
-
762
- generateMockContextDetection(prompt) {
763
- let primary_context = 'human_communication'; // Default context
764
- const lc = prompt.toLowerCase(); // one‑off lower‑case copy
765
-
766
- /* 1️⃣ Code / programming – now includes `def` / `return`. */
767
- if (lc.match(/def\b|return\b|import\b|class\b|for\b|while\b|if\b|else\b|elif\b|function\b|code\b|python|javascript|java|c\+\+/i)) {
768
- primary_context = 'code_generation';
769
-
770
- /* 2️⃣ Image / art – unchanged. */
771
- } else if (lc.match(/image|generate|dall-e|midjourney/i)) {
772
- primary_context = 'image_generation';
773
-
774
- /* 3️⃣ Automation – unchanged. */
775
- } else if (lc.match(/automate|script|api/i)) {
776
- primary_context = 'technical_automation';
777
-
778
- /* 4️⃣ LLM / analysis – newly added keyword “analyze”. */
779
- } else if (lc.match(/analyze|explain|evaluate|summary|research|paper|analysis|interpret|discussion|assessment|compare|contrast/i)) {
780
- primary_context = 'llm_interaction';
781
- }
782
-
783
- return {
784
- primary_context: primary_context,
785
- confidence: 0.75,
786
- secondary_contexts: ['llm_interaction'],
787
- detected_parameters: [],
788
- mock_mode: true,
789
- reason: 'Backend unavailable — using local pattern matching as fallback.'
790
- };
791
- }
792
-
793
- async handleOptimizePrompt(args) {
794
- if (!args.prompt) throw new Error('Prompt is required');
795
-
796
- const manager = new CloudApiKeyManager(this.apiKey);
797
-
798
- try {
799
- const validation = await manager.validateApiKey();
800
-
801
- if (validation.mock_mode || this.developmentMode) {
802
- // In mock/dev mode, we still need a context for mock generation
803
- const mockContext = args.ai_context || 'human_communication';
804
- const mockGoals = args.goals || ['clarity'];
805
- const mockEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
806
- const mockResult = this.generateMockOptimization(args.prompt, mockGoals, mockContext, mockEnableBayesian);
807
- const formatted = this.formatOptimizationResult(mockResult, { detectedContext: mockContext, enableBayesian: mockEnableBayesian });
808
- return { content: [{ type: "text", text: formatted }] };
809
- }
810
-
811
- // 1. Detect AI Context from backend
812
- let detectedContext = args.ai_context;
813
- if (!detectedContext) {
814
- try {
815
- const contextDetectionResult = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
816
- detectedContext = contextDetectionResult.primary_context;
817
- console.error(`Detected AI Context from backend: ${detectedContext}`);
818
- } catch (contextError) {
819
- console.error(`Failed to detect AI context from backend, falling back to default: ${contextError.message}`);
820
- detectedContext = 'human_communication'; // Fallback
821
- }
822
- }
823
-
824
- // 2. Call the main optimization endpoint
825
- const optimizationPayload = {
826
- prompt: args.prompt,
827
- goals: args.goals || ['clarity'],
828
- ai_context: detectedContext,
829
- };
830
-
831
- if (args.value_hierarchy && args.value_hierarchy.length > 0) {
832
- optimizationPayload.value_hierarchy = args.value_hierarchy;
833
- }
834
-
835
- if (args.intent_frame && typeof args.intent_frame === 'object') {
836
- const { perspective, out_of_scope, success_definition } = args.intent_frame;
837
- if (perspective || (out_of_scope && out_of_scope.length > 0) || success_definition) {
838
- optimizationPayload.intent_frame = args.intent_frame;
839
- }
840
- }
841
-
842
- const result = await this.callBackendAPI(ENDPOINTS.OPTIMIZE, optimizationPayload);
843
-
844
- const enableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
845
- return { content: [{ type: "text", text: this.formatOptimizationResult(result, { detectedContext, enableBayesian }) }] };
846
-
847
- } catch (error) {
848
- if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout') || error.message.includes('Connection')) {
849
- const fallbackContext = args.ai_context || 'human_communication';
850
- const fallbackEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
851
- const fallbackResult = this.rulesBasedOptimize(args.prompt, fallbackContext, args.goals || ['clarity']);
852
- fallbackResult.fallback_mode = true;
853
- fallbackResult.error_reason = error.message;
854
- const formatted = this.formatOptimizationResult(fallbackResult, { detectedContext: fallbackContext, enableBayesian: fallbackEnableBayesian });
855
- return { content: [{ type: "text", text: formatted }] };
856
- }
857
- throw new Error(`Optimization failed: ${error.message}`);
858
- }
859
- }
860
-
861
- async handleGetQuotaStatus() {
862
- const manager = new CloudApiKeyManager(this.apiKey);
863
- const info = await manager.getApiKeyInfo();
864
- return { content: [{ type: "text", text: this.formatQuotaStatus(info) }] };
865
- }
866
-
867
- async handleSearchTemplates(args) {
868
- try {
869
- const params = new URLSearchParams({
870
- page: (args.page || 1).toString(),
871
- per_page: Math.min(args.limit || 5, 20).toString(),
872
- sort_by: args.sort_by || 'confidence_score',
873
- sort_order: args.sort_order || 'desc'
874
- });
875
-
876
- if (args.query) params.append('query', args.query);
877
- if (args.ai_context) params.append('ai_context', args.ai_context);
878
- if (args.sophistication_level) params.append('sophistication_level', args.sophistication_level);
879
- if (args.complexity_level) params.append('complexity_level', args.complexity_level);
880
- if (args.optimization_strategy) params.append('optimization_strategy', args.optimization_strategy);
881
-
882
- const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
883
- const result = await this.callBackendAPI(endpoint, null, 'GET');
884
-
885
- const searchResult = {
886
- templates: result.templates || [],
887
- total: result.total || 0,
888
- query: args.query,
889
- ai_context: args.ai_context,
890
- sophistication_level: args.sophistication_level,
891
- complexity_level: args.complexity_level
892
- };
893
-
894
- const formatted = this.formatTemplateSearchResults(searchResult, args);
895
- return { content: [{ type: "text", text: formatted }] };
896
-
897
- } catch (error) {
898
- console.error(`Template search failed: ${error.message}`);
899
- const fallbackResult = {
900
- templates: [],
901
- total: 0,
902
- message: "Template search is temporarily unavailable.",
903
- error: error.message,
904
- fallback_mode: true
905
- };
906
- const formatted = this.formatTemplateSearchResults(fallbackResult, args);
907
- return { content: [{ type: "text", text: formatted }] };
908
- }
909
- }
910
-
911
- async handleListRecentTemplates(args) {
912
- try {
913
- const limit = Math.min(Math.max(args.limit || 10, 1), 20);
914
- const params = new URLSearchParams({
915
- page: '1',
916
- per_page: limit.toString(),
917
- sort_by: 'created_at',
918
- sort_order: 'desc'
919
- });
920
-
921
- const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
922
- const result = await this.callBackendAPI(endpoint, null, 'GET');
923
-
924
- const templates = result.templates || [];
925
- let output = `# 📋 Recent Templates\n\n`;
926
- output += `Showing **${templates.length}** most recently saved template(s).\n\n`;
927
-
928
- if (templates.length === 0) {
929
- output += `📭 No templates found yet.\nRun \`optimize_prompt\` to start building your template library.\n`;
930
- } else {
931
- output += `## 📋 **Template Results**\n`;
932
- templates.forEach((t, index) => {
933
- const confidence = t.confidence_score ? `${(t.confidence_score * 100).toFixed(1)}%` : 'N/A';
934
- const preview = t.optimized_prompt ? t.optimized_prompt.substring(0, 60) + '...' : 'Preview unavailable';
935
- output += `### ${index + 1}. ${t.title}\n`;
936
- output += `- **Confidence:** ${confidence}\n`;
937
- output += `- **ID:** \`${t.id}\`\n`;
938
- output += `- **Preview:** ${preview}\n`;
939
- if (t.ai_context) output += `- **Context:** ${t.ai_context}\n`;
940
- if (t.optimization_goals && t.optimization_goals.length) {
941
- output += `- **Goals:** ${t.optimization_goals.join(', ')}\n`;
942
- }
943
- output += `\n`;
944
- });
945
- output += `💡 Use \`get_template\` with an ID above to view the full optimized prompt.\n`;
946
- }
947
-
948
- return { content: [{ type: "text", text: output }] };
949
- } catch (error) {
950
- return { content: [{ type: "text", text: `❌ Could not retrieve recent templates: ${error.message}` }] };
951
- }
952
- }
953
-
954
- async handleGetOptimizationInsights(args) {
955
- if (!this.bayesianOptimizationEnabled) {
956
- return { content: [{ type: "text", text: "🧠 Bayesian optimization features are not enabled. Set ENABLE_BAYESIAN_OPTIMIZATION=true to access advanced insights." }] };
957
- }
958
-
959
- try {
960
- // Try to get insights from backend
961
- const endpoint = `${ENDPOINTS.ANALYTICS_BAYESIAN_INSIGHTS}?depth=${args.analysis_depth || 'detailed'}&recommendations=${args.include_recommendations !== false}`;
962
- const result = await this.callBackendAPI(endpoint, null, 'GET');
963
-
964
- return { content: [{ type: "text", text: this.formatOptimizationInsights(result) }] };
965
-
966
- } catch (error) {
967
- // Fallback to mock insights
968
- const mockInsights = {
969
- bayesian_status: {
970
- optimization_active: true,
971
- total_optimizations: 47,
972
- improvement_rate: '23.5%',
973
- confidence_score: 0.89
974
- },
975
- parameter_insights: {
976
- most_effective_goals: ['clarity', 'technical_accuracy', 'analytical_depth'],
977
- context_performance: {
978
- 'code_generation': 0.92,
979
- 'llm_interaction': 0.87,
980
- 'technical_automation': 0.84
981
- },
982
- optimization_trends: 'Steady improvement in technical contexts'
983
- },
984
- recommendations: args.include_recommendations !== false ? [
985
- 'Focus on technical_accuracy for code generation prompts',
986
- 'Combine clarity with analytical_depth for best results',
987
- 'Consider using structured_output context for data tasks'
988
- ] : []
989
- };
990
-
991
- return { content: [{ type: "text", text: this.formatOptimizationInsights(mockInsights) }] };
992
- }
993
- }
994
-
995
- async handleGetRealTimeStatus() {
996
- if (!this.aguiFeatures) {
997
- return { content: [{ type: "text", text: "⚡ AG-UI real-time features are not enabled. Set ENABLE_AGUI_FEATURES=true to access real-time optimization capabilities." }] };
998
- }
999
-
1000
- try {
1001
- const result = await this.callBackendAPI(ENDPOINTS.AGUI_STATUS, null, 'GET');
1002
-
1003
- return { content: [{ type: "text", text: this.formatRealTimeStatus(result) }] };
1004
-
1005
- } catch (error) {
1006
- const mockStatus = {
1007
- agui_status: 'available',
1008
- streaming_optimization: true,
1009
- websocket_support: true,
1010
- real_time_analytics: true,
1011
- active_optimizations: 3,
1012
- average_response_time: '1.2s',
1013
- features: {
1014
- live_optimization: true,
1015
- collaborative_editing: true,
1016
- instant_feedback: true,
1017
- performance_monitoring: true
1018
- }
1019
- };
1020
-
1021
- return { content: [{ type: "text", text: this.formatRealTimeStatus(mockStatus) }] };
1022
- }
1023
- }
1024
-
1025
- async handleDetectAIContext(args) {
1026
- if (!args.prompt) throw new Error('Prompt is required');
1027
-
1028
- const formatResult = (result) => {
1029
- let output = `# 🧠 AI Context Detection Result\n\n`;
1030
- output += `**Primary Context:** ${result.primary_context}\n`;
1031
- output += `**Confidence:** ${(result.confidence * 100).toFixed(1)}%\n`;
1032
- if (result.secondary_contexts && result.secondary_contexts.length > 0) {
1033
- output += `**Secondary Contexts:** ${result.secondary_contexts.join(', ')}\n`;
1034
- }
1035
-
1036
- const detections = result.detected_parameters ?? [];
1037
- const safeDetections = detections.filter(d => d && d.name);
1038
-
1039
- if (safeDetections.length > 0) {
1040
- output += `**Detected Parameters:** ${safeDetections.map(d => d.name).join(', ')}\n`;
1041
- }
1042
-
1043
- if (result.mock_mode) {
1044
- output += `\n⚠️ **Fallback Mode Active:** Using mock data due to development mode or network issues.\n`;
1045
- }
1046
- return { content: [{ type: "text", text: output }] };
1047
- };
1048
-
1049
- try {
1050
- const manager = new CloudApiKeyManager(this.apiKey);
1051
- const validation = await manager.validateApiKey();
1052
-
1053
- if (validation.mock_mode || this.developmentMode) {
1054
- const mockResult = this.generateMockContextDetection(args.prompt);
1055
- return formatResult(mockResult);
1056
- }
1057
-
1058
- const result = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
1059
- return formatResult(result);
1060
-
1061
- } catch (error) {
1062
- // Fallback for ANY error during the process (missing key, network, etc.)
1063
- const fallbackResult = this.generateMockContextDetection(args.prompt);
1064
- return formatResult(fallbackResult);
1065
- }
1066
- }
1067
-
1068
- async handleCreateTemplate(args) {
1069
- // Client-side validation before network call
1070
- const requiredStrings = ['title', 'original_prompt', 'optimized_prompt'];
1071
- for (const field of requiredStrings) {
1072
- if (!args[field] || typeof args[field] !== 'string' || args[field].trim() === '') {
1073
- return { content: [{ type: "text", text: `❌ Missing required field: '${field}'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
1074
- }
1075
- }
1076
- if (args.confidence_score === undefined || args.confidence_score === null ||
1077
- typeof args.confidence_score !== 'number' || args.confidence_score < 0 || args.confidence_score > 1) {
1078
- return { content: [{ type: "text", text: `❌ Missing required field: 'confidence_score'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
1079
- }
1080
-
1081
- try {
1082
- const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.CREATE, args);
1083
- let output = `# ✅ Template Created Successfully!\n\n`;
1084
- output += `**Title:** ${result.title}\n`;
1085
- output += `**ID:** \`${result.id}\`\n`;
1086
- output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1087
- output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
1088
- output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
1089
- output += `\n**Optimized Prompt Preview:**\n\`\`\`\n${result.optimized_prompt.substring(0, 150)}...\n\`\`\`\n`;
1090
- return { content: [{ type: "text", text: output }] };
1091
- } catch (error) {
1092
- throw new Error(`Failed to create template: ${error.message}`);
1093
- }
1094
- }
1095
-
1096
- async handleGetTemplate(args) {
1097
- if (!args.template_id) throw new Error('Template ID is required');
1098
- try {
1099
- const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.GET(args.template_id), null, 'GET');
1100
- let output = `# 📄 Template Details\n\n`;
1101
- output += `**Title:** ${result.title}\n`;
1102
- output += `**ID:** \`${result.id}\`\n`;
1103
- output += `**Description:** ${result.description || 'N/A'}\n`;
1104
- output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
1105
- output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1106
- output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
1107
- output += `**Tags:** ${result.tags ? result.tags.join(', ') : 'None'}\n\n`;
1108
- output += `**Original Prompt:**\n\`\`\`\n${result.original_prompt}\n\`\`\`\n\n`;
1109
- output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n`;
1110
- return { content: [{ type: "text", text: output }] };
1111
- } catch (error) {
1112
- const msg = error.message || '';
1113
- if (msg.includes('404') || msg.toLowerCase().includes('not found')) {
1114
- 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.`);
1115
- }
1116
- throw new Error(`Failed to retrieve template: ${error.message}`);
1117
- }
1118
- }
1119
-
1120
- async handleUpdateTemplate(args) {
1121
- if (!args.template_id) throw new Error('Template ID is required');
1122
- try {
1123
- const { template_id, ...updateData } = args;
1124
- // Filter out undefined values so we only send fields that are being updated
1125
- Object.keys(updateData).forEach(key => updateData[key] === undefined && delete updateData[key]);
1126
-
1127
- const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.UPDATE(template_id), updateData, 'PATCH'); // PATCH is better for partial updates
1128
- let output = `# ✅ Template Updated Successfully!\n\n`;
1129
- output += `**ID:** \`${result.id}\`\n`;
1130
- output += `**Title:** ${result.title}\n\n`;
1131
- output += `Use 'get_template' with the ID to see the full updated template.`;
1132
- return { content: [{ type: "text", text: output }] };
1133
- } catch (error) {
1134
- throw new Error(`Failed to update template: ${error.message}`);
1135
- }
1136
- }
1137
-
1138
- async handleDeleteTemplate(args) {
1139
- if (!args.template_id) throw new Error('Template ID is required');
1140
- try {
1141
- const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.DELETE(args.template_id), null, 'DELETE');
1142
- const title = result.message || `Template ${args.template_id}`;
1143
- return { content: [{ type: "text", text: `# 🗑️ Template Deleted\n\n${title}` }] };
1144
- } catch (error) {
1145
- throw new Error(`Failed to delete template: ${error.message}`);
1146
- }
1147
- }
1148
-
1149
- async handleGenerateAgentSop(args) {
1150
- if (!args.goal) throw new Error('goal is required');
1151
- const payload = { goal: args.goal };
1152
- if (args.context) payload.context = args.context;
1153
- if (args.model_id) payload.model_id = args.model_id;
1154
- if (args.intent_frame) payload.intent_frame = args.intent_frame;
1155
- try {
1156
- const result = await this.callBackendAPI(ENDPOINTS.CE.SOP, payload);
1157
- const sopContent = result.sop || result.content || result.result || JSON.stringify(result, null, 2);
1158
- return { content: [{ type: "text", text: `# Agent SOP Generated\n\n${sopContent}\n\n---\n*Generated by MCP Prompt Optimizer CE*` }] };
1159
- } catch (error) {
1160
- throw new Error(`Failed to generate SOP: ${error.message}`);
1161
- }
1162
- }
1163
-
1164
- async handleGenerateSkillPackage(args) {
1165
- if (!args.goal) throw new Error('goal is required');
1166
- const payload = { goal: args.goal, format: args.format || 'knowledge_doc' };
1167
- if (args.model_id) payload.model_id = args.model_id;
1168
- let workflowError = null;
1169
- try {
1170
- const startResult = await this.callBackendAPI(ENDPOINTS.CE.GENERATE_SKILL_PACKAGE, payload);
1171
- const sessionId = startResult.session_id;
1172
- if (!sessionId) {
1173
- return { content: [{ type: "text", text: this._formatSkillPackage(startResult) }] };
1174
- }
1175
- for (let i = 0; i < 24; i++) {
1176
- await new Promise(resolve => setTimeout(resolve, 5000));
1177
- const status = await this.callBackendAPI(ENDPOINTS.CE.SESSION(sessionId), null, 'GET');
1178
- const state = status.workflow_state || status.current_state;
1179
- if (state === 'complete') return { content: [{ type: "text", text: this._formatSkillPackage(status) }] };
1180
- if (state === 'failed') {
1181
- workflowError = new Error(`Generation failed: ${status.error || 'Unknown error'}`);
1182
- throw workflowError;
1183
- }
1184
- }
1185
- workflowError = new Error(`Timed out after 120s. Session ID: ${sessionId}`);
1186
- throw workflowError;
1187
- } catch (error) {
1188
- if (error === workflowError) throw error;
1189
- throw new Error(`Failed to generate skill package: ${error.message}`);
1190
- }
1191
- }
1192
-
1193
- async handleTransformForFramework(args) {
1194
- if (!args.sop_content) throw new Error('sop_content is required');
1195
- if (!args.goal) throw new Error('goal is required');
1196
- if (!args.framework) throw new Error('framework is required');
1197
- const valid = ['langchain_tool', 'autogen_agent', 'claude_skill'];
1198
- if (!valid.includes(args.framework)) throw new Error(`framework must be one of: ${valid.join(', ')}`);
1199
- try {
1200
- const result = await this.callBackendAPI(ENDPOINTS.CE.TRANSFORM, {
1201
- sop_content: args.sop_content, goal: args.goal, framework: args.framework
1202
- });
1203
- const code = result.code || result.content || result.result || JSON.stringify(result, null, 2);
1204
- return { content: [{ type: "text", text: `# ${args.framework} Implementation\n\n\`\`\`python\n${code}\n\`\`\`\n\n---\n*Transformed by MCP Prompt Optimizer CE*` }] };
1205
- } catch (error) {
1206
- throw new Error(`Failed to transform: ${error.message}`);
1207
- }
1208
- }
1209
-
1210
- async handleGetCEQuotaStatus() {
1211
- try {
1212
- const result = await this.callBackendAPI(ENDPOINTS.CE.QUOTA, null, 'GET');
1213
- const lines = ['## CE Credit Balance', ''];
1214
- if (result.is_unlimited) {
1215
- lines.push(`Credits: **Unlimited** (${result.credits_used || 0} used this period)`);
1216
- } else {
1217
- lines.push(`Credits: **${result.credits_remaining ?? 'N/A'}** of ${result.credits_limit} remaining (${result.credits_used || 0} used)`);
1218
- }
1219
- lines.push('', '## Available Workflows');
1220
- if (result.workflow_availability) {
1221
- for (const [type, info] of Object.entries(result.workflow_availability)) {
1222
- lines.push(`- ${info.available ? '✓' : '✗'} ${type}: ${info.cost_credits} credit(s)`);
1223
- }
1224
- }
1225
- if (result.message) lines.push('', result.message);
1226
- return { content: [{ type: "text", text: lines.join('\n') }] };
1227
- } catch (error) {
1228
- throw new Error(`Failed to get CE quota: ${error.message}`);
1229
- }
1230
- }
1231
-
1232
- async handleGenerateHarnessBundle(args) {
1233
- if (!args.sop_content && !args.session_id) {
1234
- return { content: [{ type: "text", text: "Error: provide either sop_content or session_id." }] };
1235
- }
1236
- // Normalize deploy_target: string → [string], array → array, undefined → ["claude_code"]
1237
- let deployTargets;
1238
- if (!args.deploy_target) {
1239
- deployTargets = ["claude_code"];
1240
- } else if (Array.isArray(args.deploy_target)) {
1241
- deployTargets = args.deploy_target;
1242
- } else {
1243
- deployTargets = [args.deploy_target];
1244
- }
1245
- // Guard: empty array falls back to default
1246
- if (deployTargets.length === 0) {
1247
- deployTargets = ["claude_code"];
1248
- }
1249
-
1250
- const payload = {
1251
- goal: args.goal,
1252
- deploy_target: deployTargets.length === 1 ? deployTargets[0] : deployTargets,
1253
- platform: deployTargets[0],
1254
- user_goal: args.goal,
1255
- sop_content: args.sop_content || "",
1256
- };
1257
-
1258
- // If session_id provided, first fetch session artifacts for sop_content
1259
- if (args.session_id) {
1260
- try {
1261
- const status = await this.callBackendAPI(ENDPOINTS.CE.SESSION(args.session_id), null, "GET");
1262
- const sop = status.artifacts?.sop_content || status.sop_content || "";
1263
- if (sop) payload.sop_content = sop;
1264
- } catch (sessionErr) {
1265
- console.error(`[handleGenerateHarnessBundle] Could not fetch session ${args.session_id}:`, sessionErr.message || sessionErr);
1266
- // Proceed with empty sop_content; backend will handle gracefully
1267
- }
1268
- }
1269
-
1270
- try {
1271
- await this.callBackendAPI(ENDPOINTS.CE.HARNESS_BUNDLE, payload);
1272
- return {
1273
- content: [{
1274
- type: "text",
1275
- text: `# Harness Bundle Requested\n\nDeploy target: **${deployTargets.join(", ")}**\nGoal: ${args.goal}\n\nDownload from the CE dashboard or via the /harness-bundle API endpoint.`
1276
- }]
1277
- };
1278
- } catch (error) {
1279
- const msg = error?.message || String(error);
1280
- if (msg.includes("TIER_LIMIT_REACHED")) {
1281
- return { content: [{ type: "text",
1282
- text: `Upgrade required: this deploy target requires Pro tier or higher. Upgrade at /pricing.`
1283
- }] };
1284
- }
1285
- throw error;
1286
- }
1287
- }
1288
-
1289
- async handleExploreSopApproaches(args) {
1290
- if (!args.goal) {
1291
- return { content: [{ type: "text", text: "Error: goal is required." }] };
1292
- }
1293
-
1294
- // If blend_description provided, explore then blend in one call chain
1295
- if (args.blend_description) {
1296
- try {
1297
- const explorePayload = {
1298
- goal: args.goal,
1299
- context: args.context || undefined,
1300
- perspective: args.perspective || undefined,
1301
- out_of_scope: args.out_of_scope || undefined,
1302
- success_definition: args.success_definition || undefined,
1303
- };
1304
- const exploreResult = await this.callBackendAPI(ENDPOINTS.CE.SOP_EXPLORE, explorePayload);
1305
- const blendPayload = {
1306
- variants: exploreResult.variants,
1307
- blend_description: args.blend_description,
1308
- goal: args.goal,
1309
- };
1310
- const blendResult = await this.callBackendAPI(ENDPOINTS.CE.SOP_BLEND, blendPayload);
1311
- return {
1312
- content: [{
1313
- type: "text",
1314
- text: `# Blended SOP\n\n${blendResult.sop_content}`
1315
- }]
1316
- };
1317
- } catch (error) {
1318
- throw new Error(`Failed to blend SOP approaches: ${error.message}`);
1319
- }
1320
- }
1321
-
1322
- // Standard exploration: return 3 variant summaries
1323
- try {
1324
- const payload = {
1325
- goal: args.goal,
1326
- context: args.context || undefined,
1327
- perspective: args.perspective || undefined,
1328
- out_of_scope: args.out_of_scope || undefined,
1329
- success_definition: args.success_definition || undefined,
1330
- };
1331
- const result = await this.callBackendAPI(ENDPOINTS.CE.SOP_EXPLORE, payload);
1332
-
1333
- const variantSummaries = result.variants.map(v => {
1334
- const rec = v.id === result.recommended ? " *(Recommended)*" : "";
1335
- return `## Variant ${v.id} — ${v.approach.replace('_', '-')}${rec}\n\n${v.content.slice(0, 600)}${v.content.length > 600 ? '\n\n...(truncated)' : ''}`;
1336
- }).join('\n\n---\n\n');
1337
-
1338
- return {
1339
- content: [{
1340
- type: "text",
1341
- text: `# SOP Exploration Results\n\n**Goal:** ${args.goal}\n**Recommended:** Variant ${result.recommended}\n\n---\n\n${variantSummaries}\n\n---\n\n*To select a variant, call generate_skill_package with the full content of your chosen variant as sop_content. To blend variants, re-call explore_sop_approaches with blend_description.*`
1342
- }]
1343
- };
1344
- } catch (error) {
1345
- if (error.message && error.message.includes('403')) {
1346
- return { content: [{ type: "text", text: "Error: SOP exploration requires Innovator tier. Upgrade at /pricing." }] };
1347
- }
1348
- throw new Error(`Failed to explore SOP approaches: ${error.message}`);
1349
- }
1350
- }
1351
-
1352
- _formatSkillPackage(result) {
1353
- const sections = ['# Skill Package Generated'];
1354
- const artifacts = result.artifacts || result.steps || {};
1355
- if (typeof artifacts === 'object' && Object.keys(artifacts).length > 0) {
1356
- for (const [key, value] of Object.entries(artifacts)) {
1357
- if (value && typeof value === 'string') sections.push(`\n## ${key}\n\n${value}`);
1358
- }
1359
- } else {
1360
- sections.push('\n```json\n' + JSON.stringify(result, null, 2) + '\n```');
1361
- }
1362
- sections.push('\n---\n*Generated by MCP Prompt Optimizer CE*');
1363
- return sections.join('\n');
1364
- }
1365
-
1366
- _buildUrl(path) {
1367
- return `${this.backendUrl}${path}`;
1368
- }
1369
-
1370
- async callBackendAPI(endpoint, data, method = 'POST') {
1371
- return new Promise((resolve, reject) => {
1372
- const url = this._buildUrl(endpoint);
1373
-
1374
- const options = {
1375
- method: method,
1376
- headers: {
1377
- 'x-api-key': this.apiKey,
1378
- 'Content-Type': 'application/json',
1379
- 'User-Agent': `mcp-prompt-optimizer/${packageJson.version}`,
1380
- 'Accept': 'application/json',
1381
- 'Connection': 'close'
1382
- },
1383
- timeout: this.requestTimeout
1384
- };
1385
-
1386
- const client = this.backendUrl.startsWith('https://') ? https : require('http');
1387
- const req = client.request(url, options, (res) => {
1388
- let responseData = '';
1389
-
1390
- res.on('data', (chunk) => {
1391
- responseData += chunk;
1392
- });
1393
-
1394
- res.on('end', () => {
1395
- try {
1396
- if (res.statusCode >= 200 && res.statusCode < 300) {
1397
- const contentType = res.headers['content-type'] || '';
1398
- if (contentType.includes('application/json') || contentType === '') {
1399
- try {
1400
- const parsed = JSON.parse(responseData);
1401
- resolve(parsed);
1402
- } catch (e) {
1403
- reject(new Error(`Invalid response format: ${e.message}`));
1404
- }
1405
- } else {
1406
- // Binary or non-JSON response (e.g., application/zip) — return metadata
1407
- resolve({ _binary: true, contentType, size: responseData.length });
1408
- }
1409
- } else {
1410
- let errorMessage;
1411
- try {
1412
- const error = JSON.parse(responseData);
1413
- errorMessage = (typeof error.detail === 'object' && error.detail !== null)
1414
- ? JSON.stringify(error.detail)
1415
- : (error.detail || error.message || `HTTP ${res.statusCode}`);
1416
- } catch {
1417
- errorMessage = `HTTP ${res.statusCode}: ${responseData}`;
1418
- }
1419
- reject(new Error(errorMessage));
1420
- }
1421
- } catch (parseError) {
1422
- reject(new Error(`Invalid response format: ${parseError.message}`));
1423
- }
1424
- });
1425
- });
1426
-
1427
- req.on('error', (error) => {
1428
- if (error.code === 'ENOTFOUND') {
1429
- reject(new Error(`DNS resolution failed: Cannot resolve ${this.backendUrl.replace(/^https?:\/\//, '')}`));
1430
- } else if (error.code === 'ECONNREFUSED') {
1431
- reject(new Error(`Connection refused: Backend server may be down`));
1432
- } else if (error.code === 'ETIMEDOUT') {
1433
- reject(new Error(`Connection timeout: Backend server is not responding`));
1434
- } else if (error.code === 'ECONNRESET') {
1435
- reject(new Error(`Connection reset: Network instability detected`));
1436
- } else {
1437
- reject(new Error(`Network error: ${error.message}`));
1438
- }
1439
- });
1440
-
1441
- req.on('timeout', () => {
1442
- req.destroy();
1443
- reject(new Error('Request timeout - backend may be unavailable'));
1444
- });
1445
-
1446
- if (method !== 'GET' && data) {
1447
- req.write(JSON.stringify(data));
1448
- }
1449
- req.end();
1450
- });
1451
- }
1452
-
1453
- formatOptimizationResult(result, context) {
1454
- let output;
1455
- if (result.rules_based) {
1456
- if (result.fallback_mode) {
1457
- output = `# 🔧 Prompt Optimized (Local Rules)\n\n`;
1458
- output += `*Optimized using local rule templates — LLM quality available once you connect your API key.*\n\n`;
1459
- } else {
1460
- output = `# 🔧 Rules-Based Optimization Applied\n\n`;
1461
- output += `*API key not validated — optimized using local rule templates. `;
1462
- output += `Set \`MCP_API_KEY\` for full LLM optimization.*\n\n`;
1463
- }
1464
- output += `**Template:** \`${result.template_used || 'general'}\`\n\n`;
1465
- output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1466
- } else if (result.fallback_mode) {
1467
- output = `# 🔧 Optimized (local rules — backend slow)\n\n`;
1468
- output += `*Backend unavailable this time — applied local rule templates. Try again for LLM optimization.*\n\n`;
1469
- output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1470
- } else {
1471
- output = `# 🎯 Optimized Prompt\n\n${result.optimized_prompt}\n\n`;
1472
- if (result.confidence_score < 0.25) {
1473
- output += `> ℹ️ *Low confidence indicates the backend applied rules-based optimization (no LLM). `;
1474
- output += `Ensure \`OPENROUTER_API_KEY\` is configured in the backend for full LLM enhancement.*\n\n`;
1475
- }
1476
- }
1477
- if (result.rules_based) {
1478
- output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}% *(rules-based — LLM optimization typically 70–95%)*\n`;
1479
- } else {
1480
- output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1481
- }
1482
- output += `**AI Context:** ${result.metadata?.context_detection?.ai_context || context.detectedContext}\n`;
1483
-
1484
- if (result.template_saved) {
1485
- output += `\n📁 **Template Auto-Save**\n✅ Automatically saved as template (ID: \`${result.template_id}\`)\n*Confidence threshold: >70% required for auto-save*\n`;
1486
- }
1487
-
1488
- if (result.templates_found?.length) {
1489
- output += `\n📋 **Similar Templates Found**\nFound **${result.templates_found.length}** similar template(s):\n`;
1490
- result.templates_found.slice(0, 3).forEach(t => {
1491
- output += `- ${t.title} (${(t.confidence_score * 100).toFixed(1)}% match) ID: \`${t.id}\`\n`;
1492
- });
1493
- output += `\n💡 Use \`get_template\` with any ID above to view the full optimized prompt.\n`;
1494
- }
1495
-
1496
- if (result.optimization_insights) {
1497
- const metrics = result.optimization_insights.improvement_metrics;
1498
- if (metrics) {
1499
- output += `\n📊 **Optimization Insights**\n`;
1500
- if (metrics.clarity_improvement) output += `- Clarity: +${(metrics.clarity_improvement * 100).toFixed(1)}%\n`;
1501
- if (metrics.specificity_improvement) output += `- Specificity: +${(metrics.specificity_improvement * 100).toFixed(1)}%\n`;
1502
- if (metrics.context_alignment) output += `- Context Alignment: +${(metrics.context_alignment * 100).toFixed(1)}%\n`;
1503
- }
1504
-
1505
- if (result.optimization_insights.recommendations?.length) {
1506
- output += `\n💡 **Recommendations:**\n`;
1507
- result.optimization_insights.recommendations.forEach(rec => {
1508
- output += `- ${rec}\n`;
1509
- });
1510
- }
1511
- }
1512
-
1513
- // Add Bayesian insights if available
1514
- if (result.bayesian_insights && context.enableBayesian) {
1515
- output += `\n🧠 **Bayesian Optimization Insights**\n`;
1516
- const bayesian = result.bayesian_insights;
1517
-
1518
- if (bayesian.parameter_optimization) {
1519
- output += `**Parameter Tuning:**\n`;
1520
- if (bayesian.parameter_optimization.temperature_adjustment) {
1521
- output += `- Temperature: ${bayesian.parameter_optimization.temperature_adjustment}\n`;
1522
- }
1523
- if (bayesian.parameter_optimization.goal_prioritization) {
1524
- output += `- Goal Priority: ${bayesian.parameter_optimization.goal_prioritization}\n`;
1525
- }
1526
- }
1527
-
1528
- if (bayesian.performance_prediction) {
1529
- output += `**Performance Prediction:**\n`;
1530
- output += `- Expected Improvement: ${bayesian.performance_prediction.expected_improvement}\n`;
1531
- output += `- Confidence Interval: ${bayesian.performance_prediction.confidence_interval}\n`;
1532
- }
1533
-
1534
- if (bayesian.next_optimization_recommendation) {
1535
- output += `**Next Optimization:**\n`;
1536
- output += `- Suggested Goals: ${bayesian.next_optimization_recommendation.suggested_goals.join(', ')}\n`;
1537
- output += `- Estimated Improvement: ${bayesian.next_optimization_recommendation.estimated_improvement}\n`;
1538
- }
1539
- }
1540
-
1541
- if (!result.fallback_mode) {
1542
- if (result.quota_used != null) {
1543
- if (result.quota_limit == null) {
1544
- // Unlimited plan — show status only, no upsell
1545
- output += `\n📊 **Usage:** ${result.quota_used} optimizations — ✓ Unlimited plan\n`;
1546
- } else {
1547
- const remaining = result.quota_limit - result.quota_used;
1548
- if (result.quota_used >= result.quota_limit) {
1549
- output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} quota reached. **[Upgrade for more →](https://promptoptimizer.xyz/pricing)**\n`;
1550
- } else if (remaining <= 2) {
1551
- output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} LLM optimizations (${remaining} left) [Upgrade for more](https://promptoptimizer.xyz/pricing)\n`;
1552
- } else {
1553
- output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} LLM optimizations this month — [Upgrade for more](https://promptoptimizer.xyz/pricing)\n`;
1554
- }
1555
- }
1556
- }
1557
- output += `\n🔗 **Quick Actions**\n- Dashboard: https://promptoptimizer.xyz/dashboard\n- Analytics: https://promptoptimizer.xyz/analytics\n`;
1558
- } else {
1559
- const confPct = Math.round((result.confidence_score || 0) * 100);
1560
- output += `\n---\n`;
1561
- output += `\n💡 **Unlock LLM Optimization — Free**\n\n`;
1562
- output += `Local rules reached **${confPct}% confidence**. LLM optimization typically achieves **70–95%** — `;
1563
- output += `more specific, context-aware, and effective for your actual intent.\n\n`;
1564
- output += `**Get started free** (no credit card):\n`;
1565
- output += `1. Sign up at https://promptoptimizer.xyz\n`;
1566
- output += `2. Generate your API key at https://promptoptimizer.xyz/dashboard\n`;
1567
- output += `3. Run in your terminal:\n\n`;
1568
- output += `\`\`\`\nnpx mcp-prompt-optimizer connect\n\`\`\`\n\n`;
1569
- output += `You get **7 LLM optimizations/month free**. Upgrade anytime for more.\n`;
1570
- }
1571
-
1572
- return output;
1573
- }
1574
-
1575
- formatQuotaStatus(result) {
1576
- let output = `# 📊 Account Status\n\n**Plan:** ${result.tier || 'free'}\n`;
1577
-
1578
- const quota = result.quota || {};
1579
- if (quota.unlimited) {
1580
- output += `**Usage:** 🟢 Unlimited\n`;
1581
- } else {
1582
- const used = quota.used || 0;
1583
- const limit = quota.limit || 5000;
1584
- const percentage = limit > 0 ? ((used / limit) * 100).toFixed(1) : 0;
1585
-
1586
- let statusIcon = '🟢';
1587
- if (percentage >= 90) statusIcon = '🔴';
1588
- else if (percentage >= 75) statusIcon = '🟡';
1589
-
1590
- output += `**Usage:** ${statusIcon} ${used}/${limit} (${percentage}%)\n`;
1591
-
1592
- const remaining = limit - used;
1593
- if (remaining <= 0) {
1594
- output += `\n❌ **Quota Exhausted** You have no optimizations remaining this month.\n`;
1595
- output += `Upgrade at https://promptoptimizer.xyz/local-license\n`;
1596
- output += `*(Quota resets at the start of your next billing cycle)*\n`;
1597
- } else if (percentage >= 90) {
1598
- output += `\n⚠️ **Critical** — ${remaining} optimization${remaining === 1 ? '' : 's'} remaining. Upgrade at https://promptoptimizer.xyz/local-license\n`;
1599
- } else if (percentage >= 75) {
1600
- output += `\n⚠️ **Warning** — Approaching your monthly limit.\n`;
1601
- }
1602
- }
1603
-
1604
- output += `\n## **Available Features**\n`;
1605
- if (result.features) {
1606
- if (result.features.optimization) output += `✅ Prompt Optimization\n`;
1607
- if (result.features.template_search) output += `✅ Template Search & Management\n`;
1608
- if (result.features.template_auto_save) output += `✅ Template Auto-Save\n`;
1609
- if (result.features.optimization_insights) output += `✅ Optimization Insights\n`;
1610
- if (this.bayesianOptimizationEnabled) output += `🧠 Bayesian Optimization\n`;
1611
- if (this.aguiFeatures) output += `⚡ AG-UI Real-time Features\n`;
1612
- }
1613
-
1614
- if (result.mode) {
1615
- output += `\n## 🔧 **Mode Status**\n`;
1616
- if (result.mode.development) output += `⚙️ Development Mode\n`;
1617
- if (result.mode.mock) output += `🎭 Mock Mode\n`;
1618
- if (result.mode.fallback) output += `🔄 Fallback Mode\n`;
1619
- if (result.mode.offline) output += `📱 Offline Mode\n`;
1620
- }
1621
-
1622
- output += `\n## 🔗 **Account Management**\n`;
1623
- output += `- Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n`;
1624
- output += `- Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
1625
- output += `- Upgrade: https://promptoptimizer.xyz/local-license\n`;
1626
-
1627
- return output;
1628
- }
1629
-
1630
- formatTemplateSearchResults(result, originalArgs) {
1631
- let output = `# 🔍 Template Search Results\n\n`;
1632
-
1633
- if (originalArgs.query || originalArgs.ai_context || originalArgs.sophistication_level) {
1634
- output += `**Search Criteria:**\n`;
1635
- if (originalArgs.query) output += `- Query: "${originalArgs.query}"\n`;
1636
- if (originalArgs.ai_context) output += `- AI Context: ${originalArgs.ai_context}\n`;
1637
- if (originalArgs.sophistication_level) output += `- Sophistication: ${originalArgs.sophistication_level}\n`;
1638
- if (originalArgs.complexity_level) output += `- Complexity: ${originalArgs.complexity_level}\n`;
1639
- output += `\n`;
1640
- }
1641
-
1642
- output += `Found **${result.total}** template(s)\n\n`;
1643
-
1644
- if (!result.templates || result.templates.length === 0) {
1645
- output += `📭 **No Templates Found**\n`;
1646
- const hasActiveFilters = originalArgs.query || originalArgs.ai_context || originalArgs.sophistication_level || originalArgs.complexity_level;
1647
- if (hasActiveFilters) {
1648
- output += `No templates matched your filters. Try removing \`ai_context\` or \`query\` filters.\n`;
1649
- } else {
1650
- output += `You don't have any saved templates yet. Templates are automatically saved when optimization confidence is >70%.\n`;
1651
- output += `Run \`optimize_prompt\` to start building your template library.\n`;
1652
- }
1653
- } else {
1654
- output += `## 📋 **Template Results**\n`;
1655
- result.templates.forEach((t, index) => {
1656
- const confidence = t.confidence_score ? `${(t.confidence_score * 100).toFixed(1)}%` : 'N/A';
1657
- const preview = t.optimized_prompt ? t.optimized_prompt.substring(0, 60) + '...' : 'Preview unavailable';
1658
-
1659
- output += `### ${index + 1}. ${t.title}\n`;
1660
- output += `- **Confidence:** ${confidence}\n`;
1661
- output += `- **ID:** \`${t.id}\`\n`;
1662
- output += `- **Preview:** ${preview}\n`;
1663
- if (t.ai_context) output += `- **Context:** ${t.ai_context}\n`;
1664
- if (t.optimization_goals && t.optimization_goals.length) {
1665
- output += `- **Goals:** ${t.optimization_goals.join(', ')}\n`;
1666
- }
1667
- output += `\n`;
1668
- });
1669
-
1670
- output += `## 💡 **Template Usage Guide**\n`;
1671
- output += `- Copy prompts for immediate use\n`;
1672
- output += `- Use template IDs to reference specific templates\n`;
1673
- output += `- High-confidence templates (>80%) are most reliable\n`;
1674
- }
1675
-
1676
- if (result.fallback_mode) {
1677
- output += `\n⚠️ **Search Temporarily Unavailable**\n${result.message}\n`;
1678
- }
1679
-
1680
- return output;
1681
- }
1682
-
1683
- formatOptimizationInsights(insights) {
1684
- let output = `# 🧠 Bayesian Optimization Insights\n\n`;
1685
-
1686
- if (insights.bayesian_status) {
1687
- const status = insights.bayesian_status;
1688
- output += `## 📊 **Status Overview**\n`;
1689
- output += `- **Status:** ${status.optimization_active ? '🟢 Active' : '🔴 Inactive'}\n`;
1690
- output += `- **Total Optimizations:** ${status.total_optimizations}\n`;
1691
- output += `- **Improvement Rate:** ${status.improvement_rate}\n`;
1692
- output += `- **System Confidence:** ${(status.confidence_score * 100).toFixed(1)}%\n\n`;
1693
- }
1694
-
1695
- if (insights.parameter_insights) {
1696
- const params = insights.parameter_insights;
1697
- output += `## 🎯 **Parameter Analysis**\n`;
1698
-
1699
- if (params.most_effective_goals) {
1700
- output += `**Most Effective Goals:**\n`;
1701
- params.most_effective_goals.forEach(goal => {
1702
- output += `- ${goal}\n`;
1703
- });
1704
- output += `\n`;
1705
- }
1706
-
1707
- if (params.context_performance) {
1708
- output += `**Context Performance:**\n`;
1709
- Object.entries(params.context_performance).forEach(([context, score]) => {
1710
- const percentage = (score * 100).toFixed(1);
1711
- const icon = score >= 0.9 ? '🟢' : score >= 0.8 ? '🟡' : '🔴';
1712
- output += `- ${context}: ${icon} ${percentage}%\n`;
1713
- });
1714
- output += `\n`;
1715
- }
1716
-
1717
- if (params.optimization_trends) {
1718
- output += `**Trends:** ${params.optimization_trends}\n\n`;
1719
- }
1720
- }
1721
-
1722
- if (insights.recommendations && insights.recommendations.length) {
1723
- output += `## 💡 **Optimization Recommendations**\n`;
1724
- insights.recommendations.forEach((rec, index) => {
1725
- output += `${index + 1}. ${rec}\n`;
1726
- });
1727
- output += `\n`;
1728
- }
1729
-
1730
- output += `## 🔗 **Advanced Analytics**\n`;
1731
- output += `- Full Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
1732
- output += `- Performance Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n`;
1733
-
1734
- return output;
1735
- }
1736
-
1737
- formatRealTimeStatus(status) {
1738
- let output = `# AG-UI Real-Time Status\n\n`;
1739
-
1740
- output += `## 🚀 **Service Status**\n`;
1741
- output += `- **AG-UI Status:** ${status.agui_status === 'available' ? '🟢 Available' : '🔴 Unavailable'}\n`;
1742
- output += `- **Streaming Optimization:** ${status.streaming_optimization ? '✅ Enabled' : '❌ Disabled'}\n`;
1743
- output += `- **WebSocket Support:** ${status.websocket_support ? '✅ Enabled' : '❌ Disabled'}\n`;
1744
- output += `- **Real-time Analytics:** ${status.real_time_analytics ? '✅ Enabled' : '❌ Disabled'}\n\n`;
1745
-
1746
- if (status.active_optimizations !== undefined) {
1747
- output += `## 📈 **Current Activity**\n`;
1748
- output += `- **Active Optimizations:** ${status.active_optimizations}\n`;
1749
- output += `- **Average Response Time:** ${status.average_response_time}\n\n`;
1750
- }
1751
-
1752
- if (status.features) {
1753
- const features = status.features;
1754
- output += `## **Available Features**\n`;
1755
- if (features.live_optimization) output += `✅ Live Optimization\n`;
1756
- if (features.collaborative_editing) output += `✅ Collaborative Editing\n`;
1757
- if (features.instant_feedback) output += `✅ Instant Feedback\n`;
1758
- if (features.performance_monitoring) output += `✅ Performance Monitoring\n`;
1759
- output += `\n`;
1760
- }
1761
-
1762
- output += `## 🔗 **Real-Time Access**\n`;
1763
- output += `- Live Dashboard: https://promptoptimizer-blog.vercel.app/live\n`;
1764
- output += `- WebSocket Endpoint: Available via API\n`;
1765
-
1766
- return output;
1767
- }
1768
-
1769
- async run() {
1770
- const transport = new StdioServerTransport();
1771
- await this.server.connect(transport);
1772
- }
1773
- }
1774
-
1775
- async function startValidatedMCPServer() {
1776
- console.log(`🚀 MCP Prompt Optimizer - Professional Cloud Server v${packageJson.version}\n`);
1777
- console.log(`🧠 Bayesian Optimization: ${process.env.ENABLE_BAYESIAN_OPTIMIZATION === 'true' ? 'Enabled' : 'Disabled'}`);
1778
- console.log(`⚡ AG-UI Features: ${process.env.ENABLE_AGUI_FEATURES === 'true' ? 'Enabled' : 'Disabled'}\n`);
1779
-
1780
- try {
1781
- const apiKey = process.env.OPTIMIZER_API_KEY;
1782
- if (!apiKey) {
1783
- console.error('❌ API key required. Get one at https://promptoptimizer.xyz/local-license');
1784
- process.exit(1);
1785
- }
1786
-
1787
- // SECURITY: No development mode bypass - backend validation required
1788
- const manager = new CloudApiKeyManager(apiKey);
1789
- console.log('🔧 Validating API key...\n');
1790
- const validation = await manager.validateAndPrepare();
1791
-
1792
- console.log('🔧 Starting MCP server...\n');
1793
- const mcpServer = new MCPPromptOptimizer();
1794
- console.log('✅ MCP server ready for connections');
1795
-
1796
- // Enhanced status display
1797
- const quotaDisplay = validation.quotaStatus.unlimited ?
1798
- 'Unlimited' :
1799
- `${validation.quotaStatus.remaining}/${validation.quotaStatus.limit} remaining`;
1800
-
1801
- console.log(`📊 Plan: ${validation.tier} | Quota: ${quotaDisplay}`);
1802
-
1803
- if (validation.mode.mock) console.log('🎭 Running in mock mode');
1804
- if (validation.mode.development) console.log('⚙️ Development mode active');
1805
- if (validation.mode.fallback) console.log('🔄 Fallback mode active');
1806
- if (validation.mode.offline) console.log('📱 Offline mode active');
1807
-
1808
- await mcpServer.run();
1809
- } catch (error) {
1810
- console.error(`❌ Failed to start MCP server: ${error.message}`);
1811
- process.exit(1);
1812
- }
1813
- }
1814
-
1815
- async function runConnectWizard() {
1816
- const readline = require('readline');
1817
- const fs = require('fs');
1818
- const path = require('path');
1819
- const os = require('os');
1820
-
1821
- // Known MCP client config locations keyed by [client, platform]
1822
- const CLIENT_CONFIGS = [
1823
- {
1824
- name: 'Claude Desktop',
1825
- paths: {
1826
- win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json'),
1827
- darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
1828
- linux: path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json'),
1829
- },
1830
- serverKey: 'mcp-prompt-optimizer',
1831
- },
1832
- {
1833
- name: 'Cursor',
1834
- paths: {
1835
- win32: path.join(os.homedir(), '.cursor', 'mcp.json'),
1836
- darwin: path.join(os.homedir(), '.cursor', 'mcp.json'),
1837
- linux: path.join(os.homedir(), '.cursor', 'mcp.json'),
1838
- },
1839
- serverKey: 'mcp-prompt-optimizer',
1840
- },
1841
- {
1842
- name: 'VS Code Cline / Roo',
1843
- paths: {
1844
- win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1845
- darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1846
- linux: path.join(os.homedir(), '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1847
- },
1848
- serverKey: 'mcp-prompt-optimizer',
1849
- },
1850
- {
1851
- name: 'Continue.dev',
1852
- paths: {
1853
- win32: path.join(os.homedir(), '.continue', 'config.json'),
1854
- darwin: path.join(os.homedir(), '.continue', 'config.json'),
1855
- linux: path.join(os.homedir(), '.continue', 'config.json'),
1856
- },
1857
- serverKey: 'mcp-prompt-optimizer',
1858
- },
1859
- ];
1860
-
1861
- function safeWriteConfig(filePath, newConfig) {
1862
- const backupPath = filePath + '.bak';
1863
- // Backup
1864
- if (fs.existsSync(filePath)) {
1865
- fs.copyFileSync(filePath, backupPath);
1866
- }
1867
- try {
1868
- const serialized = JSON.stringify(newConfig, null, 2);
1869
- fs.writeFileSync(filePath, serialized, 'utf8');
1870
- // Verify round-trip
1871
- JSON.parse(fs.readFileSync(filePath, 'utf8'));
1872
- } catch (e) {
1873
- // Restore backup on any failure
1874
- if (fs.existsSync(backupPath)) {
1875
- fs.copyFileSync(backupPath, filePath);
1876
- }
1877
- throw e;
1878
- }
1879
- }
1880
-
1881
- function patchConfig(config, serverKey, apiKey) {
1882
- if (!config.mcpServers) config.mcpServers = {};
1883
- if (config.mcpServers[serverKey]) {
1884
- if (!config.mcpServers[serverKey].env) config.mcpServers[serverKey].env = {};
1885
- config.mcpServers[serverKey].env.OPTIMIZER_API_KEY = apiKey;
1886
- } else {
1887
- config.mcpServers[serverKey] = {
1888
- command: 'npx',
1889
- args: ['-y', 'mcp-prompt-optimizer'],
1890
- env: { OPTIMIZER_API_KEY: apiKey },
1891
- };
1892
- }
1893
- return config;
1894
- }
1895
-
1896
- console.log('\n🔌 Prompt Optimizer Connect Wizard\n');
1897
-
1898
- // Detect which clients are installed
1899
- const platform = process.platform;
1900
- const found = CLIENT_CONFIGS
1901
- .map(c => ({ ...c, configPath: c.paths[platform] || c.paths.linux }))
1902
- .filter(c => fs.existsSync(c.configPath));
1903
-
1904
- if (found.length === 0) {
1905
- console.log('❌ No supported MCP client config found. Supported clients:');
1906
- CLIENT_CONFIGS.forEach(c => {
1907
- const p = c.paths[platform] || c.paths.linux;
1908
- console.log(` ${c.name}: ${p}`);
1909
- });
1910
- console.log('\nOpen your MCP client first to create its config file, then re-run this command.');
1911
- process.exit(1);
1912
- }
1913
-
1914
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1915
-
1916
- function askApiKey(cb) {
1917
- rl.question('Paste your API key (get one free at https://promptoptimizer.xyz/dashboard): ', (key) => {
1918
- cb((key || '').trim());
1919
- });
1920
- }
1921
-
1922
- function askClient(clients, cb) {
1923
- console.log('Multiple MCP clients detected. Which one should be configured?');
1924
- clients.forEach((c, i) => console.log(` ${i + 1}) ${c.name}`));
1925
- rl.question('Enter number (or press Enter for all): ', (ans) => {
1926
- const n = parseInt(ans, 10);
1927
- if (!ans.trim()) {
1928
- cb(clients);
1929
- } else if (n >= 1 && n <= clients.length) {
1930
- cb([clients[n - 1]]);
1931
- } else {
1932
- console.log('Invalid selection, configuring all.');
1933
- cb(clients);
1934
- }
1935
- });
1936
- }
1937
-
1938
- function applyToClients(clients, apiKey) {
1939
- rl.close();
1940
- let ok = 0;
1941
- for (const client of clients) {
1942
- let config;
1943
- try {
1944
- config = JSON.parse(fs.readFileSync(client.configPath, 'utf8'));
1945
- } catch (e) {
1946
- console.log(`❌ Could not read ${client.name} config: ${e.message}`);
1947
- continue;
1948
- }
1949
- try {
1950
- const patched = patchConfig(config, client.serverKey, apiKey);
1951
- safeWriteConfig(client.configPath, patched);
1952
- console.log(`✅ ${client.name} configured (${client.configPath})`);
1953
- ok++;
1954
- } catch (e) {
1955
- console.log(`❌ Could not write ${client.name} config: ${e.message}`);
1956
- console.log(' Try running as administrator, or edit the file manually.');
1957
- }
1958
- }
1959
- if (ok > 0) {
1960
- console.log('\n👉 Restart your MCP client(s) to activate LLM optimization.');
1961
- console.log(' Free plan: 7 LLM optimizations/month.');
1962
- console.log(' Upgrade at https://promptoptimizer.xyz/pricing\n');
1963
- }
1964
- }
1965
-
1966
- askApiKey((apiKey) => {
1967
- if (!apiKey.startsWith('sk-')) {
1968
- rl.close();
1969
- console.log('\n❌ Invalid key — must start with "sk-". Get one at https://promptoptimizer.xyz/dashboard');
1970
- process.exit(1);
1971
- }
1972
- if (found.length === 1) {
1973
- applyToClients(found, apiKey);
1974
- } else {
1975
- askClient(found, (chosen) => applyToClients(chosen, apiKey));
1976
- }
1977
- });
1978
- }
1979
-
1980
- if (require.main === module) {
1981
- const args = process.argv.slice(2);
1982
- if (args[0] === 'connect') {
1983
- runConnectWizard();
1984
- } else {
1985
- startValidatedMCPServer();
1986
- }
1987
- }
1988
-
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Prompt Optimizer - Professional Cloud-Based MCP Server
5
+ * Production-grade with Bayesian optimization, AG-UI real-time features, enhanced network resilience,
6
+ * development mode, and complete backend alignment
7
+ *
8
+ * Version: 3.2.0 - add delete_template tool (15 tools total)
9
+ */
10
+
11
+ const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
12
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
13
+ const { CallToolRequestSchema, ListToolsRequestSchema } = require('@modelcontextprotocol/sdk/types.js');
14
+ const https = require('https');
15
+ const CloudApiKeyManager = require('./lib/api-key-manager');
16
+ const packageJson = require('./package.json');
17
+ const OPTIMIZATION_TEMPLATES = require('./lib/optimization-templates.json');
18
+
19
+ const API_KEYS_PREFIX = '/api/v1/api-keys';
20
+ const MCP_PREFIX = '/api/v1/mcp';
21
+
22
+ const ENDPOINTS = {
23
+ /** Detect AI context (POST) — MCP endpoint, API-key auth */
24
+ DETECT_CONTEXT: `${MCP_PREFIX}/detect-context`,
25
+
26
+ /** Prompt optimization (POST) — MCP endpoint, API-key auth */
27
+ OPTIMIZE: `${MCP_PREFIX}/optimize`,
28
+
29
+ /** CRUD on templates — MCP endpoints, API-key auth */
30
+ TEMPLATE: {
31
+ /** Create (POST) */
32
+ CREATE: `${MCP_PREFIX}/templates`,
33
+
34
+ /** Read (GET) */
35
+ GET: (id) => `${MCP_PREFIX}/templates/${id}`,
36
+
37
+ /** Update (PATCH) */
38
+ UPDATE: (id) => `${MCP_PREFIX}/templates/${id}`,
39
+
40
+ /** Delete (DELETE) */
41
+ DELETE: (id) => `${MCP_PREFIX}/templates/${id}`,
42
+ },
43
+
44
+ /** Search templates (GET) — MCP endpoint, API-key auth */
45
+ SEARCH_TEMPLATES: `${MCP_PREFIX}/templates`,
46
+
47
+ /** Quota status (GET) — MCP endpoint, API-key auth */
48
+ QUOTA_STATUS: `${MCP_PREFIX}/quota-status`,
49
+
50
+ /** Validate API key (POST) — standard api-keys router */
51
+ VALIDATE_KEY: `${API_KEYS_PREFIX}/validate`,
52
+
53
+ /** Bayesian insights (GET) */
54
+ ANALYTICS_BAYESIAN_INSIGHTS:
55
+ '/api/v1/analytics/bayesian-insights',
56
+
57
+ /** AG‑UI status (GET) */
58
+ AGUI_STATUS: '/api/status',
59
+
60
+ /** Context Engineer (CE) endpoints */
61
+ CE: {
62
+ SOP: '/api/v1/context-engineer/sop',
63
+ GENERATE_SKILL_PACKAGE: '/api/v1/context-engineer/generate-skill-package',
64
+ SESSION: (id) => `/api/v1/context-engineer/sessions/${id}`,
65
+ TRANSFORM: '/api/v1/context-engineer/transform',
66
+ QUOTA: '/api/v1/context-engineer/quota',
67
+ HARNESS_BUNDLE: '/api/v1/context-engineer/harness-bundle',
68
+ SOP_EXPLORE: '/api/v1/context-engineer/sop-explore',
69
+ SOP_BLEND: '/api/v1/context-engineer/sop-blend',
70
+ },
71
+ };
72
+
73
+ const DEPLOY_TARGET_ENUM = [
74
+ "claude_code", "claude_desktop", "cursor", "copilot",
75
+ "windsurf", "cline", "zed", "replit", "openai_agents", "ollama",
76
+ "amazon_q", "aider", "continue_dev", "crewai"
77
+ ];
78
+
79
+ class MCPPromptOptimizer {
80
+ constructor() {
81
+ this.server = new Server(
82
+ {
83
+ name: "mcp-prompt-optimizer",
84
+ version: packageJson.version,
85
+ },
86
+ {
87
+ capabilities: {
88
+ tools: {},
89
+ },
90
+ }
91
+ );
92
+
93
+ this.backendUrl = process.env.OPTIMIZER_BACKEND_URL || 'https://p01--project-optimizer--fvmrdk8m9k9j.code.run';
94
+ this.apiKey = process.env.OPTIMIZER_API_KEY;
95
+ // SECURITY: Development mode removed - all environments require backend validation
96
+ this.developmentMode = false;
97
+ this.requestTimeout = parseInt(process.env.OPTIMIZER_REQUEST_TIMEOUT) || 30000;
98
+
99
+ // Feature flags: enabled by default, set to 'false' to disable
100
+ this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION !== 'false';
101
+ this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES !== 'false';
102
+
103
+ this.setupMCPHandlers();
104
+ }
105
+
106
+ setupMCPHandlers() {
107
+ this.server.setRequestHandler(ListToolsRequestSchema, async () => {
108
+ const baseTools = [
109
+ {
110
+ name: "optimize_prompt",
111
+ description: "🎯 Professional AI-powered prompt optimization with intelligent context detection, Bayesian optimization, template auto-save, and comprehensive optimization insights",
112
+ inputSchema: {
113
+ type: "object",
114
+ properties: {
115
+ prompt: {
116
+ type: "string",
117
+ description: "The prompt text to optimize"
118
+ },
119
+ goals: {
120
+ type: "array",
121
+ items: { type: "string" },
122
+ description: "Optimization goals (e.g., 'clarity', 'conciseness', 'creativity', 'technical_accuracy', 'analytical_depth', 'creative_enhancement')",
123
+ default: ["clarity"]
124
+ },
125
+ ai_context: {
126
+ type: "string",
127
+ enum: [
128
+ "human_communication", "llm_interaction", "image_generation", "technical_automation",
129
+ "structured_output", "code_generation", "api_automation", "data_analysis",
130
+ "creative_writing", "business_strategy", "technical_strategy", "academic_research",
131
+ "legal_compliance", "medical_healthcare", "educational_content"
132
+ ],
133
+ description: "The context for the AI's task (auto-detected if not specified with enhanced detection)"
134
+ },
135
+ enable_bayesian: {
136
+ type: "boolean",
137
+ description: "Enable Bayesian optimization features for parameter tuning (if available)",
138
+ default: true
139
+ },
140
+ value_hierarchy: {
141
+ type: "array",
142
+ description: "Ordered list of values/constraints the optimizer must respect. NON_NEGOTIABLE entries force LLM-tier routing and inject hard constraints into the system prompt. Example: [{label:'NON_NEGOTIABLE',description:'Never suggest removing error handling'},{label:'HIGH',description:'Preserve technical terminology'}]",
143
+ items: {
144
+ type: "object",
145
+ properties: {
146
+ label: {
147
+ type: "string",
148
+ enum: ["NON_NEGOTIABLE", "HIGH", "MEDIUM", "LOW"],
149
+ description: "Priority level for this constraint"
150
+ },
151
+ description: {
152
+ type: "string",
153
+ description: "The value or constraint to enforce during optimization"
154
+ }
155
+ },
156
+ required: ["label", "description"]
157
+ }
158
+ },
159
+ intent_frame: {
160
+ type: "object",
161
+ description: "Question Method intent framing — steers optimization toward a specific angle, excludes off-topic territory, and defines what success looks like. Any non-null field floors routing to HYBRID tier minimum.",
162
+ properties: {
163
+ perspective: {
164
+ type: "string",
165
+ description: "The angle or thesis to optimize from (e.g. 'growth is a retention problem, not an acquisition problem'). Gives the optimizer a north-star direction."
166
+ },
167
+ out_of_scope: {
168
+ type: "array",
169
+ items: { type: "string" },
170
+ description: "Topics, approaches, or angles to explicitly exclude from optimization (e.g. ['pricing strategy', 'acquisition channels'])."
171
+ },
172
+ success_definition: {
173
+ type: "string",
174
+ description: "Narrative description of what a successful optimized output achieves (e.g. 'reader understands why churn drives flat revenue even with user growth')."
175
+ }
176
+ }
177
+ }
178
+ },
179
+ required: ["prompt"]
180
+ }
181
+ },
182
+ {
183
+ name: "get_quota_status",
184
+ description: "📊 Check subscription status, quota usage, and account information with detailed insights and Bayesian optimization metrics",
185
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
186
+ },
187
+ {
188
+ name: "create_template",
189
+ description: "➕ Create a new optimization template.",
190
+ inputSchema: {
191
+ type: "object",
192
+ properties: {
193
+ title: { type: "string", description: "Title of the template" },
194
+ description: { type: "string", description: "Description of the template" },
195
+ original_prompt: { type: "string", description: "The original prompt text" },
196
+ optimized_prompt: { type: "string", description: "The optimized prompt text" },
197
+ optimization_goals: { type: "array", items: { type: "string" }, description: "Goals for this optimization (e.g., 'clarity', 'conciseness', 'creativity', 'technical_accuracy', 'analytical_depth', 'creative_enhancement')" },
198
+ confidence_score: { type: "number", description: "Confidence score of the optimization (0.0-1.0)" },
199
+ model_used: { type: "string", description: "Model used for optimization" },
200
+ optimization_tier: { type: "string", description: "Tier of optimization (e.g., rules, llm, hybrid)" },
201
+ ai_context_detected: { type: "string", description: "Detected AI context (e.g., code_generation, image_generation)" },
202
+ is_public: { type: "boolean", default: false, description: "Whether the template is public" },
203
+ tags: { type: "array", items: { type: "string" }, description: "Tags for the template" }
204
+ },
205
+ required: ["title", "original_prompt", "optimized_prompt", "confidence_score"]
206
+ }
207
+ },
208
+ {
209
+ name: "get_template",
210
+ description: "🔍 Retrieve a specific template by its ID.",
211
+ inputSchema: {
212
+ type: "object",
213
+ properties: {
214
+ template_id: { type: "string", description: "The ID of the template to retrieve" }
215
+ },
216
+ required: ["template_id"]
217
+ }
218
+ },
219
+ {
220
+ name: "update_template",
221
+ description: "✏️ Update an existing optimization template.",
222
+ inputSchema: {
223
+ type: "object",
224
+ properties: {
225
+ template_id: { type: "string", description: "The ID of the template to update" },
226
+ title: { type: "string", description: "New title for the template" },
227
+ description: { type: "string", description: "New description for the template" },
228
+ original_prompt: { type: "string", description: "New original prompt text" },
229
+ optimized_prompt: { type: "string", description: "New optimized prompt text" },
230
+ optimization_goals: { type: "array", items: { type: "string" }, description: "New optimization goals" },
231
+ confidence_score: { type: "number", description: "New confidence score (0.0-1.0)" },
232
+ model_used: { type: "string", description: "New model used for optimization" },
233
+ optimization_tier: { type: "string", description: "New tier of optimization" },
234
+ ai_context_detected: { type: "string", description: "New detected AI context" },
235
+ is_public: { type: "boolean", description: "Whether the template is public" },
236
+ tags: { type: "array", items: { type: "string" }, description: "New tags for the template" }
237
+ },
238
+ required: ["template_id"]
239
+ }
240
+ },
241
+ {
242
+ name: "delete_template",
243
+ description: "🗑️ Delete a saved optimization template by ID.",
244
+ inputSchema: {
245
+ type: "object",
246
+ properties: {
247
+ template_id: { type: "string", description: "The ID of the template to delete" }
248
+ },
249
+ required: ["template_id"]
250
+ }
251
+ },
252
+ {
253
+ name: "search_templates",
254
+ description: "🔍 Search your saved template library with AI-aware filtering, context-based search, and sophisticated template matching",
255
+ inputSchema: {
256
+ type: "object",
257
+ properties: {
258
+ query: {
259
+ type: "string",
260
+ description: "Search term to filter templates by content or title"
261
+ },
262
+ ai_context: {
263
+ type: "string",
264
+ enum: ["human_communication", "llm_interaction", "image_generation", "technical_automation", "structured_output", "code_generation", "api_automation"],
265
+ description: "Filter templates by AI context type"
266
+ },
267
+ sophistication_level: {
268
+ type: "string",
269
+ enum: ["basic", "intermediate", "advanced", "expert"],
270
+ description: "Filter by template sophistication level"
271
+ },
272
+ complexity_level: {
273
+ type: "string",
274
+ enum: ["simple", "moderate", "complex", "very_complex"],
275
+ description: "Filter by template complexity level"
276
+ },
277
+ optimization_strategy: {
278
+ type: "string",
279
+ description: "Filter by optimization strategy used"
280
+ },
281
+ limit: {
282
+ type: "number",
283
+ default: 5,
284
+ description: "Number of templates to return (1-20)"
285
+ },
286
+ page: {
287
+ type: "number",
288
+ default: 1,
289
+ description: "Page number for pagination (use with limit to access results beyond the first page)"
290
+ },
291
+ sort_by: {
292
+ type: "string",
293
+ enum: ["created_at", "confidence_score", "usage_count", "title"],
294
+ default: "confidence_score",
295
+ description: "Sort templates by field"
296
+ },
297
+ sort_order: {
298
+ type: "string",
299
+ enum: ["asc", "desc"],
300
+ default: "desc",
301
+ description: "Sort order"
302
+ }
303
+ }
304
+ }
305
+ },
306
+ {
307
+ name: "list_recent_templates",
308
+ description: "📋 List your most recently saved optimization templates, sorted by creation date.",
309
+ inputSchema: {
310
+ type: "object",
311
+ properties: {
312
+ limit: {
313
+ type: "number",
314
+ default: 10,
315
+ description: "Number of recent templates to return (1-20)"
316
+ }
317
+ }
318
+ }
319
+ },
320
+ {
321
+ name: "detect_ai_context",
322
+ description: "🧠 Detects the AI context for a given prompt using advanced backend analysis.",
323
+ inputSchema: {
324
+ type: "object",
325
+ properties: {
326
+ prompt: {
327
+ type: "string",
328
+ description: "The prompt text for which to detect the AI context"
329
+ }
330
+ },
331
+ required: ["prompt"]
332
+ }
333
+ },
334
+ {
335
+ name: "generate_agent_sop",
336
+ description: "Generate a structured SOP document for an AI agent from a goal description.",
337
+ inputSchema: {
338
+ type: "object",
339
+ properties: {
340
+ goal: { type: "string", description: "What the agent should accomplish" },
341
+ context: { type: "string", description: "Additional context (optional)" },
342
+ model_id: { type: "string", description: "Model to use (optional)" },
343
+ intent_frame: {
344
+ type: "object",
345
+ description: "Optional IntentFrame to sharpen SOP scope and success criteria.",
346
+ properties: {
347
+ perspective: { type: "string", description: "The agent role or viewpoint (e.g. DevOps engineer)." },
348
+ out_of_scope: { type: "string", description: "What is explicitly excluded from this workflow." },
349
+ success_definition: { type: "string", description: "Measurable criteria that define success." }
350
+ },
351
+ additionalProperties: false
352
+ }
353
+ },
354
+ required: ["goal"]
355
+ }
356
+ },
357
+ {
358
+ name: "generate_skill_package",
359
+ description: "Generate a complete skill package (SOP + SKILL.md + examples + helper.py) for an AI agent. Takes 30-120 seconds (async).",
360
+ inputSchema: {
361
+ type: "object",
362
+ properties: {
363
+ goal: { type: "string", description: "What the agent should accomplish" },
364
+ format: { type: "string", enum: ["knowledge_doc", "agent_spec"], description: "Output format" },
365
+ model_id: { type: "string", description: "Model to use (optional)" }
366
+ },
367
+ required: ["goal"]
368
+ }
369
+ },
370
+ {
371
+ name: "transform_for_framework",
372
+ description: "Transform a SOP into native code for LangChain, AutoGen, or Claude Code.",
373
+ inputSchema: {
374
+ type: "object",
375
+ properties: {
376
+ sop_content: { type: "string", description: "SOP content to transform" },
377
+ goal: { type: "string", description: "What the agent should accomplish" },
378
+ framework: { type: "string", enum: ["langchain_tool", "autogen_agent", "claude_skill"], description: "Target framework" }
379
+ },
380
+ required: ["sop_content", "goal", "framework"]
381
+ }
382
+ },
383
+ {
384
+ name: "get_ce_quota_status",
385
+ description: "Check your Context Engineer credit balance and available workflow types.",
386
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
387
+ },
388
+ {
389
+ name: "generate_harness_bundle",
390
+ description: (
391
+ "Generate a deployment-ready Agentic Harness ZIP bundle for a specific platform. "
392
+ + "Returns a confirmation message when the bundle is queued. "
393
+ + "Explorer+ required for non-default deploy targets."
394
+ ),
395
+ inputSchema: {
396
+ type: "object",
397
+ properties: {
398
+ goal: {
399
+ type: "string",
400
+ description: "The workflow goal the harness is built for."
401
+ },
402
+ deploy_target: {
403
+ oneOf: [
404
+ {
405
+ type: "string",
406
+ enum: DEPLOY_TARGET_ENUM,
407
+ description: "Single deploy target."
408
+ },
409
+ {
410
+ type: "array",
411
+ minItems: 1,
412
+ items: {
413
+ type: "string",
414
+ enum: DEPLOY_TARGET_ENUM
415
+ },
416
+ description: "Multiple deploy targets simultaneously (Creator+ required)."
417
+ }
418
+ ],
419
+ description: (
420
+ "Target deployment platform(s). Single string (Explorer+) or array (Creator+). "
421
+ + "amazon_q, aider, continue_dev, crewai require Creator+. "
422
+ + "Default: claude_code."
423
+ )
424
+ },
425
+ session_id: {
426
+ type: "string",
427
+ description: "Optional: session ID from a prior generate_skill_package call to reuse SOP."
428
+ },
429
+ sop_content: {
430
+ type: "string",
431
+ description: "The SOP content to base the harness on (required if no session_id)."
432
+ }
433
+ },
434
+ required: ["goal"]
435
+ }
436
+ },
437
+ {
438
+ name: "explore_sop_approaches",
439
+ description: (
440
+ "Generate 3 parallel SOP variants (process-oriented, decision-tree, role-based) for comparison before committing. " +
441
+ "Returns exploration_html (self-contained comparison grid), variants array, and a recommended variant. " +
442
+ "Innovator tier required. " +
443
+ "Optionally provide blend_description to skip comparison and receive a single blended SOP instead."
444
+ ),
445
+ inputSchema: {
446
+ type: "object",
447
+ properties: {
448
+ goal: {
449
+ type: "string",
450
+ description: "The workflow goal to generate SOP variants for"
451
+ },
452
+ context: {
453
+ type: "string",
454
+ description: "Optional background context or documentation excerpt"
455
+ },
456
+ blend_description: {
457
+ type: "string",
458
+ description: "Optional: if provided, skips variant comparison and blends all 3 into one SOP using this description"
459
+ },
460
+ perspective: { type: "string", description: "Agent role or viewpoint (IntentFrame)" },
461
+ out_of_scope: { type: "string", description: "What is explicitly excluded (IntentFrame)" },
462
+ success_definition: { type: "string", description: "Measurable success criteria (IntentFrame)" },
463
+ },
464
+ required: ["goal"],
465
+ additionalProperties: false
466
+ }
467
+ },
468
+ ];
469
+
470
+ // Add advanced tools if Bayesian optimization is enabled
471
+ if (this.bayesianOptimizationEnabled) {
472
+ baseTools.push({
473
+ name: "get_optimization_insights",
474
+ description: "🧠 Get advanced Bayesian optimization insights, performance analytics, and parameter tuning recommendations",
475
+ inputSchema: {
476
+ type: "object",
477
+ properties: {
478
+ analysis_depth: {
479
+ type: "string",
480
+ enum: ["basic", "detailed", "comprehensive"],
481
+ default: "detailed",
482
+ description: "Depth of analysis to provide"
483
+ },
484
+ include_recommendations: {
485
+ type: "boolean",
486
+ default: true,
487
+ description: "Include optimization recommendations"
488
+ }
489
+ }
490
+ }
491
+ });
492
+ }
493
+
494
+ // Add AG-UI tools if enabled
495
+ if (this.aguiFeatures) {
496
+ baseTools.push({
497
+ name: "get_real_time_status",
498
+ description: "⚡ Get real-time optimization status, AG-UI capabilities, and streaming optimization availability",
499
+ inputSchema: { type: "object", properties: {}, additionalProperties: false }
500
+ });
501
+ }
502
+
503
+ return { tools: baseTools };
504
+ });
505
+
506
+ this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
507
+ const { name, arguments: args } = request.params;
508
+ try {
509
+ switch (name) {
510
+ case "optimize_prompt": return await this.handleOptimizePrompt(args);
511
+ case "get_quota_status": return await this.handleGetQuotaStatus();
512
+ case "search_templates": return await this.handleSearchTemplates(args);
513
+ case "list_recent_templates": return await this.handleListRecentTemplates(args);
514
+ case "detect_ai_context": return await this.handleDetectAIContext(args);
515
+ case "create_template": return await this.handleCreateTemplate(args);
516
+ case "get_template": return await this.handleGetTemplate(args);
517
+ case "update_template": return await this.handleUpdateTemplate(args);
518
+ case "delete_template": return await this.handleDeleteTemplate(args);
519
+ case "get_optimization_insights": return await this.handleGetOptimizationInsights(args);
520
+ case "get_real_time_status": return await this.handleGetRealTimeStatus();
521
+ case "generate_agent_sop": return await this.handleGenerateAgentSop(args);
522
+ case "generate_skill_package": return await this.handleGenerateSkillPackage(args);
523
+ case "transform_for_framework": return await this.handleTransformForFramework(args);
524
+ case "get_ce_quota_status": return await this.handleGetCEQuotaStatus();
525
+ case "generate_harness_bundle": return await this.handleGenerateHarnessBundle(args);
526
+ case "explore_sop_approaches": return await this.handleExploreSopApproaches(args);
527
+ default: throw new Error(`Unknown tool: ${name}`);
528
+ }
529
+ } catch (error) {
530
+ throw new Error(`Tool execution failed: ${error.message}`);
531
+ }
532
+ });
533
+ }
534
+
535
+ // ─── Rules-Based Optimization (offline / fallback tier) ─────────────────────
536
+
537
+ /**
538
+ * Select the best-matching template for a prompt using pattern scoring.
539
+ * Mirrors the backend's pattern-based fallback (no LLM required).
540
+ */
541
+ _matchTemplate(prompt, backendContext) {
542
+ const lc = prompt.toLowerCase();
543
+ let bestTemplate = null;
544
+ let bestScore = 0;
545
+ let fallbackName = null;
546
+
547
+ for (const [name, template] of Object.entries(OPTIMIZATION_TEMPLATES)) {
548
+ if (template.context !== backendContext) continue;
549
+ if (name.startsWith('fallback_')) { fallbackName = name; continue; }
550
+
551
+ let hits = 0;
552
+ for (const pattern of template.patterns) {
553
+ if (pattern === '.*') continue;
554
+ if (lc.includes(pattern.toLowerCase())) hits++;
555
+ }
556
+ if (hits === 0) continue;
557
+
558
+ // Confidence: 1 hit → 0.6, 2 hits → 0.75, 3+ hits → 0.9 (mirrors backend)
559
+ const patternConf = hits === 1 ? 0.6 : hits === 2 ? 0.75 : 0.9;
560
+ const score = patternConf + (template.priority || 1) / 100;
561
+
562
+ if (score > bestScore) { bestScore = score; bestTemplate = name; }
563
+ }
564
+
565
+ if (!bestTemplate) {
566
+ return { templateName: fallbackName || `fallback_${backendContext.toLowerCase()}`, matchConfidence: 0.3 };
567
+ }
568
+ return { templateName: bestTemplate, matchConfidence: bestScore };
569
+ }
570
+
571
+ /** Extract a user-defined role from the start of a prompt (e.g. "As a doctor, …"). */
572
+ _extractUserRole(request) {
573
+ const rolePatterns = [
574
+ /^['"]?(?:As a|You are a|My role is)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
575
+ /^['"]?(?:I am a|I'm a)\s+([a-zA-Z0-9\s\-/()]+?)(?:,|(?=\s*\.))/i,
576
+ ];
577
+ for (const re of rolePatterns) {
578
+ const m = request.match(re);
579
+ if (m) return m[1].trim();
580
+ }
581
+ return null;
582
+ }
583
+
584
+ /**
585
+ * Compile a template playbook into a user-facing prose prompt.
586
+ * Produces readable output instead of XML scaffolding, matching the
587
+ * result a backend LLM pass would generate from the same playbook.
588
+ */
589
+ _compilePlaybook(playbook, originalRequest) {
590
+ const parts = [];
591
+
592
+ parts.push(originalRequest.trim());
593
+ parts.push('');
594
+
595
+ const userFacingPrinciples = (playbook.principles || []).filter(p => {
596
+ const lc = p.toLowerCase();
597
+ return !lc.includes('scratchpad') &&
598
+ !lc.startsWith('first, think') &&
599
+ !/<[a-z]/i.test(p);
600
+ });
601
+
602
+ if (userFacingPrinciples.length > 0) {
603
+ parts.push('To address this effectively:');
604
+ for (const p of userFacingPrinciples) parts.push(`- ${p}`);
605
+ parts.push('');
606
+ }
607
+
608
+ if (playbook.output_format) {
609
+ parts.push(`*Response format: ${playbook.output_format}*`);
610
+ }
611
+
612
+ return parts.join('\n');
613
+ }
614
+
615
+ /**
616
+ * Enhance an image generation prompt by appending style-appropriate
617
+ * quality/composition boosters (mirrors backend _compile_image_prompt_fallback).
618
+ */
619
+ _compileImagePrompt(originalRequest) {
620
+ const text = originalRequest.trim();
621
+ const lc = text.toLowerCase();
622
+
623
+ const styles = {
624
+ photorealistic: ['photorealistic','realistic','photo','photograph','photography'],
625
+ '3d_render': ['3d','render','octane','unreal engine','blender','cinema 4d','ray tracing'],
626
+ cinematic: ['cinematic','movie','film','dramatic','epic'],
627
+ digital_art: ['digital art','concept art','digital illustration','cg','cgi'],
628
+ artistic: ['artistic','painting','watercolor','oil painting','impressionist'],
629
+ anime: ['anime','manga'],
630
+ vintage: ['vintage','retro','nostalgic'],
631
+ minimalist: ['minimalist','minimal','simple','clean'],
632
+ };
633
+
634
+ let detectedStyle = null;
635
+ for (const [style, kws] of Object.entries(styles)) {
636
+ if (kws.some(kw => lc.includes(kw))) { detectedStyle = style; break; }
637
+ }
638
+
639
+ const enhancements = [];
640
+ const hasQuality = ['high quality','8k','4k','hd','highly detailed','detailed'].some(t => lc.includes(t));
641
+ const hasLighting = ['lighting','light','shadow','illuminated','lit'].some(t => lc.includes(t));
642
+ const hasComposition = ['composition','rule of thirds','centered','framed'].some(t => lc.includes(t));
643
+
644
+ if (detectedStyle === 'photorealistic' && !hasQuality) {
645
+ enhancements.push('ultra realistic, sharp focus, professional photography');
646
+ } else if (detectedStyle === '3d_render' && !['octane','render'].some(t => lc.includes(t))) {
647
+ enhancements.push('high quality 3D render, volumetric lighting, ray traced shadows');
648
+ } else if (detectedStyle === 'cinematic' && !hasLighting) {
649
+ enhancements.push('cinematic lighting, dramatic atmosphere, film grain');
650
+ } else if (detectedStyle === 'digital_art' && !hasQuality) {
651
+ enhancements.push('highly detailed digital art, professional illustration');
652
+ } else if (detectedStyle === 'artistic' && !lc.includes('masterpiece')) {
653
+ enhancements.push('masterful technique, rich colors, artistic composition');
654
+ }
655
+
656
+ if (!hasLighting && detectedStyle !== 'minimalist') enhancements.push('dynamic lighting');
657
+ if (!hasComposition) enhancements.push('balanced composition');
658
+ if (!hasQuality) enhancements.push('high quality, 4K');
659
+
660
+ return enhancements.length > 0 ? `${text}, ${enhancements.join(', ')}` : text;
661
+ }
662
+
663
+ /**
664
+ * Core rules-based optimizer — no network, no LLM.
665
+ * Selects the best template by pattern matching, then compiles
666
+ * the playbook into a structured prompt. Confidence range: 0.35–0.55.
667
+ */
668
+ rulesBasedOptimize(prompt, aiContext, goals = []) {
669
+ const contextMap = {
670
+ code_generation: 'CODE_GENERATION',
671
+ llm_interaction: 'LLM_INTERACTION',
672
+ image_generation: 'IMAGE_GENERATION',
673
+ human_communication: 'HUMAN_COMMUNICATION',
674
+ api_automation: 'API_AUTOMATION',
675
+ technical_automation: 'TECHNICAL_AUTOMATION',
676
+ structured_output: 'STRUCTURED_OUTPUT',
677
+ creative_enhancement: 'CREATIVE_ENHANCEMENT',
678
+ creative_writing: 'CREATIVE_ENHANCEMENT',
679
+ general_assistant: 'LLM_INTERACTION',
680
+ };
681
+ const backendContext = contextMap[aiContext] || 'LLM_INTERACTION';
682
+
683
+ const { templateName, matchConfidence } = this._matchTemplate(prompt, backendContext);
684
+ const template = OPTIMIZATION_TEMPLATES[templateName];
685
+
686
+ const optimizedPrompt = backendContext === 'IMAGE_GENERATION'
687
+ ? this._compileImagePrompt(prompt)
688
+ : this._compilePlaybook(template.playbook, prompt);
689
+
690
+ // Honest confidence: rules-based tops out around 0.55
691
+ const confidence = parseFloat(Math.min(0.35 + matchConfidence * 0.2, 0.55).toFixed(2));
692
+
693
+ return {
694
+ optimized_prompt: optimizedPrompt,
695
+ confidence_score: confidence,
696
+ tier: 'rules',
697
+ template_used: templateName,
698
+ rules_based: true,
699
+ template_saved: false,
700
+ templates_found: [],
701
+ optimization_insights: null,
702
+ bayesian_insights: null,
703
+ };
704
+ }
705
+
706
+ // ─── End Rules-Based Optimization ────────────────────────────────────────────
707
+
708
+ generateMockOptimization(prompt, goals, aiContext, enableBayesian = false) {
709
+ // Use real rules-based optimization instead of fake placeholder output
710
+ const rulesResult = this.rulesBasedOptimize(prompt, aiContext, goals);
711
+ const baseResult = {
712
+ ...rulesResult,
713
+ rules_based: false, // Show as normal optimized output in mock mode
714
+ tier: 'free',
715
+ mock_mode: true,
716
+ template_saved: true,
717
+ template_id: 'test-template-123',
718
+ templates_found: [{ title: 'Similar Template 1', confidence_score: 0.85, id: 'tmpl-1' }],
719
+ optimization_insights: {
720
+ improvement_metrics: {
721
+ clarity_improvement: 0.25,
722
+ specificity_improvement: 0.20,
723
+ length_optimization: 0.15,
724
+ context_alignment: 0.30
725
+ },
726
+ user_patterns: {
727
+ optimization_confidence: '87.0%',
728
+ prompt_complexity: 'intermediate',
729
+ ai_context: aiContext
730
+ },
731
+ recommendations: [
732
+ `Context detected as ${aiContext}`,
733
+ 'Enhanced goal optimization applied',
734
+ 'Template auto-save threshold met'
735
+ ]
736
+ }
737
+ };
738
+
739
+ // Add Bayesian optimization insights if enabled
740
+ if (enableBayesian && this.bayesianOptimizationEnabled) {
741
+ baseResult.bayesian_insights = {
742
+ parameter_optimization: {
743
+ temperature_adjustment: '+0.1',
744
+ context_weight: '+0.15',
745
+ goal_prioritization: 'clarity > specificity > engagement'
746
+ },
747
+ performance_prediction: {
748
+ expected_improvement: '12-18%',
749
+ confidence_interval: '85-95%',
750
+ optimization_strategy: 'gradient_boost_context'
751
+ },
752
+ next_optimization_recommendation: {
753
+ suggested_goals: ['analytical_depth', 'creative_enhancement'],
754
+ estimated_improvement: '8-12%'
755
+ }
756
+ };
757
+ }
758
+
759
+ return baseResult;
760
+ }
761
+
762
+ generateMockContextDetection(prompt) {
763
+ let primary_context = 'human_communication'; // Default context
764
+ const lc = prompt.toLowerCase(); // one‑off lower‑case copy
765
+
766
+ /* 1️⃣ Code / programming – now includes `def` / `return`. */
767
+ if (lc.match(/def\b|return\b|import\b|class\b|for\b|while\b|if\b|else\b|elif\b|function\b|code\b|python|javascript|java|c\+\+/i)) {
768
+ primary_context = 'code_generation';
769
+
770
+ /* 2️⃣ Image / art – unchanged. */
771
+ } else if (lc.match(/image|generate|dall-e|midjourney/i)) {
772
+ primary_context = 'image_generation';
773
+
774
+ /* 3️⃣ Automation – unchanged. */
775
+ } else if (lc.match(/automate|script|api/i)) {
776
+ primary_context = 'technical_automation';
777
+
778
+ /* 4️⃣ LLM / analysis – newly added keyword “analyze”. */
779
+ } else if (lc.match(/analyze|explain|evaluate|summary|research|paper|analysis|interpret|discussion|assessment|compare|contrast/i)) {
780
+ primary_context = 'llm_interaction';
781
+ }
782
+
783
+ return {
784
+ primary_context: primary_context,
785
+ confidence: 0.75,
786
+ secondary_contexts: ['llm_interaction'],
787
+ detected_parameters: [],
788
+ mock_mode: true,
789
+ reason: 'Backend unavailable — using local pattern matching as fallback.'
790
+ };
791
+ }
792
+
793
+ async handleOptimizePrompt(args) {
794
+ if (!args.prompt) throw new Error('Prompt is required');
795
+
796
+ const manager = new CloudApiKeyManager(this.apiKey);
797
+
798
+ try {
799
+ const validation = await manager.validateApiKey();
800
+
801
+ if (validation.mock_mode || this.developmentMode) {
802
+ // In mock/dev mode, we still need a context for mock generation
803
+ const mockContext = args.ai_context || 'human_communication';
804
+ const mockGoals = args.goals || ['clarity'];
805
+ const mockEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
806
+ const mockResult = this.generateMockOptimization(args.prompt, mockGoals, mockContext, mockEnableBayesian);
807
+ const formatted = this.formatOptimizationResult(mockResult, { detectedContext: mockContext, enableBayesian: mockEnableBayesian });
808
+ return { content: [{ type: "text", text: formatted }] };
809
+ }
810
+
811
+ // 1. Detect AI Context from backend
812
+ let detectedContext = args.ai_context;
813
+ if (!detectedContext) {
814
+ try {
815
+ const contextDetectionResult = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
816
+ detectedContext = contextDetectionResult.primary_context;
817
+ console.error(`Detected AI Context from backend: ${detectedContext}`);
818
+ } catch (contextError) {
819
+ console.error(`Failed to detect AI context from backend, falling back to default: ${contextError.message}`);
820
+ detectedContext = 'human_communication'; // Fallback
821
+ }
822
+ }
823
+
824
+ // 2. Call the main optimization endpoint
825
+ const optimizationPayload = {
826
+ prompt: args.prompt,
827
+ goals: args.goals || ['clarity'],
828
+ ai_context: detectedContext,
829
+ };
830
+
831
+ if (args.value_hierarchy && args.value_hierarchy.length > 0) {
832
+ optimizationPayload.value_hierarchy = args.value_hierarchy;
833
+ }
834
+
835
+ if (args.intent_frame && typeof args.intent_frame === 'object') {
836
+ const { perspective, out_of_scope, success_definition } = args.intent_frame;
837
+ if (perspective || (out_of_scope && out_of_scope.length > 0) || success_definition) {
838
+ optimizationPayload.intent_frame = args.intent_frame;
839
+ }
840
+ }
841
+
842
+ const result = await this.callBackendAPI(ENDPOINTS.OPTIMIZE, optimizationPayload);
843
+
844
+ const enableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
845
+ return { content: [{ type: "text", text: this.formatOptimizationResult(result, { detectedContext, enableBayesian }) }] };
846
+
847
+ } catch (error) {
848
+ if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout') || error.message.includes('Connection')) {
849
+ const fallbackContext = args.ai_context || 'human_communication';
850
+ const fallbackEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
851
+ const fallbackResult = this.rulesBasedOptimize(args.prompt, fallbackContext, args.goals || ['clarity']);
852
+ fallbackResult.fallback_mode = true;
853
+ fallbackResult.error_reason = error.message;
854
+ const formatted = this.formatOptimizationResult(fallbackResult, { detectedContext: fallbackContext, enableBayesian: fallbackEnableBayesian });
855
+ return { content: [{ type: "text", text: formatted }] };
856
+ }
857
+ throw new Error(`Optimization failed: ${error.message}`);
858
+ }
859
+ }
860
+
861
+ async handleGetQuotaStatus() {
862
+ const manager = new CloudApiKeyManager(this.apiKey);
863
+ const info = await manager.getApiKeyInfo();
864
+ return { content: [{ type: "text", text: this.formatQuotaStatus(info) }] };
865
+ }
866
+
867
+ async handleSearchTemplates(args) {
868
+ try {
869
+ const params = new URLSearchParams({
870
+ page: (args.page || 1).toString(),
871
+ per_page: Math.min(args.limit || 5, 20).toString(),
872
+ sort_by: args.sort_by || 'confidence_score',
873
+ sort_order: args.sort_order || 'desc'
874
+ });
875
+
876
+ if (args.query) params.append('query', args.query);
877
+ if (args.ai_context) params.append('ai_context', args.ai_context);
878
+ if (args.sophistication_level) params.append('sophistication_level', args.sophistication_level);
879
+ if (args.complexity_level) params.append('complexity_level', args.complexity_level);
880
+ if (args.optimization_strategy) params.append('optimization_strategy', args.optimization_strategy);
881
+
882
+ const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
883
+ const result = await this.callBackendAPI(endpoint, null, 'GET');
884
+
885
+ const searchResult = {
886
+ templates: result.templates || [],
887
+ total: result.total || 0,
888
+ query: args.query,
889
+ ai_context: args.ai_context,
890
+ sophistication_level: args.sophistication_level,
891
+ complexity_level: args.complexity_level
892
+ };
893
+
894
+ const formatted = this.formatTemplateSearchResults(searchResult, args);
895
+ return { content: [{ type: "text", text: formatted }] };
896
+
897
+ } catch (error) {
898
+ console.error(`Template search failed: ${error.message}`);
899
+ const fallbackResult = {
900
+ templates: [],
901
+ total: 0,
902
+ message: "Template search is temporarily unavailable.",
903
+ error: error.message,
904
+ fallback_mode: true
905
+ };
906
+ const formatted = this.formatTemplateSearchResults(fallbackResult, args);
907
+ return { content: [{ type: "text", text: formatted }] };
908
+ }
909
+ }
910
+
911
+ async handleListRecentTemplates(args) {
912
+ try {
913
+ const limit = Math.min(Math.max(args.limit || 10, 1), 20);
914
+ const params = new URLSearchParams({
915
+ page: '1',
916
+ per_page: limit.toString(),
917
+ sort_by: 'created_at',
918
+ sort_order: 'desc'
919
+ });
920
+
921
+ const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
922
+ const result = await this.callBackendAPI(endpoint, null, 'GET');
923
+
924
+ const templates = result.templates || [];
925
+ let output = `# 📋 Recent Templates\n\n`;
926
+ output += `Showing **${templates.length}** most recently saved template(s).\n\n`;
927
+
928
+ if (templates.length === 0) {
929
+ output += `📭 No templates found yet.\nRun \`optimize_prompt\` to start building your template library.\n`;
930
+ } else {
931
+ output += `## 📋 **Template Results**\n`;
932
+ templates.forEach((t, index) => {
933
+ const confidence = t.confidence_score ? `${(t.confidence_score * 100).toFixed(1)}%` : 'N/A';
934
+ const preview = t.optimized_prompt ? t.optimized_prompt.substring(0, 60) + '...' : 'Preview unavailable';
935
+ output += `### ${index + 1}. ${t.title}\n`;
936
+ output += `- **Confidence:** ${confidence}\n`;
937
+ output += `- **ID:** \`${t.id}\`\n`;
938
+ output += `- **Preview:** ${preview}\n`;
939
+ if (t.ai_context) output += `- **Context:** ${t.ai_context}\n`;
940
+ if (t.optimization_goals && t.optimization_goals.length) {
941
+ output += `- **Goals:** ${t.optimization_goals.join(', ')}\n`;
942
+ }
943
+ output += `\n`;
944
+ });
945
+ output += `💡 Use \`get_template\` with an ID above to view the full optimized prompt.\n`;
946
+ }
947
+
948
+ return { content: [{ type: "text", text: output }] };
949
+ } catch (error) {
950
+ return { content: [{ type: "text", text: `❌ Could not retrieve recent templates: ${error.message}` }] };
951
+ }
952
+ }
953
+
954
+ async handleGetOptimizationInsights(args) {
955
+ if (!this.bayesianOptimizationEnabled) {
956
+ return { content: [{ type: "text", text: "🧠 Bayesian optimization features are not enabled. Set ENABLE_BAYESIAN_OPTIMIZATION=true to access advanced insights." }] };
957
+ }
958
+
959
+ try {
960
+ // Try to get insights from backend
961
+ const endpoint = `${ENDPOINTS.ANALYTICS_BAYESIAN_INSIGHTS}?depth=${args.analysis_depth || 'detailed'}&recommendations=${args.include_recommendations !== false}`;
962
+ const result = await this.callBackendAPI(endpoint, null, 'GET');
963
+
964
+ return { content: [{ type: "text", text: this.formatOptimizationInsights(result) }] };
965
+
966
+ } catch (error) {
967
+ // Fallback to mock insights
968
+ const mockInsights = {
969
+ bayesian_status: {
970
+ optimization_active: true,
971
+ total_optimizations: 47,
972
+ improvement_rate: '23.5%',
973
+ confidence_score: 0.89
974
+ },
975
+ parameter_insights: {
976
+ most_effective_goals: ['clarity', 'technical_accuracy', 'analytical_depth'],
977
+ context_performance: {
978
+ 'code_generation': 0.92,
979
+ 'llm_interaction': 0.87,
980
+ 'technical_automation': 0.84
981
+ },
982
+ optimization_trends: 'Steady improvement in technical contexts'
983
+ },
984
+ recommendations: args.include_recommendations !== false ? [
985
+ 'Focus on technical_accuracy for code generation prompts',
986
+ 'Combine clarity with analytical_depth for best results',
987
+ 'Consider using structured_output context for data tasks'
988
+ ] : []
989
+ };
990
+
991
+ return { content: [{ type: "text", text: this.formatOptimizationInsights(mockInsights) }] };
992
+ }
993
+ }
994
+
995
+ async handleGetRealTimeStatus() {
996
+ if (!this.aguiFeatures) {
997
+ return { content: [{ type: "text", text: "⚡ AG-UI real-time features are not enabled. Set ENABLE_AGUI_FEATURES=true to access real-time optimization capabilities." }] };
998
+ }
999
+
1000
+ try {
1001
+ const result = await this.callBackendAPI(ENDPOINTS.AGUI_STATUS, null, 'GET');
1002
+
1003
+ return { content: [{ type: "text", text: this.formatRealTimeStatus(result) }] };
1004
+
1005
+ } catch (error) {
1006
+ const mockStatus = {
1007
+ agui_status: 'available',
1008
+ streaming_optimization: true,
1009
+ websocket_support: true,
1010
+ real_time_analytics: true,
1011
+ active_optimizations: 3,
1012
+ average_response_time: '1.2s',
1013
+ features: {
1014
+ live_optimization: true,
1015
+ collaborative_editing: true,
1016
+ instant_feedback: true,
1017
+ performance_monitoring: true
1018
+ }
1019
+ };
1020
+
1021
+ return { content: [{ type: "text", text: this.formatRealTimeStatus(mockStatus) }] };
1022
+ }
1023
+ }
1024
+
1025
+ async handleDetectAIContext(args) {
1026
+ if (!args.prompt) throw new Error('Prompt is required');
1027
+
1028
+ const formatResult = (result) => {
1029
+ let output = `# 🧠 AI Context Detection Result\n\n`;
1030
+ output += `**Primary Context:** ${result.primary_context}\n`;
1031
+ output += `**Confidence:** ${(result.confidence * 100).toFixed(1)}%\n`;
1032
+ if (result.secondary_contexts && result.secondary_contexts.length > 0) {
1033
+ output += `**Secondary Contexts:** ${result.secondary_contexts.join(', ')}\n`;
1034
+ }
1035
+
1036
+ const detections = result.detected_parameters ?? [];
1037
+ const safeDetections = detections.filter(d => d && d.name);
1038
+
1039
+ if (safeDetections.length > 0) {
1040
+ output += `**Detected Parameters:** ${safeDetections.map(d => d.name).join(', ')}\n`;
1041
+ }
1042
+
1043
+ if (result.mock_mode) {
1044
+ output += `\n⚠️ **Fallback Mode Active:** Using mock data due to development mode or network issues.\n`;
1045
+ }
1046
+ return { content: [{ type: "text", text: output }] };
1047
+ };
1048
+
1049
+ try {
1050
+ const manager = new CloudApiKeyManager(this.apiKey);
1051
+ const validation = await manager.validateApiKey();
1052
+
1053
+ if (validation.mock_mode || this.developmentMode) {
1054
+ const mockResult = this.generateMockContextDetection(args.prompt);
1055
+ return formatResult(mockResult);
1056
+ }
1057
+
1058
+ const result = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
1059
+ return formatResult(result);
1060
+
1061
+ } catch (error) {
1062
+ // Fallback for ANY error during the process (missing key, network, etc.)
1063
+ const fallbackResult = this.generateMockContextDetection(args.prompt);
1064
+ return formatResult(fallbackResult);
1065
+ }
1066
+ }
1067
+
1068
+ async handleCreateTemplate(args) {
1069
+ // Client-side validation before network call
1070
+ const requiredStrings = ['title', 'original_prompt', 'optimized_prompt'];
1071
+ for (const field of requiredStrings) {
1072
+ if (!args[field] || typeof args[field] !== 'string' || args[field].trim() === '') {
1073
+ return { content: [{ type: "text", text: `❌ Missing required field: '${field}'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
1074
+ }
1075
+ }
1076
+ if (args.confidence_score === undefined || args.confidence_score === null ||
1077
+ typeof args.confidence_score !== 'number' || args.confidence_score < 0 || args.confidence_score > 1) {
1078
+ return { content: [{ type: "text", text: `❌ Missing required field: 'confidence_score'. Required fields: title, original_prompt, optimized_prompt, confidence_score (0.0–1.0)` }] };
1079
+ }
1080
+
1081
+ try {
1082
+ const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.CREATE, args);
1083
+ let output = `# ✅ Template Created Successfully!\n\n`;
1084
+ output += `**Title:** ${result.title}\n`;
1085
+ output += `**ID:** \`${result.id}\`\n`;
1086
+ output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1087
+ output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
1088
+ output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
1089
+ output += `\n**Optimized Prompt Preview:**\n\`\`\`\n${result.optimized_prompt.substring(0, 150)}...\n\`\`\`\n`;
1090
+ return { content: [{ type: "text", text: output }] };
1091
+ } catch (error) {
1092
+ throw new Error(`Failed to create template: ${error.message}`);
1093
+ }
1094
+ }
1095
+
1096
+ async handleGetTemplate(args) {
1097
+ if (!args.template_id) throw new Error('Template ID is required');
1098
+ try {
1099
+ const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.GET(args.template_id), null, 'GET');
1100
+ let output = `# 📄 Template Details\n\n`;
1101
+ output += `**Title:** ${result.title}\n`;
1102
+ output += `**ID:** \`${result.id}\`\n`;
1103
+ output += `**Description:** ${result.description || 'N/A'}\n`;
1104
+ output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
1105
+ output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1106
+ output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
1107
+ output += `**Tags:** ${result.tags ? result.tags.join(', ') : 'None'}\n\n`;
1108
+ output += `**Original Prompt:**\n\`\`\`\n${result.original_prompt}\n\`\`\`\n\n`;
1109
+ output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n`;
1110
+ return { content: [{ type: "text", text: output }] };
1111
+ } catch (error) {
1112
+ const msg = error.message || '';
1113
+ if (msg.includes('404') || msg.toLowerCase().includes('not found')) {
1114
+ 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.`);
1115
+ }
1116
+ throw new Error(`Failed to retrieve template: ${error.message}`);
1117
+ }
1118
+ }
1119
+
1120
+ async handleUpdateTemplate(args) {
1121
+ if (!args.template_id) throw new Error('Template ID is required');
1122
+ try {
1123
+ const { template_id, ...updateData } = args;
1124
+ // Filter out undefined values so we only send fields that are being updated
1125
+ Object.keys(updateData).forEach(key => updateData[key] === undefined && delete updateData[key]);
1126
+
1127
+ const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.UPDATE(template_id), updateData, 'PATCH'); // PATCH is better for partial updates
1128
+ let output = `# ✅ Template Updated Successfully!\n\n`;
1129
+ output += `**ID:** \`${result.id}\`\n`;
1130
+ output += `**Title:** ${result.title}\n\n`;
1131
+ output += `Use 'get_template' with the ID to see the full updated template.`;
1132
+ return { content: [{ type: "text", text: output }] };
1133
+ } catch (error) {
1134
+ throw new Error(`Failed to update template: ${error.message}`);
1135
+ }
1136
+ }
1137
+
1138
+ async handleDeleteTemplate(args) {
1139
+ if (!args.template_id) throw new Error('Template ID is required');
1140
+ try {
1141
+ const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.DELETE(args.template_id), null, 'DELETE');
1142
+ const title = result.message || `Template ${args.template_id}`;
1143
+ return { content: [{ type: "text", text: `# 🗑️ Template Deleted\n\n${title}` }] };
1144
+ } catch (error) {
1145
+ throw new Error(`Failed to delete template: ${error.message}`);
1146
+ }
1147
+ }
1148
+
1149
+ async handleGenerateAgentSop(args) {
1150
+ if (!args.goal) throw new Error('goal is required');
1151
+ const payload = { goal: args.goal };
1152
+ if (args.context) payload.context = args.context;
1153
+ if (args.model_id) payload.model_id = args.model_id;
1154
+ if (args.intent_frame) payload.intent_frame = args.intent_frame;
1155
+ try {
1156
+ const result = await this.callBackendAPI(ENDPOINTS.CE.SOP, payload);
1157
+ const sopContent = result.sop || result.content || result.result || JSON.stringify(result, null, 2);
1158
+ return { content: [{ type: "text", text: `# Agent SOP Generated\n\n${sopContent}\n\n---\n*Generated by MCP Prompt Optimizer CE*` }] };
1159
+ } catch (error) {
1160
+ throw new Error(`Failed to generate SOP: ${error.message}`);
1161
+ }
1162
+ }
1163
+
1164
+ async handleGenerateSkillPackage(args) {
1165
+ if (!args.goal) throw new Error('goal is required');
1166
+ const payload = { goal: args.goal, format: args.format || 'knowledge_doc' };
1167
+ if (args.model_id) payload.model_id = args.model_id;
1168
+ let workflowError = null;
1169
+ try {
1170
+ const startResult = await this.callBackendAPI(ENDPOINTS.CE.GENERATE_SKILL_PACKAGE, payload);
1171
+ const sessionId = startResult.session_id;
1172
+ if (!sessionId) {
1173
+ return { content: [{ type: "text", text: this._formatSkillPackage(startResult) }] };
1174
+ }
1175
+ for (let i = 0; i < 24; i++) {
1176
+ await new Promise(resolve => setTimeout(resolve, 5000));
1177
+ const status = await this.callBackendAPI(ENDPOINTS.CE.SESSION(sessionId), null, 'GET');
1178
+ const state = status.workflow_state || status.current_state;
1179
+ if (state === 'complete') return { content: [{ type: "text", text: this._formatSkillPackage(status) }] };
1180
+ if (state === 'failed') {
1181
+ workflowError = new Error(`Generation failed: ${status.error || 'Unknown error'}`);
1182
+ throw workflowError;
1183
+ }
1184
+ }
1185
+ workflowError = new Error(`Timed out after 120s. Session ID: ${sessionId}`);
1186
+ throw workflowError;
1187
+ } catch (error) {
1188
+ if (error === workflowError) throw error;
1189
+ throw new Error(`Failed to generate skill package: ${error.message}`);
1190
+ }
1191
+ }
1192
+
1193
+ async handleTransformForFramework(args) {
1194
+ if (!args.sop_content) throw new Error('sop_content is required');
1195
+ if (!args.goal) throw new Error('goal is required');
1196
+ if (!args.framework) throw new Error('framework is required');
1197
+ const valid = ['langchain_tool', 'autogen_agent', 'claude_skill'];
1198
+ if (!valid.includes(args.framework)) throw new Error(`framework must be one of: ${valid.join(', ')}`);
1199
+ try {
1200
+ const result = await this.callBackendAPI(ENDPOINTS.CE.TRANSFORM, {
1201
+ sop_content: args.sop_content, goal: args.goal, framework: args.framework
1202
+ });
1203
+ const code = result.code || result.content || result.result || JSON.stringify(result, null, 2);
1204
+ return { content: [{ type: "text", text: `# ${args.framework} Implementation\n\n\`\`\`python\n${code}\n\`\`\`\n\n---\n*Transformed by MCP Prompt Optimizer CE*` }] };
1205
+ } catch (error) {
1206
+ throw new Error(`Failed to transform: ${error.message}`);
1207
+ }
1208
+ }
1209
+
1210
+ async handleGetCEQuotaStatus() {
1211
+ try {
1212
+ const result = await this.callBackendAPI(ENDPOINTS.CE.QUOTA, null, 'GET');
1213
+ const lines = ['## CE Credit Balance', ''];
1214
+ if (result.is_unlimited) {
1215
+ lines.push(`Credits: **Unlimited** (${result.credits_used || 0} used this period)`);
1216
+ } else {
1217
+ lines.push(`Credits: **${result.credits_remaining ?? 'N/A'}** of ${result.credits_limit} remaining (${result.credits_used || 0} used)`);
1218
+ }
1219
+ lines.push('', '## Available Workflows');
1220
+ if (result.workflow_availability) {
1221
+ for (const [type, info] of Object.entries(result.workflow_availability)) {
1222
+ lines.push(`- ${info.available ? '✓' : '✗'} ${type}: ${info.cost_credits} credit(s)`);
1223
+ }
1224
+ }
1225
+ if (result.message) lines.push('', result.message);
1226
+ return { content: [{ type: "text", text: lines.join('\n') }] };
1227
+ } catch (error) {
1228
+ throw new Error(`Failed to get CE quota: ${error.message}`);
1229
+ }
1230
+ }
1231
+
1232
+ async handleGenerateHarnessBundle(args) {
1233
+ if (!args.sop_content && !args.session_id) {
1234
+ return { content: [{ type: "text", text: "Error: provide either sop_content or session_id." }] };
1235
+ }
1236
+ // Normalize deploy_target: string → [string], array → array, undefined → ["claude_code"]
1237
+ let deployTargets;
1238
+ if (!args.deploy_target) {
1239
+ deployTargets = ["claude_code"];
1240
+ } else if (Array.isArray(args.deploy_target)) {
1241
+ deployTargets = args.deploy_target;
1242
+ } else {
1243
+ deployTargets = [args.deploy_target];
1244
+ }
1245
+ // Guard: empty array falls back to default
1246
+ if (deployTargets.length === 0) {
1247
+ deployTargets = ["claude_code"];
1248
+ }
1249
+
1250
+ const payload = {
1251
+ goal: args.goal,
1252
+ deploy_target: deployTargets.length === 1 ? deployTargets[0] : deployTargets,
1253
+ platform: deployTargets[0],
1254
+ user_goal: args.goal,
1255
+ sop_content: args.sop_content || "",
1256
+ };
1257
+
1258
+ // If session_id provided, first fetch session artifacts for sop_content
1259
+ if (args.session_id) {
1260
+ try {
1261
+ const status = await this.callBackendAPI(ENDPOINTS.CE.SESSION(args.session_id), null, "GET");
1262
+ const sop = status.artifacts?.sop_content || status.sop_content || "";
1263
+ if (sop) payload.sop_content = sop;
1264
+ } catch (sessionErr) {
1265
+ console.error(`[handleGenerateHarnessBundle] Could not fetch session ${args.session_id}:`, sessionErr.message || sessionErr);
1266
+ // Proceed with empty sop_content; backend will handle gracefully
1267
+ }
1268
+ }
1269
+
1270
+ try {
1271
+ await this.callBackendAPI(ENDPOINTS.CE.HARNESS_BUNDLE, payload);
1272
+ return {
1273
+ content: [{
1274
+ type: "text",
1275
+ text: `# Harness Bundle Requested\n\nDeploy target: **${deployTargets.join(", ")}**\nGoal: ${args.goal}\n\nDownload from the CE dashboard or via the /harness-bundle API endpoint.`
1276
+ }]
1277
+ };
1278
+ } catch (error) {
1279
+ const msg = error?.message || String(error);
1280
+ if (msg.includes("TIER_LIMIT_REACHED")) {
1281
+ return { content: [{ type: "text",
1282
+ text: `Upgrade required: this deploy target requires Pro tier or higher. Upgrade at /pricing.`
1283
+ }] };
1284
+ }
1285
+ throw error;
1286
+ }
1287
+ }
1288
+
1289
+ async handleExploreSopApproaches(args) {
1290
+ if (!args.goal) {
1291
+ return { content: [{ type: "text", text: "Error: goal is required." }] };
1292
+ }
1293
+
1294
+ // If blend_description provided, explore then blend in one call chain
1295
+ if (args.blend_description) {
1296
+ try {
1297
+ const explorePayload = {
1298
+ goal: args.goal,
1299
+ context: args.context || undefined,
1300
+ perspective: args.perspective || undefined,
1301
+ out_of_scope: args.out_of_scope || undefined,
1302
+ success_definition: args.success_definition || undefined,
1303
+ };
1304
+ const exploreResult = await this.callBackendAPI(ENDPOINTS.CE.SOP_EXPLORE, explorePayload);
1305
+ const blendPayload = {
1306
+ variants: exploreResult.variants,
1307
+ blend_description: args.blend_description,
1308
+ goal: args.goal,
1309
+ };
1310
+ const blendResult = await this.callBackendAPI(ENDPOINTS.CE.SOP_BLEND, blendPayload);
1311
+ return {
1312
+ content: [{
1313
+ type: "text",
1314
+ text: `# Blended SOP\n\n${blendResult.sop_content}`
1315
+ }]
1316
+ };
1317
+ } catch (error) {
1318
+ throw new Error(`Failed to blend SOP approaches: ${error.message}`);
1319
+ }
1320
+ }
1321
+
1322
+ // Standard exploration: return 3 variant summaries
1323
+ try {
1324
+ const payload = {
1325
+ goal: args.goal,
1326
+ context: args.context || undefined,
1327
+ perspective: args.perspective || undefined,
1328
+ out_of_scope: args.out_of_scope || undefined,
1329
+ success_definition: args.success_definition || undefined,
1330
+ };
1331
+ const result = await this.callBackendAPI(ENDPOINTS.CE.SOP_EXPLORE, payload);
1332
+
1333
+ const variantSummaries = result.variants.map(v => {
1334
+ const rec = v.id === result.recommended ? " *(Recommended)*" : "";
1335
+ return `## Variant ${v.id} — ${v.approach.replace('_', '-')}${rec}\n\n${v.content.slice(0, 600)}${v.content.length > 600 ? '\n\n...(truncated)' : ''}`;
1336
+ }).join('\n\n---\n\n');
1337
+
1338
+ return {
1339
+ content: [{
1340
+ type: "text",
1341
+ text: `# SOP Exploration Results\n\n**Goal:** ${args.goal}\n**Recommended:** Variant ${result.recommended}\n\n---\n\n${variantSummaries}\n\n---\n\n*To select a variant, call generate_skill_package with the full content of your chosen variant as sop_content. To blend variants, re-call explore_sop_approaches with blend_description.*`
1342
+ }]
1343
+ };
1344
+ } catch (error) {
1345
+ if (error.message && error.message.includes('403')) {
1346
+ return { content: [{ type: "text", text: "Error: SOP exploration requires Innovator tier. Upgrade at /pricing." }] };
1347
+ }
1348
+ throw new Error(`Failed to explore SOP approaches: ${error.message}`);
1349
+ }
1350
+ }
1351
+
1352
+ _formatSkillPackage(result) {
1353
+ const sections = ['# Skill Package Generated'];
1354
+ const artifacts = result.artifacts || result.steps || {};
1355
+ if (typeof artifacts === 'object' && Object.keys(artifacts).length > 0) {
1356
+ for (const [key, value] of Object.entries(artifacts)) {
1357
+ if (value && typeof value === 'string') sections.push(`\n## ${key}\n\n${value}`);
1358
+ }
1359
+ } else {
1360
+ sections.push('\n```json\n' + JSON.stringify(result, null, 2) + '\n```');
1361
+ }
1362
+ sections.push('\n---\n*Generated by MCP Prompt Optimizer CE*');
1363
+ return sections.join('\n');
1364
+ }
1365
+
1366
+ _buildUrl(path) {
1367
+ return `${this.backendUrl}${path}`;
1368
+ }
1369
+
1370
+ async callBackendAPI(endpoint, data, method = 'POST') {
1371
+ return new Promise((resolve, reject) => {
1372
+ const url = this._buildUrl(endpoint);
1373
+
1374
+ const options = {
1375
+ method: method,
1376
+ headers: {
1377
+ 'x-api-key': this.apiKey,
1378
+ 'Content-Type': 'application/json',
1379
+ 'User-Agent': `mcp-prompt-optimizer/${packageJson.version}`,
1380
+ 'Accept': 'application/json',
1381
+ 'Connection': 'close'
1382
+ },
1383
+ timeout: this.requestTimeout
1384
+ };
1385
+
1386
+ const client = this.backendUrl.startsWith('https://') ? https : require('http');
1387
+ const req = client.request(url, options, (res) => {
1388
+ let responseData = '';
1389
+
1390
+ res.on('data', (chunk) => {
1391
+ responseData += chunk;
1392
+ });
1393
+
1394
+ res.on('end', () => {
1395
+ try {
1396
+ if (res.statusCode >= 200 && res.statusCode < 300) {
1397
+ const contentType = res.headers['content-type'] || '';
1398
+ if (contentType.includes('application/json') || contentType === '') {
1399
+ try {
1400
+ const parsed = JSON.parse(responseData);
1401
+ resolve(parsed);
1402
+ } catch (e) {
1403
+ reject(new Error(`Invalid response format: ${e.message}`));
1404
+ }
1405
+ } else {
1406
+ // Binary or non-JSON response (e.g., application/zip) — return metadata
1407
+ resolve({ _binary: true, contentType, size: responseData.length });
1408
+ }
1409
+ } else {
1410
+ let errorMessage;
1411
+ try {
1412
+ const error = JSON.parse(responseData);
1413
+ errorMessage = (typeof error.detail === 'object' && error.detail !== null)
1414
+ ? JSON.stringify(error.detail)
1415
+ : (error.detail || error.message || `HTTP ${res.statusCode}`);
1416
+ } catch {
1417
+ errorMessage = `HTTP ${res.statusCode}: ${responseData}`;
1418
+ }
1419
+ reject(new Error(errorMessage));
1420
+ }
1421
+ } catch (parseError) {
1422
+ reject(new Error(`Invalid response format: ${parseError.message}`));
1423
+ }
1424
+ });
1425
+ });
1426
+
1427
+ req.on('error', (error) => {
1428
+ if (error.code === 'ENOTFOUND') {
1429
+ reject(new Error(`DNS resolution failed: Cannot resolve ${this.backendUrl.replace(/^https?:\/\//, '')}`));
1430
+ } else if (error.code === 'ECONNREFUSED') {
1431
+ reject(new Error(`Connection refused: Backend server may be down`));
1432
+ } else if (error.code === 'ETIMEDOUT') {
1433
+ reject(new Error(`Connection timeout: Backend server is not responding`));
1434
+ } else if (error.code === 'ECONNRESET') {
1435
+ reject(new Error(`Connection reset: Network instability detected`));
1436
+ } else {
1437
+ reject(new Error(`Network error: ${error.message}`));
1438
+ }
1439
+ });
1440
+
1441
+ req.on('timeout', () => {
1442
+ req.destroy();
1443
+ reject(new Error('Request timeout - backend may be unavailable'));
1444
+ });
1445
+
1446
+ if (method !== 'GET' && data) {
1447
+ req.write(JSON.stringify(data));
1448
+ }
1449
+ req.end();
1450
+ });
1451
+ }
1452
+
1453
+ formatOptimizationResult(result, context) {
1454
+ let output;
1455
+ if (result.rules_based) {
1456
+ if (result.fallback_mode) {
1457
+ output = `# 🔧 Prompt Optimized (Local Rules)\n\n`;
1458
+ output += `*Optimized using local rule templates — LLM quality available once you connect your API key.*\n\n`;
1459
+ } else {
1460
+ output = `# 🔧 Rules-Based Optimization Applied\n\n`;
1461
+ output += `*API key not validated — optimized using local rule templates. `;
1462
+ output += `Set \`MCP_API_KEY\` for full LLM optimization.*\n\n`;
1463
+ }
1464
+ output += `**Template:** \`${result.template_used || 'general'}\`\n\n`;
1465
+ output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1466
+ } else if (result.fallback_mode) {
1467
+ output = `# 🔧 Optimized (local rules — backend slow)\n\n`;
1468
+ output += `*Backend unavailable this time — applied local rule templates. Try again for LLM optimization.*\n\n`;
1469
+ output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n\n`;
1470
+ } else {
1471
+ output = `# 🎯 Optimized Prompt\n\n${result.optimized_prompt}\n\n`;
1472
+ if (result.confidence_score < 0.25) {
1473
+ output += `> ℹ️ *Low confidence indicates the backend applied rules-based optimization (no LLM). `;
1474
+ output += `Ensure \`OPENROUTER_API_KEY\` is configured in the backend for full LLM enhancement.*\n\n`;
1475
+ }
1476
+ }
1477
+ if (result.rules_based) {
1478
+ output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}% *(rules-based — LLM optimization typically 70–95%)*\n`;
1479
+ } else {
1480
+ output += `**Confidence:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
1481
+ }
1482
+ output += `**AI Context:** ${result.metadata?.context_detection?.ai_context || result.metadata?.ai_context || context.detectedContext}\n`;
1483
+ if (result.metadata?.routing_score != null) {
1484
+ output += `**Routing Score:** ${result.metadata.routing_score.toFixed(3)} (${result.metadata?.routing_tier || 'unknown'})\n`;
1485
+ }
1486
+ if (!result.rules_based && !result.fallback_mode && result.metadata?.model_used) {
1487
+ output += `**Model:** ${result.metadata.model_used}\n`;
1488
+ }
1489
+
1490
+ if (result.template_saved) {
1491
+ output += `\n📁 **Template Auto-Save**\n✅ Automatically saved as template (ID: \`${result.template_id}\`)\n*Confidence threshold: >70% required for auto-save*\n`;
1492
+ }
1493
+
1494
+ if (result.templates_found?.length) {
1495
+ output += `\n📋 **Similar Templates Found**\nFound **${result.templates_found.length}** similar template(s):\n`;
1496
+ result.templates_found.slice(0, 3).forEach(t => {
1497
+ output += `- ${t.title} (${(t.confidence_score * 100).toFixed(1)}% match) — ID: \`${t.id}\`\n`;
1498
+ });
1499
+ output += `\n💡 Use \`get_template\` with any ID above to view the full optimized prompt.\n`;
1500
+ }
1501
+
1502
+ if (result.optimization_insights) {
1503
+ const metrics = result.optimization_insights.improvement_metrics;
1504
+ if (metrics) {
1505
+ output += `\n📊 **Optimization Insights**\n`;
1506
+ if (metrics.clarity_improvement) output += `- Clarity: +${(metrics.clarity_improvement * 100).toFixed(1)}%\n`;
1507
+ if (metrics.specificity_improvement) output += `- Specificity: +${(metrics.specificity_improvement * 100).toFixed(1)}%\n`;
1508
+ if (metrics.context_alignment) output += `- Context Alignment: +${(metrics.context_alignment * 100).toFixed(1)}%\n`;
1509
+ }
1510
+
1511
+ if (result.optimization_insights.recommendations?.length) {
1512
+ output += `\n💡 **Recommendations:**\n`;
1513
+ result.optimization_insights.recommendations.forEach(rec => {
1514
+ output += `- ${rec}\n`;
1515
+ });
1516
+ }
1517
+ }
1518
+
1519
+ // Add Bayesian insights if available
1520
+ if (result.bayesian_insights && context.enableBayesian) {
1521
+ output += `\n🧠 **Bayesian Optimization Insights**\n`;
1522
+ const bayesian = result.bayesian_insights;
1523
+
1524
+ if (bayesian.parameter_optimization) {
1525
+ output += `**Parameter Tuning:**\n`;
1526
+ if (bayesian.parameter_optimization.temperature_adjustment) {
1527
+ output += `- Temperature: ${bayesian.parameter_optimization.temperature_adjustment}\n`;
1528
+ }
1529
+ if (bayesian.parameter_optimization.goal_prioritization) {
1530
+ output += `- Goal Priority: ${bayesian.parameter_optimization.goal_prioritization}\n`;
1531
+ }
1532
+ }
1533
+
1534
+ if (bayesian.performance_prediction) {
1535
+ output += `**Performance Prediction:**\n`;
1536
+ output += `- Expected Improvement: ${bayesian.performance_prediction.expected_improvement}\n`;
1537
+ output += `- Confidence Interval: ${bayesian.performance_prediction.confidence_interval}\n`;
1538
+ }
1539
+
1540
+ if (bayesian.next_optimization_recommendation) {
1541
+ output += `**Next Optimization:**\n`;
1542
+ output += `- Suggested Goals: ${bayesian.next_optimization_recommendation.suggested_goals.join(', ')}\n`;
1543
+ output += `- Estimated Improvement: ${bayesian.next_optimization_recommendation.estimated_improvement}\n`;
1544
+ }
1545
+ }
1546
+
1547
+ if (!result.fallback_mode) {
1548
+ if (result.quota_used != null) {
1549
+ if (result.quota_limit == null) {
1550
+ // Unlimited plan show status only, no upsell
1551
+ output += `\n📊 **Usage:** ${result.quota_used} optimizations — Unlimited plan\n`;
1552
+ } else {
1553
+ const remaining = result.quota_limit - result.quota_used;
1554
+ if (result.quota_used >= result.quota_limit) {
1555
+ output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} — quota reached. **[Upgrade for more →](https://promptoptimizer.xyz/pricing)**\n`;
1556
+ } else if (remaining <= 2) {
1557
+ output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} LLM optimizations (${remaining} left) — [Upgrade for more](https://promptoptimizer.xyz/pricing)\n`;
1558
+ } else {
1559
+ output += `\n📊 **Usage:** ${result.quota_used}/${result.quota_limit} LLM optimizations this month — [Upgrade for more](https://promptoptimizer.xyz/pricing)\n`;
1560
+ }
1561
+ }
1562
+ }
1563
+ output += `\n🔗 **Quick Actions**\n- Dashboard: https://promptoptimizer.xyz/dashboard\n- Analytics: https://promptoptimizer.xyz/analytics\n`;
1564
+ } else {
1565
+ const confPct = Math.round((result.confidence_score || 0) * 100);
1566
+ output += `\n---\n`;
1567
+ output += `\n💡 **Unlock LLM Optimization — Free**\n\n`;
1568
+ output += `Local rules reached **${confPct}% confidence**. LLM optimization typically achieves **70–95%** — `;
1569
+ output += `more specific, context-aware, and effective for your actual intent.\n\n`;
1570
+ output += `**Get started free** (no credit card):\n`;
1571
+ output += `1. Sign up at https://promptoptimizer.xyz\n`;
1572
+ output += `2. Generate your API key at https://promptoptimizer.xyz/dashboard\n`;
1573
+ output += `3. Run in your terminal:\n\n`;
1574
+ output += `\`\`\`\nnpx mcp-prompt-optimizer connect\n\`\`\`\n\n`;
1575
+ output += `You get **7 LLM optimizations/month free**. Upgrade anytime for more.\n`;
1576
+ }
1577
+
1578
+ return output;
1579
+ }
1580
+
1581
+ formatQuotaStatus(result) {
1582
+ let output = `# 📊 Account Status\n\n**Plan:** ${result.tier || 'free'}\n`;
1583
+
1584
+ const quota = result.quota || {};
1585
+ if (quota.unlimited) {
1586
+ output += `**Usage:** 🟢 Unlimited\n`;
1587
+ } else {
1588
+ const used = quota.used || 0;
1589
+ const limit = quota.limit || 5000;
1590
+ const percentage = limit > 0 ? ((used / limit) * 100).toFixed(1) : 0;
1591
+
1592
+ let statusIcon = '🟢';
1593
+ if (percentage >= 90) statusIcon = '🔴';
1594
+ else if (percentage >= 75) statusIcon = '🟡';
1595
+
1596
+ output += `**Usage:** ${statusIcon} ${used}/${limit} (${percentage}%)\n`;
1597
+
1598
+ const remaining = limit - used;
1599
+ if (remaining <= 0) {
1600
+ output += `\n **Quota Exhausted** — You have no optimizations remaining this month.\n`;
1601
+ output += `Upgrade at https://promptoptimizer.xyz/local-license\n`;
1602
+ output += `*(Quota resets at the start of your next billing cycle)*\n`;
1603
+ } else if (percentage >= 90) {
1604
+ output += `\n⚠️ **Critical** — ${remaining} optimization${remaining === 1 ? '' : 's'} remaining. Upgrade at https://promptoptimizer.xyz/local-license\n`;
1605
+ } else if (percentage >= 75) {
1606
+ output += `\n⚠️ **Warning** — Approaching your monthly limit.\n`;
1607
+ }
1608
+ }
1609
+
1610
+ output += `\n## **Available Features**\n`;
1611
+ if (result.features) {
1612
+ if (result.features.optimization) output += `✅ Prompt Optimization\n`;
1613
+ if (result.features.template_search) output += `✅ Template Search & Management\n`;
1614
+ if (result.features.template_auto_save) output += `✅ Template Auto-Save\n`;
1615
+ if (result.features.optimization_insights) output += `✅ Optimization Insights\n`;
1616
+ if (this.bayesianOptimizationEnabled) output += `🧠 Bayesian Optimization\n`;
1617
+ if (this.aguiFeatures) output += `⚡ AG-UI Real-time Features\n`;
1618
+ }
1619
+
1620
+ if (result.mode) {
1621
+ output += `\n## 🔧 **Mode Status**\n`;
1622
+ if (result.mode.development) output += `⚙️ Development Mode\n`;
1623
+ if (result.mode.mock) output += `🎭 Mock Mode\n`;
1624
+ if (result.mode.fallback) output += `🔄 Fallback Mode\n`;
1625
+ if (result.mode.offline) output += `📱 Offline Mode\n`;
1626
+ }
1627
+
1628
+ output += `\n## 🔗 **Account Management**\n`;
1629
+ output += `- Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n`;
1630
+ output += `- Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
1631
+ output += `- Upgrade: https://promptoptimizer.xyz/local-license\n`;
1632
+
1633
+ return output;
1634
+ }
1635
+
1636
+ formatTemplateSearchResults(result, originalArgs) {
1637
+ let output = `# 🔍 Template Search Results\n\n`;
1638
+
1639
+ if (originalArgs.query || originalArgs.ai_context || originalArgs.sophistication_level) {
1640
+ output += `**Search Criteria:**\n`;
1641
+ if (originalArgs.query) output += `- Query: "${originalArgs.query}"\n`;
1642
+ if (originalArgs.ai_context) output += `- AI Context: ${originalArgs.ai_context}\n`;
1643
+ if (originalArgs.sophistication_level) output += `- Sophistication: ${originalArgs.sophistication_level}\n`;
1644
+ if (originalArgs.complexity_level) output += `- Complexity: ${originalArgs.complexity_level}\n`;
1645
+ output += `\n`;
1646
+ }
1647
+
1648
+ output += `Found **${result.total}** template(s)\n\n`;
1649
+
1650
+ if (!result.templates || result.templates.length === 0) {
1651
+ output += `📭 **No Templates Found**\n`;
1652
+ const hasActiveFilters = originalArgs.query || originalArgs.ai_context || originalArgs.sophistication_level || originalArgs.complexity_level;
1653
+ if (hasActiveFilters) {
1654
+ output += `No templates matched your filters. Try removing \`ai_context\` or \`query\` filters.\n`;
1655
+ } else {
1656
+ output += `You don't have any saved templates yet. Templates are automatically saved when optimization confidence is >70%.\n`;
1657
+ output += `Run \`optimize_prompt\` to start building your template library.\n`;
1658
+ }
1659
+ } else {
1660
+ output += `## 📋 **Template Results**\n`;
1661
+ result.templates.forEach((t, index) => {
1662
+ const confidence = t.confidence_score ? `${(t.confidence_score * 100).toFixed(1)}%` : 'N/A';
1663
+ const preview = t.optimized_prompt ? t.optimized_prompt.substring(0, 60) + '...' : 'Preview unavailable';
1664
+
1665
+ output += `### ${index + 1}. ${t.title}\n`;
1666
+ output += `- **Confidence:** ${confidence}\n`;
1667
+ output += `- **ID:** \`${t.id}\`\n`;
1668
+ output += `- **Preview:** ${preview}\n`;
1669
+ if (t.ai_context) output += `- **Context:** ${t.ai_context}\n`;
1670
+ if (t.optimization_goals && t.optimization_goals.length) {
1671
+ output += `- **Goals:** ${t.optimization_goals.join(', ')}\n`;
1672
+ }
1673
+ output += `\n`;
1674
+ });
1675
+
1676
+ output += `## 💡 **Template Usage Guide**\n`;
1677
+ output += `- Copy prompts for immediate use\n`;
1678
+ output += `- Use template IDs to reference specific templates\n`;
1679
+ output += `- High-confidence templates (>80%) are most reliable\n`;
1680
+ }
1681
+
1682
+ if (result.fallback_mode) {
1683
+ output += `\n⚠️ **Search Temporarily Unavailable**\n${result.message}\n`;
1684
+ }
1685
+
1686
+ return output;
1687
+ }
1688
+
1689
+ formatOptimizationInsights(insights) {
1690
+ let output = `# 🧠 Bayesian Optimization Insights\n\n`;
1691
+
1692
+ if (insights.bayesian_status) {
1693
+ const status = insights.bayesian_status;
1694
+ output += `## 📊 **Status Overview**\n`;
1695
+ output += `- **Status:** ${status.optimization_active ? '🟢 Active' : '🔴 Inactive'}\n`;
1696
+ output += `- **Total Optimizations:** ${status.total_optimizations}\n`;
1697
+ output += `- **Improvement Rate:** ${status.improvement_rate}\n`;
1698
+ output += `- **System Confidence:** ${(status.confidence_score * 100).toFixed(1)}%\n\n`;
1699
+ }
1700
+
1701
+ if (insights.parameter_insights) {
1702
+ const params = insights.parameter_insights;
1703
+ output += `## 🎯 **Parameter Analysis**\n`;
1704
+
1705
+ if (params.most_effective_goals) {
1706
+ output += `**Most Effective Goals:**\n`;
1707
+ params.most_effective_goals.forEach(goal => {
1708
+ output += `- ${goal}\n`;
1709
+ });
1710
+ output += `\n`;
1711
+ }
1712
+
1713
+ if (params.context_performance) {
1714
+ output += `**Context Performance:**\n`;
1715
+ Object.entries(params.context_performance).forEach(([context, score]) => {
1716
+ const percentage = (score * 100).toFixed(1);
1717
+ const icon = score >= 0.9 ? '🟢' : score >= 0.8 ? '🟡' : '🔴';
1718
+ output += `- ${context}: ${icon} ${percentage}%\n`;
1719
+ });
1720
+ output += `\n`;
1721
+ }
1722
+
1723
+ if (params.optimization_trends) {
1724
+ output += `**Trends:** ${params.optimization_trends}\n\n`;
1725
+ }
1726
+ }
1727
+
1728
+ if (insights.recommendations && insights.recommendations.length) {
1729
+ output += `## 💡 **Optimization Recommendations**\n`;
1730
+ insights.recommendations.forEach((rec, index) => {
1731
+ output += `${index + 1}. ${rec}\n`;
1732
+ });
1733
+ output += `\n`;
1734
+ }
1735
+
1736
+ output += `## 🔗 **Advanced Analytics**\n`;
1737
+ output += `- Full Analytics: https://promptoptimizer-blog.vercel.app/analytics\n`;
1738
+ output += `- Performance Dashboard: https://promptoptimizer-blog.vercel.app/dashboard\n`;
1739
+
1740
+ return output;
1741
+ }
1742
+
1743
+ formatRealTimeStatus(status) {
1744
+ let output = `# ⚡ AG-UI Real-Time Status\n\n`;
1745
+
1746
+ output += `## 🚀 **Service Status**\n`;
1747
+ output += `- **AG-UI Status:** ${status.agui_status === 'available' ? '🟢 Available' : '🔴 Unavailable'}\n`;
1748
+ output += `- **Streaming Optimization:** ${status.streaming_optimization ? '✅ Enabled' : '❌ Disabled'}\n`;
1749
+ output += `- **WebSocket Support:** ${status.websocket_support ? '✅ Enabled' : '❌ Disabled'}\n`;
1750
+ output += `- **Real-time Analytics:** ${status.real_time_analytics ? '✅ Enabled' : '❌ Disabled'}\n\n`;
1751
+
1752
+ if (status.active_optimizations !== undefined) {
1753
+ output += `## 📈 **Current Activity**\n`;
1754
+ output += `- **Active Optimizations:** ${status.active_optimizations}\n`;
1755
+ output += `- **Average Response Time:** ${status.average_response_time}\n\n`;
1756
+ }
1757
+
1758
+ if (status.features) {
1759
+ const features = status.features;
1760
+ output += `## ⚡ **Available Features**\n`;
1761
+ if (features.live_optimization) output += `✅ Live Optimization\n`;
1762
+ if (features.collaborative_editing) output += `✅ Collaborative Editing\n`;
1763
+ if (features.instant_feedback) output += `✅ Instant Feedback\n`;
1764
+ if (features.performance_monitoring) output += `✅ Performance Monitoring\n`;
1765
+ output += `\n`;
1766
+ }
1767
+
1768
+ output += `## 🔗 **Real-Time Access**\n`;
1769
+ output += `- Live Dashboard: https://promptoptimizer-blog.vercel.app/live\n`;
1770
+ output += `- WebSocket Endpoint: Available via API\n`;
1771
+
1772
+ return output;
1773
+ }
1774
+
1775
+ async run() {
1776
+ const transport = new StdioServerTransport();
1777
+ await this.server.connect(transport);
1778
+ }
1779
+ }
1780
+
1781
+ async function startValidatedMCPServer() {
1782
+ console.error(`🚀 MCP Prompt Optimizer - Professional Cloud Server v${packageJson.version}\n`);
1783
+ console.error(`🧠 Bayesian Optimization: ${process.env.ENABLE_BAYESIAN_OPTIMIZATION === 'true' ? 'Enabled' : 'Disabled'}`);
1784
+ console.error(`⚡ AG-UI Features: ${process.env.ENABLE_AGUI_FEATURES === 'true' ? 'Enabled' : 'Disabled'}\n`);
1785
+
1786
+ try {
1787
+ const apiKey = process.env.OPTIMIZER_API_KEY;
1788
+ if (!apiKey) {
1789
+ console.error(' API key required. Get one at https://promptoptimizer.xyz/local-license');
1790
+ process.exit(1);
1791
+ }
1792
+
1793
+ // SECURITY: No development mode bypass - backend validation required
1794
+ const manager = new CloudApiKeyManager(apiKey);
1795
+ console.error('🔧 Validating API key...\n');
1796
+ const validation = await manager.validateAndPrepare();
1797
+
1798
+ console.error('🔧 Starting MCP server...\n');
1799
+ const mcpServer = new MCPPromptOptimizer();
1800
+ console.error('✅ MCP server ready for connections');
1801
+
1802
+ // Enhanced status display
1803
+ const quotaDisplay = validation.quotaStatus.unlimited ?
1804
+ 'Unlimited' :
1805
+ `${validation.quotaStatus.remaining}/${validation.quotaStatus.limit} remaining`;
1806
+
1807
+ console.error(`📊 Plan: ${validation.tier} | Quota: ${quotaDisplay}`);
1808
+
1809
+ if (validation.mode.mock) console.error('🎭 Running in mock mode');
1810
+ if (validation.mode.development) console.error('⚙️ Development mode active');
1811
+ if (validation.mode.fallback) console.error('🔄 Fallback mode active');
1812
+ if (validation.mode.offline) console.error('📱 Offline mode active');
1813
+
1814
+ await mcpServer.run();
1815
+ } catch (error) {
1816
+ console.error(`❌ Failed to start MCP server: ${error.message}`);
1817
+ process.exit(1);
1818
+ }
1819
+ }
1820
+
1821
+ async function runConnectWizard() {
1822
+ const readline = require('readline');
1823
+ const fs = require('fs');
1824
+ const path = require('path');
1825
+ const os = require('os');
1826
+
1827
+ // Known MCP client config locations keyed by [client, platform]
1828
+ const CLIENT_CONFIGS = [
1829
+ {
1830
+ name: 'Claude Desktop',
1831
+ paths: {
1832
+ win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json'),
1833
+ darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
1834
+ linux: path.join(os.homedir(), '.config', 'Claude', 'claude_desktop_config.json'),
1835
+ },
1836
+ serverKey: 'mcp-prompt-optimizer',
1837
+ },
1838
+ {
1839
+ name: 'Cursor',
1840
+ paths: {
1841
+ win32: path.join(os.homedir(), '.cursor', 'mcp.json'),
1842
+ darwin: path.join(os.homedir(), '.cursor', 'mcp.json'),
1843
+ linux: path.join(os.homedir(), '.cursor', 'mcp.json'),
1844
+ },
1845
+ serverKey: 'mcp-prompt-optimizer',
1846
+ },
1847
+ {
1848
+ name: 'VS Code Cline / Roo',
1849
+ paths: {
1850
+ win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1851
+ darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1852
+ linux: path.join(os.homedir(), '.config', 'Code', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
1853
+ },
1854
+ serverKey: 'mcp-prompt-optimizer',
1855
+ },
1856
+ {
1857
+ name: 'Continue.dev',
1858
+ paths: {
1859
+ win32: path.join(os.homedir(), '.continue', 'config.json'),
1860
+ darwin: path.join(os.homedir(), '.continue', 'config.json'),
1861
+ linux: path.join(os.homedir(), '.continue', 'config.json'),
1862
+ },
1863
+ serverKey: 'mcp-prompt-optimizer',
1864
+ },
1865
+ ];
1866
+
1867
+ function safeWriteConfig(filePath, newConfig) {
1868
+ const backupPath = filePath + '.bak';
1869
+ // Backup
1870
+ if (fs.existsSync(filePath)) {
1871
+ fs.copyFileSync(filePath, backupPath);
1872
+ }
1873
+ try {
1874
+ const serialized = JSON.stringify(newConfig, null, 2);
1875
+ fs.writeFileSync(filePath, serialized, 'utf8');
1876
+ // Verify round-trip
1877
+ JSON.parse(fs.readFileSync(filePath, 'utf8'));
1878
+ } catch (e) {
1879
+ // Restore backup on any failure
1880
+ if (fs.existsSync(backupPath)) {
1881
+ fs.copyFileSync(backupPath, filePath);
1882
+ }
1883
+ throw e;
1884
+ }
1885
+ }
1886
+
1887
+ function patchConfig(config, serverKey, apiKey) {
1888
+ if (!config.mcpServers) config.mcpServers = {};
1889
+ if (config.mcpServers[serverKey]) {
1890
+ if (!config.mcpServers[serverKey].env) config.mcpServers[serverKey].env = {};
1891
+ config.mcpServers[serverKey].env.OPTIMIZER_API_KEY = apiKey;
1892
+ } else {
1893
+ config.mcpServers[serverKey] = {
1894
+ command: 'npx',
1895
+ args: ['-y', 'mcp-prompt-optimizer'],
1896
+ env: { OPTIMIZER_API_KEY: apiKey },
1897
+ };
1898
+ }
1899
+ return config;
1900
+ }
1901
+
1902
+ console.log('\n🔌 Prompt Optimizer — Connect Wizard\n');
1903
+
1904
+ // Detect which clients are installed
1905
+ const platform = process.platform;
1906
+ const found = CLIENT_CONFIGS
1907
+ .map(c => ({ ...c, configPath: c.paths[platform] || c.paths.linux }))
1908
+ .filter(c => fs.existsSync(c.configPath));
1909
+
1910
+ if (found.length === 0) {
1911
+ console.log('❌ No supported MCP client config found. Supported clients:');
1912
+ CLIENT_CONFIGS.forEach(c => {
1913
+ const p = c.paths[platform] || c.paths.linux;
1914
+ console.log(` ${c.name}: ${p}`);
1915
+ });
1916
+ console.log('\nOpen your MCP client first to create its config file, then re-run this command.');
1917
+ process.exit(1);
1918
+ }
1919
+
1920
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1921
+
1922
+ function askApiKey(cb) {
1923
+ rl.question('Paste your API key (get one free at https://promptoptimizer.xyz/dashboard): ', (key) => {
1924
+ cb((key || '').trim());
1925
+ });
1926
+ }
1927
+
1928
+ function askClient(clients, cb) {
1929
+ console.log('Multiple MCP clients detected. Which one should be configured?');
1930
+ clients.forEach((c, i) => console.log(` ${i + 1}) ${c.name}`));
1931
+ rl.question('Enter number (or press Enter for all): ', (ans) => {
1932
+ const n = parseInt(ans, 10);
1933
+ if (!ans.trim()) {
1934
+ cb(clients);
1935
+ } else if (n >= 1 && n <= clients.length) {
1936
+ cb([clients[n - 1]]);
1937
+ } else {
1938
+ console.log('Invalid selection, configuring all.');
1939
+ cb(clients);
1940
+ }
1941
+ });
1942
+ }
1943
+
1944
+ function applyToClients(clients, apiKey) {
1945
+ rl.close();
1946
+ let ok = 0;
1947
+ for (const client of clients) {
1948
+ let config;
1949
+ try {
1950
+ config = JSON.parse(fs.readFileSync(client.configPath, 'utf8'));
1951
+ } catch (e) {
1952
+ console.log(`❌ Could not read ${client.name} config: ${e.message}`);
1953
+ continue;
1954
+ }
1955
+ try {
1956
+ const patched = patchConfig(config, client.serverKey, apiKey);
1957
+ safeWriteConfig(client.configPath, patched);
1958
+ console.log(`✅ ${client.name} — configured (${client.configPath})`);
1959
+ ok++;
1960
+ } catch (e) {
1961
+ console.log(`❌ Could not write ${client.name} config: ${e.message}`);
1962
+ console.log(' Try running as administrator, or edit the file manually.');
1963
+ }
1964
+ }
1965
+ if (ok > 0) {
1966
+ console.log('\n👉 Restart your MCP client(s) to activate LLM optimization.');
1967
+ console.log(' Free plan: 7 LLM optimizations/month.');
1968
+ console.log(' Upgrade at https://promptoptimizer.xyz/pricing\n');
1969
+ }
1970
+ }
1971
+
1972
+ askApiKey((apiKey) => {
1973
+ if (!apiKey.startsWith('sk-')) {
1974
+ rl.close();
1975
+ console.log('\n❌ Invalid key must start with "sk-". Get one at https://promptoptimizer.xyz/dashboard');
1976
+ process.exit(1);
1977
+ }
1978
+ if (found.length === 1) {
1979
+ applyToClients(found, apiKey);
1980
+ } else {
1981
+ askClient(found, (chosen) => applyToClients(chosen, apiKey));
1982
+ }
1983
+ });
1984
+ }
1985
+
1986
+ if (require.main === module) {
1987
+ const args = process.argv.slice(2);
1988
+ if (args[0] === 'connect') {
1989
+ runConnectWizard();
1990
+ } else {
1991
+ startValidatedMCPServer();
1992
+ }
1993
+ }
1994
+
1989
1995
  module.exports = { MCPPromptOptimizer };