@greenarmor/ges-mcp-server 1.2.4 → 1.2.6

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 (2) hide show
  1. package/dist/server.js +216 -10
  2. package/package.json +12 -12
package/dist/server.js CHANGED
@@ -9,6 +9,7 @@ import { generateScoreFile, formatScoreOutput, computeGrade, generateBadgeSvg, i
9
9
  import { runAudit, deduplicateFindings } from "@greenarmor/ges-audit-engine";
10
10
  import { GESF_VERSION, GES_DIR, COMPLIANCE_DIR, SECURITY_DIR, CONTROLS_DIR, POLICIES_DIR, CHECKLISTS_DIR, DOCS_DIR, REPORTS_DIR, DEFAULT_FRAMEWORKS } from "@greenarmor/ges-core";
11
11
  import { appendFixHistory, createFixHistoryEntry } from "@greenarmor/ges-core";
12
+ import { addFrameworkToConfig, removeFrameworkFromConfig, loadControlsFromDisk, recordActivity, recordAIRecommendation } from "@greenarmor/ges-core";
12
13
  import { ProjectConfigSchema } from "@greenarmor/ges-core";
13
14
  import { generateComplianceDocs, generateSecurityDocs, generateConfigJson, generateMetadataJson, generateFrameworkVersionJson, generateScoreJson } from "@greenarmor/ges-doc-generator";
14
15
  import { generateAllWorkflows } from "@greenarmor/ges-cicd-generator";
@@ -199,13 +200,13 @@ const TOOLS = [
199
200
  },
200
201
  {
201
202
  name: "apply_control_override",
202
- description: "Mark a compliance control as not-applicable, pass, or another status in the project's .ges/control-overrides.json. Use this when a control doesn't apply to the project or has been verified manually.",
203
+ description: "Mark a compliance control as not-applicable. AI assistants CANNOT mark controls as 'pass' that must be verified by the GESF audit engine (run_audit). Use 'not-applicable' only when a control genuinely does not apply to the project. A detailed reason is required.",
203
204
  inputSchema: {
204
205
  type: "object",
205
206
  properties: {
206
207
  project_path: { type: "string", description: "Absolute path to the project root." },
207
208
  control_id: { type: "string", description: "Control ID to override (e.g. GDPR-ART32-004)" },
208
- status: { type: "string", description: "New status: 'not-applicable' or 'pass'" },
209
+ status: { type: "string", description: "Status: only 'not-applicable' is allowed via MCP. 'pass' must come from the audit engine." },
209
210
  reason: { type: "string", description: "Reason for the override" },
210
211
  },
211
212
  },
@@ -352,6 +353,24 @@ const TOOLS = [
352
353
  },
353
354
  },
354
355
  },
356
+ {
357
+ name: "record_recommendation",
358
+ description: "Record a recommendation or observation to .dev-logs/ai-recommendations/ for the GESF development team. Use this when you identify a potential improvement, weakness, or best-practice suggestion. Recommendations are NOT applied automatically — they are logged for human developers to review. This is the correct way to surface ideas instead of overriding controls.",
359
+ inputSchema: {
360
+ type: "object",
361
+ properties: {
362
+ project_path: { type: "string", description: "Absolute path to the project root." },
363
+ category: { type: "string", description: "Category: security, compliance, architecture, performance, best-practice, bug, or improvement." },
364
+ title: { type: "string", description: "Short title for the recommendation." },
365
+ description: { type: "string", description: "Detailed description of the observation." },
366
+ severity: { type: "string", description: "Severity: info, low, medium, or high." },
367
+ affected_controls: { type: "string", description: "Comma-separated control IDs affected (optional)." },
368
+ affected_files: { type: "string", description: "Comma-separated file paths affected (optional)." },
369
+ suggested_action: { type: "string", description: "What you suggest the developers do about this." },
370
+ },
371
+ required: ["project_path", "category", "title", "description", "suggested_action"],
372
+ },
373
+ },
355
374
  ];
356
375
  function send(message) {
357
376
  process.stdout.write(JSON.stringify(message) + "\n");
@@ -2201,6 +2220,14 @@ export function handleRequest(request) {
2201
2220
  lines.push(`\n*Note: ${projectConfig.overrides.length} control overrides applied.*`);
2202
2221
  }
2203
2222
  resultText = lines.join("\n");
2223
+ recordActivity(projectPath, {
2224
+ source: "mcp",
2225
+ action: "audit",
2226
+ title: `MCP audit completed`,
2227
+ description: `Scanned ${scannedFiles} files, found ${findings.length} findings (${critical.length} critical, ${high.length} high, ${medium.length} medium, ${low.length} low). Overall score: ${score.overall}%.`,
2228
+ status: critical.length > 0 ? "failed" : findings.length > 0 ? "partial" : "success",
2229
+ details: { findings_count: findings.length, score: score.overall, files_scanned: scannedFiles },
2230
+ });
2204
2231
  break;
2205
2232
  }
2206
2233
  case "generate_compliance_report": {
@@ -2318,13 +2345,18 @@ export function handleRequest(request) {
2318
2345
  let projectControls = [];
2319
2346
  try {
2320
2347
  const configPath = path.join(projectPath, ".ges", "config.json");
2348
+ let inMemoryControls = [];
2321
2349
  if (fs.existsSync(configPath)) {
2322
2350
  const cfg = JSON.parse(fs.readFileSync(configPath, "utf-8"));
2323
2351
  const fwLower = new Set(cfg.frameworks.map((f) => f.toLowerCase()));
2324
2352
  const allPacks = getAllPacks();
2325
2353
  const filtered = allPacks.filter((pack) => fwLower.has(pack.id.toLowerCase()));
2326
- projectControls = filtered.flatMap((p) => p.controls);
2354
+ inMemoryControls = filtered.flatMap((p) => p.controls);
2327
2355
  }
2356
+ const diskControls = loadControlsFromDisk(projectPath);
2357
+ const seenIds = new Set(inMemoryControls.map(c => c.id));
2358
+ const extraFromDisk = diskControls.filter(c => !seenIds.has(c.id));
2359
+ projectControls = [...inMemoryControls, ...extraFromDisk];
2328
2360
  }
2329
2361
  catch { /* ignore */ }
2330
2362
  const npmInstalls = getNpmInstallsFromActions(actions);
@@ -2423,6 +2455,14 @@ export function handleRequest(request) {
2423
2455
  lines.push("4. Address remaining manual review items");
2424
2456
  lines.push("5. Use `fix_recommendation` tool for detailed guidance on manual items");
2425
2457
  resultText = lines.join("\n");
2458
+ recordActivity(projectPath, {
2459
+ source: "mcp",
2460
+ action: "fix",
2461
+ title: `MCP auto-fix ${dryRun ? "planned" : "applied"}: ${applied} fixes`,
2462
+ description: `${dryRun ? "Planned" : "Applied"} ${applied} fix(es)${failed > 0 ? ` (${failed} failed)` : ""}. Scanned ${scannedFiles} files, ${findings.length} findings found.`,
2463
+ status: failed > 0 ? "partial" : "success",
2464
+ details: { fixes_applied: applied, findings_count: findings.length },
2465
+ });
2426
2466
  break;
2427
2467
  }
2428
2468
  case "apply_control_override": {
@@ -2434,8 +2474,28 @@ export function handleRequest(request) {
2434
2474
  resultText = "Error: control_id is required.";
2435
2475
  break;
2436
2476
  }
2437
- if (!["not-applicable", "pass"].includes(status)) {
2438
- resultText = `Error: status must be 'not-applicable' or 'pass'. Got: ${status}`;
2477
+ if (status === "pass") {
2478
+ resultText = [
2479
+ `# Cannot Override to "pass" via MCP\n`,
2480
+ `AI assistants cannot mark controls as "pass" — this must be verified by GESF's own audit engine.`,
2481
+ ``,
2482
+ `**Why**: Allowing AI to set "pass" creates false compliance scores. The audit engine scans actual source code to verify controls are implemented correctly.`,
2483
+ ``,
2484
+ `**Instead**:`,
2485
+ `1. Use \`implement_control\` to generate implementation files`,
2486
+ `2. Run \`run_audit\` — GESF will verify the implementation and update the score automatically`,
2487
+ `3. If the control is genuinely not applicable, use status: "not-applicable" with a detailed reason`,
2488
+ ``,
2489
+ `**For CLI users**: \`ges control <id> pass --reason "..."'\` is available for human developers who have manually verified.`,
2490
+ ].join("\n");
2491
+ break;
2492
+ }
2493
+ if (!["not-applicable"].includes(status)) {
2494
+ resultText = `Error: MCP only allows 'not-applicable'. Use 'not-applicable' for controls that don't apply to this project. Status 'pass' must come from the audit engine.`;
2495
+ break;
2496
+ }
2497
+ if (!reason || reason.trim().length < 10) {
2498
+ resultText = `Error: A detailed reason (at least 10 characters) is required when marking a control as not-applicable. Explain why this control does not apply to your project.`;
2439
2499
  break;
2440
2500
  }
2441
2501
  if (!fs.existsSync(path.join(projectPath, ".ges"))) {
@@ -2464,13 +2524,20 @@ export function handleRequest(request) {
2464
2524
  `# Control Override Applied\n`,
2465
2525
  `**Control**: ${controlId}`,
2466
2526
  `**Status**: ${status}`,
2467
- `**Reason**: ${reason || "(none provided)"}`,
2527
+ `**Reason**: ${reason}`,
2468
2528
  `**File**: ${overridePath}`,
2469
2529
  `**Total overrides**: ${overrides.length}\n`,
2470
2530
  `The override will take effect on the next \`ges audit\` or \`ges score\` run.`,
2471
2531
  `\nRun \`ges audit\` then \`ges score\` to see the updated compliance score.`,
2472
2532
  ];
2473
2533
  resultText = lines.join("\n");
2534
+ recordActivity(projectPath, {
2535
+ source: "mcp",
2536
+ action: "control_override",
2537
+ title: `Control ${controlId} → ${status}`,
2538
+ description: `MCP applied override: control ${controlId} set to ${status}. Reason: ${reason || "(none)"}`,
2539
+ details: { controls_affected: [controlId] },
2540
+ });
2474
2541
  break;
2475
2542
  }
2476
2543
  case "implement_control": {
@@ -2536,18 +2603,27 @@ export function handleRequest(request) {
2536
2603
  break;
2537
2604
  }
2538
2605
  lines.push(`**Control**: ${plan.name}\n`);
2606
+ let appliedCount = 0;
2607
+ let skippedCount = 0;
2539
2608
  for (const action of plan.actions) {
2540
2609
  const result = applyAutoFixAction(projectPath, action);
2541
2610
  if (result.applied) {
2611
+ appliedCount++;
2542
2612
  lines.push(`- ✓ [${action.type}] ${action.filePath}: ${action.description}`);
2543
2613
  }
2544
2614
  else if (result.error === "File already exists") {
2615
+ skippedCount++;
2545
2616
  lines.push(`- → [${action.type}] ${action.filePath}: Already exists (skipped)`);
2546
2617
  }
2547
2618
  else {
2548
2619
  lines.push(`- ✗ [${action.type}] ${action.filePath}: ${result.error}`);
2549
2620
  }
2550
2621
  }
2622
+ if (appliedCount > 0 || skippedCount > 0) {
2623
+ lines.push(`\n⚠️ **Control status is NOT automatically changed.**`);
2624
+ lines.push(` GESF does not allow AI to self-verify implementations.`);
2625
+ lines.push(` The control will be verified when you run \`ges audit\`.`);
2626
+ }
2551
2627
  const npmInstalls = getNpmInstallsFromActions(plan.actions);
2552
2628
  if (npmInstalls.length > 0) {
2553
2629
  lines.push(`\n## Install Dependencies\n`);
@@ -2563,9 +2639,15 @@ export function handleRequest(request) {
2563
2639
  lines.push(`\n## Next Steps`);
2564
2640
  lines.push("1. Install any npm packages listed above");
2565
2641
  lines.push("2. Import and integrate the generated files into your app");
2566
- lines.push("3. Run `ges audit` to verify the control is now passing");
2567
- lines.push(`4. Or use \`apply_control_override\` with control_id="${controlId}" if verified manually`);
2642
+ lines.push("3. Run `ges audit` GESF will verify the implementation and update the score");
2568
2643
  resultText = lines.join("\n");
2644
+ recordActivity(projectPath, {
2645
+ source: "mcp",
2646
+ action: "implement_control",
2647
+ title: `Control implemented: ${controlId} (${plan.name})`,
2648
+ description: `Auto-implemented control ${controlId} (${plan.name}). ${appliedCount} actions applied, ${skippedCount} skipped. Awaiting audit verification.`,
2649
+ details: { controls_affected: [controlId], files_created: plan.actions.filter(a => a.type === "create").map(a => a.filePath) },
2650
+ });
2569
2651
  break;
2570
2652
  }
2571
2653
  case "generate_badge": {
@@ -2678,10 +2760,22 @@ export function handleRequest(request) {
2678
2760
  fs.writeFileSync(path.join(gesDir, "framework-version.json"), frameworkVersionJson.content);
2679
2761
  const scoreJson = generateScoreJson();
2680
2762
  fs.writeFileSync(path.join(gesDir, "score.json"), scoreJson.content);
2681
- const dirs = [COMPLIANCE_DIR, SECURITY_DIR, CONTROLS_DIR, POLICIES_DIR, CHECKLISTS_DIR, DOCS_DIR, REPORTS_DIR];
2763
+ const dirs = [COMPLIANCE_DIR, SECURITY_DIR, CONTROLS_DIR, POLICIES_DIR, CHECKLISTS_DIR, DOCS_DIR, REPORTS_DIR, ".dev-logs"];
2682
2764
  for (const dir of dirs) {
2683
2765
  fs.mkdirSync(path.join(projectPath, dir), { recursive: true });
2684
2766
  }
2767
+ const gitignorePath = path.join(projectPath, ".gitignore");
2768
+ const devLogsIgnore = ".dev-logs/\n";
2769
+ if (fs.existsSync(gitignorePath)) {
2770
+ const existingGitignore = fs.readFileSync(gitignorePath, "utf-8");
2771
+ if (!existingGitignore.includes(".dev-logs/")) {
2772
+ fs.appendFileSync(gitignorePath, `\n# GESF developer logs (not for remote)\n${devLogsIgnore}`);
2773
+ }
2774
+ }
2775
+ else {
2776
+ fs.writeFileSync(gitignorePath, `# GESF developer logs (not for remote)\n${devLogsIgnore}\n`);
2777
+ }
2778
+ fs.writeFileSync(path.join(projectPath, ".dev-logs", "README.md"), `# Developer Logs\n\nThis directory is for GESF development notes, session logs, AI recommendations, and release notes.\n\n**This directory is gitignored and intended for developers only. Do not submit to remote.**\n`);
2685
2779
  const complianceDocs = generateComplianceDocs(projectName, projectType);
2686
2780
  for (const doc of complianceDocs) {
2687
2781
  const filePath = path.join(projectPath, COMPLIANCE_DIR, doc.filePath);
@@ -2725,6 +2819,13 @@ export function handleRequest(request) {
2725
2819
  lines.push(`3. Run \`ges badge\` to generate a compliance badge for README`);
2726
2820
  lines.push(`4. Review and customize documents in compliance/ and security/`);
2727
2821
  resultText = lines.join("\n");
2822
+ recordActivity(projectPath, {
2823
+ source: "mcp",
2824
+ action: "init",
2825
+ title: `Project initialized: ${projectName}`,
2826
+ description: `Initialized GESF for ${projectType} project with frameworks: ${frameworks.join(", ")}. Installed ${packs.length} policy packs.`,
2827
+ details: { packs_affected: packs.map(p => p.id), frameworks_added: frameworks.map(f => String(f)) },
2828
+ });
2728
2829
  break;
2729
2830
  }
2730
2831
  case "run_scans": {
@@ -2755,6 +2856,13 @@ export function handleRequest(request) {
2755
2856
  lines.push(`\n**${failed.length} scanner(s) reported failures.** Review findings above.`);
2756
2857
  }
2757
2858
  resultText = lines.join("\n");
2859
+ recordActivity(projectPath, {
2860
+ source: "mcp",
2861
+ action: "scan",
2862
+ title: `MCP security scans completed (${results.length} tools)`,
2863
+ description: `Ran ${results.length} scanner(s) for ${ecosystemDetail} ecosystem. ${results.filter(r => r.status === "pass").length} passed, ${failed.length} failed.`,
2864
+ status: failed.length > 0 ? "partial" : "success",
2865
+ });
2758
2866
  break;
2759
2867
  }
2760
2868
  case "doctor": {
@@ -2889,6 +2997,13 @@ export function handleRequest(request) {
2889
2997
  }
2890
2998
  lines.push(hasErrors ? "\n❌ **Validation failed.** Fix the issues above." : "\n✅ **All validations passed.**");
2891
2999
  resultText = lines.join("\n");
3000
+ recordActivity(projectPath, {
3001
+ source: "mcp",
3002
+ action: "validate",
3003
+ title: `MCP validation ${hasErrors ? "failed" : "passed"}`,
3004
+ description: hasErrors ? "Configuration or directory structure has issues." : "All validations passed.",
3005
+ status: hasErrors ? "failed" : "success",
3006
+ });
2892
3007
  break;
2893
3008
  }
2894
3009
  case "policy_list": {
@@ -2924,7 +3039,28 @@ export function handleRequest(request) {
2924
3039
  const packDir = path.join(projectPath, CONTROLS_DIR, pack.id);
2925
3040
  fs.mkdirSync(packDir, { recursive: true });
2926
3041
  fs.writeFileSync(path.join(packDir, "controls.json"), JSON.stringify(pack.controls, null, 2));
2927
- resultText = `✅ Installed policy pack: **${pack.id}** (${pack.name})\n${pack.controls.length} controls written to ${CONTROLS_DIR}/${pack.id}/controls.json`;
3042
+ const frameworksAdded = [];
3043
+ for (const fw of pack.frameworks) {
3044
+ if (addFrameworkToConfig(projectPath, fw)) {
3045
+ frameworksAdded.push(fw);
3046
+ }
3047
+ }
3048
+ const lines = [
3049
+ `✅ Installed policy pack: **${pack.id}** (${pack.name})`,
3050
+ `${pack.controls.length} controls written to ${CONTROLS_DIR}/${pack.id}/controls.json`,
3051
+ ];
3052
+ if (frameworksAdded.length > 0) {
3053
+ lines.push(`Added ${frameworksAdded.join(", ")} to project frameworks in .ges/config.json`);
3054
+ }
3055
+ lines.push(`The web dashboard will now reflect this pack's controls.`);
3056
+ resultText = lines.join("\n");
3057
+ recordActivity(projectPath, {
3058
+ source: "mcp",
3059
+ action: "policy_install",
3060
+ title: `MCP installed pack: ${pack.name}`,
3061
+ description: `Installed ${pack.controls.length} controls from ${pack.id} pack.${frameworksAdded.length > 0 ? ` Added ${frameworksAdded.join(", ")} to config frameworks.` : ""}`,
3062
+ details: { packs_affected: [pack.id], frameworks_added: frameworksAdded },
3063
+ });
2928
3064
  break;
2929
3065
  }
2930
3066
  case "policy_remove": {
@@ -2940,7 +3076,24 @@ export function handleRequest(request) {
2940
3076
  break;
2941
3077
  }
2942
3078
  fs.rmSync(packDir, { recursive: true, force: true });
3079
+ const allPacks = getAllPacks();
3080
+ const removedPack = allPacks.find(p => p.id === packId);
3081
+ if (removedPack) {
3082
+ for (const fw of removedPack.frameworks) {
3083
+ removeFrameworkFromConfig(projectPath, fw);
3084
+ }
3085
+ }
3086
+ else {
3087
+ removeFrameworkFromConfig(projectPath, packId.toUpperCase());
3088
+ }
2943
3089
  resultText = `✅ Removed policy pack: **${packId}** from ${projectPath}`;
3090
+ recordActivity(projectPath, {
3091
+ source: "mcp",
3092
+ action: "policy_remove",
3093
+ title: `MCP removed pack: ${packId}`,
3094
+ description: `Removed ${packId} pack and its controls from the project.`,
3095
+ details: { packs_affected: [packId] },
3096
+ });
2944
3097
  break;
2945
3098
  }
2946
3099
  case "update_check": {
@@ -2991,6 +3144,12 @@ export function handleRequest(request) {
2991
3144
  fs.writeFileSync(hookPath, hookContent);
2992
3145
  fs.chmodSync(hookPath, 0o755);
2993
3146
  resultText = `✅ Installed pre-commit hook at ${hookPath}\n\nThe hook will run 'ges audit --ci' before allowing commits.\n- To bypass: \`git commit --no-verify\`\n- To remove: use \`install_hooks\` with action: "uninstall"`;
3147
+ recordActivity(projectPath, {
3148
+ source: "mcp",
3149
+ action: "hooks_install",
3150
+ title: `MCP installed pre-commit hook`,
3151
+ description: `Installed pre-commit hook that runs 'ges audit --ci' before each commit.`,
3152
+ });
2994
3153
  break;
2995
3154
  }
2996
3155
  case "start_dashboard": {
@@ -3029,6 +3188,12 @@ export function handleRequest(request) {
3029
3188
  lines.push(`- Control status matrix`);
3030
3189
  lines.push(`- Audit history timeline`);
3031
3190
  resultText = lines.join("\n");
3191
+ recordActivity(projectPath, {
3192
+ source: "mcp",
3193
+ action: "dashboard_start",
3194
+ title: `Dashboard started on ${host}:${port}`,
3195
+ description: `Web dashboard is running at http://${host}:${port}`,
3196
+ });
3032
3197
  }
3033
3198
  catch (err) {
3034
3199
  const msg = err instanceof Error ? err.message : String(err);
@@ -3036,6 +3201,47 @@ export function handleRequest(request) {
3036
3201
  }
3037
3202
  break;
3038
3203
  }
3204
+ case "record_recommendation": {
3205
+ const projectPath = resolveProjectPath(args.project_path);
3206
+ const category = (args.category || "improvement");
3207
+ const title = args.title || "";
3208
+ const description = args.description || "";
3209
+ const severity = (args.severity || "info");
3210
+ const suggestedAction = args.suggested_action || "";
3211
+ const affectedControls = args.affected_controls ? args.affected_controls.split(",").map((s) => s.trim()).filter(Boolean) : [];
3212
+ const affectedFiles = args.affected_files ? args.affected_files.split(",").map((s) => s.trim()).filter(Boolean) : [];
3213
+ if (!title || !description || !suggestedAction) {
3214
+ resultText = "Error: title, description, and suggested_action are all required.";
3215
+ break;
3216
+ }
3217
+ if (!fs.existsSync(projectPath)) {
3218
+ resultText = `Project path does not exist: ${projectPath}`;
3219
+ break;
3220
+ }
3221
+ const rec = recordAIRecommendation(projectPath, {
3222
+ category,
3223
+ title,
3224
+ description,
3225
+ severity,
3226
+ affected_controls: affectedControls,
3227
+ affected_files: affectedFiles,
3228
+ suggested_action: suggestedAction,
3229
+ });
3230
+ resultText = [
3231
+ `# Recommendation Recorded\n`,
3232
+ `**ID**: ${rec.id}`,
3233
+ `**Category**: ${rec.category}`,
3234
+ `**Severity**: ${rec.severity}`,
3235
+ `**Title**: ${rec.title}`,
3236
+ ``,
3237
+ `**Written to**: \`.dev-logs/ai-recommendations/\``,
3238
+ ``,
3239
+ `This recommendation has been logged for the development team to review.`,
3240
+ `It will NOT be automatically applied to the project.`,
3241
+ `Recommendations are gitignored and intended for developers only.`,
3242
+ ].join("\n");
3243
+ break;
3244
+ }
3039
3245
  default:
3040
3246
  return {
3041
3247
  jsonrpc: "2.0",
package/package.json CHANGED
@@ -3,17 +3,17 @@
3
3
  "ges-mcp": "dist/server.js"
4
4
  },
5
5
  "dependencies": {
6
- "@greenarmor/ges-audit-engine": "1.2.4",
7
- "@greenarmor/ges-cicd-generator": "1.2.4",
8
- "@greenarmor/ges-compliance-engine": "1.2.4",
9
- "@greenarmor/ges-core": "1.2.4",
10
- "@greenarmor/ges-doc-generator": "1.2.4",
11
- "@greenarmor/ges-policy-engine": "1.2.4",
12
- "@greenarmor/ges-report-generator": "1.2.4",
13
- "@greenarmor/ges-rules-engine": "1.2.4",
14
- "@greenarmor/ges-scanner-integration": "1.2.4",
15
- "@greenarmor/ges-scoring-engine": "1.2.4",
16
- "@greenarmor/ges-web-dashboard": "1.2.4"
6
+ "@greenarmor/ges-audit-engine": "1.2.6",
7
+ "@greenarmor/ges-cicd-generator": "1.2.6",
8
+ "@greenarmor/ges-compliance-engine": "1.2.6",
9
+ "@greenarmor/ges-core": "1.2.6",
10
+ "@greenarmor/ges-doc-generator": "1.2.6",
11
+ "@greenarmor/ges-policy-engine": "1.2.6",
12
+ "@greenarmor/ges-report-generator": "1.2.6",
13
+ "@greenarmor/ges-rules-engine": "1.2.6",
14
+ "@greenarmor/ges-scanner-integration": "1.2.6",
15
+ "@greenarmor/ges-scoring-engine": "1.2.6",
16
+ "@greenarmor/ges-web-dashboard": "1.2.6"
17
17
  },
18
18
  "description": "GESF MCP Server - AI Compliance Assistant for GDPR, OWASP, NIST, CIS. Check compliance, generate policies, assess risks via MCP protocol.",
19
19
  "devDependencies": {
@@ -67,7 +67,7 @@
67
67
  },
68
68
  "type": "module",
69
69
  "types": "./dist/index.d.ts",
70
- "version": "1.2.4",
70
+ "version": "1.2.6",
71
71
  "scripts": {
72
72
  "build": "tsc",
73
73
  "clean": "rm -rf dist bundle tsconfig.tsbuildinfo",