iflow-mcp_mitmproxy-mcp 0.1.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.
- iflow_mcp_mitmproxy_mcp-0.1.0/.gitignore +16 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/.python-version +1 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/PKG-INFO +121 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/README.md +111 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/pyproject.toml +23 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/__init__.py +9 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/__main__.py +6 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/flow_utils.py +41 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/json_utils.py +100 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/protection_analysis.py +371 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/src/mitmproxy_mcp/server.py +428 -0
- iflow_mcp_mitmproxy_mcp-0.1.0/uv.lock +1223 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: iflow-mcp_mitmproxy-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A MCP server project
|
|
5
|
+
Author-email: Lucas Soeth <lucasoeth@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: mcp>=1.3.0
|
|
8
|
+
Requires-Dist: mitmproxy>=11.0.2
|
|
9
|
+
Description-Content-Type: text/markdown
|
|
10
|
+
|
|
11
|
+
# mitmproxy-mcp MCP server
|
|
12
|
+
|
|
13
|
+
A MCP server project
|
|
14
|
+
|
|
15
|
+
## Components
|
|
16
|
+
|
|
17
|
+
### Resources
|
|
18
|
+
|
|
19
|
+
The server implements a simple note storage system with:
|
|
20
|
+
- Custom note:// URI scheme for accessing individual notes
|
|
21
|
+
- Each note resource has a name, description and text/plain mimetype
|
|
22
|
+
|
|
23
|
+
### Prompts
|
|
24
|
+
|
|
25
|
+
The server provides a single prompt:
|
|
26
|
+
- summarize-notes: Creates summaries of all stored notes
|
|
27
|
+
- Optional "style" argument to control detail level (brief/detailed)
|
|
28
|
+
- Generates prompt combining all current notes with style preference
|
|
29
|
+
|
|
30
|
+
### Tools
|
|
31
|
+
|
|
32
|
+
The server implements one tool:
|
|
33
|
+
- add-note: Adds a new note to the server
|
|
34
|
+
- Takes "name" and "content" as required string arguments
|
|
35
|
+
- Updates server state and notifies clients of resource changes
|
|
36
|
+
|
|
37
|
+
## Configuration
|
|
38
|
+
|
|
39
|
+
[TODO: Add configuration details specific to your implementation]
|
|
40
|
+
|
|
41
|
+
## Quickstart
|
|
42
|
+
|
|
43
|
+
### Install
|
|
44
|
+
|
|
45
|
+
#### Claude Desktop
|
|
46
|
+
|
|
47
|
+
On MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`
|
|
48
|
+
On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
49
|
+
|
|
50
|
+
<details>
|
|
51
|
+
<summary>Development/Unpublished Servers Configuration</summary>
|
|
52
|
+
```
|
|
53
|
+
"mcpServers": {
|
|
54
|
+
"mitmproxy-mcp": {
|
|
55
|
+
"command": "uv",
|
|
56
|
+
"args": [
|
|
57
|
+
"--directory",
|
|
58
|
+
"/Users/lucas/Coding/mitmproxy-mcp",
|
|
59
|
+
"run",
|
|
60
|
+
"mitmproxy-mcp"
|
|
61
|
+
]
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
</details>
|
|
66
|
+
|
|
67
|
+
<details>
|
|
68
|
+
<summary>Published Servers Configuration</summary>
|
|
69
|
+
```
|
|
70
|
+
"mcpServers": {
|
|
71
|
+
"mitmproxy-mcp": {
|
|
72
|
+
"command": "uvx",
|
|
73
|
+
"args": [
|
|
74
|
+
"mitmproxy-mcp"
|
|
75
|
+
]
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
</details>
|
|
80
|
+
|
|
81
|
+
## Development
|
|
82
|
+
|
|
83
|
+
### Building and Publishing
|
|
84
|
+
|
|
85
|
+
To prepare the package for distribution:
|
|
86
|
+
|
|
87
|
+
1. Sync dependencies and update lockfile:
|
|
88
|
+
```bash
|
|
89
|
+
uv sync
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
2. Build package distributions:
|
|
93
|
+
```bash
|
|
94
|
+
uv build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This will create source and wheel distributions in the `dist/` directory.
|
|
98
|
+
|
|
99
|
+
3. Publish to PyPI:
|
|
100
|
+
```bash
|
|
101
|
+
uv publish
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Note: You'll need to set PyPI credentials via environment variables or command flags:
|
|
105
|
+
- Token: `--token` or `UV_PUBLISH_TOKEN`
|
|
106
|
+
- Or username/password: `--username`/`UV_PUBLISH_USERNAME` and `--password`/`UV_PUBLISH_PASSWORD`
|
|
107
|
+
|
|
108
|
+
### Debugging
|
|
109
|
+
|
|
110
|
+
Since MCP servers run over stdio, debugging can be challenging. For the best debugging
|
|
111
|
+
experience, we strongly recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector).
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
You can launch the MCP Inspector via [`npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) with this command:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npx @modelcontextprotocol/inspector uv --directory /Users/lucas/Coding/mitmproxy-mcp run mitmproxy-mcp
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
Upon launching, the Inspector will display a URL that you can access in your browser to begin debugging.
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# mitmproxy-mcp MCP server
|
|
2
|
+
|
|
3
|
+
A MCP server project
|
|
4
|
+
|
|
5
|
+
## Components
|
|
6
|
+
|
|
7
|
+
### Resources
|
|
8
|
+
|
|
9
|
+
The server implements a simple note storage system with:
|
|
10
|
+
- Custom note:// URI scheme for accessing individual notes
|
|
11
|
+
- Each note resource has a name, description and text/plain mimetype
|
|
12
|
+
|
|
13
|
+
### Prompts
|
|
14
|
+
|
|
15
|
+
The server provides a single prompt:
|
|
16
|
+
- summarize-notes: Creates summaries of all stored notes
|
|
17
|
+
- Optional "style" argument to control detail level (brief/detailed)
|
|
18
|
+
- Generates prompt combining all current notes with style preference
|
|
19
|
+
|
|
20
|
+
### Tools
|
|
21
|
+
|
|
22
|
+
The server implements one tool:
|
|
23
|
+
- add-note: Adds a new note to the server
|
|
24
|
+
- Takes "name" and "content" as required string arguments
|
|
25
|
+
- Updates server state and notifies clients of resource changes
|
|
26
|
+
|
|
27
|
+
## Configuration
|
|
28
|
+
|
|
29
|
+
[TODO: Add configuration details specific to your implementation]
|
|
30
|
+
|
|
31
|
+
## Quickstart
|
|
32
|
+
|
|
33
|
+
### Install
|
|
34
|
+
|
|
35
|
+
#### Claude Desktop
|
|
36
|
+
|
|
37
|
+
On MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`
|
|
38
|
+
On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
|
|
39
|
+
|
|
40
|
+
<details>
|
|
41
|
+
<summary>Development/Unpublished Servers Configuration</summary>
|
|
42
|
+
```
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"mitmproxy-mcp": {
|
|
45
|
+
"command": "uv",
|
|
46
|
+
"args": [
|
|
47
|
+
"--directory",
|
|
48
|
+
"/Users/lucas/Coding/mitmproxy-mcp",
|
|
49
|
+
"run",
|
|
50
|
+
"mitmproxy-mcp"
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
</details>
|
|
56
|
+
|
|
57
|
+
<details>
|
|
58
|
+
<summary>Published Servers Configuration</summary>
|
|
59
|
+
```
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"mitmproxy-mcp": {
|
|
62
|
+
"command": "uvx",
|
|
63
|
+
"args": [
|
|
64
|
+
"mitmproxy-mcp"
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
</details>
|
|
70
|
+
|
|
71
|
+
## Development
|
|
72
|
+
|
|
73
|
+
### Building and Publishing
|
|
74
|
+
|
|
75
|
+
To prepare the package for distribution:
|
|
76
|
+
|
|
77
|
+
1. Sync dependencies and update lockfile:
|
|
78
|
+
```bash
|
|
79
|
+
uv sync
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
2. Build package distributions:
|
|
83
|
+
```bash
|
|
84
|
+
uv build
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This will create source and wheel distributions in the `dist/` directory.
|
|
88
|
+
|
|
89
|
+
3. Publish to PyPI:
|
|
90
|
+
```bash
|
|
91
|
+
uv publish
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Note: You'll need to set PyPI credentials via environment variables or command flags:
|
|
95
|
+
- Token: `--token` or `UV_PUBLISH_TOKEN`
|
|
96
|
+
- Or username/password: `--username`/`UV_PUBLISH_USERNAME` and `--password`/`UV_PUBLISH_PASSWORD`
|
|
97
|
+
|
|
98
|
+
### Debugging
|
|
99
|
+
|
|
100
|
+
Since MCP servers run over stdio, debugging can be challenging. For the best debugging
|
|
101
|
+
experience, we strongly recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector).
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
You can launch the MCP Inspector via [`npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) with this command:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx @modelcontextprotocol/inspector uv --directory /Users/lucas/Coding/mitmproxy-mcp run mitmproxy-mcp
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
Upon launching, the Inspector will display a URL that you can access in your browser to begin debugging.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "iflow-mcp_mitmproxy-mcp"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "A MCP server project"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.11"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"mcp>=1.3.0",
|
|
9
|
+
"mitmproxy>=11.0.2",
|
|
10
|
+
]
|
|
11
|
+
[[project.authors]]
|
|
12
|
+
name = "Lucas Soeth"
|
|
13
|
+
email = "lucasoeth@gmail.com"
|
|
14
|
+
|
|
15
|
+
[build-system]
|
|
16
|
+
requires = [ "hatchling",]
|
|
17
|
+
build-backend = "hatchling.build"
|
|
18
|
+
|
|
19
|
+
[project.scripts]
|
|
20
|
+
mitmproxy-mcp = "mitmproxy_mcp:main"
|
|
21
|
+
|
|
22
|
+
[tool.hatch.build.targets.wheel]
|
|
23
|
+
packages = ["src/mitmproxy_mcp"]
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import json
|
|
3
|
+
from typing import Any, Dict, List, Union
|
|
4
|
+
from mitmproxy import io
|
|
5
|
+
|
|
6
|
+
# Directory where mitmproxy dump files are stored
|
|
7
|
+
DUMP_DIR = "/Users/lucas/Coding/mitmproxy-mcp/dumps"
|
|
8
|
+
|
|
9
|
+
# Cache for storing flows per session
|
|
10
|
+
FLOW_CACHE = {}
|
|
11
|
+
|
|
12
|
+
async def get_flows_from_dump(session_id: str) -> list:
|
|
13
|
+
"""
|
|
14
|
+
Retrieves flows from the dump file, using the cache if available.
|
|
15
|
+
"""
|
|
16
|
+
dump_file = os.path.join(DUMP_DIR, f"{session_id}.dump")
|
|
17
|
+
if not os.path.exists(dump_file):
|
|
18
|
+
raise FileNotFoundError("Session not found")
|
|
19
|
+
|
|
20
|
+
if session_id in FLOW_CACHE:
|
|
21
|
+
return FLOW_CACHE[session_id]
|
|
22
|
+
else:
|
|
23
|
+
with open(dump_file, "rb") as f:
|
|
24
|
+
reader = io.FlowReader(f)
|
|
25
|
+
flows = list(reader.stream())
|
|
26
|
+
FLOW_CACHE[session_id] = flows
|
|
27
|
+
return flows
|
|
28
|
+
|
|
29
|
+
def parse_json_content(content: bytes, headers: dict) -> Union[Dict, str, bytes]:
|
|
30
|
+
"""
|
|
31
|
+
Attempts to parse content as JSON if the content type indicates JSON.
|
|
32
|
+
Returns the parsed JSON or the raw content if parsing fails.
|
|
33
|
+
"""
|
|
34
|
+
content_type = headers.get("Content-Type", "").lower() if headers else ""
|
|
35
|
+
|
|
36
|
+
if "application/json" in content_type or "text/json" in content_type:
|
|
37
|
+
try:
|
|
38
|
+
return json.loads(content.decode(errors="ignore"))
|
|
39
|
+
except json.JSONDecodeError:
|
|
40
|
+
return content.decode(errors="ignore")
|
|
41
|
+
return content.decode(errors="ignore")
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
from typing import Any, Dict, List, Union
|
|
2
|
+
|
|
3
|
+
def generate_json_structure(json_data: Any, max_depth: int = 2, current_depth: int = 0) -> Any:
|
|
4
|
+
"""
|
|
5
|
+
Generate a simplified structure of JSON content, showing keys and types
|
|
6
|
+
but replacing actual values with type indicators after a certain depth.
|
|
7
|
+
"""
|
|
8
|
+
if current_depth >= max_depth:
|
|
9
|
+
if isinstance(json_data, dict):
|
|
10
|
+
return {"...": f"{len(json_data)} keys"}
|
|
11
|
+
elif isinstance(json_data, list):
|
|
12
|
+
return f"[{len(json_data)} items]"
|
|
13
|
+
else:
|
|
14
|
+
return f"({type(json_data).__name__})"
|
|
15
|
+
|
|
16
|
+
if isinstance(json_data, dict):
|
|
17
|
+
result = {}
|
|
18
|
+
for key, value in json_data.items():
|
|
19
|
+
result[key] = generate_json_structure(value, max_depth, current_depth + 1)
|
|
20
|
+
return result
|
|
21
|
+
elif isinstance(json_data, list):
|
|
22
|
+
if not json_data:
|
|
23
|
+
return []
|
|
24
|
+
# For lists, show structure of first item and count
|
|
25
|
+
sample = generate_json_structure(json_data[0], max_depth, current_depth + 1)
|
|
26
|
+
return [sample, f"... ({len(json_data)-1} more items)"] if len(json_data) > 1 else [sample]
|
|
27
|
+
else:
|
|
28
|
+
return f"({type(json_data).__name__})"
|
|
29
|
+
|
|
30
|
+
def extract_with_jsonpath(json_data: Any, path: str) -> Any:
|
|
31
|
+
"""
|
|
32
|
+
Basic implementation of JSONPath extraction.
|
|
33
|
+
Supports simple dot notation and array indexing.
|
|
34
|
+
For more complex cases, consider using a full JSONPath library.
|
|
35
|
+
"""
|
|
36
|
+
# Handle root object reference
|
|
37
|
+
if path == "$":
|
|
38
|
+
return json_data
|
|
39
|
+
|
|
40
|
+
# Strip leading $ if present
|
|
41
|
+
if path.startswith("$"):
|
|
42
|
+
path = path[1:]
|
|
43
|
+
if path.startswith("."):
|
|
44
|
+
path = path[1:]
|
|
45
|
+
|
|
46
|
+
parts = []
|
|
47
|
+
# Parse the path - handle both dot notation and brackets
|
|
48
|
+
current = ""
|
|
49
|
+
in_brackets = False
|
|
50
|
+
for char in path:
|
|
51
|
+
if char == "[":
|
|
52
|
+
if current:
|
|
53
|
+
parts.append(current)
|
|
54
|
+
current = ""
|
|
55
|
+
in_brackets = True
|
|
56
|
+
elif char == "]":
|
|
57
|
+
if in_brackets:
|
|
58
|
+
try:
|
|
59
|
+
# Handle array index
|
|
60
|
+
parts.append(int(current.strip()))
|
|
61
|
+
except ValueError:
|
|
62
|
+
# Handle quoted key
|
|
63
|
+
quoted = current.strip()
|
|
64
|
+
if (quoted.startswith("'") and quoted.endswith("'")) or \
|
|
65
|
+
(quoted.startswith('"') and quoted.endswith('"')):
|
|
66
|
+
parts.append(quoted[1:-1])
|
|
67
|
+
else:
|
|
68
|
+
parts.append(quoted)
|
|
69
|
+
current = ""
|
|
70
|
+
in_brackets = False
|
|
71
|
+
elif char == "." and not in_brackets:
|
|
72
|
+
if current:
|
|
73
|
+
parts.append(current)
|
|
74
|
+
current = ""
|
|
75
|
+
else:
|
|
76
|
+
current += char
|
|
77
|
+
|
|
78
|
+
if current:
|
|
79
|
+
parts.append(current)
|
|
80
|
+
|
|
81
|
+
# Navigate through the data
|
|
82
|
+
result = json_data
|
|
83
|
+
for part in parts:
|
|
84
|
+
try:
|
|
85
|
+
if isinstance(result, dict):
|
|
86
|
+
result = result.get(part)
|
|
87
|
+
elif isinstance(result, list) and isinstance(part, int):
|
|
88
|
+
if 0 <= part < len(result):
|
|
89
|
+
result = result[part]
|
|
90
|
+
else:
|
|
91
|
+
return None
|
|
92
|
+
else:
|
|
93
|
+
return None
|
|
94
|
+
|
|
95
|
+
if result is None:
|
|
96
|
+
break
|
|
97
|
+
except Exception:
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
return result
|