iflow-mcp_bethington-cheat-engine-server-python 0.1.0__py3-none-any.whl

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 (40) hide show
  1. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/METADATA +16 -0
  2. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/RECORD +40 -0
  3. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/WHEEL +5 -0
  4. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/entry_points.txt +2 -0
  5. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. iflow_mcp_bethington_cheat_engine_server_python-0.1.0.dist-info/top_level.txt +1 -0
  7. server/cheatengine/__init__.py +19 -0
  8. server/cheatengine/ce_bridge.py +1670 -0
  9. server/cheatengine/lua_interface.py +460 -0
  10. server/cheatengine/table_parser.py +1221 -0
  11. server/config/__init__.py +20 -0
  12. server/config/settings.py +347 -0
  13. server/config/whitelist.py +378 -0
  14. server/gui_automation/__init__.py +43 -0
  15. server/gui_automation/core/__init__.py +8 -0
  16. server/gui_automation/core/integration.py +951 -0
  17. server/gui_automation/demos/__init__.py +8 -0
  18. server/gui_automation/demos/basic_demo.py +754 -0
  19. server/gui_automation/demos/notepad_demo.py +460 -0
  20. server/gui_automation/demos/simple_demo.py +319 -0
  21. server/gui_automation/tools/__init__.py +8 -0
  22. server/gui_automation/tools/mcp_tools.py +974 -0
  23. server/main.py +519 -0
  24. server/memory/__init__.py +0 -0
  25. server/memory/analyzer.py +0 -0
  26. server/memory/reader.py +0 -0
  27. server/memory/scanner.py +0 -0
  28. server/memory/symbols.py +0 -0
  29. server/process/__init__.py +16 -0
  30. server/process/launcher.py +608 -0
  31. server/process/manager.py +185 -0
  32. server/process/monitors.py +202 -0
  33. server/process/permissions.py +131 -0
  34. server/process_whitelist.json +119 -0
  35. server/pyautogui/__init__.py +0 -0
  36. server/utils/__init__.py +37 -0
  37. server/utils/data_types.py +368 -0
  38. server/utils/formatters.py +430 -0
  39. server/utils/validators.py +340 -0
  40. server/window_automation/__init__.py +59 -0
