vibecheck-mcp-server 3.4.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/index.js +190 -14
  2. package/package.json +1 -1
  3. package/tools-v3.js +397 -64
  4. package/tools.js +495 -0
  5. package/index-v1.js +0 -698
package/index.js CHANGED
@@ -63,7 +63,7 @@ const __dirname = path.dirname(__filename);
63
63
  // CENTRALIZED CONFIGURATION
64
64
  // ============================================================================
65
65
  const CONFIG = {
66
- VERSION: "2.1.0",
66
+ VERSION: "2.2.0",
67
67
  BIN_PATH: path.join(__dirname, "..", "bin", "vibecheck.js"),
68
68
  OUTPUT_DIR: ".vibecheck",
69
69
  ENV_DEFAULTS: { VIBECHECK_SKIP_AUTH: "1" },
@@ -901,29 +901,117 @@ class VibecheckMCP {
901
901
  return '## Error: Invalid summary data\n';
902
902
  }
903
903
 
904
- // Safely extract values with defaults
905
- const score = sanitizeNumber(summary.score, 0, 100, 0);
906
- const grade = sanitizeString(summary.grade, 10) || 'N/A';
907
- const canShip = Boolean(summary.canShip);
904
+ // Safely extract values with defaults - handle different output structures
905
+ const score = sanitizeNumber(
906
+ summary.score?.overall || summary.score || summary.verdict?.score || 0,
907
+ 0, 100, 0
908
+ );
909
+ const grade = sanitizeString(summary.grade || summary.verdict?.grade, 10) || 'N/A';
910
+ const verdict = summary.verdict?.verdict || summary.verdict || (score >= 80 ? 'SHIP' : score >= 50 ? 'WARN' : 'BLOCK');
911
+ const canShip = verdict === 'SHIP' || Boolean(summary.canShip);
912
+ const findings = sanitizeArray(summary.findings || summary.report?.findings || [], 500);
908
913
 
909
- let output = `## Score: ${score}/100 (${grade})\n\n`;
910
- output += `**Verdict:** ${canShip ? "āœ… SHIP" : "🚫 NO-SHIP"}\n\n`;
911
-
914
+ // Get severity counts
915
+ const sevCounts = { critical: 0, high: 0, medium: 0, low: 0 };
916
+ for (const f of findings) {
917
+ const sev = (f.severity || 'medium').toLowerCase();
918
+ if (sev === 'block' || sev === 'critical') sevCounts.critical++;
919
+ else if (sev === 'high') sevCounts.high++;
920
+ else if (sev === 'warn' || sev === 'warning' || sev === 'medium') sevCounts.medium++;
921
+ else sevCounts.low++;
922
+ }
923
+
924
+ // Build structured output
925
+ let output = '';
926
+
927
+ // Header with verdict
928
+ const verdictEmoji = verdict === 'SHIP' ? 'āœ…' : verdict === 'WARN' ? 'āš ļø' : '🚫';
929
+ output += `## ${verdictEmoji} VERDICT: ${verdict}\n\n`;
930
+ output += `**Health Score:** ${score}/100 (${grade})\n\n`;
931
+
932
+ // Summary stats
933
+ output += `### Summary\n`;
934
+ output += `- **Total Issues:** ${findings.length}\n`;
935
+ output += `- **Critical:** ${sevCounts.critical}\n`;
936
+ output += `- **High:** ${sevCounts.high}\n`;
937
+ output += `- **Medium:** ${sevCounts.medium}\n`;
938
+ output += `- **Low:** ${sevCounts.low}\n\n`;
939
+
940
+ // Category breakdown
912
941
  if (summary.counts && typeof summary.counts === 'object') {
913
- output += "### Checks\n\n";
914
- output += "| Category | Issues |\n|----------|--------|\n";
942
+ output += "### Issue Categories\n\n";
943
+ output += "| Category | Count | Status |\n|----------|-------|--------|\n";
915
944
 
916
- // Limit to 50 categories to prevent output bloat
917
- const entries = Object.entries(summary.counts).slice(0, 50);
945
+ const entries = Object.entries(summary.counts).slice(0, 20);
918
946
  for (const [key, count] of entries) {
919
947
  const safeKey = sanitizeString(key, 50);
920
948
  const safeCount = sanitizeNumber(count, 0, 999999, 0);
921
949
  const icon = safeCount === 0 ? "āœ…" : "āš ļø";
922
- output += `| ${icon} ${safeKey} | ${safeCount} |\n`;
950
+ output += `| ${safeKey} | ${safeCount} | ${icon} |\n`;
951
+ }
952
+ output += '\n';
953
+ }
954
+
955
+ // Top findings with details (show up to 15)
956
+ if (findings.length > 0) {
957
+ output += "### Top Issues to Fix\n\n";
958
+
959
+ // Sort by severity (critical first)
960
+ const sortedFindings = findings
961
+ .sort((a, b) => {
962
+ const sevOrder = { critical: 0, block: 0, high: 1, warn: 2, warning: 2, medium: 2, low: 3, info: 4 };
963
+ const aOrder = sevOrder[(a.severity || 'medium').toLowerCase()] || 2;
964
+ const bOrder = sevOrder[(b.severity || 'medium').toLowerCase()] || 2;
965
+ return aOrder - bOrder;
966
+ })
967
+ .slice(0, 15);
968
+
969
+ for (let i = 0; i < sortedFindings.length; i++) {
970
+ const f = sortedFindings[i];
971
+ const sev = sanitizeString(f.severity || 'medium', 20).toUpperCase();
972
+ const sevEmoji = sev === 'CRITICAL' || sev === 'BLOCK' ? 'šŸ”“' : sev === 'HIGH' ? '🟠' : '🟔';
973
+ const title = sanitizeString(f.title || f.message || f.why || 'Unknown issue', 100);
974
+ const category = sanitizeString(f.category || f.type || 'Other', 30);
975
+ const file = sanitizeString(f.file || (f.evidence && f.evidence[0]?.file) || '', 150);
976
+ const line = f.line || (f.evidence && f.evidence[0]?.lines) || '';
977
+
978
+ output += `**${i + 1}. ${sevEmoji} [${sev}] ${title}**\n`;
979
+ output += ` - Category: \`${category}\`\n`;
980
+ if (file) {
981
+ output += ` - File: \`${file}\`${line ? `:${line}` : ''}\n`;
982
+ }
983
+
984
+ // Include fix hints if available
985
+ const fixHint = f.fixHints?.[0] || f.fixHint || f.fix;
986
+ if (fixHint) {
987
+ output += ` - **Fix:** ${sanitizeString(fixHint, 200)}\n`;
988
+ }
989
+ output += '\n';
990
+ }
991
+
992
+ if (findings.length > 15) {
993
+ output += `_...and ${findings.length - 15} more issues. See full report for details._\n\n`;
923
994
  }
924
995
  }
925
996
 
926
- output += `\nšŸ“„ **Report:** ${CONFIG.OUTPUT_DIR}/report.html\n`;
997
+ // Next steps based on verdict
998
+ output += "### Recommended Actions\n\n";
999
+ if (verdict === 'SHIP') {
1000
+ output += "- āœ… Code is clean and ready to ship\n";
1001
+ output += "- Consider running `vibecheck ship --badge` to generate a status badge\n";
1002
+ } else if (verdict === 'WARN') {
1003
+ output += "- Review the warnings above before shipping\n";
1004
+ output += "- Run `vibecheck fix --plan` to see fix suggestions\n";
1005
+ output += "- Consider using `vibecheck fix --apply` (PRO) to auto-fix issues\n";
1006
+ } else {
1007
+ output += "- 🚫 Critical issues must be fixed before shipping\n";
1008
+ output += "- Run `vibecheck fix --plan` to see detailed fix suggestions\n";
1009
+ output += "- Address critical issues first, then re-scan\n";
1010
+ }
1011
+
1012
+ output += `\nšŸ“„ **Full Report:** ${CONFIG.OUTPUT_DIR}/report.html\n`;
1013
+ output += `šŸ“Š **JSON Results:** ${CONFIG.OUTPUT_DIR}/results/latest.json\n`;
1014
+
927
1015
  return output;
928
1016
  }
