cyver-mcp 0.4.0__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.
- cyver_mcp-0.4.0/LICENSE +21 -0
- cyver_mcp-0.4.0/MANIFEST.in +1 -0
- cyver_mcp-0.4.0/PKG-INFO +245 -0
- cyver_mcp-0.4.0/README.pypi.md +231 -0
- cyver_mcp-0.4.0/pyproject.toml +29 -0
- cyver_mcp-0.4.0/setup.cfg +4 -0
- cyver_mcp-0.4.0/src/cyver_mcp/__init__.py +3 -0
- cyver_mcp-0.4.0/src/cyver_mcp/__main__.py +73 -0
- cyver_mcp-0.4.0/src/cyver_mcp/audit.py +93 -0
- cyver_mcp-0.4.0/src/cyver_mcp/config.py +43 -0
- cyver_mcp-0.4.0/src/cyver_mcp/finding_status.py +71 -0
- cyver_mcp-0.4.0/src/cyver_mcp/login.py +144 -0
- cyver_mcp-0.4.0/src/cyver_mcp/logout.py +69 -0
- cyver_mcp-0.4.0/src/cyver_mcp/server.py +880 -0
- cyver_mcp-0.4.0/src/cyver_mcp/setup_wizard.py +141 -0
- cyver_mcp-0.4.0/src/cyver_mcp/severity.py +67 -0
- cyver_mcp-0.4.0/src/cyver_mcp/writes.py +1664 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/PKG-INFO +245 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/SOURCES.txt +21 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/dependency_links.txt +1 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/entry_points.txt +4 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/requires.txt +3 -0
- cyver_mcp-0.4.0/src/cyver_mcp.egg-info/top_level.txt +1 -0
cyver_mcp-0.4.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Thoropass
|
|
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 @@
|
|
|
1
|
+
exclude README.md
|
cyver_mcp-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cyver-mcp
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: MCP server exposing the Cyver reporting platform to Claude via the cyver-reporting wrapper.
|
|
5
|
+
Author-email: Husain Murabbi <husain.murabbi@thoropass.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.10
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: cyver-reporting>=0.0.6
|
|
11
|
+
Requires-Dist: mcp[cli]>=1.2.0
|
|
12
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
13
|
+
Dynamic: license-file
|
|
14
|
+
|
|
15
|
+
# cyver-mcp
|
|
16
|
+
|
|
17
|
+
A Model Context Protocol (MCP) server that lets Claude read from and
|
|
18
|
+
write to the [Cyver](https://cyver.io/) pentest reporting platform
|
|
19
|
+
through chat. Wraps the
|
|
20
|
+
[`cyver-reporting`](https://pypi.org/project/cyver-reporting/) Python
|
|
21
|
+
client and exposes 32 tools across reads, writes, and a single gated
|
|
22
|
+
destructive write.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- **20 read tools** (always on): projects, continuous projects,
|
|
27
|
+
findings, clients, users, teams, client assets, plus reference
|
|
28
|
+
data (vulnerability types, report templates, compliance norm
|
|
29
|
+
templates), finding-library lookups, and a binary-file download
|
|
30
|
+
tool that returns inline image content for screenshots / PoC
|
|
31
|
+
captures.
|
|
32
|
+
- **11 write tools** (opt-in via `CYVER_ALLOW_WRITES=1`): create
|
|
33
|
+
findings (from scratch or from a library template, with inline
|
|
34
|
+
evidence), append evidence to existing findings, change finding
|
|
35
|
+
status non-destructively, create / move projects, create clients
|
|
36
|
+
and assets, attach users / assets / teams to projects, upload
|
|
37
|
+
binary evidence files.
|
|
38
|
+
- **1 destructive write** (additionally `CYVER_ALLOW_DESTRUCTIVE=1`):
|
|
39
|
+
`update_finding`, a full PUT that overwrites every field not
|
|
40
|
+
re-supplied. For status-only changes use the non-destructive
|
|
41
|
+
`update_finding_status` instead.
|
|
42
|
+
- **Dry-run preview** on every write tool. Returns the would-be
|
|
43
|
+
request body without sending.
|
|
44
|
+
- **Audit log** as JSON lines on every write. Default sink is
|
|
45
|
+
stderr; set `CYVER_AUDIT_LOG` to a file path to also append there.
|
|
46
|
+
Sensitive values redacted automatically.
|
|
47
|
+
- **Severity 0..4 ↔ label** and **finding status 1..14 ↔ label**
|
|
48
|
+
mappings applied automatically on reads and accepted by name on
|
|
49
|
+
writes.
|
|
50
|
+
- **No secrets in the MCP config block.** The server loads `.env`
|
|
51
|
+
itself.
|
|
52
|
+
|
|
53
|
+
## Requirements
|
|
54
|
+
|
|
55
|
+
- Python 3.10 or newer
|
|
56
|
+
- A Cyver portal account (username + password; 2FA supported)
|
|
57
|
+
- Claude Desktop or Claude Code
|
|
58
|
+
|
|
59
|
+
Pure Python, runs on macOS, Linux, and Windows.
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pipx install cyver-mcp
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`pipx` is the recommended path for CLI tools. Plain
|
|
68
|
+
`pip install cyver-mcp` works too if you prefer to manage your own
|
|
69
|
+
venv.
|
|
70
|
+
|
|
71
|
+
## Quick Start
|
|
72
|
+
|
|
73
|
+
### One-time setup
|
|
74
|
+
|
|
75
|
+
Run the wizard. It writes `~/.config/cyver-mcp/.env` (chmod 600) and
|
|
76
|
+
primes the encrypted refresh-token cache.
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
cyver-mcp setup
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Prompts:
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Portal hostname (e.g. app.cyver.io): app.cyver.io
|
|
86
|
+
Username or email: you@example.com
|
|
87
|
+
Password: ********
|
|
88
|
+
Enable write tools (create findings, projects, etc.)? [y/N]: y
|
|
89
|
+
2FA required. A code has been sent to your email.
|
|
90
|
+
Enter 2FA code: 123456
|
|
91
|
+
OK. Token cached for pentester session on app.cyver.io.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Re-authenticate later
|
|
95
|
+
|
|
96
|
+
When the cached token expires, refresh without re-running setup:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
cyver-mcp login
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Prompts for a 2FA code only when the wrapper raises
|
|
103
|
+
`Cyver2FARequired`. Otherwise silent.
|
|
104
|
+
|
|
105
|
+
To wipe the cache:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
cyver-mcp logout
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Connect Claude Desktop
|
|
112
|
+
|
|
113
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
114
|
+
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
115
|
+
|
|
116
|
+
```json
|
|
117
|
+
{
|
|
118
|
+
"mcpServers": {
|
|
119
|
+
"cyver": {
|
|
120
|
+
"command": "cyver-mcp"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Restart Claude Desktop. The cyver tools appear in the tool list.
|
|
127
|
+
|
|
128
|
+
### Connect Claude Code
|
|
129
|
+
|
|
130
|
+
Add the same block to `.mcp.json` in any project where you want the
|
|
131
|
+
tools available, then restart Claude Code in that directory.
|
|
132
|
+
|
|
133
|
+
### Try it
|
|
134
|
+
|
|
135
|
+
In a new chat:
|
|
136
|
+
|
|
137
|
+
> List three projects from Cyver.
|
|
138
|
+
|
|
139
|
+
Claude calls `search_projects` and returns three real project
|
|
140
|
+
records. To verify writes (if enabled):
|
|
141
|
+
|
|
142
|
+
> Use create_finding with dry_run=true to preview a Critical finding
|
|
143
|
+
> for project P-YYYY-NNNN about MFA missing.
|
|
144
|
+
|
|
145
|
+
You see a `would_send` payload back, with no actual change made on
|
|
146
|
+
the portal.
|
|
147
|
+
|
|
148
|
+
## Tools
|
|
149
|
+
|
|
150
|
+
### Reads (20, always registered)
|
|
151
|
+
|
|
152
|
+
| Tool | Purpose |
|
|
153
|
+
| --------------------------------- | ------------------------------------------------------------------------ |
|
|
154
|
+
| `search_projects` | Filter projects by client, status, or name. |
|
|
155
|
+
| `get_project` | Full detail for one project. |
|
|
156
|
+
| `list_project_report_versions` | Versions of the project's report. |
|
|
157
|
+
| `list_project_checklists` | Checklists associated with a project. |
|
|
158
|
+
| `list_project_compliance_norms` | Compliance norms attached to a project. |
|
|
159
|
+
| `search_continuous_projects` | Filter continuous projects. |
|
|
160
|
+
| `get_continuous_project` | Full detail for one continuous project. |
|
|
161
|
+
| `search_findings` | Filter by project, status, severity, type, client, or free-text. Includes `severityLabel` and `statusLabel`. |
|
|
162
|
+
| `get_finding` | Full finding detail (evidence included by default). |
|
|
163
|
+
| `search_clients` | Filter clients by name/status. |
|
|
164
|
+
| `get_client` | Full client detail. |
|
|
165
|
+
| `list_client_assets` | Assets owned by a client. |
|
|
166
|
+
| `search_users` | Filter users by name, client, or role. |
|
|
167
|
+
| `search_teams` | Filter teams by name, client, or project. |
|
|
168
|
+
| `list_vulnerability_types` | Vulnerability type catalog. |
|
|
169
|
+
| `list_compliance_norm_templates` | Available compliance norm templates. |
|
|
170
|
+
| `list_report_templates` | Available report templates. |
|
|
171
|
+
| `list_finding_libraries` | Finding-library catalog. |
|
|
172
|
+
| `list_finding_templates` | Templates inside a library. |
|
|
173
|
+
| `download_project_file` | Fetch a project file's bytes; returns an inline image content block for `image/*` MIMEs. |
|
|
174
|
+
|
|
175
|
+
### Writes (11, opt-in via `CYVER_ALLOW_WRITES=1`)
|
|
176
|
+
|
|
177
|
+
With the flag unset, the tools are not registered at all (Claude
|
|
178
|
+
can't see or call them).
|
|
179
|
+
|
|
180
|
+
| Tool | Purpose |
|
|
181
|
+
| ----------------------------- | ---------------------------------------------------------------- |
|
|
182
|
+
| `create_finding` | Create a finding on a project (with optional inline evidence; supports `template_id` for from-template creation). |
|
|
183
|
+
| `update_finding_status` | Change a finding's status without touching anything else (load-modify-save). |
|
|
184
|
+
| `add_evidence_to_finding` | Append evidence records to an existing finding (true add). |
|
|
185
|
+
| `create_project` | Create a project for a client. |
|
|
186
|
+
| `update_project_status` | Move a project (ONBOARDING / TESTING / REPORTING / REMEDIATION / COMPLETED). |
|
|
187
|
+
| `create_client` | Create a new client. |
|
|
188
|
+
| `create_client_asset` | Create an asset under a client. |
|
|
189
|
+
| `add_users_to_project` | Append users (true add, no replace). |
|
|
190
|
+
| `add_assets_to_project` | Append assets (true add, no replace). |
|
|
191
|
+
| `add_teams_to_project` | Append teams (true add, no replace). |
|
|
192
|
+
| `upload_evidence_to_project` | Upload a binary file (screenshot, PoC, etc.) as project evidence.|
|
|
193
|
+
|
|
194
|
+
Every write tool accepts `dry_run=True` and emits one audit-log
|
|
195
|
+
line per call.
|
|
196
|
+
|
|
197
|
+
### Destructive writes (1, additionally `CYVER_ALLOW_DESTRUCTIVE=1`)
|
|
198
|
+
|
|
199
|
+
| Tool | Purpose |
|
|
200
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
201
|
+
| `update_finding` | Full PUT update of an existing finding. Overwrites every field not re-supplied, replaces evidence list when supplied. |
|
|
202
|
+
|
|
203
|
+
For status-only changes prefer `update_finding_status` (non-
|
|
204
|
+
destructive, only needs `CYVER_ALLOW_WRITES`).
|
|
205
|
+
|
|
206
|
+
## Configuration
|
|
207
|
+
|
|
208
|
+
### Environment variables
|
|
209
|
+
|
|
210
|
+
The server reads `.env` from `$CYVER_CONFIG`, then `./.env`, then
|
|
211
|
+
`~/.config/cyver-mcp/.env`. Process env always wins over file values.
|
|
212
|
+
|
|
213
|
+
| Variable | Required | Purpose |
|
|
214
|
+
| ------------------------- | --------- | ----------------------------------------------------------------------------- |
|
|
215
|
+
| `CYVER_PORTAL` | yes | Portal hostname, e.g. `app.cyver.io`. |
|
|
216
|
+
| `CYVER_USERNAME` | preferred | Cyver username or email. Primary auth path. |
|
|
217
|
+
| `CYVER_PASSWORD` | preferred | Used with `CYVER_USERNAME`. |
|
|
218
|
+
| `CYVER_API_KEY` | optional | Static API key. Leave blank to use username/password. |
|
|
219
|
+
| `CYVER_SESSION_TYPE` | optional | `pentester` (default) or `client`. |
|
|
220
|
+
| `CYVER_ALLOW_WRITES` | optional | `1` to register the 11 write tools. Default: off. |
|
|
221
|
+
| `CYVER_ALLOW_DESTRUCTIVE` | optional | `1` to also register `update_finding`. Has no effect without `CYVER_ALLOW_WRITES=1`. |
|
|
222
|
+
| `CYVER_AUDIT_LOG` | optional | Path to append audit-log JSON lines. Default: stderr. |
|
|
223
|
+
| `CYVER_CONFIG` | optional | Override the `.env` search path. |
|
|
224
|
+
|
|
225
|
+
Username/password is the preferred path. Static API keys are
|
|
226
|
+
supported as a fallback when one is available.
|
|
227
|
+
|
|
228
|
+
### Audit log
|
|
229
|
+
|
|
230
|
+
Every write tool (live or dry-run) emits one JSON object per line:
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{"ts":"2026-04-27T10:46:21Z","tool":"create_finding","target":"<project_id>","result":"ok","params":{...}}
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`result` is one of `ok`, `dry_run`, or `error:<ExceptionName>`.
|
|
237
|
+
Sensitive values (passwords, tokens, 2FA codes) are redacted before
|
|
238
|
+
the line is written.
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
MIT.
|
|
243
|
+
|
|
244
|
+
Developed and maintained by penetration testers at
|
|
245
|
+
[Thoropass](https://thoropass.com/).
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# cyver-mcp
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that lets Claude read from and
|
|
4
|
+
write to the [Cyver](https://cyver.io/) pentest reporting platform
|
|
5
|
+
through chat. Wraps the
|
|
6
|
+
[`cyver-reporting`](https://pypi.org/project/cyver-reporting/) Python
|
|
7
|
+
client and exposes 32 tools across reads, writes, and a single gated
|
|
8
|
+
destructive write.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **20 read tools** (always on): projects, continuous projects,
|
|
13
|
+
findings, clients, users, teams, client assets, plus reference
|
|
14
|
+
data (vulnerability types, report templates, compliance norm
|
|
15
|
+
templates), finding-library lookups, and a binary-file download
|
|
16
|
+
tool that returns inline image content for screenshots / PoC
|
|
17
|
+
captures.
|
|
18
|
+
- **11 write tools** (opt-in via `CYVER_ALLOW_WRITES=1`): create
|
|
19
|
+
findings (from scratch or from a library template, with inline
|
|
20
|
+
evidence), append evidence to existing findings, change finding
|
|
21
|
+
status non-destructively, create / move projects, create clients
|
|
22
|
+
and assets, attach users / assets / teams to projects, upload
|
|
23
|
+
binary evidence files.
|
|
24
|
+
- **1 destructive write** (additionally `CYVER_ALLOW_DESTRUCTIVE=1`):
|
|
25
|
+
`update_finding`, a full PUT that overwrites every field not
|
|
26
|
+
re-supplied. For status-only changes use the non-destructive
|
|
27
|
+
`update_finding_status` instead.
|
|
28
|
+
- **Dry-run preview** on every write tool. Returns the would-be
|
|
29
|
+
request body without sending.
|
|
30
|
+
- **Audit log** as JSON lines on every write. Default sink is
|
|
31
|
+
stderr; set `CYVER_AUDIT_LOG` to a file path to also append there.
|
|
32
|
+
Sensitive values redacted automatically.
|
|
33
|
+
- **Severity 0..4 ↔ label** and **finding status 1..14 ↔ label**
|
|
34
|
+
mappings applied automatically on reads and accepted by name on
|
|
35
|
+
writes.
|
|
36
|
+
- **No secrets in the MCP config block.** The server loads `.env`
|
|
37
|
+
itself.
|
|
38
|
+
|
|
39
|
+
## Requirements
|
|
40
|
+
|
|
41
|
+
- Python 3.10 or newer
|
|
42
|
+
- A Cyver portal account (username + password; 2FA supported)
|
|
43
|
+
- Claude Desktop or Claude Code
|
|
44
|
+
|
|
45
|
+
Pure Python, runs on macOS, Linux, and Windows.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pipx install cyver-mcp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
`pipx` is the recommended path for CLI tools. Plain
|
|
54
|
+
`pip install cyver-mcp` works too if you prefer to manage your own
|
|
55
|
+
venv.
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
### One-time setup
|
|
60
|
+
|
|
61
|
+
Run the wizard. It writes `~/.config/cyver-mcp/.env` (chmod 600) and
|
|
62
|
+
primes the encrypted refresh-token cache.
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cyver-mcp setup
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Prompts:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
Portal hostname (e.g. app.cyver.io): app.cyver.io
|
|
72
|
+
Username or email: you@example.com
|
|
73
|
+
Password: ********
|
|
74
|
+
Enable write tools (create findings, projects, etc.)? [y/N]: y
|
|
75
|
+
2FA required. A code has been sent to your email.
|
|
76
|
+
Enter 2FA code: 123456
|
|
77
|
+
OK. Token cached for pentester session on app.cyver.io.
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Re-authenticate later
|
|
81
|
+
|
|
82
|
+
When the cached token expires, refresh without re-running setup:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
cyver-mcp login
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Prompts for a 2FA code only when the wrapper raises
|
|
89
|
+
`Cyver2FARequired`. Otherwise silent.
|
|
90
|
+
|
|
91
|
+
To wipe the cache:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
cyver-mcp logout
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Connect Claude Desktop
|
|
98
|
+
|
|
99
|
+
Edit `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
100
|
+
(macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
|
|
101
|
+
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"mcpServers": {
|
|
105
|
+
"cyver": {
|
|
106
|
+
"command": "cyver-mcp"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Restart Claude Desktop. The cyver tools appear in the tool list.
|
|
113
|
+
|
|
114
|
+
### Connect Claude Code
|
|
115
|
+
|
|
116
|
+
Add the same block to `.mcp.json` in any project where you want the
|
|
117
|
+
tools available, then restart Claude Code in that directory.
|
|
118
|
+
|
|
119
|
+
### Try it
|
|
120
|
+
|
|
121
|
+
In a new chat:
|
|
122
|
+
|
|
123
|
+
> List three projects from Cyver.
|
|
124
|
+
|
|
125
|
+
Claude calls `search_projects` and returns three real project
|
|
126
|
+
records. To verify writes (if enabled):
|
|
127
|
+
|
|
128
|
+
> Use create_finding with dry_run=true to preview a Critical finding
|
|
129
|
+
> for project P-YYYY-NNNN about MFA missing.
|
|
130
|
+
|
|
131
|
+
You see a `would_send` payload back, with no actual change made on
|
|
132
|
+
the portal.
|
|
133
|
+
|
|
134
|
+
## Tools
|
|
135
|
+
|
|
136
|
+
### Reads (20, always registered)
|
|
137
|
+
|
|
138
|
+
| Tool | Purpose |
|
|
139
|
+
| --------------------------------- | ------------------------------------------------------------------------ |
|
|
140
|
+
| `search_projects` | Filter projects by client, status, or name. |
|
|
141
|
+
| `get_project` | Full detail for one project. |
|
|
142
|
+
| `list_project_report_versions` | Versions of the project's report. |
|
|
143
|
+
| `list_project_checklists` | Checklists associated with a project. |
|
|
144
|
+
| `list_project_compliance_norms` | Compliance norms attached to a project. |
|
|
145
|
+
| `search_continuous_projects` | Filter continuous projects. |
|
|
146
|
+
| `get_continuous_project` | Full detail for one continuous project. |
|
|
147
|
+
| `search_findings` | Filter by project, status, severity, type, client, or free-text. Includes `severityLabel` and `statusLabel`. |
|
|
148
|
+
| `get_finding` | Full finding detail (evidence included by default). |
|
|
149
|
+
| `search_clients` | Filter clients by name/status. |
|
|
150
|
+
| `get_client` | Full client detail. |
|
|
151
|
+
| `list_client_assets` | Assets owned by a client. |
|
|
152
|
+
| `search_users` | Filter users by name, client, or role. |
|
|
153
|
+
| `search_teams` | Filter teams by name, client, or project. |
|
|
154
|
+
| `list_vulnerability_types` | Vulnerability type catalog. |
|
|
155
|
+
| `list_compliance_norm_templates` | Available compliance norm templates. |
|
|
156
|
+
| `list_report_templates` | Available report templates. |
|
|
157
|
+
| `list_finding_libraries` | Finding-library catalog. |
|
|
158
|
+
| `list_finding_templates` | Templates inside a library. |
|
|
159
|
+
| `download_project_file` | Fetch a project file's bytes; returns an inline image content block for `image/*` MIMEs. |
|
|
160
|
+
|
|
161
|
+
### Writes (11, opt-in via `CYVER_ALLOW_WRITES=1`)
|
|
162
|
+
|
|
163
|
+
With the flag unset, the tools are not registered at all (Claude
|
|
164
|
+
can't see or call them).
|
|
165
|
+
|
|
166
|
+
| Tool | Purpose |
|
|
167
|
+
| ----------------------------- | ---------------------------------------------------------------- |
|
|
168
|
+
| `create_finding` | Create a finding on a project (with optional inline evidence; supports `template_id` for from-template creation). |
|
|
169
|
+
| `update_finding_status` | Change a finding's status without touching anything else (load-modify-save). |
|
|
170
|
+
| `add_evidence_to_finding` | Append evidence records to an existing finding (true add). |
|
|
171
|
+
| `create_project` | Create a project for a client. |
|
|
172
|
+
| `update_project_status` | Move a project (ONBOARDING / TESTING / REPORTING / REMEDIATION / COMPLETED). |
|
|
173
|
+
| `create_client` | Create a new client. |
|
|
174
|
+
| `create_client_asset` | Create an asset under a client. |
|
|
175
|
+
| `add_users_to_project` | Append users (true add, no replace). |
|
|
176
|
+
| `add_assets_to_project` | Append assets (true add, no replace). |
|
|
177
|
+
| `add_teams_to_project` | Append teams (true add, no replace). |
|
|
178
|
+
| `upload_evidence_to_project` | Upload a binary file (screenshot, PoC, etc.) as project evidence.|
|
|
179
|
+
|
|
180
|
+
Every write tool accepts `dry_run=True` and emits one audit-log
|
|
181
|
+
line per call.
|
|
182
|
+
|
|
183
|
+
### Destructive writes (1, additionally `CYVER_ALLOW_DESTRUCTIVE=1`)
|
|
184
|
+
|
|
185
|
+
| Tool | Purpose |
|
|
186
|
+
| ----------------- | ------------------------------------------------------------------------------------------------------------- |
|
|
187
|
+
| `update_finding` | Full PUT update of an existing finding. Overwrites every field not re-supplied, replaces evidence list when supplied. |
|
|
188
|
+
|
|
189
|
+
For status-only changes prefer `update_finding_status` (non-
|
|
190
|
+
destructive, only needs `CYVER_ALLOW_WRITES`).
|
|
191
|
+
|
|
192
|
+
## Configuration
|
|
193
|
+
|
|
194
|
+
### Environment variables
|
|
195
|
+
|
|
196
|
+
The server reads `.env` from `$CYVER_CONFIG`, then `./.env`, then
|
|
197
|
+
`~/.config/cyver-mcp/.env`. Process env always wins over file values.
|
|
198
|
+
|
|
199
|
+
| Variable | Required | Purpose |
|
|
200
|
+
| ------------------------- | --------- | ----------------------------------------------------------------------------- |
|
|
201
|
+
| `CYVER_PORTAL` | yes | Portal hostname, e.g. `app.cyver.io`. |
|
|
202
|
+
| `CYVER_USERNAME` | preferred | Cyver username or email. Primary auth path. |
|
|
203
|
+
| `CYVER_PASSWORD` | preferred | Used with `CYVER_USERNAME`. |
|
|
204
|
+
| `CYVER_API_KEY` | optional | Static API key. Leave blank to use username/password. |
|
|
205
|
+
| `CYVER_SESSION_TYPE` | optional | `pentester` (default) or `client`. |
|
|
206
|
+
| `CYVER_ALLOW_WRITES` | optional | `1` to register the 11 write tools. Default: off. |
|
|
207
|
+
| `CYVER_ALLOW_DESTRUCTIVE` | optional | `1` to also register `update_finding`. Has no effect without `CYVER_ALLOW_WRITES=1`. |
|
|
208
|
+
| `CYVER_AUDIT_LOG` | optional | Path to append audit-log JSON lines. Default: stderr. |
|
|
209
|
+
| `CYVER_CONFIG` | optional | Override the `.env` search path. |
|
|
210
|
+
|
|
211
|
+
Username/password is the preferred path. Static API keys are
|
|
212
|
+
supported as a fallback when one is available.
|
|
213
|
+
|
|
214
|
+
### Audit log
|
|
215
|
+
|
|
216
|
+
Every write tool (live or dry-run) emits one JSON object per line:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{"ts":"2026-04-27T10:46:21Z","tool":"create_finding","target":"<project_id>","result":"ok","params":{...}}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`result` is one of `ok`, `dry_run`, or `error:<ExceptionName>`.
|
|
223
|
+
Sensitive values (passwords, tokens, 2FA codes) are redacted before
|
|
224
|
+
the line is written.
|
|
225
|
+
|
|
226
|
+
## License
|
|
227
|
+
|
|
228
|
+
MIT.
|
|
229
|
+
|
|
230
|
+
Developed and maintained by penetration testers at
|
|
231
|
+
[Thoropass](https://thoropass.com/).
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "cyver-mcp"
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "MCP server exposing the Cyver reporting platform to Claude via the cyver-reporting wrapper."
|
|
9
|
+
readme = "README.pypi.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "Husain Murabbi", email = "husain.murabbi@thoropass.com" }]
|
|
13
|
+
dependencies = [
|
|
14
|
+
# v0.0.4 ships heylaika/cyver-reporting PR #21 (labelList fix).
|
|
15
|
+
# PR #23 (DONE status) is still open upstream; harmless for us because
|
|
16
|
+
# our raw _send_api_request path doesn't go through the wrapper's
|
|
17
|
+
# project-status validator. Bump the floor when #23 ships.
|
|
18
|
+
"cyver-reporting>=0.0.6",
|
|
19
|
+
"mcp[cli]>=1.2.0",
|
|
20
|
+
"python-dotenv>=1.0.0",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.scripts]
|
|
24
|
+
cyver-mcp = "cyver_mcp.__main__:main"
|
|
25
|
+
cyver-mcp-login = "cyver_mcp.login:main"
|
|
26
|
+
cyver-mcp-logout = "cyver_mcp.logout:main"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["src"]
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Entry point for `cyver-mcp` (and `python -m cyver_mcp`).
|
|
2
|
+
|
|
3
|
+
Subcommand dispatcher modeled on `aws` / `gh`:
|
|
4
|
+
|
|
5
|
+
- `cyver-mcp setup` — one-time interactive setup wizard
|
|
6
|
+
- `cyver-mcp login` — re-authenticate (refresh token cache)
|
|
7
|
+
- `cyver-mcp logout` — wipe token cache
|
|
8
|
+
- `cyver-mcp` — run the MCP server (default)
|
|
9
|
+
|
|
10
|
+
The default-to-server behavior preserves the existing Claude Desktop
|
|
11
|
+
config (`["-m", "cyver_mcp"]`) — no edits needed when upgrading from
|
|
12
|
+
v0.3.x.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import argparse
|
|
18
|
+
import sys
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def main() -> int:
|
|
22
|
+
parser = argparse.ArgumentParser(
|
|
23
|
+
prog="cyver-mcp",
|
|
24
|
+
description=(
|
|
25
|
+
"MCP server for the Cyver pentest reporting platform. "
|
|
26
|
+
"Run with no subcommand to start the server."
|
|
27
|
+
),
|
|
28
|
+
)
|
|
29
|
+
subparsers = parser.add_subparsers(dest="cmd")
|
|
30
|
+
|
|
31
|
+
setup_p = subparsers.add_parser(
|
|
32
|
+
"setup",
|
|
33
|
+
help="One-time setup wizard (writes .env and primes token cache)",
|
|
34
|
+
)
|
|
35
|
+
setup_p.add_argument(
|
|
36
|
+
"--force",
|
|
37
|
+
action="store_true",
|
|
38
|
+
help="Overwrite an existing config file",
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
subparsers.add_parser(
|
|
42
|
+
"login",
|
|
43
|
+
help="Re-authenticate using saved config (refresh token cache)",
|
|
44
|
+
)
|
|
45
|
+
subparsers.add_parser(
|
|
46
|
+
"logout",
|
|
47
|
+
help="Wipe the encrypted token cache",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
args = parser.parse_args()
|
|
51
|
+
|
|
52
|
+
if args.cmd == "setup":
|
|
53
|
+
from cyver_mcp import setup_wizard
|
|
54
|
+
|
|
55
|
+
return setup_wizard.main(force=args.force)
|
|
56
|
+
if args.cmd == "login":
|
|
57
|
+
from cyver_mcp import login
|
|
58
|
+
|
|
59
|
+
return login.main()
|
|
60
|
+
if args.cmd == "logout":
|
|
61
|
+
from cyver_mcp import logout
|
|
62
|
+
|
|
63
|
+
return logout.main()
|
|
64
|
+
|
|
65
|
+
# No subcommand → run the MCP server.
|
|
66
|
+
from cyver_mcp.server import main as server_main
|
|
67
|
+
|
|
68
|
+
server_main()
|
|
69
|
+
return 0
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
if __name__ == "__main__":
|
|
73
|
+
sys.exit(main())
|