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.
@@ -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
@@ -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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """MCP server for the Cyver reporting platform."""
2
+
3
+ __version__ = "0.4.0"
@@ -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())