secscan-mcp 0.1.2__tar.gz
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.
- secscan_mcp-0.1.2/.gitignore +58 -0
- secscan_mcp-0.1.2/CHANGELOG.md +40 -0
- secscan_mcp-0.1.2/LICENSE +21 -0
- secscan_mcp-0.1.2/PKG-INFO +161 -0
- secscan_mcp-0.1.2/PLAN.md +129 -0
- secscan_mcp-0.1.2/README.md +126 -0
- secscan_mcp-0.1.2/pyproject.toml +134 -0
- secscan_mcp-0.1.2/src/secscan_mcp/__init__.py +3 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/.gitkeep +0 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/__init__.py +41 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/_util.py +39 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/bandit.py +81 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/base.py +21 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/checkov.py +74 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/custom.py +90 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/git_history.py +174 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/gitleaks.py +108 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/osv.py +77 -0
- secscan_mcp-0.1.2/src/secscan_mcp/engines/semgrep.py +95 -0
- secscan_mcp-0.1.2/src/secscan_mcp/normalize.py +219 -0
- secscan_mcp-0.1.2/src/secscan_mcp/paths.py +25 -0
- secscan_mcp-0.1.2/src/secscan_mcp/py.typed +0 -0
- secscan_mcp-0.1.2/src/secscan_mcp/rules/.gitkeep +0 -0
- secscan_mcp-0.1.2/src/secscan_mcp/rules/__init__.py +1 -0
- secscan_mcp-0.1.2/src/secscan_mcp/rules/custom_secrets.yaml +19 -0
- secscan_mcp-0.1.2/src/secscan_mcp/rules/loader.py +27 -0
- secscan_mcp-0.1.2/src/secscan_mcp/runner.py +189 -0
- secscan_mcp-0.1.2/src/secscan_mcp/server.py +205 -0
- secscan_mcp-0.1.2/tests/__init__.py +0 -0
- secscan_mcp-0.1.2/tests/conftest.py +31 -0
- secscan_mcp-0.1.2/tests/fixtures/sample_repo/leak.py +2 -0
- secscan_mcp-0.1.2/tests/test_custom_engine.py +16 -0
- secscan_mcp-0.1.2/tests/test_git_history.py +55 -0
- secscan_mcp-0.1.2/tests/test_integration.py +39 -0
- secscan_mcp-0.1.2/tests/test_normalize.py +70 -0
- secscan_mcp-0.1.2/tests/test_paths.py +15 -0
- secscan_mcp-0.1.2/tests/test_runner.py +21 -0
- secscan_mcp-0.1.2/tests/test_version.py +9 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
MANIFEST
|
|
23
|
+
|
|
24
|
+
# Virtual environments
|
|
25
|
+
.venv/
|
|
26
|
+
venv/
|
|
27
|
+
ENV/
|
|
28
|
+
env/
|
|
29
|
+
|
|
30
|
+
# Tooling caches
|
|
31
|
+
.mypy_cache/
|
|
32
|
+
.pytest_cache/
|
|
33
|
+
.ruff_cache/
|
|
34
|
+
.coverage
|
|
35
|
+
htmlcov/
|
|
36
|
+
.hypothesis/
|
|
37
|
+
|
|
38
|
+
# IDE / OS
|
|
39
|
+
.idea/
|
|
40
|
+
*.swp
|
|
41
|
+
*.swo
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# Local env and secrets (never commit)
|
|
46
|
+
.env
|
|
47
|
+
.env.*
|
|
48
|
+
!.env.example
|
|
49
|
+
*.pem
|
|
50
|
+
*.key
|
|
51
|
+
credentials.json
|
|
52
|
+
|
|
53
|
+
# Scan artifacts (generated during dev/tests)
|
|
54
|
+
.scan-output/
|
|
55
|
+
*.sarif
|
|
56
|
+
|
|
57
|
+
# uv
|
|
58
|
+
uv.lock
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. Version numbers follow [Semantic Versioning](https://semver.org/).
|
|
4
|
+
|
|
5
|
+
## [0.1.2] - 2026-06-16
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Update release process and documentation: enhance CHANGELOG.md auto-update functionality in the release script, ensuring it reflects the latest commits. Streamline release steps by clarifying prerequisites and improving user feedback during the release process.
|
|
10
|
+
- Enhance release workflow and documentation: add workflow_dispatch trigger to release.yml for manual execution, and expand PUBLISHING.md with detailed steps for setting up trusted publishing on PyPI, including environment creation and verification processes.
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
## [0.1.1] - 2026-06-16
|
|
14
|
+
|
|
15
|
+
### Added
|
|
16
|
+
|
|
17
|
+
- Git commit history secret scanning (`git_history` engine) via `include_git_history: true`
|
|
18
|
+
- PyPI publish workflow and release script (`make release-patch|minor|major`)
|
|
19
|
+
- Multi-IDE setup guide, example MCP configs, and `uvx` install path
|
|
20
|
+
- CI build job and package publishing docs
|
|
21
|
+
|
|
22
|
+
## [0.1.0] - 2026-06-16
|
|
23
|
+
|
|
24
|
+
First public release.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- MCP server with stdio transport for any IDE (Cursor, VS Code, Claude Desktop, Windsurf, etc.)
|
|
29
|
+
- Tools: `scan_secrets`, `scan_code`, `scan_dependencies`, `scan_iac`, `scan_all`, `list_available_scanners`, `explain_finding`
|
|
30
|
+
- Normalized finding schema with severity mapping, deduplication, and secret redaction
|
|
31
|
+
- Built-in **custom** secret scanner (no external CLI required)
|
|
32
|
+
- Built-in **git_history** scanner — detect secrets in past commits via `include_git_history: true`
|
|
33
|
+
- Optional engine adapters: gitleaks, semgrep, bandit, osv-scanner, checkov
|
|
34
|
+
- Multi-IDE setup guide and example MCP configs
|
|
35
|
+
- CI workflow (Python 3.11–3.13)
|
|
36
|
+
|
|
37
|
+
[0.1.1]: https://github.com/openjkai/secscan_mcp/releases/tag/v0.1.1
|
|
38
|
+
[0.1.0]: https://github.com/openjkai/secscan_mcp/releases/tag/v0.1.0
|
|
39
|
+
|
|
40
|
+
[0.1.2]: https://github.com/openjkai/secscan_mcp/releases/tag/v0.1.2
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 secscan-mcp contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: secscan-mcp
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: MCP server for codebase security scanning (secrets, SAST, SCA, IaC)
|
|
5
|
+
Project-URL: Homepage, https://github.com/openjkai/secscan_mcp
|
|
6
|
+
Project-URL: Documentation, https://github.com/openjkai/secscan_mcp#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/openjkai/secscan_mcp
|
|
8
|
+
Project-URL: Issues, https://github.com/openjkai/secscan_mcp/issues
|
|
9
|
+
Project-URL: Changelog, https://github.com/openjkai/secscan_mcp/blob/main/CHANGELOG.md
|
|
10
|
+
Author: secscan-mcp contributors
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: mcp,model-context-protocol,sast,scanner,secrets,security
|
|
14
|
+
Classifier: Development Status :: 3 - Alpha
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Security
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: mcp>=1.6.0
|
|
24
|
+
Requires-Dist: pyyaml>=6.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build>=1.0; extra == 'dev'
|
|
27
|
+
Requires-Dist: mypy>=1.14; extra == 'dev'
|
|
28
|
+
Requires-Dist: pre-commit>=4.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest-cov>=6.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
33
|
+
Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# secscan-mcp
|
|
37
|
+
|
|
38
|
+
[](https://github.com/openjkai/secscan_mcp/actions/workflows/ci.yml)
|
|
39
|
+
[](https://pypi.org/project/secscan-mcp/)
|
|
40
|
+
|
|
41
|
+
A portable **MCP server** for security scanning — works with **any AI coding assistant** that supports the [Model Context Protocol](https://modelcontextprotocol.io): Cursor, VS Code, Claude Desktop, Windsurf, Zed, Continue, and more.
|
|
42
|
+
|
|
43
|
+
Scan codebases for **hardcoded secrets**, **SAST issues**, **vulnerable dependencies**, and **IaC misconfigurations** — one install, one normalized report format.
|
|
44
|
+
|
|
45
|
+
The built-in **custom** scanner works with no extra tools. Install optional CLIs for broader coverage ([below](#optional-scanners)).
|
|
46
|
+
|
|
47
|
+
## Quick start
|
|
48
|
+
|
|
49
|
+
**1. Install** (Python 3.11+):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install secscan-mcp
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or run without installing (requires [uv](https://docs.astral.sh/uv/)):
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uvx secscan-mcp
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
For MCP config with `uvx`, use `"command": "uvx"` and `"args": ["secscan-mcp"]` — see [setup guide](docs/setup.md).
|
|
62
|
+
|
|
63
|
+
<details>
|
|
64
|
+
<summary>Install from source</summary>
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/openjkai/secscan_mcp.git
|
|
68
|
+
cd secscan_mcp && pip install .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
</details>
|
|
72
|
+
|
|
73
|
+
**2. Add to your IDE** — pick your client:
|
|
74
|
+
|
|
75
|
+
| IDE / client | Config file | Guide |
|
|
76
|
+
|--------------|-------------|-------|
|
|
77
|
+
| Cursor | `~/.cursor/mcp.json` | [setup →](docs/setup.md#cursor) |
|
|
78
|
+
| VS Code | `.vscode/mcp.json` | [setup →](docs/setup.md#vs-code-github-copilot) |
|
|
79
|
+
| Claude Desktop | OS-specific (see guide) | [setup →](docs/setup.md#claude-desktop) |
|
|
80
|
+
| Claude Code | `~/.claude/settings.json` | [setup →](docs/setup.md#claude-code) |
|
|
81
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | [setup →](docs/setup.md#windsurf) |
|
|
82
|
+
| Others | — | [Full setup guide](docs/setup.md) |
|
|
83
|
+
|
|
84
|
+
Minimal config (works in Cursor, Claude Desktop, Windsurf):
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"mcpServers": {
|
|
89
|
+
"secscan": {
|
|
90
|
+
"command": "uvx",
|
|
91
|
+
"args": ["secscan-mcp"]
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
If you installed with `pip install secscan-mcp`, you can use `"command": "secscan-mcp"` instead.
|
|
98
|
+
|
|
99
|
+
**3. Verify** — ask your agent: *"Call `list_available_scanners` and scan_secrets on this project."*
|
|
100
|
+
|
|
101
|
+
## MCP tools
|
|
102
|
+
|
|
103
|
+
| Tool | Purpose |
|
|
104
|
+
|------|---------|
|
|
105
|
+
| `list_available_scanners` | Which engines are installed on this machine |
|
|
106
|
+
| `scan_secrets` | Hardcoded credentials and secrets (optionally scan git commit history) |
|
|
107
|
+
| `scan_code` | SAST (semgrep, bandit) |
|
|
108
|
+
| `scan_dependencies` | Vulnerable packages (osv-scanner) |
|
|
109
|
+
| `scan_iac` | IaC misconfigurations (checkov) |
|
|
110
|
+
| `scan_all` | All available scanners, one unified report |
|
|
111
|
+
| `explain_finding` | Remediation hints for a `rule_id` |
|
|
112
|
+
|
|
113
|
+
Most scan tools accept `path` (directory to scan) and optional `severity_threshold` (`critical`, `high`, `medium`, `low`, `info`).
|
|
114
|
+
|
|
115
|
+
`scan_secrets` also accepts `include_git_history` (boolean). When `true`, scans past git commits for secrets removed from the working tree but still present in history — no extra tools required beyond `git`.
|
|
116
|
+
|
|
117
|
+
## Optional scanners
|
|
118
|
+
|
|
119
|
+
Install any of these to extend coverage. Missing CLIs are skipped — the server still runs.
|
|
120
|
+
|
|
121
|
+
| Engine | Category | Install (example) |
|
|
122
|
+
|--------|----------|-------------------|
|
|
123
|
+
| gitleaks | secrets | `brew install gitleaks` |
|
|
124
|
+
| semgrep | SAST | `pip install semgrep` |
|
|
125
|
+
| bandit | SAST (Python) | `pip install bandit` |
|
|
126
|
+
| osv-scanner | dependencies | `brew install osv-scanner` |
|
|
127
|
+
| checkov | IaC | `pip install checkov` |
|
|
128
|
+
|
|
129
|
+
After installing, run `list_available_scanners` again to confirm.
|
|
130
|
+
|
|
131
|
+
## Example prompts
|
|
132
|
+
|
|
133
|
+
- *"Call `list_available_scanners` and tell me what's installed."*
|
|
134
|
+
- *"Run `scan_secrets` with include_git_history on this repo — check if any secrets were ever committed."*
|
|
135
|
+
- *"Run `scan_all` with severity_threshold high and summarize the findings."*
|
|
136
|
+
- *"Explain the rule `internal-api-key`."*
|
|
137
|
+
|
|
138
|
+
## Configuration
|
|
139
|
+
|
|
140
|
+
Environment variables (optional):
|
|
141
|
+
|
|
142
|
+
| Variable | Default | Description |
|
|
143
|
+
|----------|---------|-------------|
|
|
144
|
+
| `SECSCAN_DEFAULT_TIMEOUT_SECONDS` | `300` | Per-engine scan timeout |
|
|
145
|
+
| `SECSCAN_MAX_FINDINGS` | `500` | Max findings per report |
|
|
146
|
+
| `SECSCAN_GIT_MAX_COMMITS` | `500` | Max commits scanned in git history mode |
|
|
147
|
+
|
|
148
|
+
Pass via MCP config `env` block — see [setup guide](docs/setup.md#environment-variables).
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
make install-dev # editable install + dev tools
|
|
154
|
+
make check # lint + typecheck + test
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and [PLAN.md](PLAN.md).
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
MIT
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# secscan-mcp — product plan
|
|
2
|
+
|
|
3
|
+
## Vision
|
|
4
|
+
|
|
5
|
+
**secscan-mcp** is a portable [Model Context Protocol](https://modelcontextprotocol.io) server that gives any AI coding assistant — in any IDE — a single, normalized API for security scanning.
|
|
6
|
+
|
|
7
|
+
One install. One report format. Works in Cursor, VS Code, Claude Desktop, Windsurf, and any other MCP host.
|
|
8
|
+
|
|
9
|
+
## What it does
|
|
10
|
+
|
|
11
|
+
| Category | Engines | MCP tool |
|
|
12
|
+
|----------|---------|----------|
|
|
13
|
+
| Secrets (working tree) | custom (built-in), gitleaks | `scan_secrets` |
|
|
14
|
+
| Secrets (git history) | git_history (built-in), gitleaks | `scan_secrets` + `include_git_history: true` |
|
|
15
|
+
| SAST | semgrep, bandit | `scan_code` |
|
|
16
|
+
| Dependencies | osv-scanner | `scan_dependencies` |
|
|
17
|
+
| IaC | checkov | `scan_iac` |
|
|
18
|
+
| All | whatever is installed | `scan_all` |
|
|
19
|
+
|
|
20
|
+
The **custom** engine scans current files with zero external tools. The **git_history** engine scans past commits for secrets that were removed from the working tree but remain in git history — critical because deleting a secret from code does not remove it from old commits.
|
|
21
|
+
|
|
22
|
+
Optional CLIs (gitleaks, semgrep, etc.) extend coverage when present; missing CLIs are skipped gracefully.
|
|
23
|
+
|
|
24
|
+
## Git history scanning
|
|
25
|
+
|
|
26
|
+
Many credential leaks happen in **commits**, not just the current checkout. Developers often delete a secret from source but forget it persists in git history — where it can be found by anyone with repo access or after a public push.
|
|
27
|
+
|
|
28
|
+
**How it works:**
|
|
29
|
+
|
|
30
|
+
1. Call `scan_secrets` with `"include_git_history": true`
|
|
31
|
+
2. **git_history** (built-in, requires `git`) walks recent commits (`git log -p`) and applies the same regex rules as the custom scanner to added lines in patches
|
|
32
|
+
3. **gitleaks** (optional) runs its own history-aware detect when installed
|
|
33
|
+
4. Findings include commit SHA, date, and remediation guidance (rotate + rewrite history)
|
|
34
|
+
|
|
35
|
+
**Limits:** `SECSCAN_GIT_MAX_COMMITS` (default `500`) caps how far back to scan.
|
|
36
|
+
|
|
37
|
+
## Architecture
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
MCP host (any IDE)
|
|
41
|
+
│ stdio
|
|
42
|
+
▼
|
|
43
|
+
server.py ← MCP tools
|
|
44
|
+
│
|
|
45
|
+
runner.py ← parallel runs, timeouts, path safety
|
|
46
|
+
│
|
|
47
|
+
engines/* ← one adapter per scanner CLI
|
|
48
|
+
│
|
|
49
|
+
normalize.py ← Finding schema, severity, dedupe, redaction
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Phases
|
|
53
|
+
|
|
54
|
+
### Phase 0 — Core engine ✅
|
|
55
|
+
|
|
56
|
+
- [x] Normalized `Finding` / `ScanReport` schema
|
|
57
|
+
- [x] Engine adapters (custom, gitleaks, semgrep, bandit, osv, checkov)
|
|
58
|
+
- [x] Parallel runner with timeouts and path validation
|
|
59
|
+
- [x] MCP server with 7 tools (stdio transport)
|
|
60
|
+
- [x] Unit tests for normalize, paths, runner, custom engine
|
|
61
|
+
|
|
62
|
+
### Phase 1 — Universal distribution ✅
|
|
63
|
+
|
|
64
|
+
Goal: any developer can install and configure in their IDE in under 2 minutes.
|
|
65
|
+
|
|
66
|
+
- [x] PLAN.md (this file)
|
|
67
|
+
- [x] README reframed as IDE-agnostic MCP server
|
|
68
|
+
- [x] Multi-IDE setup guide ([docs/setup.md](docs/setup.md))
|
|
69
|
+
- [x] Example MCP configs per host (`docs/examples/`)
|
|
70
|
+
- [x] Fix placeholder URLs in `pyproject.toml`
|
|
71
|
+
- [x] CI workflow (lint, typecheck, test on push)
|
|
72
|
+
- [x] Git history secret scanning (`git_history` engine)
|
|
73
|
+
- [x] Integration tests with `@pytest.mark.integration` marker
|
|
74
|
+
|
|
75
|
+
### Phase 2 — PyPI publish (current)
|
|
76
|
+
|
|
77
|
+
Goal: one-line install without cloning the repo.
|
|
78
|
+
|
|
79
|
+
- [ ] Publish `secscan-mcp` to PyPI (create GitHub Release `v0.1.0` — see [docs/PUBLISHING.md](docs/PUBLISHING.md))
|
|
80
|
+
- [x] Document `pip install secscan-mcp` and `uvx secscan-mcp`
|
|
81
|
+
- [x] GitHub Actions release workflow (tag → build → publish)
|
|
82
|
+
- [x] CHANGELOG.md and semver releases
|
|
83
|
+
|
|
84
|
+
### Phase 3 — MCP polish
|
|
85
|
+
|
|
86
|
+
Goal: agents use the tools correctly without hand-holding.
|
|
87
|
+
|
|
88
|
+
- [ ] Rich tool descriptions and parameter docs
|
|
89
|
+
- [ ] Server instructions for MCP hosts
|
|
90
|
+
- [ ] Expand `explain_finding` rule coverage
|
|
91
|
+
- [ ] Smoke-test in Cursor, VS Code, and Claude Desktop
|
|
92
|
+
- [ ] Default `include_git_history: true` guidance for pre-push / pre-PR workflows
|
|
93
|
+
|
|
94
|
+
### Phase 4 — Community & discovery
|
|
95
|
+
|
|
96
|
+
Goal: become the default security MCP.
|
|
97
|
+
|
|
98
|
+
- [ ] SECURITY.md, issue templates
|
|
99
|
+
- [ ] Submit to MCP registries and awesome lists
|
|
100
|
+
- [ ] Optional VS Code manifest for "Install from manifest"
|
|
101
|
+
- [ ] Optional Docker image for team deployments
|
|
102
|
+
|
|
103
|
+
## Non-goals (for now)
|
|
104
|
+
|
|
105
|
+
- HTTP/SSE transport (stdio covers all major hosts today)
|
|
106
|
+
- IDE-specific plugins or extensions
|
|
107
|
+
- Hosted/remote scan service
|
|
108
|
+
|
|
109
|
+
## Quality gate
|
|
110
|
+
|
|
111
|
+
Before marking any phase done:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
make check # ruff + mypy + pytest
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Integration tests (when CLIs are installed):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
pytest -m integration
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Environment variables
|
|
124
|
+
|
|
125
|
+
| Variable | Default | Description |
|
|
126
|
+
|----------|---------|-------------|
|
|
127
|
+
| `SECSCAN_DEFAULT_TIMEOUT_SECONDS` | `300` | Per-engine scan timeout |
|
|
128
|
+
| `SECSCAN_MAX_FINDINGS` | `500` | Cap findings in a single report |
|
|
129
|
+
| `SECSCAN_GIT_MAX_COMMITS` | `500` | Max commits to scan in git history mode |
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# secscan-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/openjkai/secscan_mcp/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/secscan-mcp/)
|
|
5
|
+
|
|
6
|
+
A portable **MCP server** for security scanning — works with **any AI coding assistant** that supports the [Model Context Protocol](https://modelcontextprotocol.io): Cursor, VS Code, Claude Desktop, Windsurf, Zed, Continue, and more.
|
|
7
|
+
|
|
8
|
+
Scan codebases for **hardcoded secrets**, **SAST issues**, **vulnerable dependencies**, and **IaC misconfigurations** — one install, one normalized report format.
|
|
9
|
+
|
|
10
|
+
The built-in **custom** scanner works with no extra tools. Install optional CLIs for broader coverage ([below](#optional-scanners)).
|
|
11
|
+
|
|
12
|
+
## Quick start
|
|
13
|
+
|
|
14
|
+
**1. Install** (Python 3.11+):
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install secscan-mcp
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Or run without installing (requires [uv](https://docs.astral.sh/uv/)):
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uvx secscan-mcp
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
For MCP config with `uvx`, use `"command": "uvx"` and `"args": ["secscan-mcp"]` — see [setup guide](docs/setup.md).
|
|
27
|
+
|
|
28
|
+
<details>
|
|
29
|
+
<summary>Install from source</summary>
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/openjkai/secscan_mcp.git
|
|
33
|
+
cd secscan_mcp && pip install .
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
</details>
|
|
37
|
+
|
|
38
|
+
**2. Add to your IDE** — pick your client:
|
|
39
|
+
|
|
40
|
+
| IDE / client | Config file | Guide |
|
|
41
|
+
|--------------|-------------|-------|
|
|
42
|
+
| Cursor | `~/.cursor/mcp.json` | [setup →](docs/setup.md#cursor) |
|
|
43
|
+
| VS Code | `.vscode/mcp.json` | [setup →](docs/setup.md#vs-code-github-copilot) |
|
|
44
|
+
| Claude Desktop | OS-specific (see guide) | [setup →](docs/setup.md#claude-desktop) |
|
|
45
|
+
| Claude Code | `~/.claude/settings.json` | [setup →](docs/setup.md#claude-code) |
|
|
46
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | [setup →](docs/setup.md#windsurf) |
|
|
47
|
+
| Others | — | [Full setup guide](docs/setup.md) |
|
|
48
|
+
|
|
49
|
+
Minimal config (works in Cursor, Claude Desktop, Windsurf):
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"secscan": {
|
|
55
|
+
"command": "uvx",
|
|
56
|
+
"args": ["secscan-mcp"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
If you installed with `pip install secscan-mcp`, you can use `"command": "secscan-mcp"` instead.
|
|
63
|
+
|
|
64
|
+
**3. Verify** — ask your agent: *"Call `list_available_scanners` and scan_secrets on this project."*
|
|
65
|
+
|
|
66
|
+
## MCP tools
|
|
67
|
+
|
|
68
|
+
| Tool | Purpose |
|
|
69
|
+
|------|---------|
|
|
70
|
+
| `list_available_scanners` | Which engines are installed on this machine |
|
|
71
|
+
| `scan_secrets` | Hardcoded credentials and secrets (optionally scan git commit history) |
|
|
72
|
+
| `scan_code` | SAST (semgrep, bandit) |
|
|
73
|
+
| `scan_dependencies` | Vulnerable packages (osv-scanner) |
|
|
74
|
+
| `scan_iac` | IaC misconfigurations (checkov) |
|
|
75
|
+
| `scan_all` | All available scanners, one unified report |
|
|
76
|
+
| `explain_finding` | Remediation hints for a `rule_id` |
|
|
77
|
+
|
|
78
|
+
Most scan tools accept `path` (directory to scan) and optional `severity_threshold` (`critical`, `high`, `medium`, `low`, `info`).
|
|
79
|
+
|
|
80
|
+
`scan_secrets` also accepts `include_git_history` (boolean). When `true`, scans past git commits for secrets removed from the working tree but still present in history — no extra tools required beyond `git`.
|
|
81
|
+
|
|
82
|
+
## Optional scanners
|
|
83
|
+
|
|
84
|
+
Install any of these to extend coverage. Missing CLIs are skipped — the server still runs.
|
|
85
|
+
|
|
86
|
+
| Engine | Category | Install (example) |
|
|
87
|
+
|--------|----------|-------------------|
|
|
88
|
+
| gitleaks | secrets | `brew install gitleaks` |
|
|
89
|
+
| semgrep | SAST | `pip install semgrep` |
|
|
90
|
+
| bandit | SAST (Python) | `pip install bandit` |
|
|
91
|
+
| osv-scanner | dependencies | `brew install osv-scanner` |
|
|
92
|
+
| checkov | IaC | `pip install checkov` |
|
|
93
|
+
|
|
94
|
+
After installing, run `list_available_scanners` again to confirm.
|
|
95
|
+
|
|
96
|
+
## Example prompts
|
|
97
|
+
|
|
98
|
+
- *"Call `list_available_scanners` and tell me what's installed."*
|
|
99
|
+
- *"Run `scan_secrets` with include_git_history on this repo — check if any secrets were ever committed."*
|
|
100
|
+
- *"Run `scan_all` with severity_threshold high and summarize the findings."*
|
|
101
|
+
- *"Explain the rule `internal-api-key`."*
|
|
102
|
+
|
|
103
|
+
## Configuration
|
|
104
|
+
|
|
105
|
+
Environment variables (optional):
|
|
106
|
+
|
|
107
|
+
| Variable | Default | Description |
|
|
108
|
+
|----------|---------|-------------|
|
|
109
|
+
| `SECSCAN_DEFAULT_TIMEOUT_SECONDS` | `300` | Per-engine scan timeout |
|
|
110
|
+
| `SECSCAN_MAX_FINDINGS` | `500` | Max findings per report |
|
|
111
|
+
| `SECSCAN_GIT_MAX_COMMITS` | `500` | Max commits scanned in git history mode |
|
|
112
|
+
|
|
113
|
+
Pass via MCP config `env` block — see [setup guide](docs/setup.md#environment-variables).
|
|
114
|
+
|
|
115
|
+
## Development
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
make install-dev # editable install + dev tools
|
|
119
|
+
make check # lint + typecheck + test
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
See [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and [PLAN.md](PLAN.md).
|
|
123
|
+
|
|
124
|
+
## License
|
|
125
|
+
|
|
126
|
+
MIT
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "secscan-mcp"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "MCP server for codebase security scanning (secrets, SAST, SCA, IaC)"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "secscan-mcp contributors" }]
|
|
13
|
+
keywords = ["mcp", "security", "sast", "secrets", "scanner", "model-context-protocol"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: Security",
|
|
23
|
+
]
|
|
24
|
+
dependencies = [
|
|
25
|
+
"mcp>=1.6.0",
|
|
26
|
+
"pyyaml>=6.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
dev = [
|
|
31
|
+
"pre-commit>=4.0",
|
|
32
|
+
"pytest>=8.0",
|
|
33
|
+
"pytest-asyncio>=0.24",
|
|
34
|
+
"pytest-cov>=6.0",
|
|
35
|
+
"ruff>=0.9",
|
|
36
|
+
"mypy>=1.14",
|
|
37
|
+
"types-PyYAML>=6.0",
|
|
38
|
+
"build>=1.0",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
secscan-mcp = "secscan_mcp.server:main"
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/openjkai/secscan_mcp"
|
|
46
|
+
Documentation = "https://github.com/openjkai/secscan_mcp#readme"
|
|
47
|
+
Repository = "https://github.com/openjkai/secscan_mcp"
|
|
48
|
+
Issues = "https://github.com/openjkai/secscan_mcp/issues"
|
|
49
|
+
Changelog = "https://github.com/openjkai/secscan_mcp/blob/main/CHANGELOG.md"
|
|
50
|
+
|
|
51
|
+
[tool.hatch.version]
|
|
52
|
+
path = "src/secscan_mcp/__init__.py"
|
|
53
|
+
|
|
54
|
+
[tool.hatch.build]
|
|
55
|
+
dev-mode-dirs = ["src"]
|
|
56
|
+
|
|
57
|
+
[tool.hatch.build.targets.wheel]
|
|
58
|
+
packages = ["src/secscan_mcp"]
|
|
59
|
+
|
|
60
|
+
[tool.hatch.build.targets.sdist]
|
|
61
|
+
include = [
|
|
62
|
+
"/src",
|
|
63
|
+
"/tests",
|
|
64
|
+
"/README.md",
|
|
65
|
+
"/PLAN.md",
|
|
66
|
+
"/CHANGELOG.md",
|
|
67
|
+
"/LICENSE",
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[tool.ruff]
|
|
71
|
+
target-version = "py311"
|
|
72
|
+
line-length = 100
|
|
73
|
+
src = ["src", "tests"]
|
|
74
|
+
|
|
75
|
+
[tool.ruff.lint]
|
|
76
|
+
select = [
|
|
77
|
+
"E", # pycodestyle errors
|
|
78
|
+
"W", # pycodestyle warnings
|
|
79
|
+
"F", # pyflakes
|
|
80
|
+
"I", # isort
|
|
81
|
+
"B", # flake8-bugbear
|
|
82
|
+
"UP", # pyupgrade
|
|
83
|
+
"SIM", # flake8-simplify
|
|
84
|
+
"RUF", # ruff-specific
|
|
85
|
+
]
|
|
86
|
+
ignore = ["E501"] # line length handled by formatter
|
|
87
|
+
|
|
88
|
+
[tool.ruff.lint.isort]
|
|
89
|
+
known-first-party = ["secscan_mcp"]
|
|
90
|
+
|
|
91
|
+
[tool.ruff.format]
|
|
92
|
+
quote-style = "double"
|
|
93
|
+
indent-style = "space"
|
|
94
|
+
skip-magic-trailing-comma = false
|
|
95
|
+
line-ending = "auto"
|
|
96
|
+
|
|
97
|
+
[tool.mypy]
|
|
98
|
+
python_version = "3.11"
|
|
99
|
+
strict = true
|
|
100
|
+
warn_return_any = true
|
|
101
|
+
warn_unused_ignores = true
|
|
102
|
+
disallow_untyped_defs = true
|
|
103
|
+
disallow_incomplete_defs = true
|
|
104
|
+
check_untyped_defs = true
|
|
105
|
+
no_implicit_optional = true
|
|
106
|
+
show_error_codes = true
|
|
107
|
+
files = ["src"]
|
|
108
|
+
mypy_path = ["src"]
|
|
109
|
+
|
|
110
|
+
[[tool.mypy.overrides]]
|
|
111
|
+
module = ["mcp.*"]
|
|
112
|
+
ignore_missing_imports = true
|
|
113
|
+
|
|
114
|
+
[[tool.mypy.overrides]]
|
|
115
|
+
module = ["secscan_mcp.server"]
|
|
116
|
+
disable_error_code = ["misc", "no-untyped-call", "untyped-decorator"]
|
|
117
|
+
|
|
118
|
+
[tool.pytest.ini_options]
|
|
119
|
+
testpaths = ["tests"]
|
|
120
|
+
asyncio_mode = "auto"
|
|
121
|
+
addopts = "-ra --strict-markers"
|
|
122
|
+
markers = [
|
|
123
|
+
"integration: tests that invoke external scanner CLIs",
|
|
124
|
+
"slow: long-running scans",
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
[tool.coverage.run]
|
|
128
|
+
source = ["secscan_mcp"]
|
|
129
|
+
branch = true
|
|
130
|
+
|
|
131
|
+
[tool.coverage.report]
|
|
132
|
+
fail_under = 0
|
|
133
|
+
show_missing = true
|
|
134
|
+
skip_empty = true
|
|
File without changes
|