mcp-proxy-adapter 6.9.17__py3-none-any.whl β 6.9.18__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.
- mcp_proxy_adapter/api/app.py +52 -52
- mcp_proxy_adapter/api/handlers.py +5 -5
- mcp_proxy_adapter/api/middleware/__init__.py +8 -8
- mcp_proxy_adapter/api/middleware/base.py +14 -14
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
- mcp_proxy_adapter/api/middleware/factory.py +17 -17
- mcp_proxy_adapter/api/middleware/logging.py +6 -6
- mcp_proxy_adapter/api/middleware/performance.py +3 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
- mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
- mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
- mcp_proxy_adapter/api/tool_integration.py +3 -2
- mcp_proxy_adapter/api/tools.py +4 -3
- mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
- mcp_proxy_adapter/commands/base.py +10 -10
- mcp_proxy_adapter/commands/builtin_commands.py +6 -6
- mcp_proxy_adapter/commands/catalog_manager.py +74 -74
- mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
- mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
- mcp_proxy_adapter/commands/command_registry.py +68 -67
- mcp_proxy_adapter/commands/config_command.py +3 -1
- mcp_proxy_adapter/commands/dependency_manager.py +10 -10
- mcp_proxy_adapter/commands/help_command.py +21 -20
- mcp_proxy_adapter/commands/hooks.py +27 -27
- mcp_proxy_adapter/commands/key_management_command.py +19 -18
- mcp_proxy_adapter/commands/plugins_command.py +2 -1
- mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
- mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
- mcp_proxy_adapter/commands/registration_status_command.py +4 -4
- mcp_proxy_adapter/commands/reload_command.py +5 -5
- mcp_proxy_adapter/commands/role_test_command.py +2 -1
- mcp_proxy_adapter/commands/roles_management_command.py +9 -8
- mcp_proxy_adapter/commands/security_command.py +3 -2
- mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
- mcp_proxy_adapter/commands/token_management_command.py +12 -11
- mcp_proxy_adapter/commands/transport_management_command.py +2 -2
- mcp_proxy_adapter/config.py +3 -3
- mcp_proxy_adapter/core/__init__.py +1 -1
- mcp_proxy_adapter/core/app_runner.py +3 -3
- mcp_proxy_adapter/core/auth_validator.py +9 -9
- mcp_proxy_adapter/core/certificate_utils.py +27 -27
- mcp_proxy_adapter/core/client_manager.py +13 -13
- mcp_proxy_adapter/core/client_security.py +26 -26
- mcp_proxy_adapter/core/config_converter.py +18 -18
- mcp_proxy_adapter/core/config_validator.py +5 -1
- mcp_proxy_adapter/core/crl_utils.py +22 -22
- mcp_proxy_adapter/core/logging.py +21 -13
- mcp_proxy_adapter/core/mtls_asgi.py +7 -7
- mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
- mcp_proxy_adapter/core/mtls_proxy.py +9 -9
- mcp_proxy_adapter/core/mtls_server.py +18 -18
- mcp_proxy_adapter/core/protocol_manager.py +29 -29
- mcp_proxy_adapter/core/proxy_registration.py +67 -67
- mcp_proxy_adapter/core/security_adapter.py +18 -18
- mcp_proxy_adapter/core/security_factory.py +16 -16
- mcp_proxy_adapter/core/security_integration.py +6 -6
- mcp_proxy_adapter/core/server_adapter.py +12 -12
- mcp_proxy_adapter/core/server_engine.py +17 -17
- mcp_proxy_adapter/core/signal_handler.py +12 -12
- mcp_proxy_adapter/core/ssl_utils.py +12 -12
- mcp_proxy_adapter/core/transport_manager.py +14 -14
- mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
- mcp_proxy_adapter/core/utils.py +5 -5
- mcp_proxy_adapter/custom_openapi.py +7 -7
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
- mcp_proxy_adapter/examples/full_application/main.py +28 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
- mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
- mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.17.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.9.18.dist-info/RECORD +149 -0
- mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.17.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/top_level.txt +0 -0
mcp_proxy_adapter/api/app.py
CHANGED
@@ -35,7 +35,7 @@ from mcp_proxy_adapter.api.schemas import (
|
|
35
35
|
from mcp_proxy_adapter.api.tools import get_tool_description, execute_tool
|
36
36
|
from mcp_proxy_adapter.config import config
|
37
37
|
from mcp_proxy_adapter.core.errors import MicroserviceError, NotFoundError
|
38
|
-
from mcp_proxy_adapter.core.logging import
|
38
|
+
from mcp_proxy_adapter.core.logging import get_global_logger, RequestLogger
|
39
39
|
from mcp_proxy_adapter.core.ssl_utils import SSLUtils
|
40
40
|
from mcp_proxy_adapter.commands.command_registry import registry
|
41
41
|
from mcp_proxy_adapter.custom_openapi import custom_openapi_with_fallback
|
@@ -76,13 +76,13 @@ def _determine_registration_url(config: Dict[str, Any]) -> str:
|
|
76
76
|
# Use protocol from registration configuration
|
77
77
|
# Convert mtls to https for URL construction (mTLS is still HTTPS)
|
78
78
|
protocol = "https" if registration_protocol == "mtls" else registration_protocol
|
79
|
-
|
79
|
+
get_global_logger().info(f"π Using registration.protocol: {registration_protocol} -> {protocol}")
|
80
80
|
else:
|
81
81
|
# Fallback to server protocol
|
82
82
|
verify_client = config.get("transport", {}).get("verify_client", False)
|
83
83
|
ssl_enabled = server_protocol in ["https", "mtls"] or verify_client
|
84
84
|
protocol = "https" if ssl_enabled else "http"
|
85
|
-
|
85
|
+
get_global_logger().info(f"β οΈ Fallback to server.protocol: {server_protocol} -> {protocol} (verify_client={verify_client})")
|
86
86
|
|
87
87
|
# Determine host
|
88
88
|
if not public_host:
|
@@ -108,7 +108,7 @@ def _determine_registration_url(config: Dict[str, Any]) -> str:
|
|
108
108
|
# Build URL
|
109
109
|
server_url = f"{protocol}://{resolved_host}:{resolved_port}"
|
110
110
|
|
111
|
-
|
111
|
+
get_global_logger().info(
|
112
112
|
"π Registration URL selection: server_host=%s, server_port=%s, public_host=%s, public_port=%s, protocol=%s, resolved_host=%s, resolved_port=%s, server_url=%s",
|
113
113
|
server_host, server_port, public_host, public_port, protocol, resolved_host, resolved_port, server_url
|
114
114
|
)
|
@@ -188,13 +188,13 @@ def create_lifespan(config_path: Optional[str] = None, current_config: Optional[
|
|
188
188
|
|
189
189
|
# Initialize proxy registration
|
190
190
|
initialize_proxy_registration(config_to_use)
|
191
|
-
|
191
|
+
get_global_logger().info(
|
192
192
|
"π Initialized proxy registration with server_url: %s",
|
193
193
|
early_server_url,
|
194
194
|
)
|
195
195
|
|
196
196
|
except Exception as e:
|
197
|
-
|
197
|
+
get_global_logger().error(f"Failed to initialize async registration: {e}")
|
198
198
|
|
199
199
|
# Initialize system using unified logic (may perform registration)
|
200
200
|
# Set global config for reload_system
|
@@ -212,10 +212,10 @@ def create_lifespan(config_path: Optional[str] = None, current_config: Optional[
|
|
212
212
|
else:
|
213
213
|
init_result = await registry.reload_system(config_obj=config_obj)
|
214
214
|
|
215
|
-
|
215
|
+
get_global_logger().info(
|
216
216
|
f"Application started with {init_result['total_commands']} commands registered"
|
217
217
|
)
|
218
|
-
|
218
|
+
get_global_logger().info(f"System initialization result: {init_result}")
|
219
219
|
|
220
220
|
# Proxy registration manager is already initialized in registry.reload_system()
|
221
221
|
|
@@ -231,57 +231,57 @@ def create_lifespan(config_path: Optional[str] = None, current_config: Optional[
|
|
231
231
|
|
232
232
|
# Update proxy registration with final server URL
|
233
233
|
try:
|
234
|
-
|
234
|
+
get_global_logger().info(f"π Updated proxy registration with final server_url: {server_url}")
|
235
235
|
|
236
236
|
except Exception as e:
|
237
|
-
|
237
|
+
get_global_logger().error(f"Failed to update proxy registration: {e}")
|
238
238
|
|
239
239
|
try:
|
240
240
|
print("π Registration server_url resolved to (print):", server_url)
|
241
241
|
except Exception:
|
242
242
|
pass
|
243
243
|
except Exception as e:
|
244
|
-
|
244
|
+
get_global_logger().error(f"Failed to recompute registration URL: {e}")
|
245
245
|
server_url = early_server_url
|
246
246
|
|
247
247
|
# Proxy registration is now handled in registry.reload_system()
|
248
248
|
# after all commands are loaded, ensuring complete command schema
|
249
|
-
|
249
|
+
get_global_logger().info("βΉοΈ Proxy registration will be handled after command loading completes")
|
250
250
|
|
251
251
|
# Add delayed registration task to allow server to fully start
|
252
252
|
async def delayed_registration():
|
253
253
|
"""Delayed registration to ensure server is fully started."""
|
254
254
|
await asyncio.sleep(2) # Wait for server to start listening
|
255
|
-
|
255
|
+
get_global_logger().info("π Attempting delayed proxy registration after server startup")
|
256
256
|
try:
|
257
257
|
from mcp_proxy_adapter.core.proxy_registration import register_with_proxy, initialize_proxy_registration
|
258
258
|
# Ensure proxy registration manager is initialized
|
259
259
|
initialize_proxy_registration(config_to_use)
|
260
260
|
success = await register_with_proxy(server_url)
|
261
261
|
if success:
|
262
|
-
|
262
|
+
get_global_logger().info("β
Delayed proxy registration successful")
|
263
263
|
else:
|
264
|
-
|
264
|
+
get_global_logger().warning("β οΈ Delayed proxy registration failed")
|
265
265
|
except Exception as e:
|
266
|
-
|
266
|
+
get_global_logger().error(f"β Delayed proxy registration error: {e}")
|
267
267
|
|
268
268
|
asyncio.create_task(delayed_registration())
|
269
269
|
|
270
270
|
yield # Application is running
|
271
271
|
|
272
272
|
# Shutdown events
|
273
|
-
|
273
|
+
get_global_logger().info("Application shutting down")
|
274
274
|
|
275
275
|
# Stop proxy registration (this will also unregister)
|
276
276
|
try:
|
277
277
|
unregistration_success = await unregister_from_proxy()
|
278
278
|
if unregistration_success:
|
279
|
-
|
279
|
+
get_global_logger().info("β
Proxy unregistration completed successfully")
|
280
280
|
else:
|
281
|
-
|
281
|
+
get_global_logger().warning("β οΈ Proxy unregistration failed or was disabled")
|
282
282
|
|
283
283
|
except Exception as e:
|
284
|
-
|
284
|
+
get_global_logger().error(f"β Failed to stop proxy registration: {e}")
|
285
285
|
|
286
286
|
return lifespan
|
287
287
|
|
@@ -306,7 +306,7 @@ def create_ssl_context(
|
|
306
306
|
ssl_enabled = protocol in ["https", "mtls"] or verify_client
|
307
307
|
|
308
308
|
if not ssl_enabled:
|
309
|
-
|
309
|
+
get_global_logger().info("SSL is disabled in configuration")
|
310
310
|
return None
|
311
311
|
|
312
312
|
# Get certificate paths from configuration
|
@@ -326,7 +326,7 @@ def create_ssl_context(
|
|
326
326
|
ca_cert = str(project_root / ca_cert)
|
327
327
|
|
328
328
|
if not cert_file or not key_file:
|
329
|
-
|
329
|
+
get_global_logger().warning("SSL enabled but certificate or key file not specified")
|
330
330
|
return None
|
331
331
|
|
332
332
|
try:
|
@@ -341,13 +341,13 @@ def create_ssl_context(
|
|
341
341
|
max_tls_version="1.3",
|
342
342
|
)
|
343
343
|
|
344
|
-
|
344
|
+
get_global_logger().info(
|
345
345
|
f"SSL context created successfully for mode: https_only"
|
346
346
|
)
|
347
347
|
return ssl_context
|
348
348
|
|
349
349
|
except Exception as e:
|
350
|
-
|
350
|
+
get_global_logger().error(f"Failed to create SSL context: {e}")
|
351
351
|
return None
|
352
352
|
|
353
353
|
|
@@ -421,14 +421,14 @@ def create_app(
|
|
421
421
|
warnings = [r for r in _validation_results if r.level == "warning"]
|
422
422
|
|
423
423
|
if errors:
|
424
|
-
|
424
|
+
get_global_logger().critical("CRITICAL CONFIG ERROR: Invalid configuration at startup:")
|
425
425
|
for _e in errors:
|
426
|
-
|
426
|
+
get_global_logger().critical(f" - {_e.message}")
|
427
427
|
raise SystemExit(1)
|
428
428
|
for _w in warnings:
|
429
|
-
|
429
|
+
get_global_logger().warning(f"Config warning: {_w.message}")
|
430
430
|
except Exception as _ex:
|
431
|
-
|
431
|
+
get_global_logger().error(f"Failed to run startup configuration validation: {_ex}")
|
432
432
|
|
433
433
|
# Security check: Validate all authentication configurations before startup (legacy checks kept for compatibility)
|
434
434
|
security_errors = []
|
@@ -562,13 +562,13 @@ def create_app(
|
|
562
562
|
|
563
563
|
# If there are security errors, block startup
|
564
564
|
if security_errors:
|
565
|
-
|
565
|
+
get_global_logger().critical(
|
566
566
|
"CRITICAL SECURITY ERROR: Authentication configuration issues detected:"
|
567
567
|
)
|
568
568
|
for error in security_errors:
|
569
|
-
|
570
|
-
|
571
|
-
|
569
|
+
get_global_logger().critical(f" - {error}")
|
570
|
+
get_global_logger().critical("Server startup blocked for security reasons.")
|
571
|
+
get_global_logger().critical(
|
572
572
|
"Please fix authentication configuration or disable authentication features."
|
573
573
|
)
|
574
574
|
raise SystemExit(1)
|
@@ -592,11 +592,11 @@ def create_app(
|
|
592
592
|
# This ensures commands are available before the server starts accepting requests
|
593
593
|
try:
|
594
594
|
from mcp_proxy_adapter.commands.builtin_commands import register_builtin_commands
|
595
|
-
|
595
|
+
get_global_logger().info("Registering built-in commands during app creation...")
|
596
596
|
registered_count = register_builtin_commands()
|
597
|
-
|
597
|
+
get_global_logger().info(f"Registered {registered_count} built-in commands during app creation")
|
598
598
|
except Exception as e:
|
599
|
-
|
599
|
+
get_global_logger().error(f"Failed to register built-in commands during app creation: {e}")
|
600
600
|
# Don't fail app creation, but log the error
|
601
601
|
|
602
602
|
# Configure CORS
|
@@ -611,13 +611,13 @@ def create_app(
|
|
611
611
|
# Add request logging middleware for debugging
|
612
612
|
@app.middleware("http")
|
613
613
|
async def debug_request_middleware(request: Request, call_next):
|
614
|
-
|
614
|
+
get_global_logger().debug(f"FastAPI Request START: {request.method} {request.url.path}")
|
615
615
|
try:
|
616
616
|
response = await call_next(request)
|
617
|
-
|
617
|
+
get_global_logger().debug(f"FastAPI Request COMPLETED: {response.status_code}")
|
618
618
|
return response
|
619
619
|
except Exception as e:
|
620
|
-
|
620
|
+
get_global_logger().error(f"FastAPI Request ERROR: {e}", exc_info=True)
|
621
621
|
raise
|
622
622
|
|
623
623
|
# Setup middleware using the new middleware package
|
@@ -626,11 +626,11 @@ def create_app(
|
|
626
626
|
# Add request logging middleware
|
627
627
|
# @app.middleware("http")
|
628
628
|
# async def log_requests(request: Request, call_next):
|
629
|
-
#
|
630
|
-
#
|
631
|
-
#
|
629
|
+
# get_global_logger().info(f"π REQUEST LOG: {request.method} {request.url.path}")
|
630
|
+
# get_global_logger().info(f"π REQUEST LOG: Headers: {dict(request.headers)}")
|
631
|
+
# get_global_logger().info(f"π REQUEST LOG: Client: {request.client}")
|
632
632
|
# response = await call_next(request)
|
633
|
-
#
|
633
|
+
# get_global_logger().info(f"π RESPONSE LOG: Status: {response.status_code}")
|
634
634
|
# return response
|
635
635
|
|
636
636
|
# Use custom OpenAPI schema
|
@@ -664,8 +664,8 @@ def create_app(
|
|
664
664
|
# Get request_id from middleware state
|
665
665
|
request_id = getattr(request.state, "request_id", None)
|
666
666
|
|
667
|
-
# Create request
|
668
|
-
req_logger = RequestLogger(__name__, request_id) if request_id else
|
667
|
+
# Create request get_global_logger() for this endpoint
|
668
|
+
req_logger = RequestLogger(__name__, request_id) if request_id else get_global_logger()
|
669
669
|
|
670
670
|
# Check if it's a batch request
|
671
671
|
if isinstance(request_data, list):
|
@@ -716,8 +716,8 @@ def create_app(
|
|
716
716
|
# Get request_id from middleware state
|
717
717
|
request_id = getattr(request.state, "request_id", None)
|
718
718
|
|
719
|
-
# Create request
|
720
|
-
req_logger = RequestLogger(__name__, request_id) if request_id else
|
719
|
+
# Create request get_global_logger() for this endpoint
|
720
|
+
req_logger = RequestLogger(__name__, request_id) if request_id else get_global_logger()
|
721
721
|
|
722
722
|
try:
|
723
723
|
# Determine request format (CommandRequest or JSON-RPC)
|
@@ -875,8 +875,8 @@ def create_app(
|
|
875
875
|
# Get request_id from middleware state
|
876
876
|
request_id = getattr(request.state, "request_id", None)
|
877
877
|
|
878
|
-
# Create request
|
879
|
-
req_logger = RequestLogger(__name__, request_id) if request_id else
|
878
|
+
# Create request get_global_logger() for this endpoint
|
879
|
+
req_logger = RequestLogger(__name__, request_id) if request_id else get_global_logger()
|
880
880
|
|
881
881
|
try:
|
882
882
|
command_info = registry.get_command_info(command_name)
|
@@ -922,12 +922,12 @@ def create_app(
|
|
922
922
|
return description
|
923
923
|
|
924
924
|
except NotFoundError as e:
|
925
|
-
|
925
|
+
get_global_logger().warning(f"Tool not found: {tool_name}")
|
926
926
|
return JSONResponse(
|
927
927
|
status_code=404, content={"error": {"code": 404, "message": str(e)}}
|
928
928
|
)
|
929
929
|
except Exception as e:
|
930
|
-
|
930
|
+
get_global_logger().exception(f"Error generating tool description: {e}")
|
931
931
|
return JSONResponse(
|
932
932
|
status_code=500,
|
933
933
|
content={
|
@@ -952,12 +952,12 @@ def create_app(
|
|
952
952
|
result = await execute_tool(tool_name, **params)
|
953
953
|
return result
|
954
954
|
except NotFoundError as e:
|
955
|
-
|
955
|
+
get_global_logger().warning(f"Tool not found: {tool_name}")
|
956
956
|
return JSONResponse(
|
957
957
|
status_code=404, content={"error": {"code": 404, "message": str(e)}}
|
958
958
|
)
|
959
959
|
except Exception as e:
|
960
|
-
|
960
|
+
get_global_logger().exception(f"Error executing tool {tool_name}: {e}")
|
961
961
|
return JSONResponse(
|
962
962
|
status_code=500,
|
963
963
|
content={
|
@@ -21,7 +21,7 @@ from mcp_proxy_adapter.core.errors import (
|
|
21
21
|
InternalError,
|
22
22
|
CommandError,
|
23
23
|
)
|
24
|
-
from mcp_proxy_adapter.core.logging import
|
24
|
+
from mcp_proxy_adapter.core.logging import get_global_logger, RequestLogger, get_logger
|
25
25
|
|
26
26
|
|
27
27
|
async def execute_command(
|
@@ -45,8 +45,8 @@ async def execute_command(
|
|
45
45
|
MethodNotFoundError: If command is not found.
|
46
46
|
MicroserviceError: In case of command execution error.
|
47
47
|
"""
|
48
|
-
# Create request
|
49
|
-
log = RequestLogger(__name__, request_id) if request_id else
|
48
|
+
# Create request get_global_logger() if request_id is provided
|
49
|
+
log = RequestLogger(__name__, request_id) if request_id else get_global_logger()
|
50
50
|
|
51
51
|
try:
|
52
52
|
log.info(f"Executing command: {command_name}")
|
@@ -155,8 +155,8 @@ async def handle_json_rpc(
|
|
155
155
|
Returns:
|
156
156
|
JSON-RPC response.
|
157
157
|
"""
|
158
|
-
# Create request
|
159
|
-
log = RequestLogger(__name__, request_id) if request_id else
|
158
|
+
# Create request get_global_logger() if request_id is provided
|
159
|
+
log = RequestLogger(__name__, request_id) if request_id else get_global_logger()
|
160
160
|
|
161
161
|
# Support both standard JSON-RPC and simplified formats
|
162
162
|
method = None
|
@@ -6,7 +6,7 @@ This package contains middleware components for request processing.
|
|
6
6
|
from typing import Dict, Any, Optional
|
7
7
|
from fastapi import FastAPI
|
8
8
|
|
9
|
-
from mcp_proxy_adapter.core.logging import
|
9
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
10
10
|
from mcp_proxy_adapter.config import config
|
11
11
|
from .base import BaseMiddleware
|
12
12
|
from .factory import MiddlewareFactory
|
@@ -39,10 +39,10 @@ def setup_middleware(app: FastAPI, app_config: Optional[Dict[str, Any]] = None)
|
|
39
39
|
|
40
40
|
# Validate middleware configuration
|
41
41
|
if not factory.validate_middleware_config():
|
42
|
-
|
42
|
+
get_global_logger().error("Middleware configuration validation failed")
|
43
43
|
raise SystemExit(1)
|
44
44
|
|
45
|
-
|
45
|
+
get_global_logger().info("Using unified security middleware")
|
46
46
|
middleware_list = factory.create_all_middleware()
|
47
47
|
|
48
48
|
# Add middleware to application AFTER protocol middleware
|
@@ -52,13 +52,13 @@ def setup_middleware(app: FastAPI, app_config: Optional[Dict[str, Any]] = None)
|
|
52
52
|
# This is a proper ASGI middleware
|
53
53
|
app.middleware("http")(middleware.dispatch)
|
54
54
|
else:
|
55
|
-
|
55
|
+
get_global_logger().warning(
|
56
56
|
f"Middleware {middleware.__class__.__name__} doesn't have dispatch method"
|
57
57
|
)
|
58
58
|
|
59
59
|
# Log middleware information
|
60
60
|
middleware_info = factory.get_middleware_info()
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
get_global_logger().info(f"Middleware setup completed:")
|
62
|
+
get_global_logger().info(f" - Total middleware: {middleware_info['total_middleware']}")
|
63
|
+
get_global_logger().info(f" - Types: {', '.join(middleware_info['middleware_types'])}")
|
64
|
+
get_global_logger().info(f" - Security enabled: {middleware_info['security_enabled']}")
|
@@ -8,7 +8,7 @@ import logging
|
|
8
8
|
from starlette.middleware.base import BaseHTTPMiddleware
|
9
9
|
from fastapi import Request, Response
|
10
10
|
|
11
|
-
from mcp_proxy_adapter.core.logging import
|
11
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
12
12
|
|
13
13
|
|
14
14
|
class BaseMiddleware(BaseHTTPMiddleware):
|
@@ -30,32 +30,32 @@ class BaseMiddleware(BaseHTTPMiddleware):
|
|
30
30
|
Response.
|
31
31
|
"""
|
32
32
|
middleware_name = self.__class__.__name__
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
33
|
+
get_global_logger().info(f"π STEP 1: {middleware_name}.dispatch START - {request.method} {request.url.path}")
|
34
|
+
get_global_logger().info(f"π STEP 1.1: {middleware_name} - Request headers: {dict(request.headers)}")
|
35
|
+
get_global_logger().info(f"π STEP 1.2: {middleware_name} - Request URL: {request.url}")
|
36
|
+
get_global_logger().info(f"π STEP 1.3: {middleware_name} - Request scope: {request.scope}")
|
37
37
|
|
38
38
|
try:
|
39
39
|
# Process request before calling the main handler
|
40
|
-
|
40
|
+
get_global_logger().info(f"π STEP 2: {middleware_name}.before_request START")
|
41
41
|
await self.before_request(request)
|
42
|
-
|
42
|
+
get_global_logger().info(f"π STEP 3: {middleware_name}.before_request COMPLETED")
|
43
43
|
|
44
44
|
# Call the next middleware or main handler
|
45
|
-
|
45
|
+
get_global_logger().info(f"π STEP 4: {middleware_name}.call_next START - About to call next middleware/endpoint")
|
46
46
|
response = await call_next(request)
|
47
|
-
|
48
|
-
|
47
|
+
get_global_logger().info(f"π STEP 5: {middleware_name}.call_next COMPLETED - Status: {response.status_code}")
|
48
|
+
get_global_logger().info(f"π STEP 5.1: {middleware_name} - Response headers: {dict(response.headers)}")
|
49
49
|
|
50
50
|
# Process response after calling the main handler
|
51
|
-
|
51
|
+
get_global_logger().info(f"π STEP 6: {middleware_name}.after_response START")
|
52
52
|
response = await self.after_response(request, response)
|
53
|
-
|
53
|
+
get_global_logger().info(f"π STEP 7: {middleware_name}.after_response COMPLETED")
|
54
54
|
|
55
|
-
|
55
|
+
get_global_logger().info(f"π STEP 8: {middleware_name}.dispatch COMPLETED SUCCESSFULLY")
|
56
56
|
return response
|
57
57
|
except Exception as e:
|
58
|
-
|
58
|
+
get_global_logger().error(f"β STEP ERROR: {middleware_name}.dispatch ERROR: {str(e)}", exc_info=True)
|
59
59
|
# If an error occurred, call the error handler
|
60
60
|
return await self.handle_error(request, e)
|
61
61
|
|
@@ -13,7 +13,7 @@ from typing import Dict, Any, Optional, Callable, Awaitable
|
|
13
13
|
from fastapi import Request, Response
|
14
14
|
from starlette.middleware.base import BaseHTTPMiddleware
|
15
15
|
|
16
|
-
from mcp_proxy_adapter.core.logging import
|
16
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
17
17
|
|
18
18
|
|
19
19
|
class CommandPermissionMiddleware(BaseHTTPMiddleware):
|
@@ -45,7 +45,7 @@ class CommandPermissionMiddleware(BaseHTTPMiddleware):
|
|
45
45
|
# Add more commands as needed
|
46
46
|
}
|
47
47
|
|
48
|
-
|
48
|
+
get_global_logger().info("Command permission middleware initialized")
|
49
49
|
|
50
50
|
async def dispatch(
|
51
51
|
self, request: Request, call_next: Callable[[Request], Awaitable[Response]]
|
@@ -90,13 +90,13 @@ class CommandPermissionMiddleware(BaseHTTPMiddleware):
|
|
90
90
|
# Get user info from request state
|
91
91
|
user_info = getattr(request.state, "user", None)
|
92
92
|
if not user_info:
|
93
|
-
|
93
|
+
get_global_logger().warning(f"No user info found for command {method}")
|
94
94
|
return await call_next(request)
|
95
95
|
|
96
96
|
user_roles = user_info.get("roles", [])
|
97
97
|
user_permissions = user_info.get("permissions", [])
|
98
98
|
|
99
|
-
|
99
|
+
get_global_logger().debug(
|
100
100
|
f"Checking permissions for {method}: user_roles={user_roles}, required={required_permissions}"
|
101
101
|
)
|
102
102
|
|
@@ -106,7 +106,7 @@ class CommandPermissionMiddleware(BaseHTTPMiddleware):
|
|
106
106
|
)
|
107
107
|
|
108
108
|
if not has_permission:
|
109
|
-
|
109
|
+
get_global_logger().warning(
|
110
110
|
f"Permission denied for {method}: user_roles={user_roles}, required={required_permissions}"
|
111
111
|
)
|
112
112
|
|
@@ -125,11 +125,11 @@ class CommandPermissionMiddleware(BaseHTTPMiddleware):
|
|
125
125
|
media_type="application/json",
|
126
126
|
)
|
127
127
|
|
128
|
-
|
128
|
+
get_global_logger().debug(f"Permission granted for {method}")
|
129
129
|
return await call_next(request)
|
130
130
|
|
131
131
|
except Exception as e:
|
132
|
-
|
132
|
+
get_global_logger().error(f"Error in command permission middleware: {e}")
|
133
133
|
return await call_next(request)
|
134
134
|
|
135
135
|
def _check_permissions(
|
@@ -8,7 +8,7 @@ from typing import Callable, Awaitable, Dict, Any, Optional
|
|
8
8
|
from fastapi import Request, Response
|
9
9
|
from starlette.responses import JSONResponse
|
10
10
|
|
11
|
-
from mcp_proxy_adapter.core.logging import
|
11
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
12
12
|
from mcp_proxy_adapter.core.errors import (
|
13
13
|
MicroserviceError,
|
14
14
|
CommandError,
|
@@ -44,18 +44,18 @@ class ErrorHandlingMiddleware(BaseMiddleware):
|
|
44
44
|
Returns:
|
45
45
|
Response.
|
46
46
|
"""
|
47
|
-
|
47
|
+
get_global_logger().debug(f"π ErrorHandlingMiddleware.dispatch START - {request.method} {request.url.path}")
|
48
48
|
try:
|
49
49
|
# Call the next middleware or main handler
|
50
|
-
|
50
|
+
get_global_logger().debug(f"π ErrorHandlingMiddleware - About to call next handler")
|
51
51
|
response = await call_next(request)
|
52
|
-
|
52
|
+
get_global_logger().debug(f"π ErrorHandlingMiddleware - Next handler completed with status: {response.status_code}")
|
53
53
|
return response
|
54
54
|
|
55
55
|
except CommandError as e:
|
56
56
|
# Command error
|
57
57
|
request_id = getattr(request.state, "request_id", "unknown")
|
58
|
-
|
58
|
+
get_global_logger().debug(f"[{request_id}] Command error: {str(e)}")
|
59
59
|
|
60
60
|
# ΠΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ, ΡΠ²Π»ΡΠ΅ΡΡΡ Π»ΠΈ Π·Π°ΠΏΡΠΎΡ JSON-RPC
|
61
61
|
is_jsonrpc = self._is_json_rpc_request(request)
|
@@ -84,7 +84,7 @@ class ErrorHandlingMiddleware(BaseMiddleware):
|
|
84
84
|
except ValidationError as e:
|
85
85
|
# Validation error
|
86
86
|
request_id = getattr(request.state, "request_id", "unknown")
|
87
|
-
|
87
|
+
get_global_logger().debug(f"[{request_id}] Validation error: {str(e)}")
|
88
88
|
|
89
89
|
# Get JSON-RPC request ID if available
|
90
90
|
request_id_jsonrpc = await self._get_json_rpc_id(request)
|
@@ -110,7 +110,7 @@ class ErrorHandlingMiddleware(BaseMiddleware):
|
|
110
110
|
except MicroserviceError as e:
|
111
111
|
# Other microservice error
|
112
112
|
request_id = getattr(request.state, "request_id", "unknown")
|
113
|
-
|
113
|
+
get_global_logger().debug(f"[{request_id}] Microservice error: {str(e)}")
|
114
114
|
|
115
115
|
# Get JSON-RPC request ID if available
|
116
116
|
request_id_jsonrpc = await self._get_json_rpc_id(request)
|
@@ -136,7 +136,7 @@ class ErrorHandlingMiddleware(BaseMiddleware):
|
|
136
136
|
except Exception as e:
|
137
137
|
# Unexpected error
|
138
138
|
request_id = getattr(request.state, "request_id", "unknown")
|
139
|
-
|
139
|
+
get_global_logger().debug(f"[{request_id}] Unexpected error: {str(e)}")
|
140
140
|
|
141
141
|
# Get JSON-RPC request ID if available
|
142
142
|
request_id_jsonrpc = await self._get_json_rpc_id(request)
|
@@ -197,6 +197,6 @@ class ErrorHandlingMiddleware(BaseMiddleware):
|
|
197
197
|
request.state.json_rpc_id = request_id
|
198
198
|
return request_id
|
199
199
|
except Exception as e:
|
200
|
-
|
200
|
+
get_global_logger().warning(f"Error parsing JSON-RPC ID: {str(e)}")
|
201
201
|
|
202
202
|
return None
|