iflow-mcp_developermode-korea_reversecore-mcp 1.0.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 (79) hide show
  1. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/METADATA +543 -0
  2. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/RECORD +79 -0
  3. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/WHEEL +5 -0
  4. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/entry_points.txt +2 -0
  5. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/licenses/LICENSE +21 -0
  6. iflow_mcp_developermode_korea_reversecore_mcp-1.0.0.dist-info/top_level.txt +1 -0
  7. reversecore_mcp/__init__.py +9 -0
  8. reversecore_mcp/core/__init__.py +78 -0
  9. reversecore_mcp/core/audit.py +101 -0
  10. reversecore_mcp/core/binary_cache.py +138 -0
  11. reversecore_mcp/core/command_spec.py +357 -0
  12. reversecore_mcp/core/config.py +432 -0
  13. reversecore_mcp/core/container.py +288 -0
  14. reversecore_mcp/core/decorators.py +152 -0
  15. reversecore_mcp/core/error_formatting.py +93 -0
  16. reversecore_mcp/core/error_handling.py +142 -0
  17. reversecore_mcp/core/evidence.py +229 -0
  18. reversecore_mcp/core/exceptions.py +296 -0
  19. reversecore_mcp/core/execution.py +240 -0
  20. reversecore_mcp/core/ghidra.py +642 -0
  21. reversecore_mcp/core/ghidra_helper.py +481 -0
  22. reversecore_mcp/core/ghidra_manager.py +234 -0
  23. reversecore_mcp/core/json_utils.py +131 -0
  24. reversecore_mcp/core/loader.py +73 -0
  25. reversecore_mcp/core/logging_config.py +206 -0
  26. reversecore_mcp/core/memory.py +721 -0
  27. reversecore_mcp/core/metrics.py +198 -0
  28. reversecore_mcp/core/mitre_mapper.py +365 -0
  29. reversecore_mcp/core/plugin.py +45 -0
  30. reversecore_mcp/core/r2_helpers.py +404 -0
  31. reversecore_mcp/core/r2_pool.py +403 -0
  32. reversecore_mcp/core/report_generator.py +268 -0
  33. reversecore_mcp/core/resilience.py +252 -0
  34. reversecore_mcp/core/resource_manager.py +169 -0
  35. reversecore_mcp/core/result.py +132 -0
  36. reversecore_mcp/core/security.py +213 -0
  37. reversecore_mcp/core/validators.py +238 -0
  38. reversecore_mcp/dashboard/__init__.py +221 -0
  39. reversecore_mcp/prompts/__init__.py +56 -0
  40. reversecore_mcp/prompts/common.py +24 -0
  41. reversecore_mcp/prompts/game.py +280 -0
  42. reversecore_mcp/prompts/malware.py +1219 -0
  43. reversecore_mcp/prompts/report.py +150 -0
  44. reversecore_mcp/prompts/security.py +136 -0
  45. reversecore_mcp/resources.py +329 -0
  46. reversecore_mcp/server.py +727 -0
  47. reversecore_mcp/tools/__init__.py +49 -0
  48. reversecore_mcp/tools/analysis/__init__.py +74 -0
  49. reversecore_mcp/tools/analysis/capa_tools.py +215 -0
  50. reversecore_mcp/tools/analysis/die_tools.py +180 -0
  51. reversecore_mcp/tools/analysis/diff_tools.py +643 -0
  52. reversecore_mcp/tools/analysis/lief_tools.py +272 -0
  53. reversecore_mcp/tools/analysis/signature_tools.py +591 -0
  54. reversecore_mcp/tools/analysis/static_analysis.py +479 -0
  55. reversecore_mcp/tools/common/__init__.py +58 -0
  56. reversecore_mcp/tools/common/file_operations.py +352 -0
  57. reversecore_mcp/tools/common/memory_tools.py +516 -0
  58. reversecore_mcp/tools/common/patch_explainer.py +230 -0
  59. reversecore_mcp/tools/common/server_tools.py +115 -0
  60. reversecore_mcp/tools/ghidra/__init__.py +19 -0
  61. reversecore_mcp/tools/ghidra/decompilation.py +975 -0
  62. reversecore_mcp/tools/ghidra/ghidra_tools.py +1052 -0
  63. reversecore_mcp/tools/malware/__init__.py +61 -0
  64. reversecore_mcp/tools/malware/adaptive_vaccine.py +579 -0
  65. reversecore_mcp/tools/malware/dormant_detector.py +756 -0
  66. reversecore_mcp/tools/malware/ioc_tools.py +228 -0
  67. reversecore_mcp/tools/malware/vulnerability_hunter.py +519 -0
  68. reversecore_mcp/tools/malware/yara_tools.py +214 -0
  69. reversecore_mcp/tools/patch_explainer.py +19 -0
  70. reversecore_mcp/tools/radare2/__init__.py +13 -0
  71. reversecore_mcp/tools/radare2/r2_analysis.py +972 -0
  72. reversecore_mcp/tools/radare2/r2_session.py +376 -0
  73. reversecore_mcp/tools/radare2/radare2_mcp_tools.py +1183 -0
  74. reversecore_mcp/tools/report/__init__.py +4 -0
  75. reversecore_mcp/tools/report/email.py +82 -0
  76. reversecore_mcp/tools/report/report_mcp_tools.py +344 -0
  77. reversecore_mcp/tools/report/report_tools.py +1076 -0
  78. reversecore_mcp/tools/report/session.py +194 -0
  79. reversecore_mcp/tools/report_tools.py +11 -0