@@ -0,0 +1,378 @@
1
+ """
2
+ Process Whitelist Module
3
+ Manages allowed processes for security
4
+ """
5
+
6
+ import json
7
+ import os
8
+ import logging
9
+ import re
10
+ from typing import List, Set, Dict, Any, Optional
11
+ from dataclasses import dataclass
12
+ from datetime import datetime
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+ @dataclass
17
+ class WhitelistEntry:
18
+ """Single whitelist entry"""
19
+ process_name: str
20
+ description: str
21
+ category: str
22
+ added_date: str
23
+ enabled: bool = True
24
+ exact_match: bool = True
25
+
26
+ def matches(self, process_name: str) -> bool:
27
+ """Check if this entry matches a process name"""
28
+ if not self.enabled:
29
+ return False
30
+
31
+ if self.exact_match:
32
+ return self.process_name.lower() == process_name.lower()
33
+ else:
34
+ # Pattern matching for non-exact matches
35
+ try:
36
+ pattern = self.process_name.replace('*', '.*').replace('?', '.')
37
+ return bool(re.match(pattern, process_name, re.IGNORECASE))
38
+ except re.error:
39
+ # Fallback to exact match if regex is invalid
40
+ return self.process_name.lower() == process_name.lower()
41
+
42
+ class ProcessWhitelist:
43
+ """Manages process whitelist for security"""
44
+
45
+ def __init__(self):
46
+ self.entries: List[WhitelistEntry] = []
47
+ self.enabled = True
48
+ self.whitelist_file: Optional[str] = None
49
+ self.last_modified = 0
50
+ self._initialize_defaults()
51
+
52
+ def _initialize_defaults(self):
53
+ """Initialize with default safe processes"""
54
+ default_entries = [
55
+ # Development tools
56
+ WhitelistEntry("notepad.exe", "Windows Notepad", "system", self._get_timestamp()),
57
+ WhitelistEntry("code.exe", "Visual Studio Code", "development", self._get_timestamp()),
58
+ WhitelistEntry("devenv.exe", "Visual Studio", "development", self._get_timestamp()),
59
+ WhitelistEntry("windbg.exe", "Windows Debugger", "development", self._get_timestamp()),
60
+ WhitelistEntry("x64dbg.exe", "x64dbg Debugger", "development", self._get_timestamp()),
61
+ WhitelistEntry("ollydbg.exe", "OllyDbg Debugger", "development", self._get_timestamp()),
62
+
63
+ # Common safe applications
64
+ WhitelistEntry("calc.exe", "Windows Calculator", "system", self._get_timestamp()),
65
+ WhitelistEntry("mspaint.exe", "Microsoft Paint", "system", self._get_timestamp()),
66
+ WhitelistEntry("wordpad.exe", "Windows WordPad", "system", self._get_timestamp()),
67
+
68
+ # Games (educational purposes)
69
+ WhitelistEntry("minesweeper.exe", "Minesweeper", "game", self._get_timestamp()),
70
+ WhitelistEntry("solitaire.exe", "Solitaire", "game", self._get_timestamp()),
71
+
72
+ # Test applications
73
+ WhitelistEntry("test*.exe", "Test Applications", "test", self._get_timestamp(), exact_match=False),
74
+ WhitelistEntry("demo*.exe", "Demo Applications", "test", self._get_timestamp(), exact_match=False),
75
+ ]
76
+
77
+ self.entries = default_entries
78
+
79
+ def _get_timestamp(self) -> str:
80
+ """Get current timestamp as string"""
81
+ return datetime.now().isoformat()
82
+
83
+ def load_whitelist(self, whitelist_path: str):
84
+ """Load whitelist from file
85
+
86
+ Args:
87
+ whitelist_path: Path to whitelist file
88
+ """
89
+ self.whitelist_file = whitelist_path
90
+
91
+ if not os.path.exists(whitelist_path):
92
+ logger.info(f"Whitelist file not found, creating default: {whitelist_path}")
93
+ self.save_whitelist()
94
+ return
95
+
96
+ try:
97
+ # Check if file was modified
98
+ file_mtime = os.path.getmtime(whitelist_path)
99
+ if file_mtime <= self.last_modified:
100
+ return # No changes
101
+
102
+ with open(whitelist_path, 'r') as f:
103
+ data = json.load(f)
104
+
105
+ # Load configuration
106
+ self.enabled = data.get('enabled', True)
107
+
108
+ # Load entries
109
+ entries_data = data.get('entries', [])
110
+ self.entries = []
111
+
112
+ for entry_data in entries_data:
113
+ entry = WhitelistEntry(
114
+ process_name=entry_data['process_name'],
115
+ description=entry_data.get('description', ''),
116
+ category=entry_data.get('category', 'custom'),
117
+ added_date=entry_data.get('added_date', self._get_timestamp()),
118
+ enabled=entry_data.get('enabled', True),
119
+ exact_match=entry_data.get('exact_match', True)
120
+ )
121
+ self.entries.append(entry)
122
+
123
+ self.last_modified = file_mtime
124
+ logger.info(f"Loaded {len(self.entries)} whitelist entries from {whitelist_path}")
125
+
126
+ except Exception as e:
127
+ logger.error(f"Failed to load whitelist from {whitelist_path}: {e}")
128
+ logger.info("Using default whitelist")
129
+
130
+ def save_whitelist(self, whitelist_path: Optional[str] = None):
131
+ """Save whitelist to file
132
+
133
+ Args:
134
+ whitelist_path: Path to save whitelist (optional)
135
+ """
136
+ save_path = whitelist_path or self.whitelist_file or "process_whitelist.json"
137
+
138
+ try:
139
+ data = {
140
+ 'enabled': self.enabled,
141
+ 'description': 'Process whitelist for MCP Cheat Engine Server',
142
+ 'last_updated': self._get_timestamp(),
143
+ 'entries': []
144
+ }
145
+
146
+ for entry in self.entries:
147
+ entry_data = {
148
+ 'process_name': entry.process_name,
149
+ 'description': entry.description,
150
+ 'category': entry.category,
151
+ 'added_date': entry.added_date,
152
+ 'enabled': entry.enabled,
153
+ 'exact_match': entry.exact_match
154
+ }
155
+ data['entries'].append(entry_data)
156
+
157
+ with open(save_path, 'w') as f:
158
+ json.dump(data, f, indent=2)
159
+
160
+ logger.info(f"Saved whitelist to {save_path}")
161
+
162
+ except Exception as e:
163
+ logger.error(f"Failed to save whitelist to {save_path}: {e}")
164
+
165
+ def is_enabled(self) -> bool:
166
+ """Check if whitelist is enabled"""
167
+ return self.enabled
168
+
169
+ def is_allowed(self, process_name: str) -> bool:
170
+ """Check if a process is allowed by the whitelist
171
+
172
+ Args:
173
+ process_name: Name of the process to check
174
+
175
+ Returns:
176
+ True if allowed, False otherwise
177
+ """
178
+ if not self.enabled:
179
+ return True # If whitelist is disabled, allow all
180
+
181
+ # Check against each whitelist entry
182
+ for entry in self.entries:
183
+ if entry.matches(process_name):
184
+ return True
185
+
186
+ return False
187
+
188
+ def add_process(self, process_name: str, description: str = "", category: str = "custom") -> bool:
189
+ """Add a process to the whitelist
190
+
191
+ Args:
192
+ process_name: Name of the process
193
+ description: Description of the process
194
+ category: Category for organization
195
+
196
+ Returns:
197
+ True if added, False if already exists
198
+ """
199
+ # Check if already exists
200
+ for entry in self.entries:
201
+ if entry.process_name.lower() == process_name.lower() and entry.exact_match:
202
+ return False
203
+
204
+ entry = WhitelistEntry(
205
+ process_name=process_name,
206
+ description=description or f"Custom entry for {process_name}",
207
+ category=category,
208
+ added_date=self._get_timestamp()
209
+ )
210
+
211
+ self.entries.append(entry)
212
+ logger.info(f"Added process to whitelist: {process_name}")
213
+
214
+ # Auto-save if we have a file path
215
+ if self.whitelist_file:
216
+ self.save_whitelist()
217
+
218
+ return True
219
+
220
+ def remove_process(self, process_name: str) -> bool:
221
+ """Remove a process from the whitelist
222
+
223
+ Args:
224
+ process_name: Name of the process to remove
225
+
226
+ Returns:
227
+ True if removed, False if not found
228
+ """
229
+ original_count = len(self.entries)
230
+ self.entries = [entry for entry in self.entries
231
+ if entry.process_name.lower() != process_name.lower()]
232
+
233
+ removed = len(self.entries) < original_count
234
+
235
+ if removed:
236
+ logger.info(f"Removed process from whitelist: {process_name}")
237
+ # Auto-save if we have a file path
238
+ if self.whitelist_file:
239
+ self.save_whitelist()
240
+
241
+ return removed
242
+
243
+ def enable_process(self, process_name: str) -> bool:
244
+ """Enable a process in the whitelist
245
+
246
+ Args:
247
+ process_name: Name of the process to enable
248
+
249
+ Returns:
250
+ True if found and enabled, False otherwise
251
+ """
252
+ for entry in self.entries:
253
+ if entry.process_name.lower() == process_name.lower():
254
+ entry.enabled = True
255
+ logger.info(f"Enabled process in whitelist: {process_name}")
256
+ return True
257
+
258
+ return False
259
+
260
+ def disable_process(self, process_name: str) -> bool:
261
+ """Disable a process in the whitelist
262
+
263
+ Args:
264
+ process_name: Name of the process to disable
265
+
266
+ Returns:
267
+ True if found and disabled, False otherwise
268
+ """
269
+ for entry in self.entries:
270
+ if entry.process_name.lower() == process_name.lower():
271
+ entry.enabled = False
272
+ logger.info(f"Disabled process in whitelist: {process_name}")
273
+ return True
274
+
275
+ return False
276
+
277
+ def get_processes_by_category(self, category: str) -> List[WhitelistEntry]:
278
+ """Get all processes in a specific category
279
+
280
+ Args:
281
+ category: Category to filter by
282
+
283
+ Returns:
284
+ List of whitelist entries in the category
285
+ """
286
+ return [entry for entry in self.entries if entry.category == category]
287
+
288
+ def get_all_categories(self) -> Set[str]:
289
+ """Get all categories in the whitelist"""
290
+ return {entry.category for entry in self.entries}
291
+
292
+ def get_enabled_processes(self) -> List[str]:
293
+ """Get list of all enabled process names"""
294
+ return [entry.process_name for entry in self.entries if entry.enabled]
295
+
296
+ def get_whitelist_summary(self) -> Dict[str, Any]:
297
+ """Get summary of whitelist status"""
298
+ enabled_count = sum(1 for entry in self.entries if entry.enabled)
299
+ categories = self.get_all_categories()
300
+
301
+ return {
302
+ 'enabled': self.enabled,
303
+ 'total_entries': len(self.entries),
304
+ 'enabled_entries': enabled_count,
305
+ 'disabled_entries': len(self.entries) - enabled_count,
306
+ 'categories': sorted(list(categories)),
307
+ 'last_modified': self.last_modified
308
+ }
309
+
310
+ def import_processes(self, process_list: List[str], category: str = "imported"):
311
+ """Import a list of processes to the whitelist
312
+
313
+ Args:
314
+ process_list: List of process names to import
315
+ category: Category for the imported processes
316
+ """
317
+ added_count = 0
318
+
319
+ for process_name in process_list:
320
+ if self.add_process(process_name, f"Imported process", category):
321
+ added_count += 1
322
+
323
+ logger.info(f"Imported {added_count} processes to whitelist")
324
+ return added_count
325
+
326
+ def export_processes(self, category: Optional[str] = None) -> List[str]:
327
+ """Export process names from the whitelist
328
+
329
+ Args:
330
+ category: Optional category filter
331
+
332
+ Returns:
333
+ List of process names
334
+ """
335
+ if category:
336
+ return [entry.process_name for entry in self.entries
337
+ if entry.category == category and entry.enabled]
338
+ else:
339
+ return [entry.process_name for entry in self.entries if entry.enabled]
340
+
341
+ def validate_process_name(self, process_name: str) -> bool:
342
+ """Validate a process name format
343
+
344
+ Args:
345
+ process_name: Process name to validate
346
+
347
+ Returns:
348
+ True if valid, False otherwise
349
+ """
350
+ if not process_name or not isinstance(process_name, str):
351
+ return False
352
+
353
+ # Check length
354
+ if len(process_name) > 255:
355
+ return False
356
+
357
+ # Check for valid characters (allowing wildcards for pattern matching)
358
+ valid_chars = re.compile(r'^[a-zA-Z0-9_\-\.\*\?]+\.exe$', re.IGNORECASE)
359
+ return bool(valid_chars.match(process_name))
360
+
361
+ def cleanup_entries(self):
362
+ """Remove duplicate and invalid entries"""
363
+ seen = set()
364
+ valid_entries = []
365
+
366
+ for entry in self.entries:
367
+ key = (entry.process_name.lower(), entry.exact_match)
368
+ if key not in seen and self.validate_process_name(entry.process_name):
369
+ seen.add(key)
370
+ valid_entries.append(entry)
371
+
372
+ removed_count = len(self.entries) - len(valid_entries)
373
+ self.entries = valid_entries
374
+
375
+ if removed_count > 0:
376
+ logger.info(f"Cleaned up {removed_count} invalid/duplicate whitelist entries")
377
+
378
+ return removed_count
@@ -0,0 +1,43 @@
1
+ """
2
+ GUI Automation Module
3
+ =====================
4
+
5
+ GUI automation module for the MCP Cheat Engine Server.
6
+
7
+ This module provides comprehensive PyAutoGUI integration as part of the
8
+ MCP Cheat Engine Server, offering secure and powerful GUI automation capabilities.
9
+
10
+ Modules:
11
+ --------
12
+ - core.integration: Main PyAutoGUI controller and integration
13
+ - tools.mcp_tools: MCP tool definitions for PyAutoGUI functionality
14
+ - demos: Example usage and demonstration scripts
15
+ - tests: Test suites for validation
16
+
17
+ Usage:
18
+ ------
19
+ from server.gui_automation.core.integration import PyAutoGUIController
20
+ from server.gui_automation.tools.mcp_tools import ALL_PYAUTOGUI_TOOLS, PyAutoGUIToolHandler
21
+
22
+ # Initialize controller
23
+ controller = PyAutoGUIController()
24
+
25
+ # Use MCP tools
26
+ from server.gui_automation.tools.mcp_tools import get_pyautogui_controller
27
+ gui = get_pyautogui_controller()
28
+ """
29
+
30
+ # Re-export main components for easy access
31
+ from .core.integration import PyAutoGUIController, get_pyautogui_controller, PYAUTOGUI_AVAILABLE
32
+ from .tools.mcp_tools import ALL_PYAUTOGUI_TOOLS, PyAutoGUIToolHandler
33
+
34
+ __version__ = "1.0.0"
35
+ __author__ = "MCP Cheat Engine Server"
36
+
37
+ __all__ = [
38
+ 'PyAutoGUIController',
39
+ 'get_pyautogui_controller',
40
+ 'PYAUTOGUI_AVAILABLE',
41
+ 'ALL_PYAUTOGUI_TOOLS',
42
+ 'PyAutoGUIToolHandler'
43
+ ]
@@ -0,0 +1,8 @@
1
+ """
2
+ PyAutoGUI Core Package
3
+ =====================
4
+
5
+ Core integration and controller functionality.
6
+ """
7
+
8
+ __all__ = ['integration']