iflow-mcp_anton-prosterity-documentation-search-enhanced 1.9.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.
- documentation_search_enhanced/__init__.py +14 -0
- documentation_search_enhanced/__main__.py +6 -0
- documentation_search_enhanced/config.json +1674 -0
- documentation_search_enhanced/config_manager.py +233 -0
- documentation_search_enhanced/config_validator.py +79 -0
- documentation_search_enhanced/content_enhancer.py +578 -0
- documentation_search_enhanced/docker_manager.py +87 -0
- documentation_search_enhanced/logger.py +179 -0
- documentation_search_enhanced/main.py +2170 -0
- documentation_search_enhanced/project_generator.py +260 -0
- documentation_search_enhanced/project_scanner.py +85 -0
- documentation_search_enhanced/reranker.py +230 -0
- documentation_search_enhanced/site_index_builder.py +274 -0
- documentation_search_enhanced/site_index_downloader.py +222 -0
- documentation_search_enhanced/site_search.py +1325 -0
- documentation_search_enhanced/smart_search.py +473 -0
- documentation_search_enhanced/snyk_integration.py +657 -0
- documentation_search_enhanced/vector_search.py +303 -0
- documentation_search_enhanced/version_resolver.py +189 -0
- documentation_search_enhanced/vulnerability_scanner.py +545 -0
- documentation_search_enhanced/web_scraper.py +117 -0
- iflow_mcp_anton_prosterity_documentation_search_enhanced-1.9.0.dist-info/METADATA +195 -0
- iflow_mcp_anton_prosterity_documentation_search_enhanced-1.9.0.dist-info/RECORD +26 -0
- iflow_mcp_anton_prosterity_documentation_search_enhanced-1.9.0.dist-info/WHEEL +4 -0
- iflow_mcp_anton_prosterity_documentation_search_enhanced-1.9.0.dist-info/entry_points.txt +2 -0
- iflow_mcp_anton_prosterity_documentation_search_enhanced-1.9.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Enhanced logging module for documentation-search-enhanced MCP server.
|
|
3
|
+
Inspired by AWS MCP logging patterns.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from enum import Enum
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LogLevel(Enum):
|
|
15
|
+
"""Logging levels matching AWS MCP patterns"""
|
|
16
|
+
|
|
17
|
+
ERROR = "ERROR"
|
|
18
|
+
WARN = "WARN"
|
|
19
|
+
INFO = "INFO"
|
|
20
|
+
DEBUG = "DEBUG"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class StructuredLogger:
|
|
24
|
+
"""Structured logger with AWS MCP-style formatting"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, name: str = "documentation-search-enhanced"):
|
|
27
|
+
self.name = name
|
|
28
|
+
self.logger = logging.getLogger(name)
|
|
29
|
+
self._setup_logger()
|
|
30
|
+
|
|
31
|
+
def _setup_logger(self):
|
|
32
|
+
"""Setup logger with environment-based configuration"""
|
|
33
|
+
log_level = os.getenv("FASTMCP_LOG_LEVEL", "INFO").upper()
|
|
34
|
+
|
|
35
|
+
# Map string levels to logging constants
|
|
36
|
+
level_map = {
|
|
37
|
+
"ERROR": logging.ERROR,
|
|
38
|
+
"WARN": logging.WARNING,
|
|
39
|
+
"INFO": logging.INFO,
|
|
40
|
+
"DEBUG": logging.DEBUG,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
self.logger.setLevel(level_map.get(log_level, logging.INFO))
|
|
44
|
+
|
|
45
|
+
# Clear existing handlers
|
|
46
|
+
self.logger.handlers.clear()
|
|
47
|
+
|
|
48
|
+
# Create console handler
|
|
49
|
+
handler = logging.StreamHandler(sys.stderr)
|
|
50
|
+
|
|
51
|
+
# Create structured formatter
|
|
52
|
+
formatter = StructuredFormatter()
|
|
53
|
+
handler.setFormatter(formatter)
|
|
54
|
+
|
|
55
|
+
self.logger.addHandler(handler)
|
|
56
|
+
|
|
57
|
+
# Prevent propagation to root logger
|
|
58
|
+
self.logger.propagate = False
|
|
59
|
+
|
|
60
|
+
def error(self, message: str, **kwargs):
|
|
61
|
+
"""Log error with structured data"""
|
|
62
|
+
self._log(logging.ERROR, message, **kwargs)
|
|
63
|
+
|
|
64
|
+
def warn(self, message: str, **kwargs):
|
|
65
|
+
"""Log warning with structured data"""
|
|
66
|
+
self._log(logging.WARNING, message, **kwargs)
|
|
67
|
+
|
|
68
|
+
def info(self, message: str, **kwargs):
|
|
69
|
+
"""Log info with structured data"""
|
|
70
|
+
self._log(logging.INFO, message, **kwargs)
|
|
71
|
+
|
|
72
|
+
def debug(self, message: str, **kwargs):
|
|
73
|
+
"""Log debug with structured data"""
|
|
74
|
+
self._log(logging.DEBUG, message, **kwargs)
|
|
75
|
+
|
|
76
|
+
def _log(self, level: int, message: str, **kwargs):
|
|
77
|
+
"""Internal logging method with structured data"""
|
|
78
|
+
# Filter out None values and convert to strings
|
|
79
|
+
filtered_kwargs = {
|
|
80
|
+
k: str(v) if v is not None else "unknown" for k, v in kwargs.items()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
extra = {
|
|
84
|
+
"structured_data": filtered_kwargs,
|
|
85
|
+
"server_name": self.name,
|
|
86
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
87
|
+
}
|
|
88
|
+
self.logger.log(level, message, extra=extra)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class StructuredFormatter(logging.Formatter):
|
|
92
|
+
"""Custom formatter for structured logging"""
|
|
93
|
+
|
|
94
|
+
def format(self, record):
|
|
95
|
+
"""Format log record with structured data"""
|
|
96
|
+
log_obj = {
|
|
97
|
+
"timestamp": getattr(record, "timestamp", datetime.utcnow().isoformat()),
|
|
98
|
+
"level": record.levelname,
|
|
99
|
+
"server": getattr(record, "server_name", "documentation-search-enhanced"),
|
|
100
|
+
"message": record.getMessage(),
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
# Add structured data if present
|
|
104
|
+
structured_data = getattr(record, "structured_data", {})
|
|
105
|
+
if structured_data:
|
|
106
|
+
log_obj.update(structured_data)
|
|
107
|
+
|
|
108
|
+
# Add exception info if present
|
|
109
|
+
if record.exc_info:
|
|
110
|
+
log_obj["exception"] = self.formatException(record.exc_info)
|
|
111
|
+
|
|
112
|
+
return json.dumps(log_obj)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class PerformanceTracker:
|
|
116
|
+
"""Track performance metrics like AWS MCP servers"""
|
|
117
|
+
|
|
118
|
+
def __init__(self, logger: StructuredLogger):
|
|
119
|
+
self.logger = logger
|
|
120
|
+
self.start_time = datetime.utcnow()
|
|
121
|
+
|
|
122
|
+
def track_request(self, tool_name: str, library: str = None, query: str = None):
|
|
123
|
+
"""Track request metrics"""
|
|
124
|
+
return RequestContext(self.logger, tool_name, library, query)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
class RequestContext:
|
|
128
|
+
"""Context manager for tracking individual requests"""
|
|
129
|
+
|
|
130
|
+
def __init__(
|
|
131
|
+
self,
|
|
132
|
+
logger: StructuredLogger,
|
|
133
|
+
tool_name: str,
|
|
134
|
+
library: str = None,
|
|
135
|
+
query: str = None,
|
|
136
|
+
):
|
|
137
|
+
self.logger = logger
|
|
138
|
+
self.tool_name = tool_name
|
|
139
|
+
self.library = library
|
|
140
|
+
self.query = query
|
|
141
|
+
self.start_time = None
|
|
142
|
+
|
|
143
|
+
def __enter__(self):
|
|
144
|
+
self.start_time = datetime.utcnow()
|
|
145
|
+
self.logger.info(
|
|
146
|
+
f"Starting {self.tool_name} request",
|
|
147
|
+
tool_name=self.tool_name,
|
|
148
|
+
library=self.library or "unknown",
|
|
149
|
+
query_length=len(self.query) if self.query else 0,
|
|
150
|
+
)
|
|
151
|
+
return self
|
|
152
|
+
|
|
153
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
154
|
+
if self.start_time is None:
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
duration = (datetime.utcnow() - self.start_time).total_seconds()
|
|
158
|
+
|
|
159
|
+
if exc_type:
|
|
160
|
+
self.logger.error(
|
|
161
|
+
f"Failed {self.tool_name} request",
|
|
162
|
+
tool_name=self.tool_name,
|
|
163
|
+
library=self.library or "unknown",
|
|
164
|
+
duration_seconds=duration,
|
|
165
|
+
error_type=exc_type.__name__,
|
|
166
|
+
error_message=str(exc_val),
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
self.logger.info(
|
|
170
|
+
f"Completed {self.tool_name} request",
|
|
171
|
+
tool_name=self.tool_name,
|
|
172
|
+
library=self.library or "unknown",
|
|
173
|
+
duration_seconds=duration,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# Global logger instance
|
|
178
|
+
logger = StructuredLogger()
|
|
179
|
+
performance_tracker = PerformanceTracker(logger)
|