mcp-prompt-optimizer 1.5.0 → 2.2.3
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/CHANGELOG.md +26 -9
- package/CROSS-PLATFORM.md +3 -3
- package/README.md +99 -39
- package/index.js +311 -130
- package/lib/api-key-manager.js +191 -138
- package/lib/check-status.js +1 -1
- package/package.json +3 -3
- package/tests/README.md +0 -232
- package/tests/comprehensive-test.js +0 -692
- package/tests/integration-test.js +0 -446
- package/tests/minimal-test.js +0 -265
- package/tests/quick-test.js +0 -282
- package/tests/simple-test.js +0 -171
- package/tests/test-runner.js +0 -322
package/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Production-grade with Bayesian optimization, AG-UI real-time features, enhanced network resilience,
|
|
6
6
|
* development mode, and complete backend alignment
|
|
7
7
|
*
|
|
8
|
-
* Version: 2.
|
|
8
|
+
* Version: 2.2.0 - Aligned with FastAPI Backend production-v2.2.0-stable
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
|
|
@@ -15,6 +15,53 @@ const https = require('https');
|
|
|
15
15
|
const CloudApiKeyManager = require('./lib/api-key-manager');
|
|
16
16
|
const packageJson = require('./package.json');
|
|
17
17
|
|
|
18
|
+
const API_KEYS_PREFIX = '/api/v1/api-keys';
|
|
19
|
+
|
|
20
|
+
const ENDPOINTS = {
|
|
21
|
+
/** Detect AI context (POST) */
|
|
22
|
+
DETECT_CONTEXT: '/api/v1/templates/detect-context',
|
|
23
|
+
|
|
24
|
+
/** Prompt optimization (POST) */
|
|
25
|
+
OPTIMIZE: '/api/v1/optimize',
|
|
26
|
+
|
|
27
|
+
/** CRUD on templates */
|
|
28
|
+
TEMPLATE: {
|
|
29
|
+
/** Create (POST) */
|
|
30
|
+
CREATE: '/api/v1/templates/',
|
|
31
|
+
|
|
32
|
+
/** Read (GET) */
|
|
33
|
+
GET: (id) => `/api/v1/templates/${id}`,
|
|
34
|
+
|
|
35
|
+
/** Update (PATCH) */
|
|
36
|
+
UPDATE: (id) => `/api/v1/templates/${id}`,
|
|
37
|
+
|
|
38
|
+
/** Delete (DELETE) */
|
|
39
|
+
DELETE: (id) => `/api/v1/templates/${id}`,
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Search templates
|
|
44
|
+
* (In the current code‑base this is *not* a dedicated `/search` path –
|
|
45
|
+
* the original implementation appends query‑params to `/api/v1/templates/`.
|
|
46
|
+
* We keep the original path here so that the existing `handleSearchTemplates`
|
|
47
|
+
* handler does not need any change other than using the constant.
|
|
48
|
+
*/
|
|
49
|
+
SEARCH_TEMPLATES: '/api/v1/templates/',
|
|
50
|
+
|
|
51
|
+
/** Quota status (GET) – note the plural “api‑keys” */
|
|
52
|
+
QUOTA_STATUS: `${API_KEYS_PREFIX}/quota-status`,
|
|
53
|
+
|
|
54
|
+
/** Validate API key (POST) – also under the plural router */
|
|
55
|
+
VALIDATE_KEY: `${API_KEYS_PREFIX}/validate`,
|
|
56
|
+
|
|
57
|
+
/** Bayesian insights (GET) */
|
|
58
|
+
ANALYTICS_BAYESIAN_INSIGHTS:
|
|
59
|
+
'/api/v1/analytics/bayesian-insights',
|
|
60
|
+
|
|
61
|
+
/** AG‑UI status (GET) */
|
|
62
|
+
AGUI_STATUS: '/api/v1/agui/status',
|
|
63
|
+
};
|
|
64
|
+
|
|
18
65
|
class MCPPromptOptimizer {
|
|
19
66
|
constructor() {
|
|
20
67
|
this.server = new Server(
|
|
@@ -35,8 +82,8 @@ class MCPPromptOptimizer {
|
|
|
35
82
|
this.requestTimeout = parseInt(process.env.OPTIMIZER_REQUEST_TIMEOUT) || 30000;
|
|
36
83
|
|
|
37
84
|
// NEW: Feature flags aligned with backend
|
|
38
|
-
this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION
|
|
39
|
-
this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES
|
|
85
|
+
this.bayesianOptimizationEnabled = process.env.ENABLE_BAYESIAN_OPTIMIZATION === 'true';
|
|
86
|
+
this.aguiFeatures = process.env.ENABLE_AGUI_FEATURES === 'true';
|
|
40
87
|
|
|
41
88
|
this.setupMCPHandlers();
|
|
42
89
|
}
|
|
@@ -82,6 +129,60 @@ class MCPPromptOptimizer {
|
|
|
82
129
|
description: "📊 Check subscription status, quota usage, and account information with detailed insights and Bayesian optimization metrics",
|
|
83
130
|
inputSchema: { type: "object", properties: {}, additionalProperties: false }
|
|
84
131
|
},
|
|
132
|
+
{
|
|
133
|
+
name: "create_template",
|
|
134
|
+
description: "➕ Create a new optimization template.",
|
|
135
|
+
inputSchema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
title: { type: "string", description: "Title of the template" },
|
|
139
|
+
description: { type: "string", description: "Description of the template" },
|
|
140
|
+
original_prompt: { type: "string", description: "The original prompt text" },
|
|
141
|
+
optimized_prompt: { type: "string", description: "The optimized prompt text" },
|
|
142
|
+
optimization_goals: { type: "array", items: { type: "string" }, description: "Goals for this optimization (e.g., 'clarity', 'conciseness', 'creativity', 'technical_accuracy', 'analytical_depth', 'creative_enhancement')" },
|
|
143
|
+
confidence_score: { type: "number", description: "Confidence score of the optimization (0.0-1.0)" },
|
|
144
|
+
model_used: { type: "string", description: "Model used for optimization" },
|
|
145
|
+
optimization_tier: { type: "string", description: "Tier of optimization (e.g., rules, llm, hybrid)" },
|
|
146
|
+
ai_context_detected: { type: "string", description: "Detected AI context (e.g., code_generation, image_generation)" },
|
|
147
|
+
is_public: { type: "boolean", default: false, description: "Whether the template is public" },
|
|
148
|
+
tags: { type: "array", items: { type: "string" }, description: "Tags for the template" }
|
|
149
|
+
},
|
|
150
|
+
required: ["title", "original_prompt", "optimized_prompt", "confidence_score"]
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "get_template",
|
|
155
|
+
description: "🔍 Retrieve a specific template by its ID.",
|
|
156
|
+
inputSchema: {
|
|
157
|
+
type: "object",
|
|
158
|
+
properties: {
|
|
159
|
+
template_id: { type: "string", description: "The ID of the template to retrieve" }
|
|
160
|
+
},
|
|
161
|
+
required: ["template_id"]
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: "update_template",
|
|
166
|
+
description: "✏️ Update an existing optimization template.",
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: {
|
|
170
|
+
template_id: { type: "string", description: "The ID of the template to update" },
|
|
171
|
+
title: { type: "string", description: "New title for the template" },
|
|
172
|
+
description: { type: "string", description: "New description for the template" },
|
|
173
|
+
original_prompt: { type: "string", description: "New original prompt text" },
|
|
174
|
+
optimized_prompt: { type: "string", description: "New optimized prompt text" },
|
|
175
|
+
optimization_goals: { type: "array", items: { type: "string" }, description: "New optimization goals" },
|
|
176
|
+
confidence_score: { type: "number", description: "New confidence score (0.0-1.0)" },
|
|
177
|
+
model_used: { type: "string", description: "New model used for optimization" },
|
|
178
|
+
optimization_tier: { type: "string", description: "New tier of optimization" },
|
|
179
|
+
ai_context_detected: { type: "string", description: "New detected AI context" },
|
|
180
|
+
is_public: { type: "boolean", description: "Whether the template is public" },
|
|
181
|
+
tags: { type: "array", items: { type: "string" }, description: "New tags for the template" }
|
|
182
|
+
},
|
|
183
|
+
required: ["template_id"]
|
|
184
|
+
}
|
|
185
|
+
},
|
|
85
186
|
{
|
|
86
187
|
name: "search_templates",
|
|
87
188
|
description: "🔍 Search your saved template library with AI-aware filtering, context-based search, and sophisticated template matching",
|
|
@@ -130,7 +231,21 @@ class MCPPromptOptimizer {
|
|
|
130
231
|
}
|
|
131
232
|
}
|
|
132
233
|
}
|
|
133
|
-
}
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: "detect_ai_context",
|
|
237
|
+
description: "🧠 Detects the AI context for a given prompt using advanced backend analysis.",
|
|
238
|
+
inputSchema: {
|
|
239
|
+
type: "object",
|
|
240
|
+
properties: {
|
|
241
|
+
prompt: {
|
|
242
|
+
type: "string",
|
|
243
|
+
description: "The prompt text for which to detect the AI context"
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
required: ["prompt"]
|
|
247
|
+
}
|
|
248
|
+
},
|
|
134
249
|
];
|
|
135
250
|
|
|
136
251
|
// Add advanced tools if Bayesian optimization is enabled
|
|
@@ -176,6 +291,10 @@ class MCPPromptOptimizer {
|
|
|
176
291
|
case "optimize_prompt": return await this.handleOptimizePrompt(args);
|
|
177
292
|
case "get_quota_status": return await this.handleGetQuotaStatus();
|
|
178
293
|
case "search_templates": return await this.handleSearchTemplates(args);
|
|
294
|
+
case "detect_ai_context": return await this.handleDetectAIContext(args);
|
|
295
|
+
case "create_template": return await this.handleCreateTemplate(args);
|
|
296
|
+
case "get_template": return await this.handleGetTemplate(args);
|
|
297
|
+
case "update_template": return await this.handleUpdateTemplate(args);
|
|
179
298
|
case "get_optimization_insights": return await this.handleGetOptimizationInsights(args);
|
|
180
299
|
case "get_real_time_status": return await this.handleGetRealTimeStatus();
|
|
181
300
|
default: throw new Error(`Unknown tool: ${name}`);
|
|
@@ -186,95 +305,6 @@ class MCPPromptOptimizer {
|
|
|
186
305
|
});
|
|
187
306
|
}
|
|
188
307
|
|
|
189
|
-
detectAIContext(prompt) {
|
|
190
|
-
const p = prompt.toLowerCase();
|
|
191
|
-
|
|
192
|
-
// Enhanced AI context detection with weighted scoring system - aligned with backend
|
|
193
|
-
const contextScores = {
|
|
194
|
-
image_generation: 0,
|
|
195
|
-
code_generation: 0,
|
|
196
|
-
api_automation: 0,
|
|
197
|
-
technical_automation: 0,
|
|
198
|
-
structured_output: 0,
|
|
199
|
-
llm_interaction: 0,
|
|
200
|
-
human_communication: 0
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
const contextKeywords = {
|
|
204
|
-
image_generation: {
|
|
205
|
-
"photorealistic": 3.0, "photography": 3.0, "create image": 3.0, "generate picture": 3.0, "--ar": 3.5,
|
|
206
|
-
"gothic": 2.5, "aspect ratio": 2.5, "16:9": 2.5, "render": 2.5, "make visual": 2.5, "digital art": 2.5,
|
|
207
|
-
"edits": 2.0, "style": 2.0, "high resolution": 2.0, "cinematic": 2.0, "draw": 2.0, "painting": 2.0, "illustration": 2.0,
|
|
208
|
-
"image": 1.5, "visual": 1.5, "artwork": 1.5, "picture": 1.5, "design": 1.5, "sketch": 1.5, "logo": 1.5
|
|
209
|
-
},
|
|
210
|
-
code_generation: {
|
|
211
|
-
"```": 3.5, "fibonacci": 3.0, "def ": 3.0, "class ": 3.0, "algorithm": 2.5, "debug": 2.5, "recursive": 2.5,
|
|
212
|
-
"script": 2.0, "programming": 2.0, "python": 2.0, "javascript": 2.0, "function": 2.0, "c++": 2.0, "import": 2.0,
|
|
213
|
-
"java": 1.5, "sql": 1.5, "loop": 1.5, "code": 1.5, "variable": 1.5, "return": 1.5, "if ": 1.0, "else": 1.0,
|
|
214
|
-
"photography": -3.0, "photorealistic": -3.0, "gothic": -2.5, "style": -2.0, "cinematic": -2.0, "visual design": -2.0, "artwork": -2.0
|
|
215
|
-
},
|
|
216
|
-
api_automation: {
|
|
217
|
-
"api": 3.0, "curl": 2.5, "endpoint": 2.5, "get request": 2.5, "post request": 2.5, "webhook": 2.5, "swagger": 2.5, "openapi": 2.5,
|
|
218
|
-
"json": 2.0, "rest": 2.0, "http": 2.0, "put request": 2.0, "delete request": 2.0, "oauth": 2.0, "postman": 2.0, "bearer token": 2.0, "axios": 2.0, "api key": 2.0, "status code": 2.0,
|
|
219
|
-
"authentication": 1.5, "request": 1.5, "response": 1.5, "xml": 1.5, "insomnia": 1.5, "fetch": 1.5, "requests": 1.5, "headers": 1.5, "payload": 1.5
|
|
220
|
-
},
|
|
221
|
-
technical_automation: {
|
|
222
|
-
"automate": 3.0, "ci/cd": 3.0, "docker": 2.5, "kubernetes": 2.5, "deploy": 2.5, "deployment": 2.5, "automation": 2.5, "pipeline": 2.5, "github actions": 2.5, "shell script": 2.5,
|
|
223
|
-
"jenkins": 2.0, "workflow": 2.0, "gitlab ci": 2.0, "azure devops": 2.0, "k8s": 2.0, "terraform": 2.0, "ansible": 2.0, "bash": 2.0, "powershell": 2.0, "cron": 2.0, "infrastructure": 2.0,
|
|
224
|
-
"helm": 1.5, "chef": 1.5, "puppet": 1.5, "batch": 1.5, "scheduled": 1.5, "monitoring": 1.5
|
|
225
|
-
},
|
|
226
|
-
structured_output: {
|
|
227
|
-
"json": 2.5, "csv": 2.5, "schema": 2.5, "format data": 2.5, "data structure": 2.5,
|
|
228
|
-
"xml": 2.0, "yaml": 2.0, "format": 2.0, "table": 2.0, "spreadsheet": 2.0, "parse": 2.0, "serialize": 2.0, "deserialize": 2.0,
|
|
229
|
-
"toml": 1.5, "structure": 1.5, "template": 1.5, "database": 1.5, "export": 1.5, "extract": 1.5, "transform": 1.5, "convert": 1.5, "organize": 1.5, "layout": 1.5, "report": 1.5, "dashboard": 1.5, "chart": 1.5
|
|
230
|
-
},
|
|
231
|
-
llm_interaction: {
|
|
232
|
-
"analyze": 2.5, "analysis": 2.5, "evaluate": 2.0, "assess": 2.0, "research": 2.0, "compare": 2.0, "explain": 2.0, "summarize": 2.0, "pros and cons": 2.0,
|
|
233
|
-
"study": 1.5, "contrast": 1.5, "examine": 1.5, "investigate": 1.5, "review": 1.5, "critique": 1.5, "describe": 1.5, "interpret": 1.5, "comprehensive": 1.5, "detailed": 1.5, "thorough": 1.5, "in-depth": 1.5, "advantages": 1.5, "disadvantages": 1.5, "opinion": 1.5, "perspective": 1.5, "viewpoint": 1.5
|
|
234
|
-
},
|
|
235
|
-
human_communication: {
|
|
236
|
-
"email": 2.5, "message": 2.0, "letter": 2.0, "compose": 2.0, "communicate": 2.0, "correspondence": 2.0,
|
|
237
|
-
"memo": 1.5, "write": 1.5, "draft": 1.5, "send": 1.5, "reply": 1.5, "respond": 1.5, "formal": 1.5, "informal": 1.5, "professional": 1.5, "business": 1.5, "greeting": 1.5, "introduction": 1.5, "conclusion": 1.5, "signature": 1.5, "meeting": 1.5, "appointment": 1.5, "schedule": 1.5, "call": 1.5, "conversation": 1.5, "discussion": 1.5, "chat": 1.5,
|
|
238
|
-
"create": -0.5
|
|
239
|
-
}
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
// Calculate scores based on keyword presence
|
|
243
|
-
for (const [context, keywords] of Object.entries(contextKeywords)) {
|
|
244
|
-
for (const [keyword, weight] of Object.entries(keywords)) {
|
|
245
|
-
if (p.includes(keyword)) {
|
|
246
|
-
contextScores[context] += weight;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
// Find the highest scoring context
|
|
252
|
-
const maxScore = Math.max(...Object.values(contextScores));
|
|
253
|
-
if (maxScore <= 0) {
|
|
254
|
-
return 'human_communication';
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
const detectedContext = Object.keys(contextScores).find(key => contextScores[key] === maxScore) || 'human_communication';
|
|
258
|
-
return detectedContext;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
enhanceGoalsForContext(originalGoals, aiContext) {
|
|
262
|
-
const goals = new Set(originalGoals);
|
|
263
|
-
|
|
264
|
-
const contextGoals = {
|
|
265
|
-
image_generation: ['creative_enhancement', 'parameter_preservation', 'technical_accuracy'],
|
|
266
|
-
llm_interaction: ['analytical_depth', 'context_specificity', 'token_efficiency'],
|
|
267
|
-
technical_automation: ['technical_accuracy', 'parameter_preservation', 'specificity'],
|
|
268
|
-
code_generation: ['syntax_clarity', 'best_practices', 'maintainability', 'technical_accuracy'],
|
|
269
|
-
structured_output: ['format_compliance', 'data_validation', 'schema_adherence'],
|
|
270
|
-
api_automation: ['endpoint_clarity', 'parameter_specification', 'error_handling'],
|
|
271
|
-
human_communication: ['clarity', 'professionalism', 'engagement']
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
(contextGoals[aiContext] || ['clarity', 'actionability']).forEach(g => goals.add(g));
|
|
275
|
-
return Array.from(goals);
|
|
276
|
-
}
|
|
277
|
-
|
|
278
308
|
generateMockOptimization(prompt, goals, aiContext, enableBayesian = false) {
|
|
279
309
|
const optimized_prompt = `Enhanced for ${aiContext}: ${prompt}`;
|
|
280
310
|
const baseResult = {
|
|
@@ -328,47 +358,98 @@ class MCPPromptOptimizer {
|
|
|
328
358
|
return baseResult;
|
|
329
359
|
}
|
|
330
360
|
|
|
361
|
+
generateMockContextDetection(prompt) {
|
|
362
|
+
let primary_context = 'human_communication'; // Default context
|
|
363
|
+
const lc = prompt.toLowerCase(); // one‑off lower‑case copy
|
|
364
|
+
|
|
365
|
+
/* 1️⃣ Code / programming – now includes `def` / `return`. */
|
|
366
|
+
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)) {
|
|
367
|
+
primary_context = 'code_generation';
|
|
368
|
+
|
|
369
|
+
/* 2️⃣ Image / art – unchanged. */
|
|
370
|
+
} else if (lc.match(/image|generate|dall-e|midjourney/i)) {
|
|
371
|
+
primary_context = 'image_generation';
|
|
372
|
+
|
|
373
|
+
/* 3️⃣ Automation – unchanged. */
|
|
374
|
+
} else if (lc.match(/automate|script|api/i)) {
|
|
375
|
+
primary_context = 'technical_automation';
|
|
376
|
+
|
|
377
|
+
/* 4️⃣ LLM / analysis – newly added keyword “analyze”. */
|
|
378
|
+
} else if (lc.match(/analyze|explain|evaluate|summary|research|paper|analysis|interpret|discussion|assessment|compare|contrast/i)) {
|
|
379
|
+
primary_context = 'llm_interaction';
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return {
|
|
383
|
+
primary_context: primary_context,
|
|
384
|
+
confidence: 0.75,
|
|
385
|
+
secondary_contexts: ['llm_interaction'],
|
|
386
|
+
detected_parameters: [],
|
|
387
|
+
mock_mode: true,
|
|
388
|
+
reason: 'Running in development/fallback mode.'
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
|
|
331
392
|
async handleOptimizePrompt(args) {
|
|
332
393
|
if (!args.prompt) throw new Error('Prompt is required');
|
|
333
394
|
|
|
334
|
-
const detectedContext = args.ai_context || this.detectAIContext(args.prompt);
|
|
335
|
-
const enhancedGoals = this.enhanceGoalsForContext(args.goals || ['clarity'], detectedContext);
|
|
336
|
-
const enableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
|
|
337
|
-
|
|
338
395
|
const manager = new CloudApiKeyManager(this.apiKey, { developmentMode: this.developmentMode });
|
|
339
396
|
|
|
340
397
|
try {
|
|
341
398
|
const validation = await manager.validateApiKey();
|
|
342
399
|
|
|
343
400
|
if (validation.mock_mode || this.developmentMode) {
|
|
344
|
-
|
|
345
|
-
const
|
|
401
|
+
// In mock/dev mode, we still need a context for mock generation
|
|
402
|
+
const mockContext = args.ai_context || 'human_communication';
|
|
403
|
+
const mockGoals = args.goals || ['clarity'];
|
|
404
|
+
const mockEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
|
|
405
|
+
const mockResult = this.generateMockOptimization(args.prompt, mockGoals, mockContext, mockEnableBayesian);
|
|
406
|
+
const formatted = this.formatOptimizationResult(mockResult, { detectedContext: mockContext, enableBayesian: mockEnableBayesian });
|
|
346
407
|
return { content: [{ type: "text", text: formatted }] };
|
|
347
408
|
}
|
|
348
409
|
|
|
349
|
-
//
|
|
350
|
-
|
|
410
|
+
// 1. Detect AI Context from backend
|
|
411
|
+
let detectedContext = args.ai_context;
|
|
412
|
+
if (!detectedContext) {
|
|
413
|
+
try {
|
|
414
|
+
const contextDetectionResult = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
|
|
415
|
+
detectedContext = contextDetectionResult.primary_context;
|
|
416
|
+
console.error(`Detected AI Context from backend: ${detectedContext}`);
|
|
417
|
+
} catch (contextError) {
|
|
418
|
+
console.error(`Failed to detect AI context from backend, falling back to default: ${contextError.message}`);
|
|
419
|
+
detectedContext = 'human_communication'; // Fallback
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// 2. Call the main optimization endpoint
|
|
424
|
+
const enableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
|
|
425
|
+
const optimizationPayload = {
|
|
351
426
|
prompt: args.prompt,
|
|
352
|
-
goals:
|
|
353
|
-
|
|
427
|
+
goals: args.goals || ['clarity'], // Pass original goals, backend will enhance
|
|
428
|
+
context: {
|
|
429
|
+
ai_context: detectedContext
|
|
430
|
+
},
|
|
431
|
+
enable_bayesian: enableBayesian,
|
|
354
432
|
metadata: {
|
|
355
|
-
enable_bayesian: enableBayesian,
|
|
356
433
|
mcp_version: packageJson.version,
|
|
357
434
|
feature_flags: {
|
|
358
435
|
bayesian_optimization: this.bayesianOptimizationEnabled,
|
|
359
436
|
agui_features: this.aguiFeatures
|
|
360
437
|
}
|
|
361
438
|
}
|
|
362
|
-
}
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
const result = await this.callBackendAPI(ENDPOINTS.OPTIMIZE, optimizationPayload);
|
|
363
442
|
|
|
364
443
|
return { content: [{ type: "text", text: this.formatOptimizationResult(result, { detectedContext, enableBayesian }) }] };
|
|
365
444
|
|
|
366
445
|
} catch (error) {
|
|
367
|
-
if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout')) {
|
|
368
|
-
const
|
|
446
|
+
if (error.message.includes('Network') || error.message.includes('DNS') || error.message.includes('timeout') || error.message.includes('Connection')) {
|
|
447
|
+
const fallbackContext = args.ai_context || 'human_communication';
|
|
448
|
+
const fallbackEnableBayesian = args.enable_bayesian !== false && this.bayesianOptimizationEnabled;
|
|
449
|
+
const fallbackResult = this.generateMockOptimization(args.prompt, args.goals || ['clarity'], fallbackContext, fallbackEnableBayesian);
|
|
369
450
|
fallbackResult.fallback_mode = true;
|
|
370
451
|
fallbackResult.error_reason = error.message;
|
|
371
|
-
const formatted = this.formatOptimizationResult(fallbackResult, { detectedContext, enableBayesian });
|
|
452
|
+
const formatted = this.formatOptimizationResult(fallbackResult, { detectedContext: fallbackContext, enableBayesian: fallbackEnableBayesian });
|
|
372
453
|
return { content: [{ type: "text", text: formatted }] };
|
|
373
454
|
}
|
|
374
455
|
throw new Error(`Optimization failed: ${error.message}`);
|
|
@@ -396,7 +477,7 @@ class MCPPromptOptimizer {
|
|
|
396
477
|
if (args.complexity_level) params.append('complexity_level', args.complexity_level);
|
|
397
478
|
if (args.optimization_strategy) params.append('optimization_strategy', args.optimization_strategy);
|
|
398
479
|
|
|
399
|
-
const endpoint =
|
|
480
|
+
const endpoint = `${ENDPOINTS.SEARCH_TEMPLATES}?${params.toString()}`;
|
|
400
481
|
const result = await this.callBackendAPI(endpoint, null, 'GET');
|
|
401
482
|
|
|
402
483
|
const searchResult = {
|
|
@@ -432,7 +513,7 @@ class MCPPromptOptimizer {
|
|
|
432
513
|
|
|
433
514
|
try {
|
|
434
515
|
// Try to get insights from backend
|
|
435
|
-
const endpoint =
|
|
516
|
+
const endpoint = `${ENDPOINTS.ANALYTICS_BAYESIAN_INSIGHTS}?depth=${args.analysis_depth || 'detailed'}&recommendations=${args.include_recommendations !== false}`;
|
|
436
517
|
const result = await this.callBackendAPI(endpoint, null, 'GET');
|
|
437
518
|
|
|
438
519
|
return { content: [{ type: "text", text: this.formatOptimizationInsights(result) }] };
|
|
@@ -472,8 +553,7 @@ class MCPPromptOptimizer {
|
|
|
472
553
|
}
|
|
473
554
|
|
|
474
555
|
try {
|
|
475
|
-
const
|
|
476
|
-
const result = await this.callBackendAPI(endpoint, null, 'GET');
|
|
556
|
+
const result = await this.callBackendAPI(ENDPOINTS.AGUI_STATUS, null, 'GET');
|
|
477
557
|
|
|
478
558
|
return { content: [{ type: "text", text: this.formatRealTimeStatus(result) }] };
|
|
479
559
|
|
|
@@ -497,9 +577,110 @@ class MCPPromptOptimizer {
|
|
|
497
577
|
}
|
|
498
578
|
}
|
|
499
579
|
|
|
580
|
+
async handleDetectAIContext(args) {
|
|
581
|
+
if (!args.prompt) throw new Error('Prompt is required');
|
|
582
|
+
|
|
583
|
+
const formatResult = (result) => {
|
|
584
|
+
let output = `# 🧠 AI Context Detection Result\n\n`;
|
|
585
|
+
output += `**Primary Context:** ${result.primary_context}\n`;
|
|
586
|
+
output += `**Confidence:** ${(result.confidence * 100).toFixed(1)}%\n`;
|
|
587
|
+
if (result.secondary_contexts && result.secondary_contexts.length > 0) {
|
|
588
|
+
output += `**Secondary Contexts:** ${result.secondary_contexts.join(', ')}\n`;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
const detections = result.detected_parameters ?? [];
|
|
592
|
+
const safeDetections = detections.filter(d => d && d.name);
|
|
593
|
+
|
|
594
|
+
if (safeDetections.length > 0) {
|
|
595
|
+
output += `**Detected Parameters:** ${safeDetections.map(d => d.name).join(', ')}\n`;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
if (result.mock_mode) {
|
|
599
|
+
output += `\n⚠️ **Fallback Mode Active:** Using mock data due to development mode or network issues.\n`;
|
|
600
|
+
}
|
|
601
|
+
return { content: [{ type: "text", text: output }] };
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
try {
|
|
605
|
+
const manager = new CloudApiKeyManager(this.apiKey, { developmentMode: this.developmentMode });
|
|
606
|
+
const validation = await manager.validateApiKey();
|
|
607
|
+
|
|
608
|
+
if (validation.mock_mode || this.developmentMode) {
|
|
609
|
+
const mockResult = this.generateMockContextDetection(args.prompt);
|
|
610
|
+
return formatResult(mockResult);
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const result = await this.callBackendAPI(ENDPOINTS.DETECT_CONTEXT, { prompt: args.prompt });
|
|
614
|
+
return formatResult(result);
|
|
615
|
+
|
|
616
|
+
} catch (error) {
|
|
617
|
+
// Fallback for ANY error during the process (missing key, network, etc.)
|
|
618
|
+
const fallbackResult = this.generateMockContextDetection(args.prompt);
|
|
619
|
+
return formatResult(fallbackResult);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
async handleCreateTemplate(args) {
|
|
624
|
+
try {
|
|
625
|
+
const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.CREATE, args);
|
|
626
|
+
let output = `# ✅ Template Created Successfully!\n\n`;
|
|
627
|
+
output += `**Title:** ${result.title}\n`;
|
|
628
|
+
output += `**ID:** \`${result.id}\`\n`;
|
|
629
|
+
output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
|
|
630
|
+
output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
|
|
631
|
+
output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
|
|
632
|
+
output += `\n**Optimized Prompt Preview:**\n\`\`\`\n${result.optimized_prompt.substring(0, 150)}...\n\`\`\`\n`;
|
|
633
|
+
return { content: [{ type: "text", text: output }] };
|
|
634
|
+
} catch (error) {
|
|
635
|
+
throw new Error(`Failed to create template: ${error.message}`);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
async handleGetTemplate(args) {
|
|
640
|
+
if (!args.template_id) throw new Error('Template ID is required');
|
|
641
|
+
try {
|
|
642
|
+
const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.GET(args.template_id), null, 'GET');
|
|
643
|
+
let output = `# 📄 Template Details\n\n`;
|
|
644
|
+
output += `**Title:** ${result.title}\n`;
|
|
645
|
+
output += `**ID:** \`${result.id}\`\n`;
|
|
646
|
+
output += `**Description:** ${result.description || 'N/A'}\n`;
|
|
647
|
+
output += `**AI Context:** ${result.ai_context_detected || 'N/A'}\n`;
|
|
648
|
+
output += `**Confidence Score:** ${(result.confidence_score * 100).toFixed(1)}%\n`;
|
|
649
|
+
output += `**Public:** ${result.is_public ? 'Yes' : 'No'}\n`;
|
|
650
|
+
output += `**Tags:** ${result.tags ? result.tags.join(', ') : 'None'}\n\n`;
|
|
651
|
+
output += `**Original Prompt:**\n\`\`\`\n${result.original_prompt}\n\`\`\`\n\n`;
|
|
652
|
+
output += `**Optimized Prompt:**\n\`\`\`\n${result.optimized_prompt}\n\`\`\`\n`;
|
|
653
|
+
return { content: [{ type: "text", text: output }] };
|
|
654
|
+
} catch (error) {
|
|
655
|
+
throw new Error(`Failed to retrieve template: ${error.message}`);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
async handleUpdateTemplate(args) {
|
|
660
|
+
if (!args.template_id) throw new Error('Template ID is required');
|
|
661
|
+
try {
|
|
662
|
+
const { template_id, ...updateData } = args;
|
|
663
|
+
// Filter out undefined values so we only send fields that are being updated
|
|
664
|
+
Object.keys(updateData).forEach(key => updateData[key] === undefined && delete updateData[key]);
|
|
665
|
+
|
|
666
|
+
const result = await this.callBackendAPI(ENDPOINTS.TEMPLATE.UPDATE(template_id), updateData, 'PATCH'); // PATCH is better for partial updates
|
|
667
|
+
let output = `# ✅ Template Updated Successfully!\n\n`;
|
|
668
|
+
output += `**ID:** \`${result.id}\`\n`;
|
|
669
|
+
output += `**Title:** ${result.title}\n\n`;
|
|
670
|
+
output += `Use 'get_template' with the ID to see the full updated template.`;
|
|
671
|
+
return { content: [{ type: "text", text: output }] };
|
|
672
|
+
} catch (error) {
|
|
673
|
+
throw new Error(`Failed to update template: ${error.message}`);
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
async _buildUrl(path) {
|
|
678
|
+
return `${this.backendUrl}${path}`;
|
|
679
|
+
}
|
|
680
|
+
|
|
500
681
|
async callBackendAPI(endpoint, data, method = 'POST') {
|
|
501
682
|
return new Promise((resolve, reject) => {
|
|
502
|
-
const url =
|
|
683
|
+
const url = this._buildUrl(endpoint);
|
|
503
684
|
|
|
504
685
|
const options = {
|
|
505
686
|
method: method,
|
|
@@ -561,8 +742,6 @@ class MCPPromptOptimizer {
|
|
|
561
742
|
reject(new Error('Request timeout - backend may be unavailable'));
|
|
562
743
|
});
|
|
563
744
|
|
|
564
|
-
req.setTimeout(this.requestTimeout);
|
|
565
|
-
|
|
566
745
|
if (method !== 'GET' && data) {
|
|
567
746
|
req.write(JSON.stringify(data));
|
|
568
747
|
}
|
|
@@ -588,10 +767,12 @@ class MCPPromptOptimizer {
|
|
|
588
767
|
|
|
589
768
|
if (result.optimization_insights) {
|
|
590
769
|
const metrics = result.optimization_insights.improvement_metrics;
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
770
|
+
if (metrics) {
|
|
771
|
+
output += `\n📊 **Optimization Insights**\n`;
|
|
772
|
+
if (metrics.clarity_improvement) output += `- Clarity: +${(metrics.clarity_improvement * 100).toFixed(1)}%\n`;
|
|
773
|
+
if (metrics.specificity_improvement) output += `- Specificity: +${(metrics.specificity_improvement * 100).toFixed(1)}%\n`;
|
|
774
|
+
if (metrics.context_alignment) output += `- Context Alignment: +${(metrics.context_alignment * 100).toFixed(1)}%\n`;
|
|
775
|
+
}
|
|
595
776
|
|
|
596
777
|
if (result.optimization_insights.recommendations?.length) {
|
|
597
778
|
output += `\n💡 **Recommendations:**\n`;
|
|
@@ -826,9 +1007,9 @@ class MCPPromptOptimizer {
|
|
|
826
1007
|
}
|
|
827
1008
|
|
|
828
1009
|
async function startValidatedMCPServer() {
|
|
829
|
-
console.
|
|
830
|
-
console.
|
|
831
|
-
console.
|
|
1010
|
+
console.log(`🚀 MCP Prompt Optimizer - Professional Cloud Server v${packageJson.version}\n`);
|
|
1011
|
+
console.log(`🧠 Bayesian Optimization: ${process.env.ENABLE_BAYESIAN_OPTIMIZATION === 'true' ? 'Enabled' : 'Disabled'}`);
|
|
1012
|
+
console.log(`⚡ AG-UI Features: ${process.env.ENABLE_AGUI_FEATURES === 'true' ? 'Enabled' : 'Disabled'}\n`);
|
|
832
1013
|
|
|
833
1014
|
try {
|
|
834
1015
|
const apiKey = process.env.OPTIMIZER_API_KEY;
|
|
@@ -838,24 +1019,24 @@ async function startValidatedMCPServer() {
|
|
|
838
1019
|
}
|
|
839
1020
|
|
|
840
1021
|
const manager = new CloudApiKeyManager(apiKey, { developmentMode: process.env.OPTIMIZER_DEV_MODE === 'true' });
|
|
841
|
-
console.
|
|
1022
|
+
console.log('🔧 Validating API key...\n');
|
|
842
1023
|
const validation = await manager.validateAndPrepare();
|
|
843
1024
|
|
|
844
|
-
console.
|
|
1025
|
+
console.log('🔧 Starting MCP server...\n');
|
|
845
1026
|
const mcpServer = new MCPPromptOptimizer();
|
|
846
|
-
console.
|
|
1027
|
+
console.log('✅ MCP server ready for connections');
|
|
847
1028
|
|
|
848
1029
|
// Enhanced status display
|
|
849
1030
|
const quotaDisplay = validation.quotaStatus.unlimited ?
|
|
850
1031
|
'Unlimited' :
|
|
851
1032
|
`${validation.quotaStatus.remaining}/${validation.quotaStatus.limit} remaining`;
|
|
852
1033
|
|
|
853
|
-
console.
|
|
1034
|
+
console.log(`📊 Plan: ${validation.tier} | Quota: ${quotaDisplay}`);
|
|
854
1035
|
|
|
855
|
-
if (validation.mode.mock) console.
|
|
856
|
-
if (validation.mode.development) console.
|
|
857
|
-
if (validation.mode.fallback) console.
|
|
858
|
-
if (validation.mode.offline) console.
|
|
1036
|
+
if (validation.mode.mock) console.log('🎭 Running in mock mode');
|
|
1037
|
+
if (validation.mode.development) console.log('⚙️ Development mode active');
|
|
1038
|
+
if (validation.mode.fallback) console.log('🔄 Fallback mode active');
|
|
1039
|
+
if (validation.mode.offline) console.log('📱 Offline mode active');
|
|
859
1040
|
|
|
860
1041
|
await mcpServer.run();
|
|
861
1042
|
} catch (error) {
|