mcppt 1.1.0__tar.gz → 3.0.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.
Files changed (32) hide show
  1. {mcppt-1.1.0 → mcppt-3.0.0}/.github/workflows/ci.yml +2 -5
  2. {mcppt-1.1.0 → mcppt-3.0.0}/PKG-INFO +107 -100
  3. {mcppt-1.1.0 → mcppt-3.0.0}/README.md +106 -99
  4. mcppt-3.0.0/mcppt/__init__.py +1 -0
  5. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/cli.py +1 -1
  6. {mcppt-1.1.0 → mcppt-3.0.0}/pyproject.toml +1 -1
  7. {mcppt-1.1.0 → mcppt-3.0.0}/smoke_test.py +2 -2
  8. {mcppt-1.1.0 → mcppt-3.0.0}/vuln_server.py +3 -3
  9. mcppt-1.1.0/mcppt/__init__.py +0 -1
  10. {mcppt-1.1.0 → mcppt-3.0.0}/.gitignore +0 -0
  11. {mcppt-1.1.0 → mcppt-3.0.0}/LICENSE +0 -0
  12. {mcppt-1.1.0 → mcppt-3.0.0}/OPERATOR_GUIDE.md +0 -0
  13. {mcppt-1.1.0 → mcppt-3.0.0}/app.py +0 -0
  14. {mcppt-1.1.0 → mcppt-3.0.0}/docs/MCPTROTTER_ARTICLE.md +0 -0
  15. {mcppt-1.1.0 → mcppt-3.0.0}/docs/MCPTROTTER_MEDIUM.md +0 -0
  16. {mcppt-1.1.0 → mcppt-3.0.0}/docs/STUDY_GUIDE.md +0 -0
  17. {mcppt-1.1.0 → mcppt-3.0.0}/docs/mcptrotter.jpeg +0 -0
  18. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/checks.py +0 -0
  19. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/core.py +0 -0
  20. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/report.py +0 -0
  21. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/server.py +0 -0
  22. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/shell.py +0 -0
  23. {mcppt-1.1.0 → mcppt-3.0.0}/mcppt/tui.py +0 -0
  24. {mcppt-1.1.0 → mcppt-3.0.0}/requirements.txt +0 -0
  25. {mcppt-1.1.0 → mcppt-3.0.0}/test_report.md +0 -0
  26. {mcppt-1.1.0 → mcppt-3.0.0}/test_server.log +0 -0
  27. {mcppt-1.1.0 → mcppt-3.0.0}/test_server.py +0 -0
  28. {mcppt-1.1.0 → mcppt-3.0.0}/tests/__init__.py +0 -0
  29. {mcppt-1.1.0 → mcppt-3.0.0}/tests/test_checks.py +0 -0
  30. {mcppt-1.1.0 → mcppt-3.0.0}/tests/test_core.py +0 -0
  31. {mcppt-1.1.0 → mcppt-3.0.0}/wbs_mcppt_result.md +0 -0
  32. {mcppt-1.1.0 → mcppt-3.0.0}/wbs_scan_report.md +0 -0
@@ -64,17 +64,14 @@ jobs:
64
64
  needs: build
65
65
  runs-on: ubuntu-latest
66
66
  if: startsWith(github.ref, 'refs/tags/v')
67
- environment:
68
- name: pypi
69
- url: https://pypi.org/project/mcppt/
70
- permissions:
71
- id-token: write # trusted publishing (no API key needed)
72
67
  steps:
73
68
  - uses: actions/download-artifact@v4
74
69
  with:
75
70
  name: dist
76
71
  path: dist/
77
72
  - uses: pypa/gh-action-pypi-publish@release/v1
73
+ with:
74
+ password: ${{ secrets.PYPI_API_TOKEN }}
78
75
 
79
76
  # ── Create GitHub Release on version tag ───────────────────────────────────
80
77
  release:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcppt
3
- Version: 1.1.0
3
+ Version: 3.0.0
4
4
  Summary: MCPTROTTER — MCP Security Framework: 31 automated checks + manual exploration shell
5
5
  Project-URL: Homepage, https://github.com/gurudeepmallam-cmd/mcppt
6
6
  Project-URL: Repository, https://github.com/gurudeepmallam-cmd/mcppt
@@ -30,7 +30,7 @@ Provides-Extra: ui
30
30
  Requires-Dist: streamlit>=1.30; extra == 'ui'
31
31
  Description-Content-Type: text/markdown
32
32
 
33
- # MCPTROTTER — MCP Pentest Tool
33
+ # MCPTROTTER — MCP Security Framework
34
34
 
35
35
  <p align="center">
36
36
  <img src="https://raw.githubusercontent.com/gurudeepmallam-cmd/mcppt/main/docs/mcptrotter.jpeg" alt="MCPTROTTER" width="380"/>
@@ -39,7 +39,7 @@ Description-Content-Type: text/markdown
39
39
  <p align="center">
40
40
  <img src="https://img.shields.io/pypi/v/mcppt?label=PyPI&color=orange"/>
41
41
  <img src="https://img.shields.io/badge/python-3.10%2B-blue"/>
42
- <img src="https://img.shields.io/badge/checks-28-red"/>
42
+ <img src="https://img.shields.io/badge/checks-31-red"/>
43
43
  <img src="https://img.shields.io/badge/license-MIT-green"/>
44
44
  <img src="https://img.shields.io/badge/part%20of-Bugtrotter-black"/>