929
1017
 
@@ -1196,6 +1284,12 @@ class VibecheckMCP {
1196
1284
  // Resources
1197
1285
  this.server.setRequestHandler(ListResourcesRequestSchema, async () => ({
1198
1286
  resources: [
1287
+ {
1288
+ uri: "vibecheck://status",
1289
+ name: "Server Status",
1290
+ description: "Current MCP server health, version, and rate limits",
1291
+ mimeType: "application/json",
1292
+ },
1199
1293
  {
1200
1294
  uri: "vibecheck://config",
1201
1295
  name: "vibecheck Config",
@@ -1244,6 +1338,12 @@ class VibecheckMCP {
1244
1338
  description: "Last prove loop results (ctx → reality → ship → fix)",
1245
1339
  mimeType: "application/json",
1246
1340
  },
1341
+ {
1342
+ uri: "vibecheck://registry",
1343
+ name: "Command Registry",
1344
+ description: "Available commands and their tiers",
1345
+ mimeType: "application/json",
1346
+ },
1247
1347
  ],
1248
1348
  }));
1249
1349
 
@@ -1390,6 +1490,82 @@ class VibecheckMCP {
1390
1490
  return await safeReadResource(provePath, "No prove results. Run vibecheck.prove first.");
1391
1491
  }
1392
1492
 
1493
+ // Server status resource - live health check
1494
+ if (uri === "vibecheck://status") {
1495
+ const rateCheck = checkRateLimit(null);
1496
+ const circuitCheck = checkCircuitBreaker();
1497
+
1498
+ const status = {
1499
+ server: {
1500
+ version: CONFIG.VERSION,
1501
+ uptime: Math.floor(process.uptime()),
1502
+ transport: 'stdio',
1503
+ nodeVersion: process.version,
1504
+ },
1505
+ health: {
1506
+ status: circuitCheck.allowed ? 'healthy' : 'degraded',
1507
+ circuitBreaker: circuitBreakerState.state,
1508
+ failureCount: circuitBreakerState.failures,
1509
+ },
1510
+ rateLimit: {
1511
+ remaining: rateCheck.remaining,
1512
+ resetIn: rateCheck.resetIn || 0,
1513
+ limit: CONFIG.LIMITS.RATE_LIMIT_MAX_CALLS,
1514
+ window: CONFIG.LIMITS.RATE_LIMIT_WINDOW_MS,
1515
+ },
1516
+ features: {
1517
+ hardening: true,
1518
+ auditLogging: true,
1519
+ secretRedaction: true,
1520
+ pathSecurity: true,
1521
+ },
1522
+ timestamp: new Date().toISOString(),
1523
+ };
1524
+
1525
+ return {
1526
+ contents: [{ uri, mimeType: "application/json", text: JSON.stringify(status, null, 2) }],
1527
+ };
1528
+ }
1529
+
1530
+ // Registry resource - available commands and tiers
1531
+ if (uri === "vibecheck://registry") {
1532
+ const registry = {
1533
+ version: CONFIG.VERSION,
1534
+ tiers: {
1535
+ free: {
1536
+ name: 'FREE',
1537
+ price: '$0',
1538
+ description: 'Inspect & Observe',
1539
+ },
1540
+ pro: {
1541
+ name: 'PRO',
1542
+ price: '$69/mo',
1543
+ description: 'Fix, Prove & Enforce',
1544
+ },
1545
+ },
1546
+ tools: Object.entries(V3_TOOL_TIERS).map(([name, tier]) => ({
1547
+ name,
1548
+ tier,
1549
+ })),
1550
+ resources: [
1551
+ 'vibecheck://status',
1552
+ 'vibecheck://config',
1553
+ 'vibecheck://summary',
1554
+ 'vibecheck://truthpack',
1555
+ 'vibecheck://missions',
1556
+ 'vibecheck://reality',
1557
+ 'vibecheck://findings',
1558
+ 'vibecheck://share',
1559
+ 'vibecheck://prove',
1560
+ 'vibecheck://registry',
1561
+ ],
1562
+ };
1563
+
1564
+ return {
1565
+ contents: [{ uri, mimeType: "application/json", text: JSON.stringify(registry, null, 2) }],
1566
+ };
1567
+ }
1568
+
1393
1569
  return {
1394
1570
  contents: [{
1395
1571
  uri,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vibecheck-mcp-server",
3
- "version": "3.4.0",
3
+ "version": "3.5.0",
4
4
  "description": "Professional MCP server for vibecheck - Intelligent development environment vibechecks",
5
5
  "type": "module",
6
6
  "main": "index.js",