mcp-proxy-adapter 6.9.16__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 +57 -55
- 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 +88 -80
- 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_factory.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/run_proxy_server.py +20 -10
- 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.16.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.16.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.16.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.16.dist-info β mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.16.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
|
)
|
@@ -187,14 +187,14 @@ def create_lifespan(config_path: Optional[str] = None, current_config: Optional[
|
|
187
187
|
)
|
188
188
|
|
189
189
|
# Initialize proxy registration
|
190
|
-
initialize_proxy_registration()
|
191
|
-
|
190
|
+
initialize_proxy_registration(config_to_use)
|
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,16 +212,16 @@ 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
|
|
222
222
|
# Recompute registration URL AFTER config reload using final config
|
223
223
|
try:
|
224
|
-
final_config =
|
224
|
+
final_config = config_to_use # config_to_use is already a dict
|
225
225
|
server_config = final_config.get("server", {})
|
226
226
|
server_host = server_config.get("host", "0.0.0.0")
|
227
227
|
server_port = server_config.get("port", 8000)
|
@@ -231,55 +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
|
-
from mcp_proxy_adapter.core.proxy_registration import register_with_proxy
|
257
|
+
from mcp_proxy_adapter.core.proxy_registration import register_with_proxy, initialize_proxy_registration
|
258
|
+
# Ensure proxy registration manager is initialized
|
259
|
+
initialize_proxy_registration(config_to_use)
|
258
260
|
success = await register_with_proxy(server_url)
|
259
261
|
if success:
|
260
|
-
|
262
|
+
get_global_logger().info("β
Delayed proxy registration successful")
|
261
263
|
else:
|
262
|
-
|
264
|
+
get_global_logger().warning("β οΈ Delayed proxy registration failed")
|
263
265
|
except Exception as e:
|
264
|
-
|
266
|
+
get_global_logger().error(f"β Delayed proxy registration error: {e}")
|
265
267
|
|
266
268
|
asyncio.create_task(delayed_registration())
|
267
269
|
|
268
270
|
yield # Application is running
|
269
271
|
|
270
272
|
# Shutdown events
|
271
|
-
|
273
|
+
get_global_logger().info("Application shutting down")
|
272
274
|
|
273
275
|
# Stop proxy registration (this will also unregister)
|
274
276
|
try:
|
275
277
|
unregistration_success = await unregister_from_proxy()
|
276
278
|
if unregistration_success:
|
277
|
-
|
279
|
+
get_global_logger().info("β
Proxy unregistration completed successfully")
|
278
280
|
else:
|
279
|
-
|
281
|
+
get_global_logger().warning("β οΈ Proxy unregistration failed or was disabled")
|
280
282
|
|
281
283
|
except Exception as e:
|
282
|
-
|
284
|
+
get_global_logger().error(f"β Failed to stop proxy registration: {e}")
|
283
285
|
|
284
286
|
return lifespan
|
285
287
|
|
@@ -304,7 +306,7 @@ def create_ssl_context(
|
|
304
306
|
ssl_enabled = protocol in ["https", "mtls"] or verify_client
|
305
307
|
|
306
308
|
if not ssl_enabled:
|
307
|
-
|
309
|
+
get_global_logger().info("SSL is disabled in configuration")
|
308
310
|
return None
|
309
311
|
|
310
312
|
# Get certificate paths from configuration
|
@@ -324,7 +326,7 @@ def create_ssl_context(
|
|
324
326
|
ca_cert = str(project_root / ca_cert)
|
325
327
|
|
326
328
|
if not cert_file or not key_file:
|
327
|
-
|
329
|
+
get_global_logger().warning("SSL enabled but certificate or key file not specified")
|
328
330
|
return None
|
329
331
|
|
330
332
|
try:
|
@@ -339,13 +341,13 @@ def create_ssl_context(
|
|
339
341
|
max_tls_version="1.3",
|
340
342
|
)
|
341
343
|
|
342
|
-
|
344
|
+
get_global_logger().info(
|
343
345
|
f"SSL context created successfully for mode: https_only"
|
344
346
|
)
|
345
347
|
return ssl_context
|
346
348
|
|
347
349
|
except Exception as e:
|
348
|
-
|
350
|
+
get_global_logger().error(f"Failed to create SSL context: {e}")
|
349
351
|
return None
|
350
352
|
|
351
353
|
|
@@ -419,14 +421,14 @@ def create_app(
|
|
419
421
|
warnings = [r for r in _validation_results if r.level == "warning"]
|
420
422
|
|
421
423
|
if errors:
|
422
|
-
|
424
|
+
get_global_logger().critical("CRITICAL CONFIG ERROR: Invalid configuration at startup:")
|
423
425
|
for _e in errors:
|
424
|
-
|
426
|
+
get_global_logger().critical(f" - {_e.message}")
|
425
427
|
raise SystemExit(1)
|
426
428
|
for _w in warnings:
|
427
|
-
|
429
|
+
get_global_logger().warning(f"Config warning: {_w.message}")
|
428
430
|
except Exception as _ex:
|
429
|
-
|
431
|
+
get_global_logger().error(f"Failed to run startup configuration validation: {_ex}")
|
430
432
|
|
431
433
|
# Security check: Validate all authentication configurations before startup (legacy checks kept for compatibility)
|
432
434
|
security_errors = []
|
@@ -560,13 +562,13 @@ def create_app(
|
|
560
562
|
|
561
563
|
# If there are security errors, block startup
|
562
564
|
if security_errors:
|
563
|
-
|
565
|
+
get_global_logger().critical(
|
564
566
|
"CRITICAL SECURITY ERROR: Authentication configuration issues detected:"
|
565
567
|
)
|
566
568
|
for error in security_errors:
|
567
|
-
|
568
|
-
|
569
|
-
|
569
|
+
get_global_logger().critical(f" - {error}")
|
570
|
+
get_global_logger().critical("Server startup blocked for security reasons.")
|
571
|
+
get_global_logger().critical(
|
570
572
|
"Please fix authentication configuration or disable authentication features."
|
571
573
|
)
|
572
574
|
raise SystemExit(1)
|
@@ -590,11 +592,11 @@ def create_app(
|
|
590
592
|
# This ensures commands are available before the server starts accepting requests
|
591
593
|
try:
|
592
594
|
from mcp_proxy_adapter.commands.builtin_commands import register_builtin_commands
|
593
|
-
|
595
|
+
get_global_logger().info("Registering built-in commands during app creation...")
|
594
596
|
registered_count = register_builtin_commands()
|
595
|
-
|
597
|
+
get_global_logger().info(f"Registered {registered_count} built-in commands during app creation")
|
596
598
|
except Exception as e:
|
597
|
-
|
599
|
+
get_global_logger().error(f"Failed to register built-in commands during app creation: {e}")
|
598
600
|
# Don't fail app creation, but log the error
|
599
601
|
|
600
602
|
# Configure CORS
|
@@ -609,13 +611,13 @@ def create_app(
|
|
609
611
|
# Add request logging middleware for debugging
|
610
612
|
@app.middleware("http")
|
611
613
|
async def debug_request_middleware(request: Request, call_next):
|
612
|
-
|
614
|
+
get_global_logger().debug(f"FastAPI Request START: {request.method} {request.url.path}")
|
613
615
|
try:
|
614
616
|
response = await call_next(request)
|
615
|
-
|
617
|
+
get_global_logger().debug(f"FastAPI Request COMPLETED: {response.status_code}")
|
616
618
|
return response
|
617
619
|
except Exception as e:
|
618
|
-
|
620
|
+
get_global_logger().error(f"FastAPI Request ERROR: {e}", exc_info=True)
|
619
621
|
raise
|
620
622
|
|
621
623
|
# Setup middleware using the new middleware package
|
@@ -624,11 +626,11 @@ def create_app(
|
|
624
626
|
# Add request logging middleware
|
625
627
|
# @app.middleware("http")
|
626
628
|
# async def log_requests(request: Request, call_next):
|
627
|
-
#
|
628
|
-
#
|
629
|
-
#
|
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}")
|
630
632
|
# response = await call_next(request)
|
631
|
-
#
|
633
|
+
# get_global_logger().info(f"π RESPONSE LOG: Status: {response.status_code}")
|
632
634
|
# return response
|
633
635
|
|
634
636
|
# Use custom OpenAPI schema
|
@@ -662,8 +664,8 @@ def create_app(
|
|
662
664
|
# Get request_id from middleware state
|
663
665
|
request_id = getattr(request.state, "request_id", None)
|
664
666
|
|
665
|
-
# Create request
|
666
|
-
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()
|
667
669
|
|
668
670
|
# Check if it's a batch request
|
669
671
|
if isinstance(request_data, list):
|
@@ -714,8 +716,8 @@ def create_app(
|
|
714
716
|
# Get request_id from middleware state
|
715
717
|
request_id = getattr(request.state, "request_id", None)
|
716
718
|
|
717
|
-
# Create request
|
718
|
-
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()
|
719
721
|
|
720
722
|
try:
|
721
723
|
# Determine request format (CommandRequest or JSON-RPC)
|
@@ -873,8 +875,8 @@ def create_app(
|
|
873
875
|
# Get request_id from middleware state
|
874
876
|
request_id = getattr(request.state, "request_id", None)
|
875
877
|
|
876
|
-
# Create request
|
877
|
-
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()
|
878
880
|
|
879
881
|
try:
|
880
882
|
command_info = registry.get_command_info(command_name)
|
@@ -920,12 +922,12 @@ def create_app(
|
|
920
922
|
return description
|
921
923
|
|
922
924
|
except NotFoundError as e:
|
923
|
-
|
925
|
+
get_global_logger().warning(f"Tool not found: {tool_name}")
|
924
926
|
return JSONResponse(
|
925
927
|
status_code=404, content={"error": {"code": 404, "message": str(e)}}
|
926
928
|
)
|
927
929
|
except Exception as e:
|
928
|
-
|
930
|
+
get_global_logger().exception(f"Error generating tool description: {e}")
|
929
931
|
return JSONResponse(
|
930
932
|
status_code=500,
|
931
933
|
content={
|
@@ -950,12 +952,12 @@ def create_app(
|
|
950
952
|
result = await execute_tool(tool_name, **params)
|
951
953
|
return result
|
952
954
|
except NotFoundError as e:
|
953
|
-
|
955
|
+
get_global_logger().warning(f"Tool not found: {tool_name}")
|
954
956
|
return JSONResponse(
|
955
957
|
status_code=404, content={"error": {"code": 404, "message": str(e)}}
|
956
958
|
)
|
957
959
|
except Exception as e:
|
958
|
-
|
960
|
+
get_global_logger().exception(f"Error executing tool {tool_name}: {e}")
|
959
961
|
return JSONResponse(
|
960
962
|
status_code=500,
|
961
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
|