45
45
  </p>
@@ -51,19 +51,15 @@ Description-Content-Type: text/markdown
51
51
 
52
52
  ---
53
53
 
54
- ## What it does
54
+ ## What it is
55
55
 
56
- MCPTROTTER is a command-line security scanner for **MCP (Model Context Protocol)** servers. Point it at any MCP endpoint and it runs 28 automated checks across:
56
+ MCPTROTTER is a **security framework** for testing MCP (Model Context Protocol) servers. It works two ways:
57
57
 
58
- - Authentication bypass and token abuse
59
- - Prompt injection (direct, stored, poison-all fields)
60
- - SSRF, command injection, path traversal
61
- - Session entropy and replay attacks
62
- - Tenant isolation and IDOR
63
- - Tool poisoning and rug pulls
64
- - Transport misconfigurations and secret leaks
58
+ **Manual exploration** connect to any MCP server and interact with it the way an attacker would. Call tools directly, inspect schemas, fuzz parameters, read resources, send raw JSON-RPC methods. No scan needed. You control every request.
65
59
 
66
- Works against any MCP server using Streamable HTTP transport (POST + SSE response). Integrates with Burp Suite for manual follow-up. Exports pentest-ready Markdown reports.
60
+ **Automated scanning** run 31 security checks in under 60 seconds. Auth bypass, stored injection, replay attacks, session entropy, tenant isolation, tool poisoning, command injection, and more.
61
+
62
+ Both modes route through Burp Suite so you see every request in HTTP History and can follow up in Repeater.
67
63
 
68
64
  ---
69
65
 
@@ -107,29 +103,26 @@ python test_server.py
107
103
  mcppt
108
104
  ```
109
105
 
110
- You'll see:
111
106
  ```
112
107
  __ __ ___ ___ _____ ____ ___ _____ _____ ___ ___
113
108
  | \/ | / __|| _ \|_ _| _ \ / _ \_ _|_ _| __| _ \
