SAUSERLA commited on
Commit
d309ec7
·
verified ·
1 Parent(s): 37f9172

Upload 6 files

Browse files
Files changed (1) hide show
  1. mcp_bridge.py +248 -0
mcp_bridge.py ADDED
@@ -0,0 +1,248 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+
3
+ import asyncio
4
+ import json
5
+ import logging
6
+ import sys
7
+ import requests
8
+
9
+ # Configure logging
10
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
11
+ logger = logging.getLogger("kali-mcp-bridge")
12
+
13
+ # Configuration
14
+ KALI_API_URL = "https://sauserla-kali.hf.space"
15
+
16
+ class KaliMCPBridge:
17
+ """MCP Bridge to Kali Linux API"""
18
+
19
+ def __init__(self, api_url: str = KALI_API_URL):
20
+ self.api_url = api_url.rstrip('/')
21
+ self.session = requests.Session()
22
+ logger.info(f"Initialized Kali MCP Bridge with API: {self.api_url}")
23
+
24
+ def call_api(self, endpoint: str, method: str = "GET", data: dict = None) -> dict:
25
+ """Make API call to Kali server"""
26
+ url = f"{self.api_url}{endpoint}"
27
+ try:
28
+ if method.upper() == "POST":
29
+ response = self.session.post(url, json=data, timeout=300)
30
+ else:
31
+ response = self.session.get(url, timeout=30)
32
+ response.raise_for_status()
33
+ return response.json()
34
+ except requests.exceptions.RequestException as e:
35
+ logger.error(f"API call failed: {str(e)}")
36
+ return {"error": str(e)}
37
+
38
+ def execute_command(self, command: str) -> dict:
39
+ """Execute a command via the API"""
40
+ data = {"command": command}
41
+ return self.call_api("/api/command", "POST", data)
42
+
43
+ def health_check(self) -> dict:
44
+ """Check server health"""
45
+ return self.call_api("/health")
46
+
47
+ # MCP Protocol Implementation (Simplified)
48
+ class MCPServer:
49
+ """Simple MCP server implementation"""
50
+
51
+ def __init__(self):
52
+ self.kali_bridge = KaliMCPBridge()
53
+ self.tools = {
54
+ "execute_command": {
55
+ "name": "execute_command",
56
+ "description": "Execute arbitrary commands on Kali Linux",
57
+ "inputSchema": {
58
+ "type": "object",
59
+ "properties": {
60
+ "command": {
61
+ "type": "string",
62
+ "description": "The shell command to execute on Kali Linux"
63
+ }
64
+ },
65
+ "required": ["command"]
66
+ }
67
+ },
68
+ "server_health": {
69
+ "name": "server_health",
70
+ "description": "Check the health status of the Kali Linux server",
71
+ "inputSchema": {
72
+ "type": "object",
73
+ "properties": {}
74
+ }
75
+ }
76
+ }
77
+
78
+ def handle_initialize(self, request: dict) -> dict:
79
+ """Handle initialization request"""
80
+ return {
81
+ "jsonrpc": "2.0",
82
+ "id": request.get("id"),
83
+ "result": {
84
+ "protocolVersion": "2024-11-05",
85
+ "capabilities": {
86
+ "tools": {}
87
+ },
88
+ "serverInfo": {
89
+ "name": "kali-mcp-bridge",
90
+ "version": "1.0.0"
91
+ }
92
+ }
93
+ }
94
+
95
+ def handle_tools_list(self, request: dict) -> dict:
96
+ """Handle tools/list request"""
97
+ return {
98
+ "jsonrpc": "2.0",
99
+ "id": request.get("id"),
100
+ "result": {
101
+ "tools": list(self.tools.values())
102
+ }
103
+ }
104
+
105
+ def handle_tools_call(self, request: dict) -> dict:
106
+ """Handle tools/call request"""
107
+ params = request.get("params", {})
108
+ tool_name = params.get("name")
109
+ tool_args = params.get("arguments", {})
110
+
111
+ try:
112
+ if tool_name == "execute_command":
113
+ command = tool_args.get("command", "")
114
+ if not command:
115
+ raise ValueError("Command parameter is required")
116
+
117
+ result = self.kali_bridge.execute_command(command)
118
+
119
+ if result.get("error"):
120
+ content = f"Error: {result['error']}"
121
+ else:
122
+ output_parts = []
123
+ if result.get("stdout"):
124
+ output_parts.append(f"STDOUT:\n{result['stdout']}")
125
+ if result.get("stderr"):
126
+ output_parts.append(f"STDERR:\n{result['stderr']}")
127
+
128
+ status = "SUCCESS" if result.get("success") else "FAILED"
129
+ output_parts.append(f"Exit Code: {result.get('return_code', 'unknown')}")
130
+ output_parts.append(f"Status: {status}")
131
+
132
+ if result.get("timed_out"):
133
+ output_parts.append("WARNING: Command timed out after 180 seconds")
134
+
135
+ content = "\n\n".join(output_parts)
136
+
137
+ elif tool_name == "server_health":
138
+ health = self.kali_bridge.health_check()
139
+
140
+ if health.get("error"):
141
+ content = f"Health check failed: {health['error']}"
142
+ else:
143
+ output_parts = []
144
+ output_parts.append(f"Status: {health.get('status', 'unknown')}")
145
+ output_parts.append(f"Message: {health.get('message', '')}")
146
+ output_parts.append(f"All Essential Tools Available: {health.get('all_essential_tools_available', False)}")
147
+
148
+ tools_status = health.get('tools_status', {})
149
+ if tools_status:
150
+ output_parts.append("\nTool Status:")
151
+ for tool_name, available in tools_status.items():
152
+ status_icon = "✅" if available else "❌"
153
+ output_parts.append(f" {status_icon} {tool_name}")
154
+
155
+ content = "\n".join(output_parts)
156
+
157
+ else:
158
+ content = f"Unknown tool: {tool_name}"
159
+
160
+ return {
161
+ "jsonrpc": "2.0",
162
+ "id": request.get("id"),
163
+ "result": {
164
+ "content": [{"type": "text", "text": content}]
165
+ }
166
+ }
167
+
168
+ except Exception as e:
169
+ logger.error(f"Tool execution error: {str(e)}")
170
+ return {
171
+ "jsonrpc": "2.0",
172
+ "id": request.get("id"),
173
+ "error": {
174
+ "code": -32000,
175
+ "message": f"Tool execution failed: {str(e)}"
176
+ }
177
+ }
178
+
179
+ def process_request(self, line: str) -> str:
180
+ """Process a single JSON-RPC request"""
181
+ try:
182
+ request = json.loads(line.strip())
183
+
184
+ method = request.get("method")
185
+
186
+ if method == "initialize":
187
+ response = self.handle_initialize(request)
188
+ elif method == "tools/list":
189
+ response = self.handle_tools_list(request)
190
+ elif method == "tools/call":
191
+ response = self.handle_tools_call(request)
192
+ else:
193
+ response = {
194
+ "jsonrpc": "2.0",
195
+ "id": request.get("id"),
196
+ "error": {
197
+ "code": -32601,
198
+ "message": f"Method not found: {method}"
199
+ }
200
+ }
201
+
202
+ return json.dumps(response)
203
+
204
+ except json.JSONDecodeError as e:
205
+ logger.error(f"Invalid JSON: {str(e)}")
206
+ return json.dumps({
207
+ "jsonrpc": "2.0",
208
+ "id": None,
209
+ "error": {
210
+ "code": -32700,
211
+ "message": "Parse error"
212
+ }
213
+ })
214
+
215
+ except Exception as e:
216
+ logger.error(f"Request processing error: {str(e)}")
217
+ return json.dumps({
218
+ "jsonrpc": "2.0",
219
+ "id": None,
220
+ "error": {
221
+ "code": -32603,
222
+ "message": f"Internal error: {str(e)}"
223
+ }
224
+ })
225
+
226
+ def main():
227
+ """Main server loop"""
228
+ server = MCPServer()
229
+
230
+ # Test connection on startup
231
+ logger.info("Testing connection to Kali API...")
232
+ health = server.kali_bridge.health_check()
233
+ if health.get("error"):
234
+ logger.error(f"Failed to connect to Kali API: {health['error']}")
235
+ sys.exit(1)
236
+ else:
237
+ logger.info("✅ Successfully connected to Kali API server")
238
+
239
+ logger.info("Kali MCP Bridge started. Ready to accept MCP requests...")
240
+
241
+ # Main request/response loop
242
+ for line in sys.stdin:
243
+ if line.strip():
244
+ response = server.process_request(line)
245
+ print(response, flush=True)
246
+
247
+ if __name__ == "__main__":
248
+ main()