-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathmcp_server.py
More file actions
121 lines (93 loc) · 3.87 KB
/
Copy pathmcp_server.py
File metadata and controls
121 lines (93 loc) · 3.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# mcp_server.py
"""
reptor-mcp: MCP Server exposing reptor CLI plugins for SysReptor automation.
Creates and configures the FastMCP application. The server dynamically
generates MCP tools from all reptor CLI plugins and registers custom
direct-API tools for common operations (findings CRUD, schema, templates).
Usage:
fastmcp run mcp_server.py:mcp --transport streamable-http --port 8008
"""
import io
import logging
import os
import sys
from contextlib import asynccontextmanager
from fastmcp import FastMCP
from fastmcp.utilities.logging import get_logger
from reptor.lib.reptor import Reptor
from custom_tools import FieldExcluder, register_custom_tools
from tool_generator import ToolGenerator
logger = get_logger("reptor-mcp")
# --- Optional: dev-mode path for local reptor source ---
_reptor_dev_path = os.environ.get("REPTOR_MAIN_PATH")
if _reptor_dev_path and os.path.isdir(_reptor_dev_path):
sys.path.insert(0, _reptor_dev_path)
logger.info(f"Dev mode: added {_reptor_dev_path} to sys.path")
_initialized = False
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _create_reptor_instance() -> Reptor:
"""Create a Reptor instance with suppressed startup output."""
saved = sys.stdout, sys.stderr, sys.stdin
sys.stdout = io.StringIO()
sys.stderr = io.StringIO()
sys.stdin = io.TextIOWrapper(io.BytesIO(b""), encoding="utf-8")
try:
return Reptor()
finally:
sys.stdout, sys.stderr, sys.stdin = saved
def _configure_ssl(config) -> None:
"""Apply SSL/TLS settings from environment variables."""
if os.environ.get("REPTOR_MCP_INSECURE", "false").lower() == "true":
config.set("insecure", True)
else:
ca_bundle = os.environ.get("REQUESTS_CA_BUNDLE")
if ca_bundle:
config.set("requests_ca_bundle", ca_bundle)
config.set("insecure", False)
def _create_field_excluder() -> FieldExcluder | None:
"""Create a FieldExcluder from REPTOR_MCP_EXCLUDE_FIELDS env var."""
raw = os.environ.get("REPTOR_MCP_EXCLUDE_FIELDS", "")
fields = [f.strip() for f in raw.split(",") if f.strip()]
if fields:
logger.info(f"Field exclusion enabled for: {fields}")
return FieldExcluder(fields)
return None
# ---------------------------------------------------------------------------
# Lifespan
# ---------------------------------------------------------------------------
@asynccontextmanager
async def lifespan(app: FastMCP):
global _initialized
if not _initialized:
if os.environ.get("REPTOR_MCP_DEBUG", "false").lower() == "true":
logger.setLevel(logging.DEBUG)
logger.info("Initializing reptor-mcp server...")
reptor = _create_reptor_instance()
_configure_ssl(reptor.get_config())
reptor.plugin_manager.run_loading_sequence()
reptor.plugin_manager.load_plugins()
field_excluder = _create_field_excluder()
# Dynamic wrappers for all CLI plugins
generator = ToolGenerator(mcp_server=app, reptor_instance=reptor)
generator.generate_tools()
# Custom tools using direct reptor API
register_custom_tools(app, reptor, field_excluder)
_initialized = True
logger.info("Server ready.")
yield
_initialized = False
logger.info("Server shutting down.")
# ---------------------------------------------------------------------------
# Application
# ---------------------------------------------------------------------------
mcp = FastMCP(
name="reptor-mcp",
instructions=(
"MCP server for SysReptor pentest reporting. Exposes reptor CLI plugins "
"as tools (nmap, nessus, burp, zap, sslyze, etc.) and provides direct "
"API tools for findings CRUD, schema discovery, and template management."
),
lifespan=lifespan,
)