@greenarmor/ges-mcp-server 1.2.0 → 1.2.2
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/dist/server.d.ts +1 -0
- package/dist/server.js +116 -23
- package/package.json +13 -12
package/dist/server.d.ts
CHANGED
package/dist/server.js
CHANGED
|
@@ -8,10 +8,22 @@ const HT = ["http", "//"].join(":");
|
|
|
8
8
|
import { generateScoreFile, formatScoreOutput, computeGrade, generateBadgeSvg, injectBadgeIntoReadme, generateScoreExplainer } from "@greenarmor/ges-scoring-engine";
|
|
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
|
+
import { appendFixHistory, createFixHistoryEntry } from "@greenarmor/ges-core";
|
|
11
12
|
import { ProjectConfigSchema } from "@greenarmor/ges-core";
|
|
12
13
|
import { generateComplianceDocs, generateSecurityDocs, generateConfigJson, generateMetadataJson, generateFrameworkVersionJson, generateScoreJson } from "@greenarmor/ges-doc-generator";
|
|
13
14
|
import { generateAllWorkflows } from "@greenarmor/ges-cicd-generator";
|
|
14
15
|
import { detectProject, runAllScansWithSbom, formatScanResults, formatSbomResults } from "@greenarmor/ges-scanner-integration";
|
|
16
|
+
import { startDashboard } from "@greenarmor/ges-web-dashboard";
|
|
17
|
+
let activeDashboardServer = null;
|
|
18
|
+
export function stopDashboardServer() {
|
|
19
|
+
if (activeDashboardServer) {
|
|
20
|
+
try {
|
|
21
|
+
activeDashboardServer.close();
|
|
22
|
+
}
|
|
23
|
+
catch { /* ignore */ }
|
|
24
|
+
activeDashboardServer = null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
15
27
|
const TOOLS = [
|
|
16
28
|
{
|
|
17
29
|
name: "check_compliance",
|
|
@@ -2130,6 +2142,21 @@ export function handleRequest(request) {
|
|
|
2130
2142
|
const overriddenControls = applyControlOverrides(controls, projectConfig.overrides);
|
|
2131
2143
|
const auditedControls = updateControlsFromFindings(overriddenControls, findings);
|
|
2132
2144
|
const score = generateScoreFile(auditedControls, frameworks, findings);
|
|
2145
|
+
try {
|
|
2146
|
+
fs.writeFileSync(path.join(projectPath, ".ges", "last-audit.json"), JSON.stringify({
|
|
2147
|
+
findings, scannedFiles, timestamp: new Date().toISOString(),
|
|
2148
|
+
}, null, 2));
|
|
2149
|
+
fs.writeFileSync(path.join(projectPath, ".ges", "score.json"), JSON.stringify(score, null, 2));
|
|
2150
|
+
const metaPath = path.join(projectPath, ".ges", "metadata.json");
|
|
2151
|
+
let meta = {};
|
|
2152
|
+
try {
|
|
2153
|
+
meta = JSON.parse(fs.readFileSync(metaPath, "utf-8"));
|
|
2154
|
+
}
|
|
2155
|
+
catch { /* ignore */ }
|
|
2156
|
+
meta.last_audit = new Date().toISOString();
|
|
2157
|
+
fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2));
|
|
2158
|
+
}
|
|
2159
|
+
catch { /* ignore persistence errors */ }
|
|
2133
2160
|
const critical = findings.filter(f => f.severity === "critical");
|
|
2134
2161
|
const high = findings.filter(f => f.severity === "high");
|
|
2135
2162
|
const medium = findings.filter(f => f.severity === "medium");
|
|
@@ -2260,6 +2287,12 @@ export function handleRequest(request) {
|
|
|
2260
2287
|
}
|
|
2261
2288
|
const { findings: rawFindings, scannedFiles } = runAudit(projectPath);
|
|
2262
2289
|
const findings = deduplicateFindings(rawFindings);
|
|
2290
|
+
try {
|
|
2291
|
+
fs.writeFileSync(path.join(projectPath, ".ges", "last-audit.json"), JSON.stringify({
|
|
2292
|
+
findings, scannedFiles, timestamp: new Date().toISOString(),
|
|
2293
|
+
}, null, 2));
|
|
2294
|
+
}
|
|
2295
|
+
catch { /* ignore persistence errors */ }
|
|
2263
2296
|
if (findings.length === 0) {
|
|
2264
2297
|
resultText = `# Auto-Fix Report\n\n**Project**: ${projectPath}\n**Scanned**: ${scannedFiles} files\n\nNo issues found. Project is clean!`;
|
|
2265
2298
|
break;
|
|
@@ -2282,6 +2315,18 @@ export function handleRequest(request) {
|
|
|
2282
2315
|
resultText = lines.join("\n");
|
|
2283
2316
|
break;
|
|
2284
2317
|
}
|
|
2318
|
+
let projectControls = [];
|
|
2319
|
+
try {
|
|
2320
|
+
const configPath = path.join(projectPath, ".ges", "config.json");
|
|
2321
|
+
if (fs.existsSync(configPath)) {
|
|
2322
|
+
const cfg = JSON.parse(fs.readFileSync(configPath, "utf-8"));
|
|
2323
|
+
const fwLower = new Set(cfg.frameworks.map((f) => f.toLowerCase()));
|
|
2324
|
+
const allPacks = getAllPacks();
|
|
2325
|
+
const filtered = allPacks.filter((pack) => fwLower.has(pack.id.toLowerCase()));
|
|
2326
|
+
projectControls = filtered.flatMap((p) => p.controls);
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
catch { /* ignore */ }
|
|
2285
2330
|
const npmInstalls = getNpmInstallsFromActions(actions);
|
|
2286
2331
|
const lines = [
|
|
2287
2332
|
`# Auto-Fix Report\n`,
|
|
@@ -2300,10 +2345,28 @@ export function handleRequest(request) {
|
|
|
2300
2345
|
}
|
|
2301
2346
|
let applied = 0;
|
|
2302
2347
|
let failed = 0;
|
|
2348
|
+
const historyEntries = [];
|
|
2303
2349
|
for (const action of actions) {
|
|
2350
|
+
const matchingFindings = findings.filter(f => f.ruleId === action.ruleId);
|
|
2351
|
+
const primaryFinding = matchingFindings[0];
|
|
2352
|
+
const matchedControls = primaryFinding
|
|
2353
|
+
? projectControls.filter((c) => primaryFinding.controlIds.includes(c.id))
|
|
2354
|
+
: [];
|
|
2304
2355
|
if (dryRun) {
|
|
2305
2356
|
lines.push(`- [${action.type}] ${action.filePath}: ${action.description}`);
|
|
2306
2357
|
applied++;
|
|
2358
|
+
historyEntries.push(createFixHistoryEntry({
|
|
2359
|
+
source: "mcp",
|
|
2360
|
+
dry_run: true,
|
|
2361
|
+
finding: primaryFinding ?? {
|
|
2362
|
+
ruleId: action.ruleId, severity: "medium", category: "",
|
|
2363
|
+
title: action.description, file: "", evidence: "",
|
|
2364
|
+
description: action.description, controlIds: [], fix: action.description,
|
|
2365
|
+
},
|
|
2366
|
+
action,
|
|
2367
|
+
controls: matchedControls,
|
|
2368
|
+
applied: false,
|
|
2369
|
+
}));
|
|
2307
2370
|
}
|
|
2308
2371
|
else {
|
|
2309
2372
|
const result = applyAutoFixAction(projectPath, action);
|
|
@@ -2315,10 +2378,29 @@ export function handleRequest(request) {
|
|
|
2315
2378
|
failed++;
|
|
2316
2379
|
lines.push(`- ✗ [${action.type}] ${action.filePath}: ${action.description} — ${result.error}`);
|
|
2317
2380
|
}
|
|
2381
|
+
historyEntries.push(createFixHistoryEntry({
|
|
2382
|
+
source: "mcp",
|
|
2383
|
+
dry_run: false,
|
|
2384
|
+
finding: primaryFinding ?? {
|
|
2385
|
+
ruleId: action.ruleId, severity: "medium", category: "",
|
|
2386
|
+
title: action.description, file: "", evidence: "",
|
|
2387
|
+
description: action.description, controlIds: [], fix: action.description,
|
|
2388
|
+
},
|
|
2389
|
+
action,
|
|
2390
|
+
controls: matchedControls,
|
|
2391
|
+
applied: result.applied,
|
|
2392
|
+
error: result.applied ? undefined : result.error,
|
|
2393
|
+
}));
|
|
2318
2394
|
}
|
|
2319
2395
|
}
|
|
2396
|
+
if (historyEntries.length > 0 && !dryRun) {
|
|
2397
|
+
appendFixHistory(projectPath, historyEntries);
|
|
2398
|
+
}
|
|
2320
2399
|
lines.push(`\n## Summary\n`);
|
|
2321
2400
|
lines.push(`- Actions applied: ${applied}${failed > 0 ? ` (${failed} failed)` : ""}`);
|
|
2401
|
+
if (!dryRun && historyEntries.length > 0) {
|
|
2402
|
+
lines.push(`- Fix history recorded in .ges/fix-history.json`);
|
|
2403
|
+
}
|
|
2322
2404
|
if (npmInstalls.length > 0) {
|
|
2323
2405
|
lines.push(`\n## npm Packages to Install\n`);
|
|
2324
2406
|
lines.push("```bash");
|
|
@@ -2913,34 +2995,45 @@ export function handleRequest(request) {
|
|
|
2913
2995
|
}
|
|
2914
2996
|
case "start_dashboard": {
|
|
2915
2997
|
const projectPath = resolveProjectPath(args.project_path);
|
|
2916
|
-
const port = args.port || 3001;
|
|
2998
|
+
const port = typeof args.port === "string" ? parseInt(args.port, 10) : (args.port || 3001);
|
|
2917
2999
|
const host = args.host || "localhost";
|
|
2918
3000
|
if (!fs.existsSync(path.join(projectPath, ".ges"))) {
|
|
2919
3001
|
resultText = `GESF not initialized at ${projectPath}. Run 'init_project' first.`;
|
|
2920
3002
|
break;
|
|
2921
3003
|
}
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
3004
|
+
if (activeDashboardServer) {
|
|
3005
|
+
try {
|
|
3006
|
+
activeDashboardServer.close();
|
|
3007
|
+
}
|
|
3008
|
+
catch { /* ignore close errors */ }
|
|
3009
|
+
activeDashboardServer = null;
|
|
3010
|
+
}
|
|
3011
|
+
try {
|
|
3012
|
+
const server = startDashboard({ port, host, projectPath });
|
|
3013
|
+
activeDashboardServer = server;
|
|
3014
|
+
const proto = ["http", "//"].join(":");
|
|
3015
|
+
const lines = [];
|
|
3016
|
+
lines.push(`# GESF Web Dashboard — Running\n`);
|
|
3017
|
+
lines.push(`**Project**: ${projectPath}`);
|
|
3018
|
+
lines.push(`**Host**: ${host}`);
|
|
3019
|
+
lines.push(`**Port**: ${port}\n`);
|
|
3020
|
+
lines.push(`Dashboard server started successfully.\n`);
|
|
3021
|
+
lines.push(`## Endpoints\n`);
|
|
3022
|
+
lines.push(`- **Dashboard UI**: ${proto}${host}:${port}`);
|
|
3023
|
+
lines.push(`- **JSON API**: ${proto}${host}:${port}/api/data`);
|
|
3024
|
+
lines.push(`- **Health Check**: ${proto}${host}:${port}/health\n`);
|
|
3025
|
+
lines.push(`## Features`);
|
|
3026
|
+
lines.push(`- Visual compliance score overview`);
|
|
3027
|
+
lines.push(`- Per-framework breakdown with grades`);
|
|
3028
|
+
lines.push(`- Security findings list`);
|
|
3029
|
+
lines.push(`- Control status matrix`);
|
|
3030
|
+
lines.push(`- Audit history timeline`);
|
|
3031
|
+
resultText = lines.join("\n");
|
|
3032
|
+
}
|
|
3033
|
+
catch (err) {
|
|
3034
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
3035
|
+
resultText = `Failed to start dashboard: ${msg}\n\nMake sure port ${port} is available. Try a different port.`;
|
|
3036
|
+
}
|
|
2944
3037
|
break;
|
|
2945
3038
|
}
|
|
2946
3039
|
default:
|
package/package.json
CHANGED
|
@@ -3,21 +3,22 @@
|
|
|
3
3
|
"ges-mcp": "dist/server.js"
|
|
4
4
|
},
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@greenarmor/ges-audit-engine": "1.2.
|
|
7
|
-
"@greenarmor/ges-cicd-generator": "1.2.
|
|
8
|
-
"@greenarmor/ges-compliance-engine": "1.2.
|
|
9
|
-
"@greenarmor/ges-core": "1.2.
|
|
10
|
-
"@greenarmor/ges-doc-generator": "1.2.
|
|
11
|
-
"@greenarmor/ges-policy-engine": "1.2.
|
|
12
|
-
"@greenarmor/ges-report-generator": "1.2.
|
|
13
|
-
"@greenarmor/ges-rules-engine": "1.2.
|
|
14
|
-
"@greenarmor/ges-scanner-integration": "1.2.
|
|
15
|
-
"@greenarmor/ges-scoring-engine": "1.2.
|
|
6
|
+
"@greenarmor/ges-audit-engine": "1.2.2",
|
|
7
|
+
"@greenarmor/ges-cicd-generator": "1.2.2",
|
|
8
|
+
"@greenarmor/ges-compliance-engine": "1.2.2",
|
|
9
|
+
"@greenarmor/ges-core": "1.2.2",
|
|
10
|
+
"@greenarmor/ges-doc-generator": "1.2.2",
|
|
11
|
+
"@greenarmor/ges-policy-engine": "1.2.2",
|
|
12
|
+
"@greenarmor/ges-report-generator": "1.2.2",
|
|
13
|
+
"@greenarmor/ges-rules-engine": "1.2.2",
|
|
14
|
+
"@greenarmor/ges-scanner-integration": "1.2.2",
|
|
15
|
+
"@greenarmor/ges-scoring-engine": "1.2.2",
|
|
16
|
+
"@greenarmor/ges-web-dashboard": "1.2.2"
|
|
16
17
|
},
|
|
17
18
|
"description": "GESF MCP Server - AI Compliance Assistant for GDPR, OWASP, NIST, CIS. Check compliance, generate policies, assess risks via MCP protocol.",
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@types/node": "^22.0.0",
|
|
20
|
-
"esbuild": "^0.28.
|
|
21
|
+
"esbuild": "^0.28.1",
|
|
21
22
|
"typescript": "^6.0.0",
|
|
22
23
|
"vitest": "^4.1.8"
|
|
23
24
|
},
|
|
@@ -66,7 +67,7 @@
|
|
|
66
67
|
},
|
|
67
68
|
"type": "module",
|
|
68
69
|
"types": "./dist/index.d.ts",
|
|
69
|
-
"version": "1.2.
|
|
70
|
+
"version": "1.2.2",
|
|
70
71
|
"scripts": {
|
|
71
72
|
"build": "tsc",
|
|
72
73
|
"clean": "rm -rf dist bundle tsconfig.tsbuildinfo",
|