mcp-prompt-optimizer 3.7.3 → 3.7.5
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 +18 -0
- package/README.md +0 -1
- package/index.js +97 -98
- package/lib/api-key-manager.js +20 -4
- package/lib/check-status.js +8 -2
- package/package.json +25 -3
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [3.7.5] - 2026-07-18
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- **10 MCP tools were unconditionally broken**: `generate_agent_sop`, `transform_for_framework`, `generate_harness_bundle`, `explore_sop_approaches`, `get_prompt_by_slug`, `compile_prompt`, `list_template_versions`, `rollback_template`, `publish_template`, and `run_quick_evaluation` all called backend routes that only accepted a JWT — a credential this stdio client can never obtain (no browser, no login flow). Every call to these tools failed with an auth error, always. Backend now accepts API-key auth on these routes; verified the fix doesn't expand what a key is authorized to do (every route is scoped to the calling account's own data, same as routes that already worked).
|
|
12
|
+
- **Tier-upgrade messages never fired**: the 403-detection check looked for the literal string `'403'` inside the error body, which never appears there — only the HTTP status code carries it. Now checks the real status code, so upgrade prompts actually show up when a real tier gate is hit.
|
|
13
|
+
- **Fabricated fallback data**: `get_optimization_insights` and `get_real_time_status` silently returned hardcoded fake numbers (fake optimization counts, fake AG-UI metrics) on any backend error, indistinguishable from real account data. Both now say the data is unavailable instead of inventing it.
|
|
14
|
+
- **`formatRealTimeStatus` read the wrong fields**: it never matched the AG-UI status endpoint's actual response shape, even when the call succeeded.
|
|
15
|
+
- **`formatQuotaStatus` invented a fake `5000` quota limit** when the backend didn't report one.
|
|
16
|
+
- **Free-tier quota text said 7/month**; the real limit is 20.
|
|
17
|
+
- **Dead domain and wrong key-format references**: `promptoptimizer-blog.vercel.app` no longer resolves; some messages also claimed `sk-local-*` was a valid key format for this package (that's the sibling local package's prefix, not this one's).
|
|
18
|
+
|
|
19
|
+
## [3.7.4] - 2026-07-16
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **CLI commands were mostly non-functional**: the README documented 8 `mcp-prompt-optimizer <command>` subcommands, but the argv dispatcher only ever recognized `connect`. Running any of `check-status`, `validate-key`, `diagnose`, `clear-cache`, `help`, or `version` silently started the blocking stdio MCP server instead, hanging the terminal. All six are now wired to their existing `lib/*.js` implementations.
|
|
23
|
+
- **Unrecognized commands no longer fall through to the server.** Any argument that isn't a known command now prints an error and usage to stderr and exits 1, instead of silently starting the MCP server. This closes the bug class for future commands too, not just the six fixed here.
|
|
24
|
+
- **Dropped `test` from the documented CLI commands.** It mapped to `tests/test-runner.js`, a maintainer-only pre-publish validation script that isn't included in the published npm package (`tests/` is not in `files`), so it could never have worked for an end user.
|
|
25
|
+
|
|
8
26
|
## [3.7.3] - 2026-07-16
|
|
9
27
|
|
|
10
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -368,7 +368,6 @@ All plans include AI context detection, template management, personal model conf
|
|
|
368
368
|
npx mcp-prompt-optimizer connect # Interactive wizard: add API key to Claude Desktop config
|
|
369
369
|
mcp-prompt-optimizer check-status # Check API key and quota status
|
|
370
370
|
mcp-prompt-optimizer validate-key # Validate API key with backend
|
|
371
|
-
mcp-prompt-optimizer test # Test backend integration
|
|
372
371
|
mcp-prompt-optimizer diagnose # Run comprehensive diagnostic
|
|
373
372
|
mcp-prompt-optimizer clear-cache # Clear validation cache
|
|
374
373
|
mcp-prompt-optimizer help # Show help and setup instructions
|
package/index.js
CHANGED
|
@@ -1056,31 +1056,7 @@ class MCPPromptOptimizer {
|
|
|
1056
1056
|
return { content: [{ type: "text", text: this.formatOptimizationInsights(result) }] };
|
|
1057
1057
|
|
|
1058
1058
|
} catch (error) {
|
|
1059
|
-
|
|
1060
|
-
const mockInsights = {
|
|
1061
|
-
bayesian_status: {
|
|
1062
|
-
optimization_active: true,
|
|
1063
|
-
total_optimizations: 47,
|
|
1064
|
-
improvement_rate: '23.5%',
|
|
1065
|
-
confidence_score: 0.89
|
|
1066
|
-
},
|
|
1067
|
-
parameter_insights: {
|
|
1068
|
-
most_effective_goals: ['clarity', 'technical_accuracy', 'analytical_depth'],
|
|
1069
|
-
context_performance: {
|
|
1070
|
-
'code_generation': 0.92,
|
|
1071
|
-
'llm_interaction': 0.87,
|
|
1072
|
-
'technical_automation': 0.84
|
|
1073
|
-
},
|
|
1074
|
-
optimization_trends: 'Steady improvement in technical contexts'
|
|
1075
|
-
},
|
|
1076
|
-
recommendations: args.include_recommendations !== false ? [
|
|
1077
|
-
'Focus on technical_accuracy for code generation prompts',
|
|
1078
|
-
'Combine clarity with analytical_depth for best results',
|
|
1079
|
-
'Consider using structured_output context for data tasks'
|
|
1080
|
-
] : []
|
|
1081
|
-
};
|
|
1082
|
-
|
|
1083
|
-
return { content: [{ type: "text", text: this.formatOptimizationInsights(mockInsights) }] };
|
|
1059
|
+
return { content: [{ type: "text", text: `🧠 Optimization insights are unavailable right now (${error.message}). This is not your data — no insights were generated.` }] };
|
|
1084
1060
|
}
|
|
1085
1061
|
}
|
|
1086
1062
|
|
|
@@ -1095,22 +1071,7 @@ class MCPPromptOptimizer {
|
|
|
1095
1071
|
return { content: [{ type: "text", text: this.formatRealTimeStatus(result) }] };
|
|
1096
1072
|
|
|
1097
1073
|
} catch (error) {
|
|
1098
|
-
|
|
1099
|
-
agui_status: 'available',
|
|
1100
|
-
streaming_optimization: true,
|
|
1101
|
-
websocket_support: true,
|
|
1102
|
-
real_time_analytics: true,
|
|
1103
|
-
active_optimizations: 3,
|
|
1104
|
-
average_response_time: '1.2s',
|
|
1105
|
-
features: {
|
|
1106
|
-
live_optimization: true,
|
|
1107
|
-
collaborative_editing: true,
|
|
1108
|
-
instant_feedback: true,
|
|
1109
|
-
performance_monitoring: true
|
|
1110
|
-
}
|
|
1111
|
-
};
|
|
1112
|
-
|
|
1113
|
-
return { content: [{ type: "text", text: this.formatRealTimeStatus(mockStatus) }] };
|
|
1074
|
+
return { content: [{ type: "text", text: `⚡ AG-UI real-time status is unavailable right now (${error.message}).` }] };
|
|
1114
1075
|
}
|
|
1115
1076
|
}
|
|
1116
1077
|
|
|
@@ -1434,8 +1395,8 @@ class MCPPromptOptimizer {
|
|
|
1434
1395
|
}]
|
|
1435
1396
|
};
|
|
1436
1397
|
} catch (error) {
|
|
1437
|
-
if (error.
|
|
1438
|
-
return { content: [{ type: "text", text:
|
|
1398
|
+
if (error.statusCode === 403) {
|
|
1399
|
+
return { content: [{ type: "text", text: `Error: SOP exploration requires Innovator tier. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1439
1400
|
}
|
|
1440
1401
|
throw new Error(`Failed to explore SOP approaches: ${error.message}`);
|
|
1441
1402
|
}
|
|
@@ -1450,9 +1411,8 @@ class MCPPromptOptimizer {
|
|
|
1450
1411
|
output += `**Body:**\n\`\`\`\n${result.optimized_prompt || result.body || ''}\n\`\`\`\n`;
|
|
1451
1412
|
return { content: [{ type: "text", text: output }] };
|
|
1452
1413
|
} catch (error) {
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
return { content: [{ type: "text", text: `Upgrade required: runtime prompt delivery requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1414
|
+
if (error.statusCode === 403) {
|
|
1415
|
+
return { content: [{ type: "text", text: `Upgrade required: runtime prompt delivery requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1456
1416
|
}
|
|
1457
1417
|
throw new Error(`Failed to fetch prompt by slug: ${error.message}`);
|
|
1458
1418
|
}
|
|
@@ -1465,9 +1425,8 @@ class MCPPromptOptimizer {
|
|
|
1465
1425
|
const compiled = result.compiled_prompt || result.body || JSON.stringify(result, null, 2);
|
|
1466
1426
|
return { content: [{ type: "text", text: `# Compiled Prompt\n\n\`\`\`\n${compiled}\n\`\`\`\n` }] };
|
|
1467
1427
|
} catch (error) {
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
return { content: [{ type: "text", text: `Upgrade required: prompt compilation requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1428
|
+
if (error.statusCode === 403) {
|
|
1429
|
+
return { content: [{ type: "text", text: `Upgrade required: prompt compilation requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1471
1430
|
}
|
|
1472
1431
|
throw new Error(`Failed to compile prompt: ${error.message}`);
|
|
1473
1432
|
}
|
|
@@ -1493,9 +1452,8 @@ class MCPPromptOptimizer {
|
|
|
1493
1452
|
}
|
|
1494
1453
|
return { content: [{ type: "text", text: output }] };
|
|
1495
1454
|
} catch (error) {
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
return { content: [{ type: "text", text: `Upgrade required: template versioning requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1455
|
+
if (error.statusCode === 403) {
|
|
1456
|
+
return { content: [{ type: "text", text: `Upgrade required: template versioning requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1499
1457
|
}
|
|
1500
1458
|
throw new Error(`Failed to list template versions: ${error.message}`);
|
|
1501
1459
|
}
|
|
@@ -1509,9 +1467,8 @@ class MCPPromptOptimizer {
|
|
|
1509
1467
|
const msg = result.message || `Template rolled back to version ${args.version_number}`;
|
|
1510
1468
|
return { content: [{ type: "text", text: `# ✅ Rollback Complete\n\n${msg}\n\n**Template ID:** \`${args.template_id}\`\n**Version:** ${args.version_number}` }] };
|
|
1511
1469
|
} catch (error) {
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
return { content: [{ type: "text", text: `Upgrade required: template rollback requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1470
|
+
if (error.statusCode === 403) {
|
|
1471
|
+
return { content: [{ type: "text", text: `Upgrade required: template rollback requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1515
1472
|
}
|
|
1516
1473
|
throw new Error(`Failed to rollback template: ${error.message}`);
|
|
1517
1474
|
}
|
|
@@ -1524,9 +1481,8 @@ class MCPPromptOptimizer {
|
|
|
1524
1481
|
const msg = result.message || `Template ${args.template_id} published successfully`;
|
|
1525
1482
|
return { content: [{ type: "text", text: `# ✅ Template Published\n\n${msg}\n\nThe template is now available for runtime delivery via \`get_prompt_by_slug\`.` }] };
|
|
1526
1483
|
} catch (error) {
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
return { content: [{ type: "text", text: `Upgrade required: template publishing requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1484
|
+
if (error.statusCode === 403) {
|
|
1485
|
+
return { content: [{ type: "text", text: `Upgrade required: template publishing requires Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1530
1486
|
}
|
|
1531
1487
|
throw new Error(`Failed to publish template: ${error.message}`);
|
|
1532
1488
|
}
|
|
@@ -1556,9 +1512,8 @@ class MCPPromptOptimizer {
|
|
|
1556
1512
|
}
|
|
1557
1513
|
return { content: [{ type: "text", text: output }] };
|
|
1558
1514
|
} catch (error) {
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
return { content: [{ type: "text", text: `Upgrade required: evaluations require Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${msg}` }] };
|
|
1515
|
+
if (error.statusCode === 403) {
|
|
1516
|
+
return { content: [{ type: "text", text: `Upgrade required: evaluations require Pro tier or higher. Upgrade at /pricing.\n\nBackend error: ${error.message}` }] };
|
|
1562
1517
|
}
|
|
1563
1518
|
throw new Error(`Failed to run quick evaluation: ${error.message}`);
|
|
1564
1519
|
}
|
|
@@ -1631,7 +1586,9 @@ class MCPPromptOptimizer {
|
|
|
1631
1586
|
} catch {
|
|
1632
1587
|
errorMessage = `HTTP ${res.statusCode}: ${responseData}`;
|
|
1633
1588
|
}
|
|
1634
|
-
|
|
1589
|
+
const httpError = new Error(errorMessage);
|
|
1590
|
+
httpError.statusCode = res.statusCode;
|
|
1591
|
+
reject(httpError);
|
|
1635
1592
|
}
|
|
1636
1593
|
} catch (parseError) {
|
|
1637
1594
|
reject(new Error(`Invalid response format: ${parseError.message}`));
|
|
@@ -1787,7 +1744,7 @@ class MCPPromptOptimizer {
|
|
|
1787
1744
|
output += `2. Generate your API key at https://promptoptimizer.xyz/dashboard\n`;
|
|
1788
1745
|
output += `3. Run in your terminal:\n\n`;
|
|
1789
1746
|
output += `\`\`\`\nnpx mcp-prompt-optimizer connect\n\`\`\`\n\n`;
|
|
1790
|
-
output += `You get **
|
|
1747
|
+
output += `You get **20 LLM optimizations/month free**. Upgrade anytime for more.\n`;
|
|
1791
1748
|
}
|
|
1792
1749
|
|
|
1793
1750
|
return output;
|
|
@@ -1801,25 +1758,30 @@ class MCPPromptOptimizer {
|
|
|
1801
1758
|
output += `**Usage:** 🟢 Unlimited\n`;
|
|
1802
1759
|
} else {
|
|
1803
1760
|
const used = quota.used || 0;
|
|
1804
|
-
const limit = quota.limit
|
|
1761
|
+
const limit = quota.limit;
|
|
1762
|
+
|
|
1763
|
+
if (limit === undefined || limit === null) {
|
|
1764
|
+
output += `**Usage:** ${used} used (limit unavailable — backend did not report a quota limit)\n`;
|
|
1765
|
+
} else {
|
|
1805
1766
|
const percentage = limit > 0 ? ((used / limit) * 100).toFixed(1) : 0;
|
|
1806
|
-
|
|
1767
|
+
|
|
1807
1768
|
let statusIcon = '🟢';
|
|
1808
1769
|
if (percentage >= 90) statusIcon = '🔴';
|
|
1809
1770
|
else if (percentage >= 75) statusIcon = '🟡';
|
|
1810
|
-
|
|
1771
|
+
|
|
1811
1772
|
output += `**Usage:** ${statusIcon} ${used}/${limit} (${percentage}%)\n`;
|
|
1812
1773
|
|
|
1813
1774
|
const remaining = limit - used;
|
|
1814
1775
|
if (remaining <= 0) {
|
|
1815
1776
|
output += `\n❌ **Quota Exhausted** — You have no optimizations remaining this month.\n`;
|
|
1816
|
-
output += `Upgrade at https://promptoptimizer.xyz/
|
|
1777
|
+
output += `Upgrade at https://promptoptimizer.xyz/pricing\n`;
|
|
1817
1778
|
output += `*(Quota resets at the start of your next billing cycle)*\n`;
|
|
1818
1779
|
} else if (percentage >= 90) {
|
|
1819
|
-
output += `\n⚠️ **Critical** — ${remaining} optimization${remaining === 1 ? '' : 's'} remaining. Upgrade at https://promptoptimizer.xyz/
|
|
1780
|
+
output += `\n⚠️ **Critical** — ${remaining} optimization${remaining === 1 ? '' : 's'} remaining. Upgrade at https://promptoptimizer.xyz/pricing\n`;
|
|
1820
1781
|
} else if (percentage >= 75) {
|
|
1821
1782
|
output += `\n⚠️ **Warning** — Approaching your monthly limit.\n`;
|
|
1822
1783
|
}
|
|
1784
|
+
}
|
|
1823
1785
|
}
|
|
1824
1786
|
|
|
1825
1787
|
output += `\n## ✨ **Available Features**\n`;
|
|
@@ -1841,9 +1803,9 @@ class MCPPromptOptimizer {
|
|
|
1841
1803
|
}
|
|
1842
1804
|
|
|
1843
1805
|
output += `\n## 🔗 **Account Management**\n`;
|
|
1844
|
-
output += `- Dashboard: https://promptoptimizer
|
|
1845
|
-
output += `- Analytics: https://promptoptimizer
|
|
1846
|
-
output += `- Upgrade: https://promptoptimizer.xyz/
|
|
1806
|
+
output += `- Dashboard: https://promptoptimizer.xyz/dashboard\n`;
|
|
1807
|
+
output += `- Analytics: https://promptoptimizer.xyz/analytics\n`;
|
|
1808
|
+
output += `- Upgrade: https://promptoptimizer.xyz/pricing\n`;
|
|
1847
1809
|
|
|
1848
1810
|
return output;
|
|
1849
1811
|
}
|
|
@@ -1949,41 +1911,40 @@ class MCPPromptOptimizer {
|
|
|
1949
1911
|
}
|
|
1950
1912
|
|
|
1951
1913
|
output += `## 🔗 **Advanced Analytics**\n`;
|
|
1952
|
-
output += `- Full Analytics: https://promptoptimizer
|
|
1953
|
-
output += `- Performance Dashboard: https://promptoptimizer
|
|
1914
|
+
output += `- Full Analytics: https://promptoptimizer.xyz/analytics\n`;
|
|
1915
|
+
output += `- Performance Dashboard: https://promptoptimizer.xyz/dashboard\n`;
|
|
1954
1916
|
|
|
1955
1917
|
return output;
|
|
1956
1918
|
}
|
|
1957
1919
|
|
|
1958
1920
|
formatRealTimeStatus(status) {
|
|
1959
1921
|
let output = `# ⚡ AG-UI Real-Time Status\n\n`;
|
|
1960
|
-
|
|
1922
|
+
const metrics = status.metrics || {};
|
|
1923
|
+
|
|
1961
1924
|
output += `## 🚀 **Service Status**\n`;
|
|
1962
|
-
output += `- **AG-UI Status:** ${status.
|
|
1963
|
-
|
|
1964
|
-
output +=
|
|
1965
|
-
output += `- **
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
output += `- **
|
|
1970
|
-
output += `- **Average Response Time:** ${status.average_response_time}\n\n`;
|
|
1925
|
+
output += `- **AG-UI Status:** ${status.status === 'healthy' ? '🟢 Healthy' : '🔴 Degraded'}\n\n`;
|
|
1926
|
+
|
|
1927
|
+
output += `## 📈 **Current Activity**\n`;
|
|
1928
|
+
output += `- **Active Sessions:** ${metrics.active_sessions ?? 'unknown'}\n`;
|
|
1929
|
+
output += `- **Total Connections:** ${metrics.total_connections ?? 'unknown'}\n`;
|
|
1930
|
+
output += `- **Total Optimizations:** ${metrics.total_optimizations ?? 'unknown'}\n`;
|
|
1931
|
+
if (metrics.uptime_seconds !== undefined) {
|
|
1932
|
+
output += `- **Uptime:** ${Math.round(metrics.uptime_seconds)}s\n`;
|
|
1971
1933
|
}
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1934
|
+
output += `\n`;
|
|
1935
|
+
|
|
1936
|
+
if (metrics.features_enabled) {
|
|
1975
1937
|
output += `## ⚡ **Available Features**\n`;
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
if (features.performance_monitoring) output += `✅ Performance Monitoring\n`;
|
|
1938
|
+
for (const [feature, enabled] of Object.entries(metrics.features_enabled)) {
|
|
1939
|
+
if (enabled) output += `✅ ${feature}\n`;
|
|
1940
|
+
}
|
|
1980
1941
|
output += `\n`;
|
|
1981
1942
|
}
|
|
1982
|
-
|
|
1943
|
+
|
|
1983
1944
|
output += `## 🔗 **Real-Time Access**\n`;
|
|
1984
|
-
output += `- Live Dashboard: https://promptoptimizer
|
|
1945
|
+
output += `- Live Dashboard: https://promptoptimizer.xyz/live\n`;
|
|
1985
1946
|
output += `- WebSocket Endpoint: Available via API\n`;
|
|
1986
|
-
|
|
1947
|
+
|
|
1987
1948
|
return output;
|
|
1988
1949
|
}
|
|
1989
1950
|
|
|
@@ -2001,7 +1962,7 @@ async function startValidatedMCPServer() {
|
|
|
2001
1962
|
try {
|
|
2002
1963
|
const apiKey = process.env.OPTIMIZER_API_KEY;
|
|
2003
1964
|
if (!apiKey) {
|
|
2004
|
-
console.error('❌ API key required. Get one at https://promptoptimizer.xyz/
|
|
1965
|
+
console.error('❌ API key required. Get one free at https://promptoptimizer.xyz/dashboard');
|
|
2005
1966
|
process.exit(1);
|
|
2006
1967
|
}
|
|
2007
1968
|
|
|
@@ -2179,7 +2140,7 @@ async function runConnectWizard() {
|
|
|
2179
2140
|
}
|
|
2180
2141
|
if (ok > 0) {
|
|
2181
2142
|
console.log('\n👉 Restart your MCP client(s) to activate LLM optimization.');
|
|
2182
|
-
console.log(' Free plan:
|
|
2143
|
+
console.log(' Free plan: 20 LLM optimizations/month.');
|
|
2183
2144
|
console.log(' Upgrade at https://promptoptimizer.xyz/pricing\n');
|
|
2184
2145
|
}
|
|
2185
2146
|
}
|
|
@@ -2198,12 +2159,50 @@ async function runConnectWizard() {
|
|
|
2198
2159
|
});
|
|
2199
2160
|
}
|
|
2200
2161
|
|
|
2162
|
+
function printCliHelp() {
|
|
2163
|
+
console.log(`MCP Prompt Optimizer v${packageJson.version}
|
|
2164
|
+
|
|
2165
|
+
Usage:
|
|
2166
|
+
mcp-prompt-optimizer Start the MCP server (used by MCP clients)
|
|
2167
|
+
mcp-prompt-optimizer connect Interactive wizard: add API key to Claude Desktop config
|
|
2168
|
+
mcp-prompt-optimizer check-status Check API key and quota status
|
|
2169
|
+
mcp-prompt-optimizer validate-key Validate API key with backend
|
|
2170
|
+
mcp-prompt-optimizer diagnose Run comprehensive diagnostic
|
|
2171
|
+
mcp-prompt-optimizer clear-cache Clear validation cache
|
|
2172
|
+
mcp-prompt-optimizer help Show this help
|
|
2173
|
+
mcp-prompt-optimizer version Show version information`);
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
function printCliVersion() {
|
|
2177
|
+
console.log(packageJson.version);
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
const CLI_COMMANDS = {
|
|
2181
|
+
connect: runConnectWizard,
|
|
2182
|
+
'check-status': () => require('./lib/check-status')().then(() => process.exit(0)),
|
|
2183
|
+
'validate-key': () => require('./lib/validate-key')().then(() => process.exit(0)),
|
|
2184
|
+
'clear-cache': () => require('./lib/clear-cache')().then(() => process.exit(0)),
|
|
2185
|
+
diagnose: () => require('./lib/diagnose')().then(() => process.exit(0)),
|
|
2186
|
+
help: printCliHelp,
|
|
2187
|
+
'--help': printCliHelp,
|
|
2188
|
+
'-h': printCliHelp,
|
|
2189
|
+
version: printCliVersion,
|
|
2190
|
+
'--version': printCliVersion,
|
|
2191
|
+
'-v': printCliVersion,
|
|
2192
|
+
};
|
|
2193
|
+
|
|
2201
2194
|
if (require.main === module) {
|
|
2202
2195
|
const args = process.argv.slice(2);
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2196
|
+
const cmd = args[0];
|
|
2197
|
+
|
|
2198
|
+
if (!cmd) {
|
|
2206
2199
|
startValidatedMCPServer();
|
|
2200
|
+
} else if (CLI_COMMANDS[cmd]) {
|
|
2201
|
+
CLI_COMMANDS[cmd]();
|
|
2202
|
+
} else {
|
|
2203
|
+
console.error(`❌ Unknown command: ${cmd}\n`);
|
|
2204
|
+
printCliHelp();
|
|
2205
|
+
process.exit(1);
|
|
2207
2206
|
}
|
|
2208
2207
|
}
|
|
2209
2208
|
|
package/lib/api-key-manager.js
CHANGED
|
@@ -241,7 +241,11 @@ class CloudApiKeyManager {
|
|
|
241
241
|
// SECURITY: Offline mode removed - backend validation required
|
|
242
242
|
// No cache fallback beyond 2 hours
|
|
243
243
|
|
|
244
|
-
|
|
244
|
+
// A 4xx means the backend rejected the key itself, not a connectivity
|
|
245
|
+
// problem — telling the user to check their internet is wrong there.
|
|
246
|
+
const isClientError = error.statusCode >= 400 && error.statusCode < 500;
|
|
247
|
+
const hint = isClientError ? '' : ' Please check your internet connection.';
|
|
248
|
+
throw new Error(`API key validation failed: ${error.message}.${hint}`);
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
251
|
|
|
@@ -268,7 +272,17 @@ class CloudApiKeyManager {
|
|
|
268
272
|
} catch (error) {
|
|
269
273
|
lastError = error;
|
|
270
274
|
this.log(`Attempt ${attempt} failed: ${error.message}`, 'warn');
|
|
271
|
-
|
|
275
|
+
|
|
276
|
+
// A 4xx means the backend definitively rejected the request (bad/expired
|
|
277
|
+
// key, malformed request) — retrying with the same key can't change that.
|
|
278
|
+
// Only network errors and 5xx (transient/server-side) are worth retrying.
|
|
279
|
+
// 429 is the exception: rate limits are exactly what backoff is for.
|
|
280
|
+
const isClientError = error.statusCode >= 400 && error.statusCode < 500 && error.statusCode !== 429;
|
|
281
|
+
if (isClientError) {
|
|
282
|
+
this.log('Non-retryable client error — not retrying', 'error');
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
|
|
272
286
|
if (attempt < this.maxRetries) {
|
|
273
287
|
const delay = this.calculateRetryDelay(attempt);
|
|
274
288
|
this.log(`Retrying in ${delay}ms...`);
|
|
@@ -579,7 +593,7 @@ class CloudApiKeyManager {
|
|
|
579
593
|
|
|
580
594
|
throw new Error(
|
|
581
595
|
'API key required. Set the OPTIMIZER_API_KEY environment variable.\n' +
|
|
582
|
-
'Get your API key at: https://promptoptimizer.xyz/
|
|
596
|
+
'Get your API key at: https://promptoptimizer.xyz/dashboard'
|
|
583
597
|
);
|
|
584
598
|
}
|
|
585
599
|
|
|
@@ -690,7 +704,9 @@ class CloudApiKeyManager {
|
|
|
690
704
|
} catch {
|
|
691
705
|
errorMessage = `HTTP ${res.statusCode}: ${responseData}`;
|
|
692
706
|
}
|
|
693
|
-
|
|
707
|
+
const httpError = new Error(errorMessage);
|
|
708
|
+
httpError.statusCode = res.statusCode;
|
|
709
|
+
reject(httpError);
|
|
694
710
|
}
|
|
695
711
|
} catch (parseError) {
|
|
696
712
|
reject(new Error(`Invalid response format: ${parseError.message}`));
|
package/lib/check-status.js
CHANGED
|
@@ -10,7 +10,7 @@ async function checkStatus() {
|
|
|
10
10
|
if (!apiKey) {
|
|
11
11
|
console.error('❌ No API key found');
|
|
12
12
|
console.log('\n📝 Set your API key to check status:');
|
|
13
|
-
console.log(' export OPTIMIZER_API_KEY=sk-
|
|
13
|
+
console.log(' export OPTIMIZER_API_KEY=sk-opt-your-key-here');
|
|
14
14
|
if (developmentMode) {
|
|
15
15
|
console.log('\n🧪 Development Mode Options:');
|
|
16
16
|
console.log(' export OPTIMIZER_API_KEY=sk-dev-test-key');
|
|
@@ -25,7 +25,13 @@ async function checkStatus() {
|
|
|
25
25
|
console.log('='.repeat(50));
|
|
26
26
|
console.log(`🎯 Subscription Tier: ${apiKeyInfo.tier}`);
|
|
27
27
|
console.log(`🔑 API Key Type: ${apiKeyInfo.keyType}`);
|
|
28
|
-
console.log(
|
|
28
|
+
console.log(`${apiKeyInfo.isValid ? '✅' : '❌'} Key Status: ${apiKeyInfo.isValid ? 'Valid' : 'Invalid'}`);
|
|
29
|
+
if (!apiKeyInfo.isValid) {
|
|
30
|
+
// getApiKeyInfo() reports failure via isValid:false rather than throwing,
|
|
31
|
+
// so this catch block never sees it — exit(1) has to happen here instead.
|
|
32
|
+
if (apiKeyInfo.error) console.log(` ${apiKeyInfo.error}`);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
29
35
|
} catch (error) {
|
|
30
36
|
console.error(`❌ Status check failed: ${error.message}\n`);
|
|
31
37
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mcp-prompt-optimizer",
|
|
3
|
-
"version": "3.7.
|
|
3
|
+
"version": "3.7.5",
|
|
4
4
|
"description": "Professional cloud-based MCP server for AI-powered prompt optimization with intelligent context detection, Bayesian optimization, AG-UI real-time optimization, template auto-save, optimization insights, personal model configuration via WebUI, team collaboration, enterprise-grade features, production resilience, and startup validation. Universal compatibility with Claude Desktop, Cursor, Windsurf, and 17+ MCP clients.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -124,8 +124,8 @@
|
|
|
124
124
|
"required_keys": [
|
|
125
125
|
{
|
|
126
126
|
"name": "OPTIMIZER_API_KEY",
|
|
127
|
-
"format": "sk-opt-*, sk-team-*,
|
|
128
|
-
"description": "Cloud API key from promptoptimizer.xyz/
|
|
127
|
+
"format": "sk-opt-*, sk-team-*, or sk-dev-*",
|
|
128
|
+
"description": "Cloud API key from promptoptimizer.xyz/dashboard or development key for testing",
|
|
129
129
|
"required": true
|
|
130
130
|
}
|
|
131
131
|
],
|
|
@@ -195,6 +195,28 @@
|
|
|
195
195
|
"last_sync": "2026-06-01T00:00:00Z"
|
|
196
196
|
},
|
|
197
197
|
"release_notes": {
|
|
198
|
+
"v3.7.5": {
|
|
199
|
+
"major_features": [
|
|
200
|
+
"Fixed: 10 MCP tools (generate_agent_sop, transform_for_framework, generate_harness_bundle, explore_sop_approaches, get_prompt_by_slug, compile_prompt, list_template_versions, rollback_template, publish_template, run_quick_evaluation) called backend routes that only accepted a JWT, which this stdio client can never obtain — every call failed unconditionally. Backend now accepts API-key auth on these routes too.",
|
|
201
|
+
"Fixed: the tier-upgrade message for these tools never fired because the code checked for the literal string '403' inside the error body, which never appears there (that's the HTTP status code, not body text). Now checks the real status code.",
|
|
202
|
+
"Fixed: get_optimization_insights and get_real_time_status fell back to hardcoded fake data (fabricated optimization counts, fake AG-UI metrics) on any backend error, presented as real account data. Both now report unavailability honestly instead.",
|
|
203
|
+
"Fixed: formatRealTimeStatus was never reading the AG-UI status endpoint's actual response shape, even on success.",
|
|
204
|
+
"Fixed: formatQuotaStatus invented a fake 5000 quota limit when the backend didn't report one.",
|
|
205
|
+
"Fixed: free-tier quota text said 7/month; actual limit is 20.",
|
|
206
|
+
"Fixed: dead promptoptimizer-blog.vercel.app domain and wrong sk-local-* key-format claims (that's the sibling local package's prefix, not this one's) across index.js, check-status.js, and package.json."
|
|
207
|
+
],
|
|
208
|
+
"breaking_changes": [],
|
|
209
|
+
"migration_guide": "No migration required. Users who called any of the 10 previously-broken MCP tools will now get real results instead of an auth error."
|
|
210
|
+
},
|
|
211
|
+
"v3.7.4": {
|
|
212
|
+
"major_features": [
|
|
213
|
+
"Fixed: 6 of 8 documented CLI commands (check-status, validate-key, diagnose, clear-cache, help, version) were not implemented in the argv dispatcher and silently started the blocking MCP server instead, hanging the terminal. Now wired to their lib/*.js implementations.",
|
|
214
|
+
"Fixed: unrecognized CLI arguments now print an error + usage to stderr and exit(1), instead of silently falling through to server startup. Removes the entire hung-terminal bug class, not just the known commands.",
|
|
215
|
+
"Removed 'test' from documented CLI commands: it mapped to a maintainer-only pre-publish script (tests/test-runner.js) that isn't included in the published package."
|
|
216
|
+
],
|
|
217
|
+
"breaking_changes": [],
|
|
218
|
+
"migration_guide": "No migration required. Only affects users who ran documented CLI subcommands other than 'connect', which previously hung."
|
|
219
|
+
},
|
|
198
220
|
"v3.7.3": {
|
|
199
221
|
"major_features": [
|
|
200
222
|
"Docs only: corrected stale free-tier quota in README (7 optimizations/month -> 20), matching the backend enforcement fix"
|