@@ -0,0 +1,516 @@
1
+ """
2
+ MCP Memory Tools for AI Long-term Memory.
3
+
4
+ This module provides MCP-compatible tools for managing AI analysis memories,
5
+ enabling multi-session memory persistence and cross-project knowledge transfer.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import time
12
+ from pathlib import Path
13
+ from typing import Any
14
+
15
+ from fastmcp import FastMCP
16
+
17
+ from reversecore_mcp.core.logging_config import get_logger
18
+ from reversecore_mcp.core.memory import get_memory_store, initialize_memory_store
19
+ from reversecore_mcp.core.plugin import Plugin
20
+
21
+ logger = get_logger(__name__)
22
+
23
+
24
+ class MemoryToolsPlugin(Plugin):
25
+ """Plugin for AI memory management tools."""
26
+
27
+ name = "memory_tools"
28
+ description = "AI long-term memory management for analysis sessions"
29
+
30
+ def register(self, mcp: FastMCP) -> None:
31
+ """Register all memory tools with the MCP server."""
32
+
33
+ @mcp.tool()
34
+ async def create_analysis_session(
35
+ name: str,
36
+ binary_name: str | None = None,
37
+ binary_path: str | None = None,
38
+ ) -> dict[str, Any]:
39
+ """
40
+ Create a new analysis session to store memories.
41
+
42
+ Use this when starting a new reverse engineering analysis.
43
+ The session name should be descriptive and follow a template format
44
+ like 'malware_analysis_2024_001' or 'game_cheat_detection'.
45
+
46
+ Args:
47
+ name: Template name for the session (e.g., 'malware_sample_001')
48
+ binary_name: Name of the binary being analyzed (optional)
49
+ binary_path: Path to binary for automatic hash calculation (optional)
50
+
51
+ Returns:
52
+ Session information including ID for future reference
53
+ """
54
+ store = get_memory_store()
55
+ await store.initialize()
56
+
57
+ # Calculate hash if path provided
58
+ binary_hash = None
59
+ if binary_path:
60
+ try:
61
+ path = Path(binary_path)
62
+ if path.exists():
63
+ binary_hash = hashlib.sha256(path.read_bytes()).hexdigest()
64
+ if not binary_name:
65
+ binary_name = path.name
66
+ except Exception as e:
67
+ logger.warning(f"Could not hash binary: {e}")
68
+
69
+ session_id = await store.create_session(
70
+ name=name,
71
+ binary_name=binary_name,
72
+ binary_hash=binary_hash,
73
+ )
74
+
75
+ return {
76
+ "status": "success",
77
+ "session_id": session_id,
78
+ "name": name,
79
+ "binary_name": binary_name,
80
+ "binary_hash": binary_hash,
81
+ "message": f"Analysis session '{name}' created. Use this session_id to save memories.",
82
+ }
83
+
84
+ @mcp.tool()
85
+ async def save_analysis_memory(
86
+ session_id: str,
87
+ memory_type: str,
88
+ content: str,
89
+ category: str | None = None,
90
+ user_prompt: str | None = None,
91
+ importance: int = 5,
92
+ ) -> dict[str, Any]:
93
+ """
94
+ Save important information to long-term memory.
95
+
96
+ Use this to remember:
97
+ - Function addresses and their purposes
98
+ - Vulnerability patterns discovered
99
+ - API call sequences
100
+ - User instructions and preferences
101
+ - Interesting strings or structures
102
+
103
+ Args:
104
+ session_id: Session ID from create_analysis_session
105
+ memory_type: Type of memory:
106
+ - 'finding': Analysis discoveries
107
+ - 'pattern': Code/behavior patterns
108
+ - 'instruction': User preferences/instructions
109
+ - 'context': General context information
110
+ category: Optional category:
111
+ - 'function': Function-related info
112
+ - 'vulnerability': Security issues
113
+ - 'string': Important strings
114
+ - 'structure': Data structures
115
+ - 'api': API usage patterns
116
+ content: The actual content to remember (text or JSON string)
117
+ user_prompt: The user's prompt when this was discovered (optional)
118
+ importance: Importance level 1-10 (default 5, higher = more important)
119
+
120
+ Returns:
121
+ Confirmation with memory ID
122
+ """
123
+ store = get_memory_store()
124
+ await store.initialize()
125
+
126
+ memory_id = await store.save_memory(
127
+ session_id=session_id,
128
+ memory_type=memory_type,
129
+ content=content,
130
+ category=category,
131
+ user_prompt=user_prompt,
132
+ importance=importance,
133
+ )
134
+
135
+ return {
136
+ "status": "success",
137
+ "memory_id": memory_id,
138
+ "message": f"Memory saved (ID: {memory_id}, importance: {importance}/10)",
139
+ }
140
+
141
+ @mcp.tool()
142
+ async def recall_analysis_memory(
143
+ query: str,
144
+ session_id: str | None = None,
145
+ memory_type: str | None = None,
146
+ limit: int = 10,
147
+ ) -> dict[str, Any]:
148
+ """
149
+ Search and recall memories from past analyses.
150
+
151
+ Use this when you need to remember something from earlier,
152
+ or when the user asks about previous findings.
153
+
154
+ Args:
155
+ query: Search query (keywords or phrases)
156
+ session_id: Limit search to specific session (optional)
157
+ memory_type: Filter by type ('finding', 'pattern', 'instruction', 'context')
158
+ limit: Maximum number of results (default 10)
159
+
160
+ Returns:
161
+ List of matching memories with context
162
+ """
163
+ store = get_memory_store()
164
+ await store.initialize()
165
+
166
+ memories = await store.recall_memories(
167
+ query=query,
168
+ session_id=session_id,
169
+ memory_type=memory_type,
170
+ limit=limit,
171
+ )
172
+
173
+ return {
174
+ "status": "success",
175
+ "count": len(memories),
176
+ "memories": memories,
177
+ "message": f"Found {len(memories)} relevant memories",
178
+ }
179
+
180
+ @mcp.tool()
181
+ async def list_analysis_sessions(
182
+ status: str | None = None,
183
+ limit: int = 20,
184
+ ) -> dict[str, Any]:
185
+ """
186
+ List all analysis sessions with timestamps and status.
187
+
188
+ Use this to see what analyses have been done before,
189
+ or to find a session to resume.
190
+
191
+ Args:
192
+ status: Filter by status ('in_progress', 'completed', 'paused')
193
+ limit: Maximum number of sessions to return
194
+
195
+ Returns:
196
+ List of sessions with metadata
197
+ """
198
+ store = get_memory_store()
199
+ await store.initialize()
200
+
201
+ sessions = await store.list_sessions(status=status, limit=limit)
202
+
203
+ # Format timestamps for readability
204
+ for session in sessions:
205
+ if session.get("analysis_duration_seconds"):
206
+ duration = session["analysis_duration_seconds"]
207
+ hours = int(duration // 3600)
208
+ minutes = int((duration % 3600) // 60)
209
+ session["analysis_duration_formatted"] = f"{hours}h {minutes}m"
210
+
211
+ return {
212
+ "status": "success",
213
+ "count": len(sessions),
214
+ "sessions": sessions,
215
+ }
216
+
217
+ @mcp.tool()
218
+ async def get_session_detail(
219
+ session_id: str,
220
+ ) -> dict[str, Any]:
221
+ """
222
+ Get complete details and context for a specific session.
223
+
224
+ Use this when resuming an analysis or reviewing past work.
225
+ Returns all memories and patterns associated with the session.
226
+
227
+ Args:
228
+ session_id: Session ID to retrieve
229
+
230
+ Returns:
231
+ Full session context including all memories and patterns
232
+ """
233
+ store = get_memory_store()
234
+ await store.initialize()
235
+
236
+ context = await store.get_session_context(session_id)
237
+
238
+ if not context:
239
+ return {
240
+ "status": "error",
241
+ "message": f"Session '{session_id}' not found",
242
+ }
243
+
244
+ return {
245
+ "status": "success",
246
+ "session": context["session"],
247
+ "memories": context["memories"],
248
+ "patterns": context["patterns"],
249
+ "summary": {
250
+ "memory_count": context["memory_count"],
251
+ "pattern_count": context["pattern_count"],
252
+ },
253
+ "message": "Session context retrieved. Use this to resume analysis.",
254
+ }
255
+
256
+ @mcp.tool()
257
+ async def resume_session(
258
+ session_id: str | None = None,
259
+ binary_name: str | None = None,
260
+ ) -> dict[str, Any]:
261
+ """
262
+ Resume a previous analysis session with full context restoration.
263
+
264
+ Use this when the user says "continue where we left off" or
265
+ "resume yesterday's analysis".
266
+
267
+ Args:
268
+ session_id: Specific session ID to resume (optional)
269
+ binary_name: Find latest session for this binary (optional)
270
+
271
+ Returns:
272
+ Full session context for resumption
273
+
274
+ Note:
275
+ If neither argument provided, resumes the most recent session.
276
+ """
277
+ store = get_memory_store()
278
+ await store.initialize()
279
+
280
+ # Find session to resume
281
+ if session_id:
282
+ session = await store.get_session(session_id)
283
+ else:
284
+ session = await store.find_latest_session(binary_name)
285
+
286
+ if not session:
287
+ return {
288
+ "status": "error",
289
+ "message": "No session found to resume. Start a new session with create_analysis_session.",
290
+ }
291
+
292
+ # Update session status
293
+ await store.update_session(session["id"], status="in_progress")
294
+
295
+ # Get full context
296
+ context = await store.get_session_context(session["id"])
297
+
298
+ return {
299
+ "status": "success",
300
+ "message": f"Resuming session '{session['name']}' with {context['memory_count']} memories",
301
+ "session": context["session"],
302
+ "memories": context["memories"],
303
+ "patterns": context["patterns"],
304
+ "instructions": [
305
+ m for m in context["memories"] if m.get("memory_type") == "instruction"
306
+ ],
307
+ }
308
+
309
+ @mcp.tool()
310
+ async def complete_session(
311
+ session_id: str,
312
+ summary: str,
313
+ ) -> dict[str, Any]:
314
+ """
315
+ Mark an analysis session as completed with a summary.
316
+
317
+ Use this when finishing an analysis to save a summary
318
+ for future reference.
319
+
320
+ Args:
321
+ session_id: Session ID to complete
322
+ summary: AI-generated summary of the analysis findings
323
+
324
+ Returns:
325
+ Confirmation of completion
326
+ """
327
+ store = get_memory_store()
328
+ await store.initialize()
329
+
330
+ success = await store.update_session(
331
+ session_id=session_id,
332
+ status="completed",
333
+ summary=summary,
334
+ )
335
+
336
+ if not success:
337
+ return {
338
+ "status": "error",
339
+ "message": f"Session '{session_id}' not found",
340
+ }
341
+
342
+ return {
343
+ "status": "success",
344
+ "message": "Session marked as completed",
345
+ "summary": summary,
346
+ }
347
+
348
+ @mcp.tool()
349
+ async def save_pattern(
350
+ session_id: str,
351
+ pattern_type: str,
352
+ pattern_signature: str,
353
+ description: str | None = None,
354
+ ) -> dict[str, Any]:
355
+ """
356
+ Save a code/behavior pattern for cross-session similarity search.
357
+
358
+ Use this when you discover a notable pattern that might appear
359
+ in other samples. This enables "Hey, this looks similar to before!"
360
+
361
+ Args:
362
+ session_id: Current session ID
363
+ pattern_type: Type of pattern:
364
+ - 'api_sequence': Sequence of API calls
365
+ - 'code_pattern': Assembly/code pattern
366
+ - 'behavior': Behavioral pattern
367
+ pattern_signature: Normalized pattern signature for matching
368
+ Example: "VirtualAlloc,WriteProcessMemory,CreateRemoteThread"
369
+ description: Human-readable description of the pattern
370
+
371
+ Returns:
372
+ Confirmation with pattern ID
373
+ """
374
+ store = get_memory_store()
375
+ await store.initialize()
376
+
377
+ pattern_id = await store.save_pattern(
378
+ session_id=session_id,
379
+ pattern_type=pattern_type,
380
+ pattern_signature=pattern_signature,
381
+ description=description,
382
+ )
383
+
384
+ return {
385
+ "status": "success",
386
+ "pattern_id": pattern_id,
387
+ "message": f"Pattern saved for cross-session matching",
388
+ }
389
+
390
+ @mcp.tool()
391
+ async def find_similar_patterns(
392
+ pattern_signature: str,
393
+ pattern_type: str | None = None,
394
+ current_session_id: str | None = None,
395
+ limit: int = 10,
396
+ ) -> dict[str, Any]:
397
+ """
398
+ Find similar patterns from previous analyses.
399
+
400
+ Use this to check if current findings match anything
401
+ from past analyses. Enables knowledge transfer across projects.
402
+
403
+ Args:
404
+ pattern_signature: Pattern to search for
405
+ pattern_type: Limit to specific type (optional)
406
+ current_session_id: Exclude current session from results
407
+ limit: Maximum results
408
+
409
+ Returns:
410
+ List of similar patterns with session context
411
+ """
412
+ store = get_memory_store()
413
+ await store.initialize()
414
+
415
+ similar = await store.find_similar_patterns(
416
+ pattern_signature=pattern_signature,
417
+ pattern_type=pattern_type,
418
+ exclude_session=current_session_id,
419
+ limit=limit,
420
+ )
421
+
422
+ if similar:
423
+ message = f"Found {len(similar)} similar patterns from previous analyses!"
424
+ else:
425
+ message = "No similar patterns found in previous analyses."
426
+
427
+ return {
428
+ "status": "success",
429
+ "count": len(similar),
430
+ "similar_patterns": similar,
431
+ "message": message,
432
+ }
433
+
434
+ @mcp.tool()
435
+ async def get_relevant_context(
436
+ description: str,
437
+ current_session_id: str | None = None,
438
+ limit: int = 5,
439
+ ) -> dict[str, Any]:
440
+ """
441
+ Get relevant context from past analyses for current work.
442
+
443
+ Use this proactively when analyzing something new to check
444
+ if there's relevant knowledge from previous sessions.
445
+
446
+ Args:
447
+ description: Description of what you're currently analyzing
448
+ current_session_id: Current session to exclude
449
+ limit: Maximum relevant items
450
+
451
+ Returns:
452
+ Relevant memories from past sessions
453
+ """
454
+ store = get_memory_store()
455
+ await store.initialize()
456
+
457
+ relevant = await store.get_relevant_context(
458
+ current_analysis=description,
459
+ current_session_id=current_session_id,
460
+ limit=limit,
461
+ )
462
+
463
+ if relevant:
464
+ message = f"Found {len(relevant)} relevant memories from past analyses"
465
+ else:
466
+ message = "No relevant past context found"
467
+
468
+ return {
469
+ "status": "success",
470
+ "count": len(relevant),
471
+ "relevant_memories": relevant,
472
+ "message": message,
473
+ }
474
+
475
+ @mcp.tool()
476
+ async def update_analysis_time(
477
+ session_id: str,
478
+ duration_seconds: float,
479
+ ) -> dict[str, Any]:
480
+ """
481
+ Update the cumulative analysis time for a session.
482
+
483
+ Call this periodically to track how long an analysis takes.
484
+
485
+ Args:
486
+ session_id: Session ID
487
+ duration_seconds: Additional time to add (in seconds)
488
+
489
+ Returns:
490
+ Confirmation
491
+ """
492
+ store = get_memory_store()
493
+ await store.initialize()
494
+
495
+ success = await store.update_session(
496
+ session_id=session_id,
497
+ add_duration=duration_seconds,
498
+ )
499
+
500
+ return {
501
+ "status": "success" if success else "error",
502
+ "message": f"Added {duration_seconds:.1f}s to analysis time",
503
+ }
504
+
505
+ logger.info(f"Registered {self.name} plugin with 11 tools")
506
+
507
+
508
+ def register_memory_tools(mcp: FastMCP) -> None:
509
+ """
510
+ Register memory tools with an MCP server instance.
511
+
512
+ Args:
513
+ mcp: FastMCP server instance
514
+ """
515
+ plugin = MemoryToolsPlugin()
516
+ plugin.register(mcp)