agent-mcp-guard 0.4.5 → 0.4.7

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/README.md CHANGED
@@ -19,7 +19,7 @@ Live demo PR: [mcp-guard-demo#1](https://github.com/ChaoYue0307/mcp-guard-demo/p
19
19
  <a href="https://github.com/marketplace/actions/mcp-guard-mcp-security-scanner"><img alt="GitHub Marketplace" src="https://img.shields.io/badge/Marketplace-mcp--guard-0f766e?logo=github"></a>
20
20
  <a href="https://github.com/ChaoYue0307/mcp-guard/actions"><img alt="CI" src="https://github.com/ChaoYue0307/mcp-guard/actions/workflows/ci.yml/badge.svg"></a>
21
21
  <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-111827"></a>
22
- <a href="https://github.com/ChaoYue0307/mcp-guard/releases/tag/v0.4.5"><img alt="Release" src="https://img.shields.io/github/v/release/ChaoYue0307/mcp-guard?color=7c2d12"></a>
22
+ <a href="https://github.com/ChaoYue0307/mcp-guard/releases/tag/v0.4.7"><img alt="Release" src="https://img.shields.io/github/v/release/ChaoYue0307/mcp-guard?color=7c2d12"></a>
23
23
  </p>
24
24
 
25
25
  ## Install
@@ -93,7 +93,7 @@ mcp-guard scan --config .mcp.json --baseline .mcp-guard-baseline.json --fail-on
93
93
  Use the GitHub Action:
94
94
 
95
95
  ```yaml
96
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
96
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
97
97
  with:
98
98
  config: .mcp.json
99
99
  # policy: .mcp-guard-policy.json
@@ -116,6 +116,7 @@ Use the transparent example to evaluate what the scanner actually does:
116
116
  - generated SARIF report: [site/e2e/report.sarif](site/e2e/report.sarif)
117
117
  - generated audit summary: [site/e2e/audit/mcp-guard-executive-summary.md](site/e2e/audit/mcp-guard-executive-summary.md)
118
118
  - generated remediation plan: [site/e2e/audit/mcp-guard-remediation.md](site/e2e/audit/mcp-guard-remediation.md)
119
+ - generated remediation checklist: [site/e2e/audit/mcp-guard-remediation-checklist.md](site/e2e/audit/mcp-guard-remediation-checklist.md)
119
120
 
120
121
  The example scans 3 MCP servers and reports 9 active findings with a risk score of 98. It is synthetic, but fully reproducible from committed files.
121
122
 
@@ -149,8 +150,9 @@ For paid setup or internal review handoff, `mcp-guard audit` writes a complete e
149
150
 
150
151
  - executive summary;
151
152
  - remediation plan grouped by MCP server;
153
+ - remediation checklist for PR or handoff tracking;
152
154
  - Markdown, HTML, JSON, and SARIF reports;
153
- - machine-readable audit manifest.
155
+ - machine-readable audit manifest with artifact hashes.
154
156
 
155
157
  For stricter governance, commit `.mcp-guard-policy.json` and define the commands, remote packages, filesystem roots, and remote MCP endpoints the team has approved. See [Policy files](docs/policy.md).
156
158
 
package/action.yml CHANGED
@@ -63,6 +63,9 @@ outputs:
63
63
  remediation-report:
64
64
  description: Path to the generated remediation plan.
65
65
  value: ${{ steps.reports.outputs.remediation-report }}
66
+ remediation-checklist:
67
+ description: Path to the generated remediation checklist.
68
+ value: ${{ steps.reports.outputs.remediation-checklist }}
66
69
  audit-manifest:
67
70
  description: Path to the generated audit pack manifest.
68
71
  value: ${{ steps.reports.outputs.audit-manifest }}
@@ -114,6 +117,7 @@ runs:
114
117
  sarif_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard.sarif"
115
118
  executive_summary="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-executive-summary.md"
116
119
  remediation_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-remediation.md"
120
+ remediation_checklist="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-remediation-checklist.md"
117
121
  audit_manifest="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-audit-manifest.json"
118
122
  comment_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-pr-comment.md"
119
123
 
@@ -133,6 +137,7 @@ runs:
133
137
  "${MCP_GUARD_FAIL_ON}" \
134
138
  "${executive_summary}" \
135
139
  "${remediation_report}" \
140
+ "${remediation_checklist}" \
136
141
  "${audit_manifest}" > "${comment_report}"
137
142
 
138
143
  {
@@ -142,6 +147,7 @@ runs:
142
147
  echo "json-report=${json_report}"
143
148
  echo "sarif-report=${sarif_report}"
144
149
  echo "remediation-report=${remediation_report}"
150
+ echo "remediation-checklist=${remediation_checklist}"
145
151
  echo "audit-manifest=${audit_manifest}"
146
152
  echo "comment-report=${comment_report}"
147
153
  echo "exit-code=${status}"
@@ -161,6 +167,7 @@ runs:
161
167
  "${MCP_GUARD_FAIL_ON}" \
162
168
  "${{ steps.reports.outputs.executive-summary }}" \
163
169
  "${{ steps.reports.outputs.remediation-report }}" \
170
+ "${{ steps.reports.outputs.remediation-checklist }}" \
164
171
  "${{ steps.reports.outputs.audit-manifest }}" >> "${GITHUB_STEP_SUMMARY}"
165
172
 
166
173
  - name: Comment on pull request
package/docs/audit.md CHANGED
@@ -32,19 +32,22 @@ mcp-guard audit --config .mcp.json --fail-on high
32
32
  | --- | --- |
33
33
  | `mcp-guard-executive-summary.md` | Short decision summary for founders, security leads, and engineering managers. |
34
34
  | `mcp-guard-remediation.md` | Server-by-server remediation plan with evidence and fixes. |
35
+ | `mcp-guard-remediation-checklist.md` | Checkbox-based remediation tasks for PRs, paid setup handoff, or internal tracking. |
35
36
  | `mcp-guard-report.md` | Full Markdown scan report. |
36
37
  | `mcp-guard-report.html` | Readable HTML report for review artifacts. |
37
38
  | `mcp-guard-report.json` | Redacted machine-readable report for automation. |
38
39
  | `mcp-guard.sarif` | SARIF 2.1.0 report for GitHub code scanning. |
39
- | `mcp-guard-audit-manifest.json` | Manifest listing status, summary, policy/baseline context, and file paths. |
40
+ | `mcp-guard-audit-manifest.json` | Manifest listing status, summary, policy/baseline context, file paths, SHA-256 hashes, and artifact sizes. |
40
41
 
41
42
  ## Review Flow
42
43
 
43
44
  1. Run `mcp-guard audit` locally or through the GitHub Action.
44
45
  2. Open `mcp-guard-executive-summary.md` to decide whether the MCP setup is acceptable.
45
46
  3. Work through `mcp-guard-remediation.md` with the engineering team.
46
- 4. Use `mcp-guard-report.html` for readable evidence and `mcp-guard-report.json` or `mcp-guard.sarif` for automation.
47
- 5. Commit a reviewed policy and baseline only after the team has decided what risk is intentionally accepted.
47
+ 4. Track concrete work in `mcp-guard-remediation-checklist.md`.
48
+ 5. Use `mcp-guard-report.html` for readable evidence and `mcp-guard-report.json` or `mcp-guard.sarif` for automation.
49
+ 6. Use the `integrity.artifacts` section in `mcp-guard-audit-manifest.json` when you need to prove an audit artifact has not changed.
50
+ 7. Commit a reviewed policy and baseline only after the team has decided what risk is intentionally accepted.
48
51
 
49
52
  ## Privacy
50
53
 
package/docs/baseline.md CHANGED
@@ -30,7 +30,7 @@ If the scan finds only baseline-accepted findings, the exit code is `0`. If a ne
30
30
  ## GitHub Action
31
31
 
32
32
  ```yaml
33
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
33
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
34
34
  with:
35
35
  config: .mcp.json
36
36
  baseline: .mcp-guard-baseline.json
@@ -45,7 +45,7 @@ The generated Markdown, HTML, JSON, and PR comment separate active findings from
45
45
  {
46
46
  "version": 1,
47
47
  "generatedAt": "2026-05-10T00:00:00.000Z",
48
- "toolVersion": "0.4.5",
48
+ "toolVersion": "0.4.7",
49
49
  "findings": [
50
50
  {
51
51
  "fingerprint": "mcpg_a009b2c2",
@@ -17,7 +17,7 @@ Deliverables:
17
17
  - install the CLI and GitHub Action;
18
18
  - run `mcp-guard init` or generate an equivalent workflow manually;
19
19
  - generate Markdown, HTML, JSON, and SARIF reports;
20
- - generate a customer handoff audit pack with executive summary, remediation plan, reports, and manifest;
20
+ - generate a customer handoff audit pack with executive summary, remediation plan, remediation checklist, reports, and hashed manifest;
21
21
  - define an initial `.mcp-guard-policy.json` for approved commands, packages, directories, and remote URLs;
22
22
  - create an initial baseline for accepted known findings;
23
23
  - enable PR comments and optional SARIF upload;
@@ -54,6 +54,7 @@ Important findings include:
54
54
  - [SARIF report](../../site/e2e/report.sarif)
55
55
  - [Audit executive summary](../../site/e2e/audit/mcp-guard-executive-summary.md)
56
56
  - [Audit remediation plan](../../site/e2e/audit/mcp-guard-remediation.md)
57
+ - [Audit remediation checklist](../../site/e2e/audit/mcp-guard-remediation-checklist.md)
57
58
  - [Audit manifest](../../site/e2e/audit/mcp-guard-audit-manifest.json)
58
59
 
59
60
  ## What This Proves
@@ -61,4 +62,4 @@ Important findings include:
61
62
  - The scanner does not need the config to leave the machine.
62
63
  - Secret-like values are redacted in reports.
63
64
  - Findings include rule IDs, severity, evidence, and remediation guidance.
64
- - The same scan can feed a human-readable HTML report, automation JSON, GitHub code scanning SARIF, and a review-ready audit handoff package.
65
+ - The same scan can feed a human-readable HTML report, automation JSON, GitHub code scanning SARIF, and a review-ready audit handoff package with a remediation checklist.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Use the `mcp-guard` action to scan MCP and AI agent tool configuration in pull requests and CI.
4
4
 
5
- The action runs the CLI from the pinned GitHub Action tag, generates an audit pack with Markdown, HTML, JSON, SARIF, remediation, and manifest files, writes a job summary, uploads reports as an artifact, and fails the job when findings meet your selected severity threshold.
5
+ The action runs the CLI from the pinned GitHub Action tag, generates an audit pack with Markdown, HTML, JSON, SARIF, remediation, checklist, and hashed manifest files, writes a job summary, uploads reports as an artifact, and fails the job when findings meet your selected severity threshold.
6
6
 
7
7
  It can also use a committed baseline to accept known findings, enforce a committed policy file, and optionally post a pull request comment with only the active findings.
8
8
 
@@ -37,7 +37,7 @@ jobs:
37
37
  runs-on: ubuntu-latest
38
38
  steps:
39
39
  - uses: actions/checkout@v6
40
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
40
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
41
41
  with:
42
42
  config: .mcp.json
43
43
  fail-on: high
@@ -65,7 +65,7 @@ jobs:
65
65
  runs-on: ubuntu-latest
66
66
  steps:
67
67
  - uses: actions/checkout@v6
68
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
68
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
69
69
  with:
70
70
  config: .mcp.json
71
71
  fail-on: high
@@ -77,7 +77,7 @@ jobs:
77
77
  Use `fail-on: none` when you want artifacts and summaries without blocking a pull request.
78
78
 
79
79
  ```yaml
80
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
80
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
81
81
  with:
82
82
  fail-on: none
83
83
  ```
@@ -93,7 +93,7 @@ mcp-guard scan --config .mcp.json --write-baseline .mcp-guard-baseline.json
93
93
  Commit `.mcp-guard-baseline.json`, then reference it from the action:
94
94
 
95
95
  ```yaml
96
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
96
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
97
97
  with:
98
98
  config: .mcp.json
99
99
  baseline: .mcp-guard-baseline.json
@@ -107,7 +107,7 @@ Reports will show active findings separately from findings accepted by the basel
107
107
  Use a policy when you want CI to enforce approved commands, packages, directories, and remote URLs.
108
108
 
109
109
  ```yaml
110
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
110
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
111
111
  with:
112
112
  config: .mcp.json
113
113
  policy: .mcp-guard-policy.json
@@ -140,6 +140,7 @@ See [Policy files](policy.md) for the file format.
140
140
  | `json-report` | Path to the generated JSON report. |
141
141
  | `sarif-report` | Path to the generated SARIF report. |
142
142
  | `remediation-report` | Path to the generated remediation plan. |
143
+ | `remediation-checklist` | Path to the generated remediation checklist. |
143
144
  | `audit-manifest` | Path to the generated audit pack manifest. |
144
145
  | `comment-report` | Path to the generated pull request comment body. |
145
146
  | `exit-code` | `0` when below threshold, `2` when findings met the threshold. |
@@ -37,7 +37,7 @@ mcp-guard audit --config .mcp.json --policy .mcp-guard-policy.json --output-dir
37
37
  ## GitHub Action Setup
38
38
 
39
39
  ```yaml
40
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
40
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
41
41
  with:
42
42
  config: .mcp.json
43
43
  baseline: .mcp-guard-baseline.json
@@ -23,7 +23,7 @@ jobs:
23
23
  runs-on: ubuntu-latest
24
24
  steps:
25
25
  - uses: actions/checkout@v6
26
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
26
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
27
27
  with:
28
28
  config: .mcp.json
29
29
  fail-on: high
@@ -42,7 +42,7 @@ jobs:
42
42
  runs-on: ubuntu-latest
43
43
  steps:
44
44
  - uses: actions/checkout@v6
45
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
45
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
46
46
  with:
47
47
  config: .mcp.json
48
48
  fail-on: high
@@ -73,6 +73,7 @@ jobs:
73
73
  | `json-report` | Path to the generated JSON report. |
74
74
  | `sarif-report` | Path to the generated SARIF report. |
75
75
  | `remediation-report` | Path to the generated remediation plan. |
76
+ | `remediation-checklist` | Path to the generated remediation checklist. |
76
77
  | `audit-manifest` | Path to the generated audit pack manifest. |
77
78
  | `comment-report` | Path to the generated pull request comment body. |
78
79
  | `exit-code` | `0` when below threshold, `2` when findings met the threshold. |
@@ -86,7 +87,8 @@ The action generates an audit pack:
86
87
  - JSON for automation.
87
88
  - SARIF 2.1.0 for GitHub code scanning.
88
89
  - Remediation Markdown for server-by-server handoff.
89
- - Audit manifest JSON for downstream automation.
90
+ - Remediation checklist for PR and setup tracking.
91
+ - Audit manifest JSON with SHA-256 hashes and byte sizes for downstream automation.
90
92
 
91
93
  Secret-like values are redacted before reports are written.
92
94
 
@@ -101,7 +103,7 @@ mcp-guard scan --config .mcp.json --write-baseline .mcp-guard-baseline.json
101
103
  Then enforce only new findings:
102
104
 
103
105
  ```yaml
104
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
106
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
105
107
  with:
106
108
  config: .mcp.json
107
109
  baseline: .mcp-guard-baseline.json
@@ -113,7 +115,7 @@ Then enforce only new findings:
113
115
  Commit `.mcp-guard-policy.json` or pass `policy` to enforce approved commands, remote packages, directories, and remote MCP URLs.
114
116
 
115
117
  ```yaml
116
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
118
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
117
119
  with:
118
120
  config: .mcp.json
119
121
  policy: .mcp-guard-policy.json
@@ -82,17 +82,17 @@ Code quality
82
82
  Current release title:
83
83
 
84
84
  ```text
85
- v0.4.5
85
+ v0.4.7
86
86
  ```
87
87
 
88
88
  Release notes:
89
89
 
90
90
  ```text
91
- Audit pack release.
91
+ Audit integrity release.
92
92
 
93
- - Adds `mcp-guard audit` for executive summary, remediation plan, Markdown, HTML, JSON, SARIF, and manifest outputs.
94
- - The GitHub Action now uploads audit pack artifacts, including remediation and manifest files.
95
- - Keeps policy enforcement, baseline support, PR comments, artifacts, and SARIF upload support.
93
+ - Adds SHA-256 checksums and byte sizes for generated audit artifacts in `mcp-guard-audit-manifest.json`.
94
+ - Keeps remediation checklist, first remediation steps in PR comments, executive summary, remediation plan, Markdown, HTML, JSON, SARIF, policy, baseline, artifacts, and SARIF upload support.
95
+ - Improves paid setup and internal review handoff by making generated evidence easier to verify after delivery.
96
96
  ```
97
97
 
98
98
  ## Manual Publishing Steps
@@ -105,7 +105,7 @@ Completed:
105
105
  - README, docs, and website examples now use:
106
106
 
107
107
  ```yaml
108
- - uses: ChaoYue0307/mcp-guard-action@v0.4.5
108
+ - uses: ChaoYue0307/mcp-guard-action@v0.4.7
109
109
  ```
110
110
 
111
111
  Remaining Marketplace web step:
@@ -13,7 +13,7 @@ It is not currently advertised as an active consulting service. Keep public webs
13
13
  ## Deliverables
14
14
 
15
15
  - MCP and agent tool inventory.
16
- - `mcp-guard audit` evidence pack with executive summary, remediation plan, reports, and manifest.
16
+ - `mcp-guard audit` evidence pack with executive summary, remediation plan, remediation checklist, reports, and hashed manifest.
17
17
  - Risk report covering shell access, package execution, filesystem scope, secrets, remote servers, and dangerous commands.
18
18
  - Practical remediation checklist.
19
19
  - Optional PR with safer config and policy changes.
package/docs/roadmap.md CHANGED
@@ -13,7 +13,7 @@
13
13
  - Optional GitHub pull request comments from the Marketplace Action.
14
14
  - `mcp-guard init` for bootstrapping a GitHub Action workflow and optional baseline.
15
15
  - Policy file enforcement for approved commands, packages, directories, and remote URLs.
16
- - `mcp-guard audit` for review-ready executive summaries, remediation plans, reports, and manifests.
16
+ - `mcp-guard audit` for review-ready executive summaries, remediation plans, remediation checklists, reports, and hashed manifests.
17
17
  - npm Trusted Publishing workflow prepared for tokenless release publishing.
18
18
 
19
19
  ## Next
@@ -36,7 +36,7 @@ Configure this once on npmjs.com:
36
36
  After this is saved, run the workflow from GitHub Actions with the release tag, for example:
37
37
 
38
38
  ```text
39
- v0.4.5
39
+ v0.4.7
40
40
  ```
41
41
 
42
42
  ## Release Flow After Setup
@@ -44,7 +44,7 @@ v0.4.5
44
44
  1. Update `package.json` and `src/cli.js`.
45
45
  2. Run `npm test` and `npm run release:check`.
46
46
  3. Commit and push to `main`.
47
- 4. Create a GitHub release tag such as `v0.4.5`.
47
+ 4. Create a GitHub release tag such as `v0.4.7`.
48
48
  5. Run the `Publish npm` workflow with the same tag.
49
49
  6. Verify npm:
50
50
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-mcp-guard",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Open-source CLI scanner for risky MCP server and AI agent tool configuration.",
5
5
  "type": "module",
6
6
  "homepage": "https://chaoyue0307.github.io/mcp-guard/",
@@ -3,10 +3,17 @@
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
 
6
- const [jsonReportPath, markdownReportPath, htmlReportPath, sarifReportPath, failOn, executiveSummaryPath, remediationReportPath, auditManifestPath] = process.argv.slice(2);
6
+ const [jsonReportPath, markdownReportPath, htmlReportPath, sarifReportPath, failOn, executiveSummaryPath, remediationReportPath, maybeRemediationChecklistPath, maybeAuditManifestPath] = process.argv.slice(2);
7
+ let remediationChecklistPath = maybeRemediationChecklistPath;
8
+ let auditManifestPath = maybeAuditManifestPath;
9
+
10
+ if (!auditManifestPath && remediationChecklistPath && path.basename(remediationChecklistPath) === "mcp-guard-audit-manifest.json") {
11
+ auditManifestPath = remediationChecklistPath;
12
+ remediationChecklistPath = "";
13
+ }
7
14
 
8
15
  if (!jsonReportPath) {
9
- process.stderr.write("Usage: action-comment.js <json-report> <markdown-report> <html-report> <sarif-report> <fail-on> [executive-summary] [remediation-report] [audit-manifest]\n");
16
+ process.stderr.write("Usage: action-comment.js <json-report> <markdown-report> <html-report> <sarif-report> <fail-on> [executive-summary] [remediation-report] [remediation-checklist] [audit-manifest]\n");
10
17
  process.exit(1);
11
18
  }
12
19
 
@@ -52,6 +59,12 @@ if (findings.length === 0) {
52
59
  for (const finding of findings.slice(0, 6)) {
53
60
  lines.push(`| ${cell(finding.severity)} | ${cell(finding.id)} | ${cell(finding.serverName)} | ${cell(finding.title)} |`);
54
61
  }
62
+ lines.push("");
63
+ lines.push("### First remediation steps");
64
+ lines.push("");
65
+ for (const finding of findings.slice(0, 5)) {
66
+ lines.push(`- [ ] **${cell(finding.severity)} ${cell(finding.id)}** \`${cell(finding.serverName)}\`: ${cell(finding.recommendation)}`);
67
+ }
55
68
  }
56
69
 
57
70
  lines.push("");
@@ -67,6 +80,9 @@ if (executiveSummaryPath) {
67
80
  if (remediationReportPath) {
68
81
  lines.push(`- Remediation: \`${relative(remediationReportPath)}\``);
69
82
  }
83
+ if (remediationChecklistPath) {
84
+ lines.push(`- Remediation checklist: \`${relative(remediationChecklistPath)}\``);
85
+ }
70
86
  if (auditManifestPath) {
71
87
  lines.push(`- Audit manifest: \`${relative(auditManifestPath)}\``);
72
88
  }
@@ -3,10 +3,17 @@
3
3
  import fs from "node:fs";
4
4
  import path from "node:path";
5
5
 
6
- const [jsonReportPath, markdownReportPath, htmlReportPath, sarifReportPath, failOn, executiveSummaryPath, remediationReportPath, auditManifestPath] = process.argv.slice(2);
6
+ const [jsonReportPath, markdownReportPath, htmlReportPath, sarifReportPath, failOn, executiveSummaryPath, remediationReportPath, maybeRemediationChecklistPath, maybeAuditManifestPath] = process.argv.slice(2);
7
+ let remediationChecklistPath = maybeRemediationChecklistPath;
8
+ let auditManifestPath = maybeAuditManifestPath;
9
+
10
+ if (!auditManifestPath && remediationChecklistPath && path.basename(remediationChecklistPath) === "mcp-guard-audit-manifest.json") {
11
+ auditManifestPath = remediationChecklistPath;
12
+ remediationChecklistPath = "";
13
+ }
7
14
 
8
15
  if (!jsonReportPath) {
9
- process.stderr.write("Usage: action-summary.js <json-report> <markdown-report> <html-report> <sarif-report> <fail-on> [executive-summary] [remediation-report] [audit-manifest]\n");
16
+ process.stderr.write("Usage: action-summary.js <json-report> <markdown-report> <html-report> <sarif-report> <fail-on> [executive-summary] [remediation-report] [remediation-checklist] [audit-manifest]\n");
10
17
  process.exit(1);
11
18
  }
12
19
 
@@ -51,6 +58,15 @@ if (topFindings.length === 0) {
51
58
  }
52
59
  }
53
60
 
61
+ if (topFindings.length > 0) {
62
+ lines.push("");
63
+ lines.push("### First remediation steps");
64
+ lines.push("");
65
+ for (const finding of topFindings.slice(0, 5)) {
66
+ lines.push(`- [ ] **${cell(finding.severity)} ${cell(finding.id)}** \`${cell(finding.serverName)}\`: ${cell(finding.recommendation)}`);
67
+ }
68
+ }
69
+
54
70
  lines.push("");
55
71
  lines.push("### Reports");
56
72
  lines.push("");
@@ -64,6 +80,9 @@ if (executiveSummaryPath) {
64
80
  if (remediationReportPath) {
65
81
  lines.push(`- Remediation: \`${relative(remediationReportPath)}\``);
66
82
  }
83
+ if (remediationChecklistPath) {
84
+ lines.push(`- Remediation checklist: \`${relative(remediationChecklistPath)}\``);
85
+ }
67
86
  if (auditManifestPath) {
68
87
  lines.push(`- Audit manifest: \`${relative(auditManifestPath)}\``);
69
88
  }
@@ -2,9 +2,9 @@
2
2
  "version": 1,
3
3
  "tool": {
4
4
  "name": "mcp-guard",
5
- "version": "0.4.5"
5
+ "version": "0.4.7"
6
6
  },
7
- "generatedAt": "2026-05-10T14:16:23.655Z",
7
+ "generatedAt": "2026-05-10T20:08:00.622Z",
8
8
  "status": "needs_review",
9
9
  "failOn": "none",
10
10
  "outputDir": "site/e2e/audit",
@@ -30,10 +30,58 @@
30
30
  "files": {
31
31
  "executiveSummary": "site/e2e/audit/mcp-guard-executive-summary.md",
32
32
  "remediation": "site/e2e/audit/mcp-guard-remediation.md",
33
+ "remediationChecklist": "site/e2e/audit/mcp-guard-remediation-checklist.md",
33
34
  "markdownReport": "site/e2e/audit/mcp-guard-report.md",
34
35
  "htmlReport": "site/e2e/audit/mcp-guard-report.html",
35
36
  "jsonReport": "site/e2e/audit/mcp-guard-report.json",
36
37
  "sarifReport": "site/e2e/audit/mcp-guard.sarif",
37
38
  "manifest": "site/e2e/audit/mcp-guard-audit-manifest.json"
39
+ },
40
+ "integrity": {
41
+ "algorithm": "sha256",
42
+ "artifacts": [
43
+ {
44
+ "key": "executiveSummary",
45
+ "path": "site/e2e/audit/mcp-guard-executive-summary.md",
46
+ "bytes": 1764,
47
+ "sha256": "d4679b3353a25ed4f88479ae2594fa6a7e2b1b61a9455b56a61e10a70131c87e"
48
+ },
49
+ {
50
+ "key": "remediation",
51
+ "path": "site/e2e/audit/mcp-guard-remediation.md",
52
+ "bytes": 2752,
53
+ "sha256": "1a7a83531f9fea7f0dc8a074a378151f1f7e10a713abc93136e0200bb1dbd35a"
54
+ },
55
+ {
56
+ "key": "remediationChecklist",
57
+ "path": "site/e2e/audit/mcp-guard-remediation-checklist.md",
58
+ "bytes": 2056,
59
+ "sha256": "d75a40e9c2f243cf9193e50d6d9fa8c56e2d50950deb2f1cc843e230c002e548"
60
+ },
61
+ {
62
+ "key": "markdownReport",
63
+ "path": "site/e2e/audit/mcp-guard-report.md",
64
+ "bytes": 3297,
65
+ "sha256": "11a09f58c19ebb836ff4da6f75d050b508fc989dd41ea1c31a02dbafc3367317"
66
+ },
67
+ {
68
+ "key": "htmlReport",
69
+ "path": "site/e2e/audit/mcp-guard-report.html",
70
+ "bytes": 12988,
71
+ "sha256": "3f597e3e1423159f2665b5f5c3b754c2eda4df5645cc2707fa872ddb3c9b7a3c"
72
+ },
73
+ {
74
+ "key": "jsonReport",
75
+ "path": "site/e2e/audit/mcp-guard-report.json",
76
+ "bytes": 5938,
77
+ "sha256": "a7b2f086928c1d697c4402b37e84b055a7e12ed2bef55654a19733a80d082947"
78
+ },
79
+ {
80
+ "key": "sarifReport",
81
+ "path": "site/e2e/audit/mcp-guard.sarif",
82
+ "bytes": 20856,
83
+ "sha256": "994c3bd89e616a76c53cd3797f6323001cc11dcb1afd96ddaeeb9d53c6432ee8"
84
+ }
85
+ ]
38
86
  }
39
87
  }
@@ -1,6 +1,6 @@
1
1
  # mcp-guard Executive Summary
2
2
 
3
- Generated: 2026-05-10T14:16:23.655Z
3
+ Generated: 2026-05-10T20:08:00.622Z
4
4
  Status: **Needs review**
5
5
  Risk score: **98**
6
6
  Fail threshold: **none**
@@ -0,0 +1,32 @@
1
+ # mcp-guard Remediation Checklist
2
+
3
+ Generated: 2026-05-10T20:08:00.622Z
4
+ Risk score: **98**
5
+ Active findings: **9**
6
+
7
+ ## Release Gate
8
+
9
+ - [ ] Critical findings are removed or the MCP server is redesigned.
10
+ - [ ] High findings are reviewed before merge or rollout.
11
+ - [ ] Any accepted residual risk is documented in policy or baseline.
12
+
13
+ ## Remediation Tasks
14
+
15
+ | Done | Priority | Rule | Server | Action | Fingerprint |
16
+ | --- | --- | --- | --- | --- | --- |
17
+ | [ ] | critical | MCP010 | shell-installer | Replace the shell wrapper for server `shell-installer` with a direct reviewed executable or checked-in script. | mcpg_c2b742f0 |
18
+ | [ ] | critical | MCP050 | shell-installer | Remove the dangerous startup operation from server `shell-installer` and run setup manually after review. | mcpg_73e1a0da |
19
+ | [ ] | high | MCP021 | filesystem-all-home | Pin and approve the remote package used by server `filesystem-all-home`. | mcpg_7390d900 |
20
+ | [ ] | high | MCP030 | filesystem-all-home | Move credentials for server `filesystem-all-home` out of MCP config and rotate any exposed tokens. | mcpg_73964a76 |
21
+ | [ ] | high | MCP040 | filesystem-all-home | Constrain filesystem access for server `filesystem-all-home` to a reviewed project directory. | mcpg_70425125 |
22
+ | [ ] | high | MCP041 | filesystem-all-home | Constrain filesystem access for server `filesystem-all-home` to a reviewed project directory. | mcpg_eea814c0 |
23
+ | [ ] | high | MCP061 | remote-prod | Move credentials for server `remote-prod` out of MCP config and rotate any exposed tokens. | mcpg_ad4db81f |
24
+ | [ ] | medium | MCP020 | filesystem-all-home | Pin and approve the remote package used by server `filesystem-all-home`. | mcpg_df881ae7 |
25
+ | [ ] | medium | MCP060 | remote-prod | Review and allowlist the remote MCP endpoint used by server `remote-prod`. | mcpg_45117870 |
26
+
27
+ ## Closeout
28
+
29
+ - [ ] Re-run `mcp-guard audit` after changes.
30
+ - [ ] Commit updated `.mcp-guard-policy.json` only for reviewed approvals.
31
+ - [ ] Commit or update `.mcp-guard-baseline.json` only for intentionally accepted findings.
32
+
@@ -1,6 +1,6 @@
1
1
  # mcp-guard Remediation Plan
2
2
 
3
- Generated: 2026-05-10T14:16:23.655Z
3
+ Generated: 2026-05-10T20:08:00.622Z
4
4
 
5
5
  ## Priority
6
6
 
@@ -297,7 +297,7 @@
297
297
  <div class="metric"><strong>1</strong><span>Scanned files</span></div>
298
298
  <div class="metric"><strong>3</strong><span>MCP servers</span></div>
299
299
  <div class="metric"><strong>9</strong><span>Active findings</span></div>
300
- <div class="metric"><strong>2026-05-10 14:16 UTC</strong><span>Generated</span></div>
300
+ <div class="metric"><strong>2026-05-10 20:08 UTC</strong><span>Generated</span></div>
301
301
  </div>
302
302
  </div>
303
303
  <aside class="scorecard" aria-label="Risk score">
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "metadata": {
3
- "generatedAt": "2026-05-10T14:16:23.655Z",
3
+ "generatedAt": "2026-05-10T20:08:00.622Z",
4
4
  "cwd": ".",
5
5
  "home": "~",
6
6
  "policyPath": "",
7
7
  "policyEnabled": false,
8
- "toolVersion": "0.4.5"
8
+ "toolVersion": "0.4.7"
9
9
  },
10
10
  "policy": null,
11
11
  "scannedFiles": [
@@ -1,6 +1,6 @@
1
1
  # mcp-guard Scan Report
2
2
 
3
- Generated: 2026-05-10T14:16:23.655Z
3
+ Generated: 2026-05-10T20:08:00.622Z
4
4
 
5
5
  ## Summary
6
6
 
@@ -7,7 +7,7 @@
7
7
  "driver": {
8
8
  "name": "mcp-guard",
9
9
  "informationUri": "https://github.com/ChaoYue0307/mcp-guard",
10
- "semanticVersion": "0.4.5",
10
+ "semanticVersion": "0.4.7",
11
11
  "rules": [
12
12
  {
13
13
  "id": "MCP010",
@@ -89,6 +89,7 @@ node ./bin/mcp-guard.js audit --config site/e2e/claude_desktop_config.json --out
89
89
  <a href="report.sarif">SARIF report</a>
90
90
  <a href="audit/mcp-guard-executive-summary.md">Audit summary</a>
91
91
  <a href="audit/mcp-guard-remediation.md">Remediation plan</a>
92
+ <a href="audit/mcp-guard-remediation-checklist.md">Remediation checklist</a>
92
93
  <a href="audit/mcp-guard-audit-manifest.json">Audit manifest</a>
93
94
  <h2>Output summary</h2>
94
95
  <ul>
@@ -297,7 +297,7 @@
297
297
  <div class="metric"><strong>1</strong><span>Scanned files</span></div>
298
298
  <div class="metric"><strong>3</strong><span>MCP servers</span></div>
299
299
  <div class="metric"><strong>9</strong><span>Active findings</span></div>
300
- <div class="metric"><strong>2026-05-10 14:16 UTC</strong><span>Generated</span></div>
300
+ <div class="metric"><strong>2026-05-10 20:07 UTC</strong><span>Generated</span></div>
301
301
  </div>
302
302
  </div>
303
303
  <aside class="scorecard" aria-label="Risk score">
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "metadata": {
3
- "generatedAt": "2026-05-10T14:16:12.688Z",
3
+ "generatedAt": "2026-05-10T20:07:57.237Z",
4
4
  "cwd": ".",
5
5
  "home": "~",
6
6
  "policyPath": "",
7
7
  "policyEnabled": false,
8
- "toolVersion": "0.4.5"
8
+ "toolVersion": "0.4.7"
9
9
  },
10
10
  "policy": null,
11
11
  "scannedFiles": [
@@ -1,6 +1,6 @@
1
1
  # mcp-guard Scan Report
2
2
 
3
- Generated: 2026-05-10T14:16:12.639Z
3
+ Generated: 2026-05-10T20:07:52.252Z
4
4
 
5
5
  ## Summary
6
6
 
@@ -7,7 +7,7 @@
7
7
  "driver": {
8
8
  "name": "mcp-guard",
9
9
  "informationUri": "https://github.com/ChaoYue0307/mcp-guard",
10
- "semanticVersion": "0.4.5",
10
+ "semanticVersion": "0.4.7",
11
11
  "rules": [
12
12
  {
13
13
  "id": "MCP010",
package/src/audit.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import fs from "node:fs/promises";
2
+ import crypto from "node:crypto";
2
3
  import path from "node:path";
3
4
  import { applyBaseline, loadBaselineFile } from "./baseline.js";
4
5
  import { displayPath } from "./fingerprint.js";
@@ -8,6 +9,7 @@ import { scan } from "./scan.js";
8
9
  export const AUDIT_FILENAMES = {
9
10
  executiveSummary: "mcp-guard-executive-summary.md",
10
11
  remediation: "mcp-guard-remediation.md",
12
+ remediationChecklist: "mcp-guard-remediation-checklist.md",
11
13
  markdownReport: "mcp-guard-report.md",
12
14
  htmlReport: "mcp-guard-report.html",
13
15
  jsonReport: "mcp-guard-report.json",
@@ -43,20 +45,23 @@ export async function writeAuditPack({
43
45
 
44
46
  await fs.mkdir(resolvedOutputDir, { recursive: true });
45
47
 
46
- const manifest = buildAuditManifest(result, files, {
47
- cwd,
48
- outputDir: resolvedOutputDir,
49
- failOn
50
- });
51
-
52
48
  await Promise.all([
53
49
  fs.writeFile(files.executiveSummary, generateExecutiveSummary(result, { failOn }), "utf8"),
54
50
  fs.writeFile(files.remediation, generateRemediationPlan(result), "utf8"),
51
+ fs.writeFile(files.remediationChecklist, generateRemediationChecklist(result), "utf8"),
55
52
  fs.writeFile(files.markdownReport, generateMarkdownReport(result), "utf8"),
56
53
  fs.writeFile(files.htmlReport, generateHtmlReport(result), "utf8"),
57
54
  fs.writeFile(files.jsonReport, `${generateJsonReport(result)}\n`, "utf8"),
58
55
  fs.writeFile(files.sarifReport, `${generateSarifReport(result)}\n`, "utf8")
59
56
  ]);
57
+
58
+ const artifacts = await auditArtifacts(files, cwd);
59
+ const manifest = buildAuditManifest(result, files, {
60
+ cwd,
61
+ outputDir: resolvedOutputDir,
62
+ failOn,
63
+ artifacts
64
+ });
60
65
  await fs.writeFile(files.manifest, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
61
66
 
62
67
  return {
@@ -199,7 +204,52 @@ function generateRemediationPlan(result) {
199
204
  return `${lines.join("\n")}\n`;
200
205
  }
201
206
 
202
- function buildAuditManifest(result, files, { cwd, outputDir, failOn }) {
207
+ function generateRemediationChecklist(result) {
208
+ const lines = [];
209
+ lines.push("# mcp-guard Remediation Checklist");
210
+ lines.push("");
211
+ lines.push(`Generated: ${result.metadata.generatedAt}`);
212
+ lines.push(`Risk score: **${result.summary.riskScore}**`);
213
+ lines.push(`Active findings: **${result.summary.findingCount}**`);
214
+ lines.push("");
215
+ lines.push("## Release Gate");
216
+ lines.push("");
217
+ lines.push("- [ ] Critical findings are removed or the MCP server is redesigned.");
218
+ lines.push("- [ ] High findings are reviewed before merge or rollout.");
219
+ lines.push("- [ ] Any accepted residual risk is documented in policy or baseline.");
220
+ lines.push("");
221
+ lines.push("## Remediation Tasks");
222
+ lines.push("");
223
+ if (result.findings.length === 0) {
224
+ lines.push("No active remediation tasks.");
225
+ } else {
226
+ lines.push("| Done | Priority | Rule | Server | Action | Fingerprint |");
227
+ lines.push("| --- | --- | --- | --- | --- | --- |");
228
+ for (const finding of result.findings) {
229
+ lines.push(`| [ ] | ${cell(finding.severity)} | ${cell(finding.id)} | ${cell(finding.serverName)} | ${cell(remediationAction(finding))} | ${cell(finding.fingerprint)} |`);
230
+ }
231
+ }
232
+ lines.push("");
233
+ if (result.acceptedFindings?.length > 0) {
234
+ lines.push("## Accepted Risk Review");
235
+ lines.push("");
236
+ lines.push("| Reviewed | Rule | Server | Reason | Fingerprint |");
237
+ lines.push("| --- | --- | --- | --- | --- |");
238
+ for (const finding of result.acceptedFindings) {
239
+ lines.push(`| [ ] | ${cell(finding.id)} | ${cell(finding.serverName)} | ${cell(finding.acceptedReason || "-")} | ${cell(finding.fingerprint)} |`);
240
+ }
241
+ lines.push("");
242
+ }
243
+ lines.push("## Closeout");
244
+ lines.push("");
245
+ lines.push("- [ ] Re-run `mcp-guard audit` after changes.");
246
+ lines.push("- [ ] Commit updated `.mcp-guard-policy.json` only for reviewed approvals.");
247
+ lines.push("- [ ] Commit or update `.mcp-guard-baseline.json` only for intentionally accepted findings.");
248
+ lines.push("");
249
+ return `${lines.join("\n")}\n`;
250
+ }
251
+
252
+ function buildAuditManifest(result, files, { cwd, outputDir, failOn, artifacts }) {
203
253
  return {
204
254
  version: 1,
205
255
  tool: {
@@ -221,10 +271,29 @@ function buildAuditManifest(result, files, { cwd, outputDir, failOn }) {
221
271
  baseline: result.baseline || { enabled: false },
222
272
  files: Object.fromEntries(
223
273
  Object.entries(files).map(([key, filePath]) => [key, displayPath(filePath, cwd)])
224
- )
274
+ ),
275
+ integrity: {
276
+ algorithm: "sha256",
277
+ artifacts
278
+ }
225
279
  };
226
280
  }
227
281
 
282
+ async function auditArtifacts(files, cwd) {
283
+ const artifacts = [];
284
+ for (const [key, filePath] of Object.entries(files)) {
285
+ if (key === "manifest") continue;
286
+ const content = await fs.readFile(filePath);
287
+ artifacts.push({
288
+ key,
289
+ path: displayPath(filePath, cwd),
290
+ bytes: content.byteLength,
291
+ sha256: crypto.createHash("sha256").update(content).digest("hex")
292
+ });
293
+ }
294
+ return artifacts;
295
+ }
296
+
228
297
  function decisionGuidance(result) {
229
298
  if (result.findings.length === 0) {
230
299
  return ["No active findings were detected. Continue reviewing new MCP servers before adding them."];
@@ -273,6 +342,38 @@ function remediationPriorities(findings) {
273
342
  return items.length > 0 ? items : ["Review each active finding and document the accepted remediation path."];
274
343
  }
275
344
 
345
+ function remediationAction(finding) {
346
+ const server = finding.serverName === "<workspace>" || finding.serverName === "<config>"
347
+ ? "this config"
348
+ : `server \`${finding.serverName}\``;
349
+
350
+ if (finding.id === "MCP010") {
351
+ return `Replace the shell wrapper for ${server} with a direct reviewed executable or checked-in script.`;
352
+ }
353
+ if (finding.id === "MCP011") {
354
+ return `Move inline eval code for ${server} into reviewed source control.`;
355
+ }
356
+ if (finding.id === "MCP020" || finding.id === "MCP021" || finding.id === "MCP071") {
357
+ return `Pin and approve the remote package used by ${server}.`;
358
+ }
359
+ if (finding.id === "MCP030" || finding.id === "MCP061") {
360
+ return `Move credentials for ${server} out of MCP config and rotate any exposed tokens.`;
361
+ }
362
+ if (finding.id === "MCP040" || finding.id === "MCP041" || finding.id === "MCP072" || finding.id === "MCP073") {
363
+ return `Constrain filesystem access for ${server} to a reviewed project directory.`;
364
+ }
365
+ if (finding.id === "MCP050") {
366
+ return `Remove the dangerous startup operation from ${server} and run setup manually after review.`;
367
+ }
368
+ if (finding.id === "MCP060" || finding.id === "MCP074") {
369
+ return `Review and allowlist the remote MCP endpoint used by ${server}.`;
370
+ }
371
+ if (finding.id === "MCP070") {
372
+ return `Use an approved command for ${server} or update policy after review.`;
373
+ }
374
+ return finding.recommendation;
375
+ }
376
+
276
377
  function groupFindingsByServer(findings) {
277
378
  const groups = new Map();
278
379
  for (const finding of findings) {
@@ -287,6 +388,7 @@ function auditFileLabels(files) {
287
388
  return [
288
389
  ["Executive summary", files.executiveSummary],
289
390
  ["Remediation plan", files.remediation],
391
+ ["Remediation checklist", files.remediationChecklist],
290
392
  ["Markdown report", files.markdownReport],
291
393
  ["HTML report", files.htmlReport],
292
394
  ["JSON report", files.jsonReport],
package/src/cli.js CHANGED
@@ -7,7 +7,7 @@ import { scan } from "./scan.js";
7
7
  import { generateHtmlReport, generateJsonReport, generateMarkdownReport, generateSarifReport, generateTextReport } from "./report.js";
8
8
  import { compareSeverity, severityRank } from "./severity.js";
9
9
 
10
- const VERSION = "0.4.5";
10
+ const VERSION = "0.4.7";
11
11
 
12
12
  export async function runCli(argv, io) {
13
13
  const args = argv.slice(2);