agent-mcp-guard 0.3.0 → 0.4.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.
- package/README.md +50 -10
- package/action.yml +61 -1
- package/docs/baseline.md +70 -0
- package/docs/business-playbook.md +15 -14
- package/docs/examples/e2e-example.md +60 -0
- package/docs/github-action.md +33 -3
- package/docs/launch-checklist.md +14 -1
- package/docs/marketplace-action-readme.md +121 -0
- package/docs/marketplace.md +121 -0
- package/docs/operator-runbook.md +1 -1
- package/docs/paid-audit.md +6 -4
- package/docs/roadmap.md +4 -2
- package/examples/sample-report.md +15 -15
- package/package.json +5 -1
- package/scripts/action-comment.js +72 -0
- package/scripts/action-summary.js +7 -3
- package/scripts/prepare-marketplace-action.js +74 -0
- package/site/e2e/claude_desktop_config.json +28 -0
- package/site/e2e/index.html +107 -0
- package/site/e2e/report.html +451 -0
- package/site/e2e/report.json +173 -0
- package/site/e2e/report.md +47 -0
- package/site/e2e/report.sarif +570 -0
- package/src/baseline.js +162 -0
- package/src/cli.js +35 -5
- package/src/fingerprint.js +33 -0
- package/src/report.js +112 -42
- package/src/scan.js +8 -24
package/README.md
CHANGED
|
@@ -10,11 +10,16 @@ Local-first security scanning for MCP and AI agent tool configs.
|
|
|
10
10
|
|
|
11
11
|
Website: [chaoyue0307.github.io/mcp-guard](https://chaoyue0307.github.io/mcp-guard/)
|
|
12
12
|
|
|
13
|
+
Marketplace: [mcp-guard MCP Security Scanner](https://github.com/marketplace/actions/mcp-guard-mcp-security-scanner)
|
|
14
|
+
|
|
15
|
+
Live demo PR: [mcp-guard-demo#1](https://github.com/ChaoYue0307/mcp-guard-demo/pull/1)
|
|
16
|
+
|
|
13
17
|
<p>
|
|
14
18
|
<a href="https://www.npmjs.com/package/agent-mcp-guard"><img alt="npm version" src="https://img.shields.io/npm/v/agent-mcp-guard?color=0f766e"></a>
|
|
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>
|
|
15
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>
|
|
16
21
|
<a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-Apache--2.0-111827"></a>
|
|
17
|
-
<a href="https://github.com/ChaoYue0307/mcp-guard/releases/tag/v0.
|
|
22
|
+
<a href="https://github.com/ChaoYue0307/mcp-guard/releases/tag/v0.4.0"><img alt="Release" src="https://img.shields.io/github/v/release/ChaoYue0307/mcp-guard?color=7c2d12"></a>
|
|
18
23
|
</p>
|
|
19
24
|
|
|
20
25
|
## Install
|
|
@@ -54,15 +59,41 @@ Use in CI:
|
|
|
54
59
|
mcp-guard scan --config .mcp.json --fail-on high
|
|
55
60
|
```
|
|
56
61
|
|
|
62
|
+
Accept known findings and fail only on new risk:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
mcp-guard scan --config .mcp.json --write-baseline .mcp-guard-baseline.json
|
|
66
|
+
mcp-guard scan --config .mcp.json --baseline .mcp-guard-baseline.json --fail-on high
|
|
67
|
+
```
|
|
68
|
+
|
|
57
69
|
Use the GitHub Action:
|
|
58
70
|
|
|
59
71
|
```yaml
|
|
60
|
-
- uses: ChaoYue0307/mcp-guard@v0.
|
|
72
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
61
73
|
with:
|
|
74
|
+
config: .mcp.json
|
|
75
|
+
baseline: .mcp-guard-baseline.json
|
|
62
76
|
fail-on: high
|
|
77
|
+
comment-pr: "true"
|
|
63
78
|
upload-sarif: "true"
|
|
64
79
|
```
|
|
65
80
|
|
|
81
|
+
Inspect the live demo pull request: [ChaoYue0307/mcp-guard-demo#1](https://github.com/ChaoYue0307/mcp-guard-demo/pull/1). It intentionally introduces risky MCP config so the Action fails, uploads reports, and sends SARIF to GitHub code scanning.
|
|
82
|
+
|
|
83
|
+
## End-to-End Example
|
|
84
|
+
|
|
85
|
+
Use the transparent example to evaluate what the scanner actually does:
|
|
86
|
+
|
|
87
|
+
- input config: [site/e2e/claude_desktop_config.json](site/e2e/claude_desktop_config.json)
|
|
88
|
+
- generated Markdown report: [site/e2e/report.md](site/e2e/report.md)
|
|
89
|
+
- generated HTML report: [site/e2e/report.html](site/e2e/report.html)
|
|
90
|
+
- generated JSON report: [site/e2e/report.json](site/e2e/report.json)
|
|
91
|
+
- generated SARIF report: [site/e2e/report.sarif](site/e2e/report.sarif)
|
|
92
|
+
|
|
93
|
+
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.
|
|
94
|
+
|
|
95
|
+
For the GitHub Action workflow, inspect the public demo repository: [ChaoYue0307/mcp-guard-demo](https://github.com/ChaoYue0307/mcp-guard-demo).
|
|
96
|
+
|
|
66
97
|
## What It Finds
|
|
67
98
|
|
|
68
99
|
| Risk | Why it matters |
|
|
@@ -75,13 +106,24 @@ Use the GitHub Action:
|
|
|
75
106
|
| Remote MCP URLs | Data may leave the local trust boundary. |
|
|
76
107
|
| Dangerous command patterns | `rm -rf`, `sudo`, `chmod 777`, and curl-pipe-shell should block review. |
|
|
77
108
|
|
|
109
|
+
## Team Workflow
|
|
110
|
+
|
|
111
|
+
`mcp-guard` now supports a baseline/allowlist workflow for real teams:
|
|
112
|
+
|
|
113
|
+
1. Generate a baseline from already-known findings.
|
|
114
|
+
2. Commit the baseline file after review.
|
|
115
|
+
3. Run CI with `--baseline` so accepted findings are visible but do not fail the build.
|
|
116
|
+
4. Fail pull requests only when new high-risk MCP changes appear.
|
|
117
|
+
|
|
118
|
+
The GitHub Action can also post an optional pull request comment with the active finding summary.
|
|
119
|
+
|
|
78
120
|
## Example Output
|
|
79
121
|
|
|
80
122
|
```text
|
|
81
123
|
mcp-guard scan report
|
|
82
124
|
Scanned files: 1
|
|
83
125
|
MCP servers: 3
|
|
84
|
-
|
|
126
|
+
Active findings: 9
|
|
85
127
|
Risk score: 98
|
|
86
128
|
Critical: 2 High: 5 Medium: 2 Low: 0
|
|
87
129
|
|
|
@@ -121,24 +163,22 @@ MCP configs often contain sensitive local paths, internal hostnames, tokens, and
|
|
|
121
163
|
- secret-like values redacted in reports;
|
|
122
164
|
- text, Markdown, HTML, JSON, and SARIF output for local review, CI artifacts, and GitHub code scanning.
|
|
123
165
|
|
|
124
|
-
##
|
|
166
|
+
## Early Access and Feedback
|
|
125
167
|
|
|
126
|
-
|
|
168
|
+
Want to try `mcp-guard` on a real AI agent or MCP setup?
|
|
127
169
|
|
|
128
|
-
|
|
170
|
+
The project is currently an automated local scanner. I am collecting early users, real-world config examples, CI setup feedback, baseline workflow feedback, and rule requests to improve coverage.
|
|
129
171
|
|
|
130
172
|
Contact: [hechaoyue0307@gmail.com](mailto:hechaoyue0307@gmail.com)
|
|
131
173
|
|
|
132
|
-
Service details: [docs/paid-audit.md](docs/paid-audit.md)
|
|
133
|
-
|
|
134
174
|
## Documentation
|
|
135
175
|
|
|
136
176
|
- [Rule reference](docs/rules.md)
|
|
177
|
+
- [Baseline and allowlist](docs/baseline.md)
|
|
137
178
|
- [GitHub Action](docs/github-action.md)
|
|
179
|
+
- [Marketplace publishing plan](docs/marketplace.md)
|
|
138
180
|
- [Privacy and security](docs/privacy-and-security.md)
|
|
139
181
|
- [Roadmap](docs/roadmap.md)
|
|
140
|
-
- [Business playbook](docs/business-playbook.md)
|
|
141
|
-
- [Launch checklist](docs/launch-checklist.md)
|
|
142
182
|
- [Operator runbook](docs/operator-runbook.md)
|
|
143
183
|
|
|
144
184
|
## Exit Codes
|
package/action.yml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
name: mcp-guard
|
|
1
|
+
name: mcp-guard MCP Security Scanner
|
|
2
2
|
description: Scan MCP and AI agent tool configuration for risky commands, secrets, and broad permissions.
|
|
3
3
|
author: mcp-guard
|
|
4
4
|
|
|
@@ -15,6 +15,14 @@ inputs:
|
|
|
15
15
|
description: Fail the workflow when a finding is at least this severity. Use critical, high, medium, low, or none.
|
|
16
16
|
required: false
|
|
17
17
|
default: high
|
|
18
|
+
baseline:
|
|
19
|
+
description: Optional mcp-guard baseline/allowlist JSON path. Matching findings are accepted and do not fail the workflow.
|
|
20
|
+
required: false
|
|
21
|
+
default: ""
|
|
22
|
+
comment-pr:
|
|
23
|
+
description: "Post or update a pull request comment with the scan summary. Requires pull-requests: write permission."
|
|
24
|
+
required: false
|
|
25
|
+
default: "false"
|
|
18
26
|
output-dir:
|
|
19
27
|
description: Directory where reports will be written.
|
|
20
28
|
required: false
|
|
@@ -48,6 +56,9 @@ outputs:
|
|
|
48
56
|
exit-code:
|
|
49
57
|
description: mcp-guard threshold exit code.
|
|
50
58
|
value: ${{ steps.reports.outputs.exit-code }}
|
|
59
|
+
comment-report:
|
|
60
|
+
description: Path to the generated pull request comment body.
|
|
61
|
+
value: ${{ steps.reports.outputs.comment-report }}
|
|
51
62
|
|
|
52
63
|
runs:
|
|
53
64
|
using: composite
|
|
@@ -62,6 +73,7 @@ runs:
|
|
|
62
73
|
shell: bash
|
|
63
74
|
env:
|
|
64
75
|
MCP_GUARD_CONFIG: ${{ inputs.config }}
|
|
76
|
+
MCP_GUARD_BASELINE: ${{ inputs.baseline }}
|
|
65
77
|
MCP_GUARD_FAIL_ON: ${{ inputs.fail-on }}
|
|
66
78
|
MCP_GUARD_OUTPUT_DIR: ${{ inputs.output-dir }}
|
|
67
79
|
run: |
|
|
@@ -74,16 +86,26 @@ runs:
|
|
|
74
86
|
if [ -n "${MCP_GUARD_CONFIG}" ]; then
|
|
75
87
|
scan_args+=(--config "${MCP_GUARD_CONFIG}")
|
|
76
88
|
fi
|
|
89
|
+
if [ -n "${MCP_GUARD_BASELINE}" ]; then
|
|
90
|
+
scan_args+=(--baseline "${MCP_GUARD_BASELINE}")
|
|
91
|
+
fi
|
|
77
92
|
|
|
78
93
|
markdown_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-report.md"
|
|
79
94
|
html_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-report.html"
|
|
80
95
|
json_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-report.json"
|
|
81
96
|
sarif_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard.sarif"
|
|
97
|
+
comment_report="${MCP_GUARD_OUTPUT_DIR}/mcp-guard-pr-comment.md"
|
|
82
98
|
|
|
83
99
|
node "${guard_bin}" scan "${scan_args[@]}" --format markdown --output "${markdown_report}" --fail-on none
|
|
84
100
|
node "${guard_bin}" scan "${scan_args[@]}" --format html --output "${html_report}" --fail-on none
|
|
85
101
|
node "${guard_bin}" scan "${scan_args[@]}" --format json --output "${json_report}" --fail-on none
|
|
86
102
|
node "${guard_bin}" scan "${scan_args[@]}" --format sarif --output "${sarif_report}" --fail-on none
|
|
103
|
+
node "${GITHUB_ACTION_PATH}/scripts/action-comment.js" \
|
|
104
|
+
"${json_report}" \
|
|
105
|
+
"${markdown_report}" \
|
|
106
|
+
"${html_report}" \
|
|
107
|
+
"${sarif_report}" \
|
|
108
|
+
"${MCP_GUARD_FAIL_ON}" > "${comment_report}"
|
|
87
109
|
|
|
88
110
|
set +e
|
|
89
111
|
node "${guard_bin}" scan "${scan_args[@]}" --fail-on "${MCP_GUARD_FAIL_ON}"
|
|
@@ -95,6 +117,7 @@ runs:
|
|
|
95
117
|
echo "html-report=${html_report}"
|
|
96
118
|
echo "json-report=${json_report}"
|
|
97
119
|
echo "sarif-report=${sarif_report}"
|
|
120
|
+
echo "comment-report=${comment_report}"
|
|
98
121
|
echo "exit-code=${status}"
|
|
99
122
|
} >> "${GITHUB_OUTPUT}"
|
|
100
123
|
|
|
@@ -111,6 +134,43 @@ runs:
|
|
|
111
134
|
"${{ steps.reports.outputs.sarif-report }}" \
|
|
112
135
|
"${MCP_GUARD_FAIL_ON}" >> "${GITHUB_STEP_SUMMARY}"
|
|
113
136
|
|
|
137
|
+
- name: Comment on pull request
|
|
138
|
+
if: ${{ always() && inputs.comment-pr == 'true' && github.event_name == 'pull_request' && steps.reports.outputs.comment-report != '' }}
|
|
139
|
+
uses: actions/github-script@v7
|
|
140
|
+
env:
|
|
141
|
+
MCP_GUARD_COMMENT_PATH: ${{ steps.reports.outputs.comment-report }}
|
|
142
|
+
with:
|
|
143
|
+
script: |
|
|
144
|
+
const fs = require('fs');
|
|
145
|
+
const marker = '<!-- mcp-guard-comment -->';
|
|
146
|
+
const body = fs.readFileSync(process.env.MCP_GUARD_COMMENT_PATH, 'utf8');
|
|
147
|
+
const issue_number = context.payload.pull_request.number;
|
|
148
|
+
const { owner, repo } = context.repo;
|
|
149
|
+
const comments = await github.rest.issues.listComments({
|
|
150
|
+
owner,
|
|
151
|
+
repo,
|
|
152
|
+
issue_number,
|
|
153
|
+
per_page: 100
|
|
154
|
+
});
|
|
155
|
+
const previous = comments.data.find((comment) =>
|
|
156
|
+
comment.user?.type === 'Bot' && comment.body?.includes(marker)
|
|
157
|
+
);
|
|
158
|
+
if (previous) {
|
|
159
|
+
await github.rest.issues.updateComment({
|
|
160
|
+
owner,
|
|
161
|
+
repo,
|
|
162
|
+
comment_id: previous.id,
|
|
163
|
+
body
|
|
164
|
+
});
|
|
165
|
+
} else {
|
|
166
|
+
await github.rest.issues.createComment({
|
|
167
|
+
owner,
|
|
168
|
+
repo,
|
|
169
|
+
issue_number,
|
|
170
|
+
body
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
114
174
|
- name: Upload report artifact
|
|
115
175
|
if: ${{ always() && inputs.upload-artifact == 'true' }}
|
|
116
176
|
uses: actions/upload-artifact@v4
|
package/docs/baseline.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Baseline and Allowlist
|
|
2
|
+
|
|
3
|
+
Use a baseline when a team already has known MCP findings but wants CI to block only new risk.
|
|
4
|
+
|
|
5
|
+
The baseline is local JSON. It stores stable finding fingerprints plus enough context for review. Matching findings are marked as accepted and are excluded from `--fail-on`.
|
|
6
|
+
|
|
7
|
+
## Create a Baseline
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
mcp-guard scan \
|
|
11
|
+
--config .mcp.json \
|
|
12
|
+
--write-baseline .mcp-guard-baseline.json
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Commit the baseline with the MCP config if the accepted findings are intentional.
|
|
16
|
+
|
|
17
|
+
## Enforce Only New Findings
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
mcp-guard scan \
|
|
21
|
+
--config .mcp.json \
|
|
22
|
+
--baseline .mcp-guard-baseline.json \
|
|
23
|
+
--fail-on high
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
If the scan finds only baseline-accepted findings, the exit code is `0`. If a new high or critical finding appears, the exit code is `2`.
|
|
27
|
+
|
|
28
|
+
`--allowlist` and `--write-allowlist` are aliases for teams that prefer that wording.
|
|
29
|
+
|
|
30
|
+
## GitHub Action
|
|
31
|
+
|
|
32
|
+
```yaml
|
|
33
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
34
|
+
with:
|
|
35
|
+
config: .mcp.json
|
|
36
|
+
baseline: .mcp-guard-baseline.json
|
|
37
|
+
fail-on: high
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The generated Markdown, HTML, JSON, and PR comment separate active findings from accepted baseline findings.
|
|
41
|
+
|
|
42
|
+
## Baseline Format
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"version": 1,
|
|
47
|
+
"generatedAt": "2026-05-10T00:00:00.000Z",
|
|
48
|
+
"toolVersion": "0.4.0",
|
|
49
|
+
"findings": [
|
|
50
|
+
{
|
|
51
|
+
"fingerprint": "mcpg_a009b2c2",
|
|
52
|
+
"id": "MCP010",
|
|
53
|
+
"severity": "critical",
|
|
54
|
+
"serverName": "shell-installer",
|
|
55
|
+
"configPath": ".mcp.json",
|
|
56
|
+
"title": "Shell command executes inline script",
|
|
57
|
+
"evidence": "command=bash args=-c curl https://example.com/install.sh | bash",
|
|
58
|
+
"acceptedAt": "2026-05-10T00:00:00.000Z",
|
|
59
|
+
"reason": "Accepted current MCP findings"
|
|
60
|
+
}
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Review Guidance
|
|
66
|
+
|
|
67
|
+
- Treat the baseline like code. Review changes in pull requests.
|
|
68
|
+
- Keep the reason field specific when accepting high or critical findings.
|
|
69
|
+
- Regenerate the baseline only after reviewing why findings changed.
|
|
70
|
+
- Do not use a baseline to hide unknown third-party tools or broad filesystem access from reviewers.
|
|
@@ -4,29 +4,30 @@
|
|
|
4
4
|
|
|
5
5
|
`mcp-guard` is the local-first security scanner for teams adopting AI agents and MCP servers.
|
|
6
6
|
|
|
7
|
-
The business is not the open-source CLI alone. The CLI creates trust and distribution.
|
|
7
|
+
The business is not the open-source CLI alone. The CLI creates trust and distribution. Near-term validation comes from early users running the scanner on real setups. Revenue can start with setup help and team workflow integration before offering broader manual audits.
|
|
8
8
|
|
|
9
|
-
##
|
|
9
|
+
## Near-Term Paid Offer
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
MCP Guard CI Setup Sprint.
|
|
12
|
+
|
|
13
|
+
This is setup and product onboarding, not a manual security audit.
|
|
12
14
|
|
|
13
15
|
Deliverables:
|
|
14
16
|
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
- optional PR with safer config changes.
|
|
17
|
+
- install the CLI and GitHub Action;
|
|
18
|
+
- generate Markdown, HTML, JSON, and SARIF reports;
|
|
19
|
+
- create an initial baseline for accepted known findings;
|
|
20
|
+
- enable PR comments and optional SARIF upload;
|
|
21
|
+
- document missing rule requests for future product work;
|
|
22
|
+
- provide a short setup handoff note.
|
|
22
23
|
|
|
23
24
|
## Pricing
|
|
24
25
|
|
|
25
26
|
| Customer | Price |
|
|
26
27
|
| --- | ---: |
|
|
27
|
-
| Solo founder / indie team | USD
|
|
28
|
-
| Small startup | USD
|
|
29
|
-
| Funded team / private deployment pilot | USD
|
|
28
|
+
| Solo founder / indie team | USD 199-500 |
|
|
29
|
+
| Small startup | USD 750-2,000 |
|
|
30
|
+
| Funded team / private deployment pilot | USD 2,000-5,000 |
|
|
30
31
|
|
|
31
32
|
## Outreach Copy
|
|
32
33
|
|
|
@@ -35,7 +36,7 @@ I built mcp-guard, an open-source local scanner for MCP and AI agent tool config
|
|
|
35
36
|
|
|
36
37
|
It checks for risky shell access, unpinned npx packages, broad filesystem permissions, exposed secrets, and remote MCP servers.
|
|
37
38
|
|
|
38
|
-
I am
|
|
39
|
+
I am collecting real-world MCP and AI agent config patterns from teams using Claude, Cursor, Codex, or MCP in production-like workflows. If you can share a redacted config or run the CLI locally, your feedback can help improve the scanner's rules and reports.
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
## First 20 Targets
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# End-to-End Example
|
|
2
|
+
|
|
3
|
+
This example is designed for transparent product evaluation. It uses a synthetic MCP config committed to the repository, then runs the real `mcp-guard` CLI to generate Markdown, HTML, JSON, and SARIF outputs.
|
|
4
|
+
|
|
5
|
+
The input is intentionally unsafe so users can see whether the scanner catches concrete risks.
|
|
6
|
+
|
|
7
|
+
## Input
|
|
8
|
+
|
|
9
|
+
Config file:
|
|
10
|
+
|
|
11
|
+
- [`site/e2e/claude_desktop_config.json`](../../site/e2e/claude_desktop_config.json)
|
|
12
|
+
|
|
13
|
+
It contains three MCP server entries:
|
|
14
|
+
|
|
15
|
+
- `filesystem-all-home`: launches an unpinned remote package with broad filesystem access and a secret-like environment variable.
|
|
16
|
+
- `shell-installer`: runs `bash -c` with a curl-pipe-shell installer pattern.
|
|
17
|
+
- `remote-prod`: points at a remote MCP endpoint with a secret-like authorization header.
|
|
18
|
+
|
|
19
|
+
## Reproduce the Reports
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format markdown --output site/e2e/report.md
|
|
23
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format html --output site/e2e/report.html
|
|
24
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format json --output site/e2e/report.json
|
|
25
|
+
node ./bin/mcp-guard.js scan --config site/e2e/claude_desktop_config.json --format sarif --output site/e2e/report.sarif
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Expected Result
|
|
29
|
+
|
|
30
|
+
The current scanner reports:
|
|
31
|
+
|
|
32
|
+
- Risk score: `98`
|
|
33
|
+
- Findings: `9`
|
|
34
|
+
- Critical: `2`
|
|
35
|
+
- High: `5`
|
|
36
|
+
- Medium: `2`
|
|
37
|
+
- Low: `0`
|
|
38
|
+
|
|
39
|
+
Important findings include:
|
|
40
|
+
|
|
41
|
+
- `MCP010`: shell command executes inline script.
|
|
42
|
+
- `MCP050`: curl-pipe-shell startup command.
|
|
43
|
+
- `MCP021`: unpinned remote MCP package.
|
|
44
|
+
- `MCP030`: secret-like environment variable.
|
|
45
|
+
- `MCP040` and `MCP041`: broad working directory and filesystem argument.
|
|
46
|
+
- `MCP061`: secret-like remote header.
|
|
47
|
+
|
|
48
|
+
## Generated Artifacts
|
|
49
|
+
|
|
50
|
+
- [Markdown report](../../site/e2e/report.md)
|
|
51
|
+
- [HTML report](../../site/e2e/report.html)
|
|
52
|
+
- [JSON report](../../site/e2e/report.json)
|
|
53
|
+
- [SARIF report](../../site/e2e/report.sarif)
|
|
54
|
+
|
|
55
|
+
## What This Proves
|
|
56
|
+
|
|
57
|
+
- The scanner does not need the config to leave the machine.
|
|
58
|
+
- Secret-like values are redacted in reports.
|
|
59
|
+
- Findings include rule IDs, severity, evidence, and remediation guidance.
|
|
60
|
+
- The same scan can feed a human-readable HTML report, automation JSON, and GitHub code scanning SARIF.
|
package/docs/github-action.md
CHANGED
|
@@ -4,6 +4,10 @@ Use the `mcp-guard` action to scan MCP and AI agent tool configuration in pull r
|
|
|
4
4
|
|
|
5
5
|
The action runs the CLI from the pinned GitHub Action tag, generates Markdown, HTML, JSON, and SARIF reports, writes a job summary, uploads reports as an artifact, and fails the job when findings meet your selected severity threshold.
|
|
6
6
|
|
|
7
|
+
It can also use a committed baseline to accept known findings and optionally post a pull request comment with only the active findings.
|
|
8
|
+
|
|
9
|
+
Marketplace/action repository: <https://github.com/ChaoYue0307/mcp-guard-action>
|
|
10
|
+
|
|
7
11
|
## Basic Workflow
|
|
8
12
|
|
|
9
13
|
```yaml
|
|
@@ -16,15 +20,18 @@ on:
|
|
|
16
20
|
|
|
17
21
|
permissions:
|
|
18
22
|
contents: read
|
|
23
|
+
pull-requests: write
|
|
19
24
|
|
|
20
25
|
jobs:
|
|
21
26
|
scan:
|
|
22
27
|
runs-on: ubuntu-latest
|
|
23
28
|
steps:
|
|
24
29
|
- uses: actions/checkout@v4
|
|
25
|
-
- uses: ChaoYue0307/mcp-guard@v0.
|
|
30
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
26
31
|
with:
|
|
32
|
+
config: .mcp.json
|
|
27
33
|
fail-on: high
|
|
34
|
+
comment-pr: "true"
|
|
28
35
|
```
|
|
29
36
|
|
|
30
37
|
## Upload SARIF to GitHub Security
|
|
@@ -48,7 +55,7 @@ jobs:
|
|
|
48
55
|
runs-on: ubuntu-latest
|
|
49
56
|
steps:
|
|
50
57
|
- uses: actions/checkout@v4
|
|
51
|
-
- uses: ChaoYue0307/mcp-guard@v0.
|
|
58
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
52
59
|
with:
|
|
53
60
|
config: .mcp.json
|
|
54
61
|
fail-on: high
|
|
@@ -60,17 +67,39 @@ jobs:
|
|
|
60
67
|
Use `fail-on: none` when you want artifacts and summaries without blocking a pull request.
|
|
61
68
|
|
|
62
69
|
```yaml
|
|
63
|
-
- uses: ChaoYue0307/mcp-guard@v0.
|
|
70
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
64
71
|
with:
|
|
65
72
|
fail-on: none
|
|
66
73
|
```
|
|
67
74
|
|
|
75
|
+
## Baseline Mode
|
|
76
|
+
|
|
77
|
+
Use a baseline when you want to accept known findings and fail only on new risk.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
mcp-guard scan --config .mcp.json --write-baseline .mcp-guard-baseline.json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Commit `.mcp-guard-baseline.json`, then reference it from the action:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
87
|
+
with:
|
|
88
|
+
config: .mcp.json
|
|
89
|
+
baseline: .mcp-guard-baseline.json
|
|
90
|
+
fail-on: high
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Reports will show active findings separately from findings accepted by the baseline.
|
|
94
|
+
|
|
68
95
|
## Inputs
|
|
69
96
|
|
|
70
97
|
| Input | Default | Description |
|
|
71
98
|
| --- | --- | --- |
|
|
72
99
|
| `config` | empty | Optional MCP config path. Empty scans default project and user config locations. |
|
|
73
100
|
| `fail-on` | `high` | Fails the job for `critical`, `high`, `medium`, or `low` findings. Use `none` for report-only mode. |
|
|
101
|
+
| `baseline` | empty | Optional baseline/allowlist JSON path. Matching findings are accepted and do not fail the workflow. |
|
|
102
|
+
| `comment-pr` | `false` | Posts or updates a pull request comment with the scan summary. Requires `pull-requests: write`. |
|
|
74
103
|
| `output-dir` | `mcp-guard-report` | Directory for generated reports. |
|
|
75
104
|
| `upload-artifact` | `true` | Uploads generated reports as a workflow artifact. |
|
|
76
105
|
| `upload-sarif` | `false` | Uploads SARIF to GitHub code scanning. Requires `security-events: write`. |
|
|
@@ -84,4 +113,5 @@ Use `fail-on: none` when you want artifacts and summaries without blocking a pul
|
|
|
84
113
|
| `html-report` | Path to the generated HTML report. |
|
|
85
114
|
| `json-report` | Path to the generated JSON report. |
|
|
86
115
|
| `sarif-report` | Path to the generated SARIF report. |
|
|
116
|
+
| `comment-report` | Path to the generated pull request comment body. |
|
|
87
117
|
| `exit-code` | `0` when below threshold, `2` when findings met the threshold. |
|
package/docs/launch-checklist.md
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
- [ ] Publish with `npm publish --access public`.
|
|
11
11
|
- [ ] Generate fresh sample report with `npm run scan:example`.
|
|
12
12
|
- [ ] Add screenshots or paste report excerpt into README.
|
|
13
|
+
- [ ] Finish the GitHub Marketplace web publishing step for `mcp-guard-action`.
|
|
13
14
|
- [ ] Post a short technical article or launch note.
|
|
14
|
-
- [ ] Contact 20 early users for
|
|
15
|
+
- [ ] Contact 20 early users for scan feedback, missing rules, and CI setup needs.
|
|
15
16
|
- [ ] Follow the detailed steps in `docs/operator-runbook.md`.
|
|
16
17
|
|
|
17
18
|
## User Setup
|
|
@@ -27,6 +28,18 @@ mcp-guard scan
|
|
|
27
28
|
mcp-guard scan --config .mcp.json --fail-on high
|
|
28
29
|
```
|
|
29
30
|
|
|
31
|
+
## GitHub Action Setup
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
35
|
+
with:
|
|
36
|
+
config: .mcp.json
|
|
37
|
+
baseline: .mcp-guard-baseline.json
|
|
38
|
+
fail-on: high
|
|
39
|
+
comment-pr: "true"
|
|
40
|
+
upload-sarif: "true"
|
|
41
|
+
```
|
|
42
|
+
|
|
30
43
|
Exit codes:
|
|
31
44
|
|
|
32
45
|
- `0`: scan completed and did not hit the fail threshold.
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# mcp-guard MCP Security Scanner
|
|
2
|
+
|
|
3
|
+
Scan MCP and AI agent tool configuration in GitHub Actions before risky tools merge.
|
|
4
|
+
|
|
5
|
+
`mcp-guard` finds risky shell startup commands, leaked secret-like values, broad filesystem access, remote MCP endpoints, dangerous command patterns, and unpinned remote package runners.
|
|
6
|
+
|
|
7
|
+
## Usage
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
name: mcp-guard
|
|
11
|
+
|
|
12
|
+
on:
|
|
13
|
+
pull_request:
|
|
14
|
+
push:
|
|
15
|
+
branches: [main]
|
|
16
|
+
|
|
17
|
+
permissions:
|
|
18
|
+
contents: read
|
|
19
|
+
pull-requests: write
|
|
20
|
+
|
|
21
|
+
jobs:
|
|
22
|
+
scan:
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
27
|
+
with:
|
|
28
|
+
config: .mcp.json
|
|
29
|
+
fail-on: high
|
|
30
|
+
comment-pr: "true"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Upload SARIF to GitHub Security
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
permissions:
|
|
37
|
+
contents: read
|
|
38
|
+
security-events: write
|
|
39
|
+
|
|
40
|
+
jobs:
|
|
41
|
+
scan:
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v4
|
|
45
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
46
|
+
with:
|
|
47
|
+
config: .mcp.json
|
|
48
|
+
fail-on: high
|
|
49
|
+
upload-sarif: "true"
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Inputs
|
|
53
|
+
|
|
54
|
+
| Input | Default | Description |
|
|
55
|
+
| --- | --- | --- |
|
|
56
|
+
| `config` | empty | Optional MCP config path. Empty scans default project and user config locations. |
|
|
57
|
+
| `fail-on` | `high` | Fails the job for `critical`, `high`, `medium`, or `low` findings. Use `none` for report-only mode. |
|
|
58
|
+
| `baseline` | empty | Optional baseline/allowlist JSON path. Matching findings are accepted and do not fail the workflow. |
|
|
59
|
+
| `comment-pr` | `false` | Posts or updates a pull request comment with the scan summary. Requires `pull-requests: write`. |
|
|
60
|
+
| `output-dir` | `mcp-guard-report` | Directory for generated reports. |
|
|
61
|
+
| `upload-artifact` | `true` | Uploads generated reports as a workflow artifact. |
|
|
62
|
+
| `upload-sarif` | `false` | Uploads SARIF to GitHub code scanning. Requires `security-events: write`. |
|
|
63
|
+
| `artifact-name` | `mcp-guard-report` | Name of the uploaded artifact. |
|
|
64
|
+
|
|
65
|
+
## Outputs
|
|
66
|
+
|
|
67
|
+
| Output | Description |
|
|
68
|
+
| --- | --- |
|
|
69
|
+
| `markdown-report` | Path to the generated Markdown report. |
|
|
70
|
+
| `html-report` | Path to the generated HTML report. |
|
|
71
|
+
| `json-report` | Path to the generated JSON report. |
|
|
72
|
+
| `sarif-report` | Path to the generated SARIF report. |
|
|
73
|
+
| `comment-report` | Path to the generated pull request comment body. |
|
|
74
|
+
| `exit-code` | `0` when below threshold, `2` when findings met the threshold. |
|
|
75
|
+
|
|
76
|
+
## Reports
|
|
77
|
+
|
|
78
|
+
The action generates:
|
|
79
|
+
|
|
80
|
+
- Markdown for pull request review.
|
|
81
|
+
- HTML for review-ready artifacts.
|
|
82
|
+
- JSON for automation.
|
|
83
|
+
- SARIF 2.1.0 for GitHub code scanning.
|
|
84
|
+
|
|
85
|
+
Secret-like values are redacted before reports are written.
|
|
86
|
+
|
|
87
|
+
## Baseline Mode
|
|
88
|
+
|
|
89
|
+
Generate and commit a baseline when existing MCP risk is known and accepted:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
mcp-guard scan --config .mcp.json --write-baseline .mcp-guard-baseline.json
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Then enforce only new findings:
|
|
96
|
+
|
|
97
|
+
```yaml
|
|
98
|
+
- uses: ChaoYue0307/mcp-guard-action@v0.4.0
|
|
99
|
+
with:
|
|
100
|
+
config: .mcp.json
|
|
101
|
+
baseline: .mcp-guard-baseline.json
|
|
102
|
+
fail-on: high
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Transparent Example
|
|
106
|
+
|
|
107
|
+
Inspect a committed input config, reproduction commands, and generated Markdown, HTML, JSON, and SARIF artifacts:
|
|
108
|
+
|
|
109
|
+
https://chaoyue0307.github.io/mcp-guard/e2e/
|
|
110
|
+
|
|
111
|
+
Inspect a live GitHub Action demo pull request that intentionally fails on risky MCP config:
|
|
112
|
+
|
|
113
|
+
https://github.com/ChaoYue0307/mcp-guard-demo/pull/1
|
|
114
|
+
|
|
115
|
+
## Links
|
|
116
|
+
|
|
117
|
+
- Product site: https://chaoyue0307.github.io/mcp-guard/
|
|
118
|
+
- Marketplace listing: https://github.com/marketplace/actions/mcp-guard-mcp-security-scanner
|
|
119
|
+
- Live demo repository: https://github.com/ChaoYue0307/mcp-guard-demo
|
|
120
|
+
- Main repository: https://github.com/ChaoYue0307/mcp-guard
|
|
121
|
+
- npm package: https://www.npmjs.com/package/agent-mcp-guard
|