114
109
  | |\/| || (__| _/ | | | / | (_) || | | | | _|| /
115
110
  |_| |_| \___||_| |_| |_|_\ \___/ |_| |_| |___|_|_\
116
111
 
117
- MCP Pentest Tool v2.1 -- 16 automated security checks
112
+ MCP Pentest Framework v3.0 -- 31 checks + manual exploration
118
113
 
119
114
  by Gurudeep Mallam
120
- github : https://github.com/gurudeepmallam-cmd
121
- linkedin: https://in.linkedin.com/in/mallam-gurudeep-7734941aa
122
-
123
- type 'help' for commands, 'exit' to quit
124
115
 
125
- mcppt>
116
+ Quick start: target <url> → connect → list → scan
117
+ Manual test: call <tool> <args> | raw <method> | fuzz <tool> <param> <type>
126
118
  ```
127
119
 
128
120
  **Paste these commands one by one:**
129
121
  ```
130
122
  target http://127.0.0.1:8888/mcp
131
123
  token valid-token-abc123
132
- status
124
+ connect
125
+ list
133
126
  scan
134
127
  findings
135
128
  report demo.md
@@ -139,10 +132,10 @@ report demo.md
139
132
 
140
133
  ## Expected output — demo server scan
141
134
 
142
- Running `scan` with token set produces this (6.7 seconds):
135
+ Running `scan` with token set produces this (under 60 seconds):
143
136
 
144
137
  ```
145
- Duration: 6.7s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
138
+ Duration: ~45s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
146
139
  ```
147
140
 
148
141
  | Severity | Check | Finding |
@@ -169,43 +162,80 @@ Duration: 6.7s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
169
162
 
170
163
  ---
171
164
 
172
- ## All commands (interactive shell)
165
+ ## All commands
173
166
 
167
+ ### Setup
168
+ ```
169
+ target <url> Set MCP server URL
170
+ token <bearer> Set primary auth token
171
+ token2 <bearer> Set second user token (IDOR / scope / tenant checks)
172
+ noverify Toggle SSL verification skip (needed for self-signed certs)
173
+ proxy <url|off> Set Burp proxy: proxy http://127.0.0.1:8080
174
+ verbose Toggle raw HTTP request/response logging
175
+ status Show current session configuration
174
176
  ```
175
- Setup
176
- target <url> Set MCP server URL
177
- token <bearer> Set primary auth token
178
- token2 <bearer> Set second user token (IDOR / scope / tenant checks)
179
- noverify Toggle SSL verification skip (needed for self-signed certs)
180
- proxy <url|off> Set Burp proxy: proxy http://127.0.0.1:8080
181
- status Show current config before scanning
182
177
 
183
- Enumerate
184
- list List all tools the server exposes (names, params, descriptions)
185
- call <tool> [json] Manually call any tool
186
- call get_notes
187
- call get_user {"id": 1}
188
- call save_note {"text": "hello"}
178
+ ### Manual exploration
179
+ ```
180
+ connect Test connection + show server name, version, capabilities
181
+ list List all tools the server exposes (names, schemas, params)
182
+ inspect <tool> Show full JSON schema for a specific tool
183
+ call <tool> [json] Call any tool directly with your own arguments
184
+ call get_notes
185
+ call get_user {"id": 1}
186
+ call save_note {"text": "test injection payload"}
187
+ raw <method> [params] Send any raw JSON-RPC method
188
+ raw tools/list
189
+ raw resources/list
190
+ raw sampling/createMessage {...}
191
+ resources [read <uri>] List resources or read a specific URI
192
+ prompts [get <name>] List prompts or get a specific prompt
193
+ headers Show HTTP response headers from the last request
194
+ ```
189
195
 
190
- Scan
191
- scan Run all checks
192
- scan auth ssrf idor Run specific checks only
193
- scan stored injection Mix and match any check names
196
+ ### Targeted testing
197
+ ```
198
+ fuzz <tool> <param> <type|file> Fuzz a specific tool parameter
199
+
200
+ Built-in wordlists:
201
+ sqli SQL injection payloads
202
+ xss XSS and template injection
203
+ traversal Path traversal (../etc/passwd, encoded variants)
204
+ cmd OS command injection (; id, $(id), | whoami)
205
+ ssrf SSRF targets (169.254.169.254, localhost)
206
+ ssti Server-side template injection
207
+ inject Prompt injection payloads for LLM tools
208
+
209
+ Custom: fuzz read_file path /path/to/payloads.txt
210
+
211
+ Examples:
212
+ fuzz get_user id sqli
213
+ fuzz save_note text inject
214
+ fuzz read_file path traversal
215
+ ```
194
216
 
195
- Results
196
- findings Colour-coded findings table
197
- clear Clear findings from last scan
198
- report out.md Export Markdown report
199
- report out.json Export JSON report
217
+ ### Automated scan
218
+ ```
219
+ scan Run all 31 checks
220
+ scan auth ssrf idor Run specific checks only
221
+ scan stored injection Mix and match any check names
222
+ ```
200
223
 
201
- AI analysis (optional — paste your key first)
202
- ai claude sk-ant-... Configure Claude for analysis
203
- ai openai sk-... Configure OpenAI GPT-4o
204
- analyze Attack narrative + remediation priority from findings
224
+ ### Findings
225
+ ```
226
+ note <sev> <check> <title> [| detail] Manually log a finding
227
+ note HIGH manual_test Input reflected | seen in 500 response
228
+ findings Colour-coded findings table (scan + manual notes)
229
+ clear Clear findings and tool cache
230
+ report out.md Export Markdown report
231
+ report out.json Export JSON report
232
+ ```
205
233
 
206
- Shell
207
- help Full command reference
208
- exit Quit
234
+ ### AI analysis (optional)
235
+ ```
236
+ ai claude sk-ant-... Configure Claude for analysis
237
+ ai openai sk-... Configure OpenAI GPT-4o
238
+ analyze Attack narrative + remediation priority from findings
209
239
  ```
210
240
 
211
241
  ---
@@ -238,7 +268,7 @@ Burp Suite → **Proxy → Proxy Settings**
238
268
 
239
269
  Confirm the listener is `127.0.0.1:8080` (it is by default). No changes needed.
240
270
 
241
- ### Step 2 — Run scan through proxy
271
+ ### Step 2 — Run through proxy
242
272
 
243
273
  Inside the shell:
244
274
  ```
@@ -258,9 +288,11 @@ mcppt scan --url https://target.com/mcp --token eyJ... --proxy http://127.0.0.1:
258
288
 
259
289
  Burp → **Proxy → HTTP History**
260
290
 
261
- Every MCP tool call appears as a `POST /mcp` request. Each row shows the JSON-RPC method and the response. You'll see one row per check — `initialize`, `tools/list`, `tools/call` for each tool tested.
291
+ Every MCP tool call appears as a `POST /mcp` request. You'll see `initialize`, `tools/list`, `tools/call` for each check. Manual commands (`call`, `raw`, `fuzz`) also appear here — every request MCPTROTTER makes goes through Burp.
292
+
293
+ ### Step 4 — Send to Repeater for manual testing
262
294
 
263
- Click any row to see the full request and response body:
295
+ Right-click any request **Send to Repeater** (`Ctrl+R`).
264
296
 
265
297
  ```
266
298
  POST /mcp HTTP/1.1
@@ -271,42 +303,17 @@ Content-Type: application/json
271
303
  {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_notes","arguments":{}}}
272
304
  ```
273
305
 
274
- ### Step 4 Send to Repeater for manual testing
275
-
276
- In HTTP History, right-click any request → **Send to Repeater** (or `Ctrl+R`).
277
-
278
- Switch to the **Repeater** tab. You'll see the exact request MCPTROTTER sent.
279
-
280
- **To keep the connection alive and replay successfully:**
281
-
282
- 1. Check the **Host** field matches your target (e.g. `127.0.0.1` port `8888` for demo server, or your real target host/port)
283
- 2. If targeting HTTP (not HTTPS), make sure the **lock icon** in Repeater shows unlocked — click it to toggle if needed
284
- 3. The MCP session ID in `mcp-session-id` header may expire — if you get a session error, re-initialize:
285
- - Copy the `initialize` request from HTTP History into Repeater first
286
- - Send it, copy the `mcp-session-id` from the response header
287
- - Paste it into the header of your target request
288
- 4. Click **Send** — response appears on the right
289
-
290
- **Modifying requests in Repeater:**
291
-
292
- ```json
293
- {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
294
- "name":"get_user",
295
- "arguments":{"id": 2}
296
- }}
297
- ```
306
+ Change `"id": 2` to `"id": 1` to test IDOR. Swap the token to another user's. Modify `"name"` to call a different tool.
298
307
 
299
- Change `"id": 2` to `"id": 1` to test IDOR. Change the token in Authorization to another user's token. Modify `"name"` to call a different tool. Repeater sends exactly what you write.
308
+ If you get a session error, copy the `initialize` request from HTTP History into Repeater first, send it, and copy the `mcp-session-id` header value into your target request.
300
309
 
301
310
  ### Step 5 — Fuzz with Intruder
302
311
 
303
- Right-click a request in Repeater → **Send to Intruder**.
304
-
305
- Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**. Load a wordlist (Burp's built-in fuzzing strings, or a custom injection list). Run the attack and sort by response length or status code to spot anomalies.
312
+ Right-click any Repeater request → **Send to Intruder**. Highlight the parameter value, click **Add §**, load a wordlist, run the attack.
306
313
 
307
314
  ---
308
315
 
309
- ## All 28 checks
316
+ ## All 31 checks
310
317
 
311
318
  | # | Check | Severity | What it tests |
312
319
  |---|---|---|---|
@@ -338,6 +345,9 @@ Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**.
338
345
  | 26 | `tool_shadowing` | CRITICAL | Duplicate tool names, homoglyphs, name/desc mismatch |
339
346
  | 27 | `sampling` | CRITICAL | `sampling/createMessage` accessible without auth |
340
347
  | 28 | `schema_leak` | LOW | Sensitive field names / enum values in tool schemas |
348
+ | 29 | `http_method_confusion` | MEDIUM | GET/DELETE/PUT/PATCH accepted on MCP endpoint |
349
+ | 30 | `protocol_downgrade` | MEDIUM | Old protocol versions accepted, server version leaked |
350
+ | 31 | `batch_injection` | MEDIUM | JSON-RPC batch requests, unusual method name injection |
341
351
 
342
352
  ---
343
353
 
@@ -350,9 +360,13 @@ Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**.
350
360
  | Check all response fields for injection | 30+ min | `scan poison_all` — 5s |
351
361
  | Verify session ID entropy | 10 min | `scan session` — 2s |
352
362
  | Check replay on every tool | 20 min | `scan replay` — 5s |
353
- | Full 28-check assessment | 3–6 hours | `scan` — 30s |
363
+ | Full 31-check assessment | 3–6 hours | `scan` — under 60s |
364
+ | Inspect tool schema before testing | 5 min reading docs | `inspect <tool>` — instant |
365
+ | Call a tool with custom payload | Set up in Burp Repeater | `call <tool> {"param": "payload"}` |
366
+ | Fuzz a parameter with 50 payloads | Intruder setup + run | `fuzz <tool> <param> sqli` — 30s |
367
+ | Test any JSON-RPC method directly | Build request in Repeater | `raw <method> <params>` |
354
368
 
355
- MCPTROTTER gives you the baseline in 30 seconds. You spend your time on what matters: manually verifying findings in Burp Repeater and chaining them into a demonstrated attack path.
369
+ MCPTROTTER gives you the baseline in under 60 seconds and puts every request in Burp HTTP History. You spend your time on what matters: manually verifying findings in Repeater and chaining them into a demonstrated attack path.
356
370
 
357
371
  ---
358
372
 
@@ -364,8 +378,8 @@ MCPTROTTER is the public automated scanner extracted from **Bugtrotter** — a f
364
378
 
365
379
  | Capability | MCPTROTTER | Bugtrotter |
366
380
  |---|---|---|
367
- | Automated MCP scan (28 checks) | ✓ | ✓ |
368
- | Manual finding verification | You do it in Burp | Guided playbooks |
381
+ | Automated MCP scan (31 checks) | ✓ | ✓ |
382
+ | Manual tool exploration framework | | |
369
383
  | Chained exploit paths across tools | — | ✓ Full attack chain |
370
384
  | SAST review of MCP server code | — | ✓ |
371
385
  | Burp Suite MCP — business logic abuse | — | ✓ AI-driven |
@@ -374,27 +388,25 @@ MCPTROTTER is the public automated scanner extracted from **Bugtrotter** — a f
374
388
  | Web / API / network pentesting | — | ✓ Full engagement |
375
389
  | Final pentest report | Markdown export | Engagement-grade report |
376
390
 
377
- **MCPTROTTER in fingertips inside Bugtrotter:**
391
+ **MCPTROTTER inside Bugtrotter:**
378
392
 
379
393
  In Bugtrotter, MCPTROTTER runs as a registered MCP server. Claude Code or Claude Desktop calls it directly:
380
394
 
381
395
  ```
382
396
  "Scan https://target.com/mcp for security issues and prioritise findings"
383
397
  → Claude calls scan_target tool
384
- → MCPTROTTER runs all 28 checks
398
+ → MCPTROTTER runs all 31 checks
385
399
  → Findings returned as structured JSON to Claude
386
400
  → Claude reasons over them, chains the critical ones, drafts the report section
387
401
  ```
388
402
 
389
403
  No copy-paste. No context switching. The scan output feeds straight into the AI-driven engagement workflow — SSRF finding becomes an SSRF exploit attempt, auth bypass becomes a credential theft chain, stored injection becomes a demonstrated prompt hijack.
390
404
 
391
- That's the difference: MCPTROTTER finds the candidates in 30 seconds. Bugtrotter turns the candidates into proven, chained, client-ready findings.
392
-
393
405
  ---
394
406
 
395
407
  ## Use MCPTROTTER as an MCP server itself
396
408
 
397
- MCPTROTTER can become an MCP server — exposing its scan capability as tools that any MCP client (Claude Desktop, MCP Inspector, another agent) can call.
409
+ MCPTROTTER can expose its scan capability as tools that any MCP client (Claude Desktop, MCP Inspector, another agent) can call.
398
410
 
399
411
  ```bash
400
412
  mcppt serve-mcp --port 8899
@@ -416,12 +428,7 @@ Tools exposed:
416
428
  - `scan_target` — full scan, returns findings JSON
417
429
  - `list_tools` — enumerate tools on any MCP server
418
430
  - `call_tool` — call any tool on any MCP server
419
- - `get_checks` — list all 28 checks with descriptions
420
-
421
- Inspect with MCP Inspector:
422
- ```bash
423
- npx @modelcontextprotocol/inspector http://127.0.0.1:8899/mcp
424
- ```
431
+ - `get_checks` — list all 31 checks with descriptions
425
432
 
426
433
  ---
427
434
 
@@ -1,4 +1,4 @@
1
- # MCPTROTTER — MCP Pentest Tool
1
+ # MCPTROTTER — MCP Security Framework
2
2
 
3
3
  <p align="center">
4
4
  <img src="https://raw.githubusercontent.com/gurudeepmallam-cmd/mcppt/main/docs/mcptrotter.jpeg" alt="MCPTROTTER" width="380"/>
@@ -7,7 +7,7 @@
7
7
  <p align="center">
8
8
  <img src="https://img.shields.io/pypi/v/mcppt?label=PyPI&color=orange"/>
9
9
  <img src="https://img.shields.io/badge/python-3.10%2B-blue"/>
10
- <img src="https://img.shields.io/badge/checks-28-red"/>
10
+ <img src="https://img.shields.io/badge/checks-31-red"/>
11
11
  <img src="https://img.shields.io/badge/license-MIT-green"/>
12
12
  <img src="https://img.shields.io/badge/part%20of-Bugtrotter-black"/>
13
13
  </p>
@@ -19,19 +19,15 @@
19
19
 
20
20
  ---
21
21
 
22
- ## What it does
22
+ ## What it is
23
23
 
24
- MCPTROTTER is a command-line security scanner for **MCP (Model Context Protocol)** servers. Point it at any MCP endpoint and it runs 28 automated checks across:
24
+ MCPTROTTER is a **security framework** for testing MCP (Model Context Protocol) servers. It works two ways:
25
25
 
26
- - Authentication bypass and token abuse
27
- - Prompt injection (direct, stored, poison-all fields)
28
- - SSRF, command injection, path traversal
29
- - Session entropy and replay attacks
30
- - Tenant isolation and IDOR
31
- - Tool poisoning and rug pulls
32
- - Transport misconfigurations and secret leaks
26
+ **Manual exploration** connect to any MCP server and interact with it the way an attacker would. Call tools directly, inspect schemas, fuzz parameters, read resources, send raw JSON-RPC methods. No scan needed. You control every request.
33
27
 
34
- Works against any MCP server using Streamable HTTP transport (POST + SSE response). Integrates with Burp Suite for manual follow-up. Exports pentest-ready Markdown reports.
28
+ **Automated scanning** run 31 security checks in under 60 seconds. Auth bypass, stored injection, replay attacks, session entropy, tenant isolation, tool poisoning, command injection, and more.
29
+
30
+ Both modes route through Burp Suite so you see every request in HTTP History and can follow up in Repeater.
35
31
 
36
32
  ---
37
33
 
@@ -75,29 +71,26 @@ python test_server.py
75
71
  mcppt
76
72
  ```
77
73
 
78
- You'll see:
79
74
  ```
80
75
  __ __ ___ ___ _____ ____ ___ _____ _____ ___ ___
81
76
  | \/ | / __|| _ \|_ _| _ \ / _ \_ _|_ _| __| _ \
82
77
  | |\/| || (__| _/ | | | / | (_) || | | | | _|| /
83
78
  |_| |_| \___||_| |_| |_|_\ \___/ |_| |_| |___|_|_\
84
79
 
85
- MCP Pentest Tool v2.1 -- 16 automated security checks
80
+ MCP Pentest Framework v3.0 -- 31 checks + manual exploration
86
81
 
87
82
  by Gurudeep Mallam
88
- github : https://github.com/gurudeepmallam-cmd
89
- linkedin: https://in.linkedin.com/in/mallam-gurudeep-7734941aa
90
-
91
- type 'help' for commands, 'exit' to quit
92
83
 
93
- mcppt>
84
+ Quick start: target <url> → connect → list → scan
85
+ Manual test: call <tool> <args> | raw <method> | fuzz <tool> <param> <type>
94
86
  ```
95
87
 
96
88
  **Paste these commands one by one:**
97
89
  ```
98
90
  target http://127.0.0.1:8888/mcp
99
91
  token valid-token-abc123
100
- status
92
+ connect
93
+ list
101
94
  scan
102
95
  findings
103
96
  report demo.md
@@ -107,10 +100,10 @@ report demo.md
107
100
 
108
101
  ## Expected output — demo server scan
109
102
 
110
- Running `scan` with token set produces this (6.7 seconds):
103
+ Running `scan` with token set produces this (under 60 seconds):
111
104
 
112
105
  ```
113
- Duration: 6.7s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
106
+ Duration: ~45s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
114
107
  ```
115
108
 
116
109
  | Severity | Check | Finding |
@@ -137,43 +130,80 @@ Duration: 6.7s Findings: 6 CRITICAL 6 HIGH 13 MEDIUM 3 LOW
137
130
 
138
131
  ---
139
132
 
140
- ## All commands (interactive shell)
133
+ ## All commands
141
134
 
135
+ ### Setup
136
+ ```
137
+ target <url> Set MCP server URL
138
+ token <bearer> Set primary auth token
139
+ token2 <bearer> Set second user token (IDOR / scope / tenant checks)
140
+ noverify Toggle SSL verification skip (needed for self-signed certs)
141
+ proxy <url|off> Set Burp proxy: proxy http://127.0.0.1:8080
142
+ verbose Toggle raw HTTP request/response logging
143
+ status Show current session configuration
142
144
  ```
143
- Setup
144
- target <url> Set MCP server URL
145
- token <bearer> Set primary auth token
146
- token2 <bearer> Set second user token (IDOR / scope / tenant checks)
147
- noverify Toggle SSL verification skip (needed for self-signed certs)
148
- proxy <url|off> Set Burp proxy: proxy http://127.0.0.1:8080
149
- status Show current config before scanning
150
145
 
151
- Enumerate
152
- list List all tools the server exposes (names, params, descriptions)
153
- call <tool> [json] Manually call any tool
154
- call get_notes
155
- call get_user {"id": 1}
156
- call save_note {"text": "hello"}
146
+ ### Manual exploration
147
+ ```
148
+ connect Test connection + show server name, version, capabilities
149
+ list List all tools the server exposes (names, schemas, params)
150
+ inspect <tool> Show full JSON schema for a specific tool
151
+ call <tool> [json] Call any tool directly with your own arguments
152
+ call get_notes
153
+ call get_user {"id": 1}
154
+ call save_note {"text": "test injection payload"}
155
+ raw <method> [params] Send any raw JSON-RPC method
156
+ raw tools/list
157
+ raw resources/list
158
+ raw sampling/createMessage {...}
159
+ resources [read <uri>] List resources or read a specific URI
160
+ prompts [get <name>] List prompts or get a specific prompt
161
+ headers Show HTTP response headers from the last request
162
+ ```
157
163
 
158
- Scan
159
- scan Run all checks
160
- scan auth ssrf idor Run specific checks only
161
- scan stored injection Mix and match any check names
164
+ ### Targeted testing
165
+ ```
166
+ fuzz <tool> <param> <type|file> Fuzz a specific tool parameter
167
+
168
+ Built-in wordlists:
169
+ sqli SQL injection payloads
170
+ xss XSS and template injection
171
+ traversal Path traversal (../etc/passwd, encoded variants)
172
+ cmd OS command injection (; id, $(id), | whoami)
173
+ ssrf SSRF targets (169.254.169.254, localhost)
174
+ ssti Server-side template injection
175
+ inject Prompt injection payloads for LLM tools
176
+
177
+ Custom: fuzz read_file path /path/to/payloads.txt
178
+
179
+ Examples:
180
+ fuzz get_user id sqli
181
+ fuzz save_note text inject
182
+ fuzz read_file path traversal
183
+ ```
162
184
 
163
- Results
164
- findings Colour-coded findings table
165
- clear Clear findings from last scan
166
- report out.md Export Markdown report
167
- report out.json Export JSON report
185
+ ### Automated scan
186
+ ```
187
+ scan Run all 31 checks
188
+ scan auth ssrf idor Run specific checks only
189
+ scan stored injection Mix and match any check names
190
+ ```
168
191
 
169
- AI analysis (optional — paste your key first)
170
- ai claude sk-ant-... Configure Claude for analysis
171
- ai openai sk-... Configure OpenAI GPT-4o
172
- analyze Attack narrative + remediation priority from findings
192
+ ### Findings
193
+ ```
194
+ note <sev> <check> <title> [| detail] Manually log a finding
195
+ note HIGH manual_test Input reflected | seen in 500 response
196
+ findings Colour-coded findings table (scan + manual notes)
197
+ clear Clear findings and tool cache
198
+ report out.md Export Markdown report
199
+ report out.json Export JSON report
200
+ ```
173
201
 
174
- Shell
175
- help Full command reference
176
- exit Quit
202
+ ### AI analysis (optional)
203
+ ```
204
+ ai claude sk-ant-... Configure Claude for analysis
205
+ ai openai sk-... Configure OpenAI GPT-4o
206
+ analyze Attack narrative + remediation priority from findings
177
207
  ```
178
208
 
179
209
  ---
@@ -206,7 +236,7 @@ Burp Suite → **Proxy → Proxy Settings**
206
236
 
207
237
  Confirm the listener is `127.0.0.1:8080` (it is by default). No changes needed.
208
238
 
209
- ### Step 2 — Run scan through proxy
239
+ ### Step 2 — Run through proxy
210
240
 
211
241
  Inside the shell:
212
242
  ```
@@ -226,9 +256,11 @@ mcppt scan --url https://target.com/mcp --token eyJ... --proxy http://127.0.0.1:
226
256
 
227
257
  Burp → **Proxy → HTTP History**
228
258
 
229
- Every MCP tool call appears as a `POST /mcp` request. Each row shows the JSON-RPC method and the response. You'll see one row per check — `initialize`, `tools/list`, `tools/call` for each tool tested.
259
+ Every MCP tool call appears as a `POST /mcp` request. You'll see `initialize`, `tools/list`, `tools/call` for each check. Manual commands (`call`, `raw`, `fuzz`) also appear here — every request MCPTROTTER makes goes through Burp.
260
+
261
+ ### Step 4 — Send to Repeater for manual testing
230
262
 
231
- Click any row to see the full request and response body:
263
+ Right-click any request **Send to Repeater** (`Ctrl+R`).
232
264
 
233
265
  ```
234
266
  POST /mcp HTTP/1.1
@@ -239,42 +271,17 @@ Content-Type: application/json
239
271
  {"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get_notes","arguments":{}}}
240
272
  ```
241
273
 
242
- ### Step 4 Send to Repeater for manual testing
243
-
244
- In HTTP History, right-click any request → **Send to Repeater** (or `Ctrl+R`).
245
-
246
- Switch to the **Repeater** tab. You'll see the exact request MCPTROTTER sent.
247
-
248
- **To keep the connection alive and replay successfully:**
249
-
250
- 1. Check the **Host** field matches your target (e.g. `127.0.0.1` port `8888` for demo server, or your real target host/port)
251
- 2. If targeting HTTP (not HTTPS), make sure the **lock icon** in Repeater shows unlocked — click it to toggle if needed
252
- 3. The MCP session ID in `mcp-session-id` header may expire — if you get a session error, re-initialize:
253
- - Copy the `initialize` request from HTTP History into Repeater first
254
- - Send it, copy the `mcp-session-id` from the response header
255
- - Paste it into the header of your target request
256
- 4. Click **Send** — response appears on the right
257
-
258
- **Modifying requests in Repeater:**
259
-
260
- ```json
261
- {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{
262
- "name":"get_user",
263
- "arguments":{"id": 2}
264
- }}
265
- ```
274
+ Change `"id": 2` to `"id": 1` to test IDOR. Swap the token to another user's. Modify `"name"` to call a different tool.
266
275
 
267
- Change `"id": 2` to `"id": 1` to test IDOR. Change the token in Authorization to another user's token. Modify `"name"` to call a different tool. Repeater sends exactly what you write.
276
+ If you get a session error, copy the `initialize` request from HTTP History into Repeater first, send it, and copy the `mcp-session-id` header value into your target request.
268
277
 
269
278
  ### Step 5 — Fuzz with Intruder
270
279
 
271
- Right-click a request in Repeater → **Send to Intruder**.
272
-
273
- Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**. Load a wordlist (Burp's built-in fuzzing strings, or a custom injection list). Run the attack and sort by response length or status code to spot anomalies.
280
+ Right-click any Repeater request → **Send to Intruder**. Highlight the parameter value, click **Add §**, load a wordlist, run the attack.
274
281
 
275
282
  ---
276
283
 
277
- ## All 28 checks
284
+ ## All 31 checks
278
285
 
279
286
  | # | Check | Severity | What it tests |
280
287
  |---|---|---|---|
@@ -306,6 +313,9 @@ Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**.
306
313
  | 26 | `tool_shadowing` | CRITICAL | Duplicate tool names, homoglyphs, name/desc mismatch |
307
314
  | 27 | `sampling` | CRITICAL | `sampling/createMessage` accessible without auth |
308
315
  | 28 | `schema_leak` | LOW | Sensitive field names / enum values in tool schemas |
316
+ | 29 | `http_method_confusion` | MEDIUM | GET/DELETE/PUT/PATCH accepted on MCP endpoint |
317
+ | 30 | `protocol_downgrade` | MEDIUM | Old protocol versions accepted, server version leaked |
318
+ | 31 | `batch_injection` | MEDIUM | JSON-RPC batch requests, unusual method name injection |
309
319
 
310
320
  ---
311
321
 
@@ -318,9 +328,13 @@ Highlight the value you want to fuzz (e.g. a tool parameter), click **Add §**.
318
328
  | Check all response fields for injection | 30+ min | `scan poison_all` — 5s |
319
329
  | Verify session ID entropy | 10 min | `scan session` — 2s |
320
330
  | Check replay on every tool | 20 min | `scan replay` — 5s |
321
- | Full 28-check assessment | 3–6 hours | `scan` — 30s |
331
+ | Full 31-check assessment | 3–6 hours | `scan` — under 60s |
332
+ | Inspect tool schema before testing | 5 min reading docs | `inspect <tool>` — instant |
333
+ | Call a tool with custom payload | Set up in Burp Repeater | `call <tool> {"param": "payload"}` |
334
+ | Fuzz a parameter with 50 payloads | Intruder setup + run | `fuzz <tool> <param> sqli` — 30s |
335
+ | Test any JSON-RPC method directly | Build request in Repeater | `raw <method> <params>` |
322
336
 
323
- MCPTROTTER gives you the baseline in 30 seconds. You spend your time on what matters: manually verifying findings in Burp Repeater and chaining them into a demonstrated attack path.
337
+ MCPTROTTER gives you the baseline in under 60 seconds and puts every request in Burp HTTP History. You spend your time on what matters: manually verifying findings in Repeater and chaining them into a demonstrated attack path.
324
338
 
325
339
  ---
326
340
 
@@ -332,8 +346,8 @@ MCPTROTTER is the public automated scanner extracted from **Bugtrotter** — a f
332
346
 
333
347
  | Capability | MCPTROTTER | Bugtrotter |
334
348
  |---|---|---|
335
- | Automated MCP scan (28 checks) | ✓ | ✓ |
336
- | Manual finding verification | You do it in Burp | Guided playbooks |
349
+ | Automated MCP scan (31 checks) | ✓ | ✓ |
350
+ | Manual tool exploration framework | | |
337
351
  | Chained exploit paths across tools | — | ✓ Full attack chain |
338
352
  | SAST review of MCP server code | — | ✓ |
339
353
  | Burp Suite MCP — business logic abuse | — | ✓ AI-driven |
@@ -342,27 +356,25 @@ MCPTROTTER is the public automated scanner extracted from **Bugtrotter** — a f
342
356
  | Web / API / network pentesting | — | ✓ Full engagement |
343
357
  | Final pentest report | Markdown export | Engagement-grade report |
344
358
 
345
- **MCPTROTTER in fingertips inside Bugtrotter:**
359
+ **MCPTROTTER inside Bugtrotter:**
346
360
 
347
361
  In Bugtrotter, MCPTROTTER runs as a registered MCP server. Claude Code or Claude Desktop calls it directly:
348
362
 
349
363
  ```
350
364
  "Scan https://target.com/mcp for security issues and prioritise findings"
351
365
  → Claude calls scan_target tool
352
- → MCPTROTTER runs all 28 checks
366
+ → MCPTROTTER runs all 31 checks
353
367
  → Findings returned as structured JSON to Claude
354
368
  → Claude reasons over them, chains the critical ones, drafts the report section
355
369
  ```
356
370
 
357
371
  No copy-paste. No context switching. The scan output feeds straight into the AI-driven engagement workflow — SSRF finding becomes an SSRF exploit attempt, auth bypass becomes a credential theft chain, stored injection becomes a demonstrated prompt hijack.
358
372
 
359
- That's the difference: MCPTROTTER finds the candidates in 30 seconds. Bugtrotter turns the candidates into proven, chained, client-ready findings.
360
-
361
373
  ---
362
374
 
363
375
  ## Use MCPTROTTER as an MCP server itself
364
376
 
365
- MCPTROTTER can become an MCP server — exposing its scan capability as tools that any MCP client (Claude Desktop, MCP Inspector, another agent) can call.
377
+ MCPTROTTER can expose its scan capability as tools that any MCP client (Claude Desktop, MCP Inspector, another agent) can call.
366
378
 
367
379
  ```bash
368
380
  mcppt serve-mcp --port 8899
@@ -384,12 +396,7 @@ Tools exposed:
384
396
  - `scan_target` — full scan, returns findings JSON
385
397
  - `list_tools` — enumerate tools on any MCP server
386
398
  - `call_tool` — call any tool on any MCP server
387
- - `get_checks` — list all 28 checks with descriptions
388
-
389
- Inspect with MCP Inspector:
390
- ```bash
391
- npx @modelcontextprotocol/inspector http://127.0.0.1:8899/mcp
392
- ```
399
+ - `get_checks` — list all 31 checks with descriptions
393
400
 
394
401
  ---
395
402
 
@@ -0,0 +1 @@
1
+ __version__ = "3.0.0"
@@ -193,7 +193,7 @@ def main() -> None:
193
193
  _ensure_utf8()
194
194
  parser = argparse.ArgumentParser(
195
195
  prog="mcppt",
196
- description="MCPTROTTER v2.3 — MCP Pentest Tool | 28 automated security checks",
196
+ description="MCPTROTTER v3.0 — MCP Pentest Tool | 31 automated security checks",
197
197
  formatter_class=argparse.RawDescriptionHelpFormatter,
198
198
  epilog=EPILOG,
199
199
  )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "mcppt"
7
- version = "1.1.0"
7
+ version = "3.0.0"
8
8
  description = "MCPTROTTER — MCP Security Framework: 31 automated checks + manual exploration shell"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- MCPTROTTER Smoke Test — v2.3
3
+ MCPTROTTER Smoke Test — v3.0
4
4
  =============================
5
5
  Starts the vuln_server, runs MCPTROTTER against it, asserts expected findings.
6
6
 
@@ -128,7 +128,7 @@ EXPECTED = [
128
128
  def main():
129
129
  print()
130
130
  print(f"{BOLD}{'=' * 58}{RESET}")
131
- print(f"{BOLD} MCPTROTTER Smoke Test v2.3{RESET}")
131
+ print(f"{BOLD} MCPTROTTER Smoke Test v3.0{RESET}")
132
132
  print(f"{BOLD}{'=' * 58}{RESET}")
133
133
  print()
134
134
 
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- MCPTROTTER Vulnerable Demo Server — v2.3
3
+ MCPTROTTER Vulnerable Demo Server — v3.0
4
4
  =========================================
5
- A deliberately insecure MCP server that fires ALL 28 MCPTROTTER checks.
5
+ A deliberately insecure MCP server that fires ALL 31 MCPTROTTER checks.
6
6
  Safe to run locally: simulated dangerous behaviors (no real command execution,
7
7
  no real file reads, no real URL fetching).
8
8
 
@@ -562,7 +562,7 @@ def mcp():
562
562
  if __name__ == "__main__":
563
563
  print()
564
564
  print("=" * 62)
565
- print(" MCPTROTTER Vulnerable Demo Server v2.3")
565
+ print(" MCPTROTTER Vulnerable Demo Server v3.0")
566
566
  print(" URL : http://127.0.0.1:8888/mcp")
567
567
  print(" Token: valid-token-abc123")
568
568
  print(" Token2: other-token-xyz789")
@@ -1 +0,0 @@
1
- __version__ = "1.1.0"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes