@greenarmor/ges-mcp-server 1.2.4 → 1.2.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.
Files changed (2) hide show
  1. package/dist/server.js +104 -3
  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, saveControlOverride, loadControlsFromDisk, recordActivity } 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";
@@ -2201,6 +2202,14 @@ export function handleRequest(request) {
2201
2202
  lines.push(`\n*Note: ${projectConfig.overrides.length} control overrides applied.*`);
2202
2203
  }
2203
2204
  resultText = lines.join("\n");
2205
+ recordActivity(projectPath, {
2206
+ source: "mcp",
2207
+ action: "audit",
2208
+ title: `MCP audit completed`,
2209
+ description: `Scanned ${scannedFiles} files, found ${findings.length} findings (${critical.length} critical, ${high.length} high, ${medium.length} medium, ${low.length} low). Overall score: ${score.overall}%.`,
2210
+ status: critical.length > 0 ? "failed" : findings.length > 0 ? "partial" : "success",
2211
+ details: { findings_count: findings.length, score: score.overall, files_scanned: scannedFiles },
2212
+ });
2204
2213
  break;
2205
2214
  }
2206
2215
  case "generate_compliance_report": {
@@ -2318,13 +2327,18 @@ export function handleRequest(request) {
2318
2327
  let projectControls = [];
2319
2328
  try {
2320
2329
  const configPath = path.join(projectPath, ".ges", "config.json");
2330
+ let inMemoryControls = [];
2321
2331
  if (fs.existsSync(configPath)) {
2322
2332
  const cfg = JSON.parse(fs.readFileSync(configPath, "utf-8"));
2323
2333
  const fwLower = new Set(cfg.frameworks.map((f) => f.toLowerCase()));
2324
2334
  const allPacks = getAllPacks();
2325
2335
  const filtered = allPacks.filter((pack) => fwLower.has(pack.id.toLowerCase()));
2326
- projectControls = filtered.flatMap((p) => p.controls);
2336
+ inMemoryControls = filtered.flatMap((p) => p.controls);
2327
2337
  }
2338
+ const diskControls = loadControlsFromDisk(projectPath);
2339
+ const seenIds = new Set(inMemoryControls.map(c => c.id));
2340
+ const extraFromDisk = diskControls.filter(c => !seenIds.has(c.id));
2341
+ projectControls = [...inMemoryControls, ...extraFromDisk];
2328
2342
  }
2329
2343
  catch { /* ignore */ }
2330
2344
  const npmInstalls = getNpmInstallsFromActions(actions);
@@ -2423,6 +2437,14 @@ export function handleRequest(request) {
2423
2437
  lines.push("4. Address remaining manual review items");
2424
2438
  lines.push("5. Use `fix_recommendation` tool for detailed guidance on manual items");
2425
2439
  resultText = lines.join("\n");
2440
+ recordActivity(projectPath, {
2441
+ source: "mcp",
2442
+ action: "fix",
2443
+ title: `MCP auto-fix ${dryRun ? "planned" : "applied"}: ${applied} fixes`,
2444
+ description: `${dryRun ? "Planned" : "Applied"} ${applied} fix(es)${failed > 0 ? ` (${failed} failed)` : ""}. Scanned ${scannedFiles} files, ${findings.length} findings found.`,
2445
+ status: failed > 0 ? "partial" : "success",
2446
+ details: { fixes_applied: applied, findings_count: findings.length },
2447
+ });
2426
2448
  break;
2427
2449
  }
2428
2450
  case "apply_control_override": {
@@ -2471,6 +2493,13 @@ export function handleRequest(request) {
2471
2493
  `\nRun \`ges audit\` then \`ges score\` to see the updated compliance score.`,
2472
2494
  ];
2473
2495
  resultText = lines.join("\n");
2496
+ recordActivity(projectPath, {
2497
+ source: "mcp",
2498
+ action: "control_override",
2499
+ title: `Control ${controlId} → ${status}`,
2500
+ description: `MCP applied override: control ${controlId} set to ${status}. Reason: ${reason || "(none)"}`,
2501
+ details: { controls_affected: [controlId] },
2502
+ });
2474
2503
  break;
2475
2504
  }
2476
2505
  case "implement_control": {
@@ -2536,18 +2565,27 @@ export function handleRequest(request) {
2536
2565
  break;
2537
2566
  }
2538
2567
  lines.push(`**Control**: ${plan.name}\n`);
2568
+ let appliedCount = 0;
2569
+ let skippedCount = 0;
2539
2570
  for (const action of plan.actions) {
2540
2571
  const result = applyAutoFixAction(projectPath, action);
2541
2572
  if (result.applied) {
2573
+ appliedCount++;
2542
2574
  lines.push(`- ✓ [${action.type}] ${action.filePath}: ${action.description}`);
2543
2575
  }
2544
2576
  else if (result.error === "File already exists") {
2577
+ skippedCount++;
2545
2578
  lines.push(`- → [${action.type}] ${action.filePath}: Already exists (skipped)`);
2546
2579
  }
2547
2580
  else {
2548
2581
  lines.push(`- ✗ [${action.type}] ${action.filePath}: ${result.error}`);
2549
2582
  }
2550
2583
  }
2584
+ if (appliedCount > 0 || skippedCount > 0) {
2585
+ saveControlOverride(projectPath, controlId, "pass", `Auto-implemented by GESF (${plan.name})`);
2586
+ lines.push(`\n✅ Control **${controlId}** marked as **pass** in .ges/control-overrides.json`);
2587
+ lines.push(` The dashboard will reflect this immediately.`);
2588
+ }
2551
2589
  const npmInstalls = getNpmInstallsFromActions(plan.actions);
2552
2590
  if (npmInstalls.length > 0) {
2553
2591
  lines.push(`\n## Install Dependencies\n`);
@@ -2564,8 +2602,14 @@ export function handleRequest(request) {
2564
2602
  lines.push("1. Install any npm packages listed above");
2565
2603
  lines.push("2. Import and integrate the generated files into your app");
2566
2604
  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`);
2568
2605
  resultText = lines.join("\n");
2606
+ recordActivity(projectPath, {
2607
+ source: "mcp",
2608
+ action: "implement_control",
2609
+ title: `Control implemented: ${controlId} (${plan.name})`,
2610
+ description: `Auto-implemented control ${controlId} (${plan.name}). ${appliedCount} actions applied, ${skippedCount} skipped. Control marked as pass.`,
2611
+ details: { controls_affected: [controlId], files_created: plan.actions.filter(a => a.type === "create").map(a => a.filePath) },
2612
+ });
2569
2613
  break;
2570
2614
  }
2571
2615
  case "generate_badge": {
@@ -2725,6 +2769,13 @@ export function handleRequest(request) {
2725
2769
  lines.push(`3. Run \`ges badge\` to generate a compliance badge for README`);
2726
2770
  lines.push(`4. Review and customize documents in compliance/ and security/`);
2727
2771
  resultText = lines.join("\n");
2772
+ recordActivity(projectPath, {
2773
+ source: "mcp",
2774
+ action: "init",
2775
+ title: `Project initialized: ${projectName}`,
2776
+ description: `Initialized GESF for ${projectType} project with frameworks: ${frameworks.join(", ")}. Installed ${packs.length} policy packs.`,
2777
+ details: { packs_affected: packs.map(p => p.id), frameworks_added: frameworks.map(f => String(f)) },
2778
+ });
2728
2779
  break;
2729
2780
  }
2730
2781
  case "run_scans": {
@@ -2755,6 +2806,13 @@ export function handleRequest(request) {
2755
2806
  lines.push(`\n**${failed.length} scanner(s) reported failures.** Review findings above.`);
2756
2807
  }
2757
2808
  resultText = lines.join("\n");
2809
+ recordActivity(projectPath, {
2810
+ source: "mcp",
2811
+ action: "scan",
2812
+ title: `MCP security scans completed (${results.length} tools)`,
2813
+ description: `Ran ${results.length} scanner(s) for ${ecosystemDetail} ecosystem. ${results.filter(r => r.status === "pass").length} passed, ${failed.length} failed.`,
2814
+ status: failed.length > 0 ? "partial" : "success",
2815
+ });
2758
2816
  break;
2759
2817
  }
2760
2818
  case "doctor": {
@@ -2889,6 +2947,13 @@ export function handleRequest(request) {
2889
2947
  }
2890
2948
  lines.push(hasErrors ? "\n❌ **Validation failed.** Fix the issues above." : "\n✅ **All validations passed.**");
2891
2949
  resultText = lines.join("\n");
2950
+ recordActivity(projectPath, {
2951
+ source: "mcp",
2952
+ action: "validate",
2953
+ title: `MCP validation ${hasErrors ? "failed" : "passed"}`,
2954
+ description: hasErrors ? "Configuration or directory structure has issues." : "All validations passed.",
2955
+ status: hasErrors ? "failed" : "success",
2956
+ });
2892
2957
  break;
2893
2958
  }
2894
2959
  case "policy_list": {
@@ -2924,7 +2989,23 @@ export function handleRequest(request) {
2924
2989
  const packDir = path.join(projectPath, CONTROLS_DIR, pack.id);
2925
2990
  fs.mkdirSync(packDir, { recursive: true });
2926
2991
  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`;
2992
+ const addedToConfig = addFrameworkToConfig(projectPath, pack.id.toUpperCase());
2993
+ const lines = [
2994
+ `✅ Installed policy pack: **${pack.id}** (${pack.name})`,
2995
+ `${pack.controls.length} controls written to ${CONTROLS_DIR}/${pack.id}/controls.json`,
2996
+ ];
2997
+ if (addedToConfig) {
2998
+ lines.push(`Added ${pack.id.toUpperCase()} to project frameworks in .ges/config.json`);
2999
+ }
3000
+ lines.push(`The web dashboard will now reflect this pack's controls.`);
3001
+ resultText = lines.join("\n");
3002
+ recordActivity(projectPath, {
3003
+ source: "mcp",
3004
+ action: "policy_install",
3005
+ title: `MCP installed pack: ${pack.name}`,
3006
+ description: `Installed ${pack.controls.length} controls from ${pack.id} pack.${addedToConfig ? ` Added ${pack.id.toUpperCase()} to config frameworks.` : ""}`,
3007
+ details: { packs_affected: [pack.id], frameworks_added: addedToConfig ? [pack.id.toUpperCase()] : [] },
3008
+ });
2928
3009
  break;
2929
3010
  }
2930
3011
  case "policy_remove": {
@@ -2940,7 +3021,15 @@ export function handleRequest(request) {
2940
3021
  break;
2941
3022
  }
2942
3023
  fs.rmSync(packDir, { recursive: true, force: true });
3024
+ removeFrameworkFromConfig(projectPath, packId.toUpperCase());
2943
3025
  resultText = `✅ Removed policy pack: **${packId}** from ${projectPath}`;
3026
+ recordActivity(projectPath, {
3027
+ source: "mcp",
3028
+ action: "policy_remove",
3029
+ title: `MCP removed pack: ${packId}`,
3030
+ description: `Removed ${packId} pack and its controls from the project.`,
3031
+ details: { packs_affected: [packId] },
3032
+ });
2944
3033
  break;
2945
3034
  }
2946
3035
  case "update_check": {
@@ -2991,6 +3080,12 @@ export function handleRequest(request) {
2991
3080
  fs.writeFileSync(hookPath, hookContent);
2992
3081
  fs.chmodSync(hookPath, 0o755);
2993
3082
  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"`;
3083
+ recordActivity(projectPath, {
3084
+ source: "mcp",
3085
+ action: "hooks_install",
3086
+ title: `MCP installed pre-commit hook`,
3087
+ description: `Installed pre-commit hook that runs 'ges audit --ci' before each commit.`,
3088
+ });
2994
3089
  break;
2995
3090
  }
2996
3091
  case "start_dashboard": {
@@ -3029,6 +3124,12 @@ export function handleRequest(request) {
3029
3124
  lines.push(`- Control status matrix`);
3030
3125
  lines.push(`- Audit history timeline`);
3031
3126
  resultText = lines.join("\n");
3127
+ recordActivity(projectPath, {
3128
+ source: "mcp",
3129
+ action: "dashboard_start",
3130
+ title: `Dashboard started on ${host}:${port}`,
3131
+ description: `Web dashboard is running at http://${host}:${port}`,
3132
+ });
3032
3133
  }
3033
3134
  catch (err) {
3034
3135
  const msg = err instanceof Error ? err.message : String(err);
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.5",
7
+ "@greenarmor/ges-cicd-generator": "1.2.5",
8
+ "@greenarmor/ges-compliance-engine": "1.2.5",
9
+ "@greenarmor/ges-core": "1.2.5",
10
+ "@greenarmor/ges-doc-generator": "1.2.5",
11
+ "@greenarmor/ges-policy-engine": "1.2.5",
12
+ "@greenarmor/ges-report-generator": "1.2.5",
13
+ "@greenarmor/ges-rules-engine": "1.2.5",
14
+ "@greenarmor/ges-scanner-integration": "1.2.5",
15
+ "@greenarmor/ges-scoring-engine": "1.2.5",
16
+ "@greenarmor/ges-web-dashboard": "1.2.5"
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.5",
71
71
  "scripts": {
72
72
  "build": "tsc",
73
73
  "clean": "rm -rf dist bundle tsconfig.tsbuildinfo",