mcp-proxy-adapter 4.1.1__py3-none-any.whl → 6.0.1__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 (200) hide show
  1. mcp_proxy_adapter/__main__.py +32 -0
  2. mcp_proxy_adapter/api/app.py +290 -33
  3. mcp_proxy_adapter/api/handlers.py +32 -6
  4. mcp_proxy_adapter/api/middleware/__init__.py +38 -32
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/error_handling.py +9 -0
  7. mcp_proxy_adapter/api/middleware/factory.py +243 -0
  8. mcp_proxy_adapter/api/middleware/logging.py +32 -6
  9. mcp_proxy_adapter/api/middleware/protocol_middleware.py +201 -0
  10. mcp_proxy_adapter/api/middleware/transport_middleware.py +122 -0
  11. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  12. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
  13. mcp_proxy_adapter/commands/__init__.py +19 -4
  14. mcp_proxy_adapter/commands/auth_validation_command.py +408 -0
  15. mcp_proxy_adapter/commands/base.py +66 -32
  16. mcp_proxy_adapter/commands/builtin_commands.py +95 -0
  17. mcp_proxy_adapter/commands/catalog_manager.py +838 -0
  18. mcp_proxy_adapter/commands/cert_monitor_command.py +620 -0
  19. mcp_proxy_adapter/commands/certificate_management_command.py +608 -0
  20. mcp_proxy_adapter/commands/command_registry.py +711 -354
  21. mcp_proxy_adapter/commands/dependency_manager.py +245 -0
  22. mcp_proxy_adapter/commands/echo_command.py +81 -0
  23. mcp_proxy_adapter/commands/health_command.py +8 -1
  24. mcp_proxy_adapter/commands/help_command.py +21 -14
  25. mcp_proxy_adapter/commands/hooks.py +200 -167
  26. mcp_proxy_adapter/commands/key_management_command.py +506 -0
  27. mcp_proxy_adapter/commands/load_command.py +176 -0
  28. mcp_proxy_adapter/commands/plugins_command.py +235 -0
  29. mcp_proxy_adapter/commands/protocol_management_command.py +232 -0
  30. mcp_proxy_adapter/commands/proxy_registration_command.py +409 -0
  31. mcp_proxy_adapter/commands/reload_command.py +48 -50
  32. mcp_proxy_adapter/commands/result.py +1 -0
  33. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  34. mcp_proxy_adapter/commands/roles_management_command.py +697 -0
  35. mcp_proxy_adapter/commands/security_command.py +488 -0
  36. mcp_proxy_adapter/commands/ssl_setup_command.py +366 -0
  37. mcp_proxy_adapter/commands/token_management_command.py +529 -0
  38. mcp_proxy_adapter/commands/transport_management_command.py +144 -0
  39. mcp_proxy_adapter/commands/unload_command.py +158 -0
  40. mcp_proxy_adapter/config.py +394 -14
  41. mcp_proxy_adapter/core/app_factory.py +410 -0
  42. mcp_proxy_adapter/core/app_runner.py +272 -0
  43. mcp_proxy_adapter/core/auth_validator.py +606 -0
  44. mcp_proxy_adapter/core/certificate_utils.py +1045 -0
  45. mcp_proxy_adapter/core/client.py +574 -0
  46. mcp_proxy_adapter/core/client_manager.py +284 -0
  47. mcp_proxy_adapter/core/client_security.py +384 -0
  48. mcp_proxy_adapter/core/config_converter.py +405 -0
  49. mcp_proxy_adapter/core/config_validator.py +218 -0
  50. mcp_proxy_adapter/core/logging.py +19 -3
  51. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  52. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  53. mcp_proxy_adapter/core/protocol_manager.py +385 -0
  54. mcp_proxy_adapter/core/proxy_client.py +602 -0
  55. mcp_proxy_adapter/core/proxy_registration.py +522 -0
  56. mcp_proxy_adapter/core/role_utils.py +426 -0
  57. mcp_proxy_adapter/core/security_adapter.py +370 -0
  58. mcp_proxy_adapter/core/security_factory.py +239 -0
  59. mcp_proxy_adapter/core/security_integration.py +286 -0
  60. mcp_proxy_adapter/core/server_adapter.py +282 -0
  61. mcp_proxy_adapter/core/server_engine.py +270 -0
  62. mcp_proxy_adapter/core/settings.py +1 -0
  63. mcp_proxy_adapter/core/ssl_utils.py +234 -0
  64. mcp_proxy_adapter/core/transport_manager.py +292 -0
  65. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  66. mcp_proxy_adapter/custom_openapi.py +22 -11
  67. mcp_proxy_adapter/examples/__init__.py +13 -4
  68. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  69. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  70. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  71. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  72. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  73. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  74. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  75. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  76. mcp_proxy_adapter/examples/demo_client.py +275 -0
  77. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  78. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  79. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  80. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  81. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  82. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  83. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  84. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  85. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  86. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  87. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  88. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  89. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  90. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  91. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  92. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  93. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  94. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  95. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  96. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  97. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  98. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  99. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  100. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  101. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  102. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  103. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  104. mcp_proxy_adapter/examples/run_example.py +59 -0
  105. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  106. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  107. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  108. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  109. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  110. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  111. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  112. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  113. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  114. mcp_proxy_adapter/examples/test_config.py +148 -0
  115. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  116. mcp_proxy_adapter/examples/test_examples.py +281 -0
  117. mcp_proxy_adapter/examples/universal_client.py +620 -0
  118. mcp_proxy_adapter/main.py +93 -0
  119. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  120. mcp_proxy_adapter/version.py +5 -2
  121. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  122. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  123. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  124. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  125. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  126. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  127. mcp_proxy_adapter/commands/reload_settings_command.py +0 -125
  128. mcp_proxy_adapter/examples/README.md +0 -124
  129. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  130. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  131. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  132. mcp_proxy_adapter/examples/basic_server/config.json +0 -35
  133. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  134. mcp_proxy_adapter/examples/basic_server/server.py +0 -103
  135. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  136. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  137. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -250
  138. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  139. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  140. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  141. mcp_proxy_adapter/examples/custom_commands/config.json +0 -35
  142. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  143. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  144. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  145. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  146. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  147. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  148. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  149. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  150. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/server.py +0 -228
  153. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  154. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  155. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  156. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  157. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  158. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  159. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  160. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  161. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  162. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  163. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  164. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  165. mcp_proxy_adapter/tests/__init__.py +0 -0
  166. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  167. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  168. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  169. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  170. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  171. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  172. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  173. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  174. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  175. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  176. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  177. mcp_proxy_adapter/tests/conftest.py +0 -131
  178. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  180. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  181. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  182. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  183. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  184. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  185. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  186. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  187. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  188. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  189. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  190. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  191. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  192. mcp_proxy_adapter/tests/test_config.py +0 -127
  193. mcp_proxy_adapter/tests/test_utils.py +0 -65
  194. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  195. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  196. mcp_proxy_adapter/tests/unit/test_config.py +0 -217
  197. mcp_proxy_adapter-4.1.1.dist-info/METADATA +0 -200
  198. mcp_proxy_adapter-4.1.1.dist-info/RECORD +0 -110
  199. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  200. {mcp_proxy_adapter-4.1.1.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,140 @@
1
+ mcp_proxy_adapter/__init__.py,sha256=B7m1YWyv_Wb87-Q-JqVpHQgwajnfIgDyZ_iIxzdTbBY,1021
2
+ mcp_proxy_adapter/__main__.py,sha256=-Wp1myP9DzJNB9j97mj62C8kFk5YUbCmd0e7Rnwte0A,769
3
+ mcp_proxy_adapter/config.py,sha256=ss6A-7Ef1I7iyZ-h-bzGWGwddB47642wEhN7uwnt5bk,21563
4
+ mcp_proxy_adapter/custom_openapi.py,sha256=jYUrCy8C1mShh3sjKj-JkzSMLAvxDLTvtzSJFj5HUNg,15023
5
+ mcp_proxy_adapter/main.py,sha256=9qt_pEQdq8roUc73CumfDn6jDWP_NyfdE1lCGEynv5I,2841
6
+ mcp_proxy_adapter/openapi.py,sha256=36vOEbJjGnVZR6hUhl6mHCD29HYOEFKo2bL0JdGSm-4,13952
7
+ mcp_proxy_adapter/version.py,sha256=he5ZytTjuzxFCrKQ9AxOJw6hhMuKvgK4oyLQ4ErooZQ,76
8
+ mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ mcp_proxy_adapter/api/app.py,sha256=khl4kaI4mJ6dNbfAK7hR97Ek-eWC9NBeuXHr6GVbLoU,28911
10
+ mcp_proxy_adapter/api/handlers.py,sha256=DcZT7MVBV33q-0EJ0iFqxE0VgBkFt6d_SqoRkntwyvc,8477
11
+ mcp_proxy_adapter/api/schemas.py,sha256=xOmiSwHaapY6myEFnLu7o-LWVPM7vwmLYZXFo2c6NfE,12381
12
+ mcp_proxy_adapter/api/tool_integration.py,sha256=MrtX7vUXCGBBuZuOs3C6EF67R_U_0xMfOmlmsAz-wuE,10245
13
+ mcp_proxy_adapter/api/tools.py,sha256=rRCRN2I8Odd2biBJZKByQS15rAWf0XwLRZEHDELc7Tg,8116
14
+ mcp_proxy_adapter/api/middleware/__init__.py,sha256=2tkokajbmHLsOS_jKEgOJq-YekyIZahDWcQChMfeKdg,2146
15
+ mcp_proxy_adapter/api/middleware/base.py,sha256=aMV9YPLHkUnJECuQWYbnlEGaj6xUJFHZR_hJb0OKvu8,2282
16
+ mcp_proxy_adapter/api/middleware/command_permission_middleware.py,sha256=sSdHTZ-ZxtcV3fJmcweB3sqlQivrYO_FO0H835jnPFA,5076
17
+ mcp_proxy_adapter/api/middleware/error_handling.py,sha256=avIZTjXj1sNOT3ekKtLAYJKM7V4duX0BF9PW-j18dEY,7134
18
+ mcp_proxy_adapter/api/middleware/factory.py,sha256=yDo7f4E-YL7qQZgGApyk8HZfLYOnrpsNx-Eh3fJBikE,8404
19
+ mcp_proxy_adapter/api/middleware/logging.py,sha256=VvUUX7bN4davCzFO6GYbN1O4sgJjOspV-EBLE3xpwpc,4730
20
+ mcp_proxy_adapter/api/middleware/performance.py,sha256=dHBxTF43LEGXMKHMH3A8ybKmwAWURd_zswqq_oC4xbw,2454
21
+ mcp_proxy_adapter/api/middleware/protocol_middleware.py,sha256=iVjJrTEfKy15ZchQUo-Mu0hBg9kEP6vgzee_3PtWd6M,8115
22
+ mcp_proxy_adapter/api/middleware/transport_middleware.py,sha256=Esy2gGKpEV5RoUTilr1YKKTDc5jh5RxsomD0VXyR2pE,4396
23
+ mcp_proxy_adapter/api/middleware/unified_security.py,sha256=fDWUeIuHjYUngVnB8gVR9ES3IQSaY9VP2YPZGXATJlU,7617
24
+ mcp_proxy_adapter/api/middleware/user_info_middleware.py,sha256=CWZvwUqieNhC8_ArTvncRjFfU3RHusO-dMcUSvRv01A,6311
25
+ mcp_proxy_adapter/commands/__init__.py,sha256=r791wg4FKhWSi5rqA3vekDcGf5kr18pwF1woX-dnZKo,1525
26
+ mcp_proxy_adapter/commands/auth_validation_command.py,sha256=z612WJDVgZwaCrxdQhATwRc5i3qxH37MPuIV6SuZPn8,15083
27
+ mcp_proxy_adapter/commands/base.py,sha256=tunyrmt-LYJMQZslAZQor3KZvOrn1IYNpL5uOAnSdxc,15791
28
+ mcp_proxy_adapter/commands/builtin_commands.py,sha256=oloxk0itnY4Uy1a3ARXqHPm48RqkHxBbHqzXZ4bUGN8,3258
29
+ mcp_proxy_adapter/commands/catalog_manager.py,sha256=FVyF2Ky8DUmvFxjiem3YeC9ASFOzCZ9Lp2MsNobA1wI,34712
30
+ mcp_proxy_adapter/commands/cert_monitor_command.py,sha256=JWitmmHDeooWXt2fWLbcfAHDeHpsTL2AuBaoka7OWNE,24485
31
+ mcp_proxy_adapter/commands/certificate_management_command.py,sha256=4byTb1yCqTQCbNH_L4p_z3HithuugzI3a-H9gjiLDhg,24440
32
+ mcp_proxy_adapter/commands/command_registry.py,sha256=mPNhLnJ4L1lSyVzYXpUjeCBJkWIqEtlzpr9JcprHIf4,35260
33
+ mcp_proxy_adapter/commands/config_command.py,sha256=-Z6BGaEQTf859l56zZpHYBeZFeIVdpMYybDrd7LOPIg,3553
34
+ mcp_proxy_adapter/commands/dependency_container.py,sha256=Uz9OPRAUZN7tsVrMVgXgPQcsRD2N-e2Ixg9XarPOlnY,3410
35
+ mcp_proxy_adapter/commands/dependency_manager.py,sha256=lmY79MBkh-JRIPsYxSkdrUE9XHi4XBCbucaEMT0w6do,7683
36
+ mcp_proxy_adapter/commands/echo_command.py,sha256=R1oDNEAJSOIuODa4Nk3z4WJXhSxniNzaZtYHADlV310,2390
37
+ mcp_proxy_adapter/commands/health_command.py,sha256=cNUfvQI4MAJQK1wKfzv_snCCK-FkL-FulVSErkMA3qw,4585
38
+ mcp_proxy_adapter/commands/help_command.py,sha256=PuanwvYmVs64DhB71gaI5rBRi_ozJ6x8afr18bRpTk4,13482
39
+ mcp_proxy_adapter/commands/hooks.py,sha256=Gu5TDSgA9EBHexWMWze8wgT63i6-dMEEwG8edWbrX3U,10060
40
+ mcp_proxy_adapter/commands/key_management_command.py,sha256=qin-iYXksIXOkZEfmJpclJSOyKaz9qRinj9uVa8hkdk,19339
41
+ mcp_proxy_adapter/commands/load_command.py,sha256=2zwPOCSBck6mr5KehyyH8lPRAqYYGeUeIIJdbxMSoZk,5984
42
+ mcp_proxy_adapter/commands/plugins_command.py,sha256=Te6YQH0ukJWIHAAEJE5DmdAilpjO1QMDa_PexhfQLH0,8531
43
+ mcp_proxy_adapter/commands/protocol_management_command.py,sha256=XSrNPGagopM4SinrSmNFW12KLng7-Oc9q6NpiInJ-QI,8485
44
+ mcp_proxy_adapter/commands/proxy_registration_command.py,sha256=yqPKgpv8oPP9mn1Blo-2VRVoWUpMcMJ29stqy2Di7hk,15394
45
+ mcp_proxy_adapter/commands/reload_command.py,sha256=6yJduQlIgXhtDSH4Q8qmfR8wZW1RVC1WT1eBIpxzCNo,7507
46
+ mcp_proxy_adapter/commands/result.py,sha256=9iFyoRRZ17q3d822XTMNyqnBvWypyoyV0NiHtM2bCd4,5604
47
+ mcp_proxy_adapter/commands/role_test_command.py,sha256=Hr45vB3W8tg_GQ4FfKOEOxW10eEb-pApo2nOPjru61M,4281
48
+ mcp_proxy_adapter/commands/roles_management_command.py,sha256=JSMkW9-Hq9ncltUvBjolQdvSeTa1FY2hoU0oD2mBon4,22471
49
+ mcp_proxy_adapter/commands/security_command.py,sha256=zKTVtb8vL_DafRHtrLqC2Mhk_DjOQ-3YwhIUh8NXJfQ,18206
50
+ mcp_proxy_adapter/commands/settings_command.py,sha256=hTBrFRABJDFYwnDf2ryfqoejUe06fM4XMOoiH0Exdyo,6407
51
+ mcp_proxy_adapter/commands/ssl_setup_command.py,sha256=wCWF7VhAB21m1FF7uR7r1mG1uLu6bFkfTfpHINM7LGI,13101
52
+ mcp_proxy_adapter/commands/token_management_command.py,sha256=7sl_fRUjWMRuP7NXoLjpLTB9wEg_aZU9dp5Ji9hbThA,18147
53
+ mcp_proxy_adapter/commands/transport_management_command.py,sha256=yv2lqUqJliYGIbYW7t0HQTrt5Cu2Y02rUjVzdznLtPk,4692
54
+ mcp_proxy_adapter/commands/unload_command.py,sha256=mhRZ23sJtTwUfWkjZzH8KDRpwxUX0kdu8LbAXAURRJc,5079
55
+ mcp_proxy_adapter/core/__init__.py,sha256=Ch50cV5Nd8m-HO9rMnVModajjwDK-OdUy7hxISDFkAM,800
56
+ mcp_proxy_adapter/core/app_factory.py,sha256=Xwyz40GNOWWa7ThArweawNBY4WI4bEI3_cj251mLHCM,17797
57
+ mcp_proxy_adapter/core/app_runner.py,sha256=JPpx9rKmaHAVdFnHRl2rXycptQkTSQ13Er7Qf1KZIA4,10614
58
+ mcp_proxy_adapter/core/auth_validator.py,sha256=lJxBVkoQWSk5CNtnPYMEJSsz4FhcXK-gB5QJ_OP9jEE,20937
59
+ mcp_proxy_adapter/core/certificate_utils.py,sha256=7VOhjRcygCToYgPTUt_MgcNILdpRBRBNZSFpeS_QrfA,39541
60
+ mcp_proxy_adapter/core/client.py,sha256=YxtaHvMoqKcjWJ-2mf2FH22wUGWUZjXMEKPqxypNOPE,21340
61
+ mcp_proxy_adapter/core/client_manager.py,sha256=sKEhapMpogqb54WIWEpz2bMjrX3wvYooX-a844IfCTU,9164
62
+ mcp_proxy_adapter/core/client_security.py,sha256=8isHpvv-7H85QzI8K3Pfyr_KdvpE2xYyIT4wqWrttNU,13575
63
+ mcp_proxy_adapter/core/config_converter.py,sha256=FAA2zx-yRgqMgzg73o9Aq5CEEfodNCeaA8Yluto4wAs,16985
64
+ mcp_proxy_adapter/core/config_validator.py,sha256=qDVmkRatuDeWylIPLjMq02Vpzff6DDTE_CstpzqGi7o,7773
65
+ mcp_proxy_adapter/core/errors.py,sha256=s34OxiIR4NCJu_pYSigKXqrIvRjUUK2OWw0X4dpDjIA,5151
66
+ mcp_proxy_adapter/core/logging.py,sha256=jQlFz52Xwapef6UD4p0acmaGFumD9XuexwW4frDN_ZM,9626
67
+ mcp_proxy_adapter/core/mtls_asgi.py,sha256=X2lAj3wk3L85amRCp_-10sqvZa5wJf_diXhwrrQReSo,5311
68
+ mcp_proxy_adapter/core/mtls_asgi_app.py,sha256=VeolP08TTaqYU5fGeaZexj6EBWBDugoVrEGXzJW4PuM,6406
69
+ mcp_proxy_adapter/core/protocol_manager.py,sha256=ISFRXjUuK4Q3uMbVB8-O_ozQSsDEH0PQA_HAKGeUrrw,14763
70
+ mcp_proxy_adapter/core/proxy_client.py,sha256=shP373Yelz7Fja22U6XnH0kT9XtPtWEFwOFlYFO97gw,22511
71
+ mcp_proxy_adapter/core/proxy_registration.py,sha256=87ko1vw61nHJGo0-xrObXiyQhrYK2K6nKr8rXID-j8c,19424
72
+ mcp_proxy_adapter/core/role_utils.py,sha256=wMoTVz3gF5fM7jozNMwsEwPkp1tui26M-t_KH1Oz8gs,12880
73
+ mcp_proxy_adapter/core/security_adapter.py,sha256=wZ3OH1WzhUdpN8N8CrGJSFFVNi474DqdazIqQ1T8PN4,13343
74
+ mcp_proxy_adapter/core/security_factory.py,sha256=4r7qvBq30XfosGD_b1ZHyNVLN8rOQ3NAKuaCOCEK8jA,8262
75
+ mcp_proxy_adapter/core/security_integration.py,sha256=6oJKVCL1CRnk3sTWX-PBzDjv737oe4QL-9r3l89kRkc,13715
76
+ mcp_proxy_adapter/core/server_adapter.py,sha256=8dhUlLxuYjaoNgMHieFCFgDRjxskP--Y5uoAhbN6RLw,9823
77
+ mcp_proxy_adapter/core/server_engine.py,sha256=SFENSDrVMlBD--HgKSRVklhrtLKSRSZhs_3UHxFCGbg,9540
78
+ mcp_proxy_adapter/core/settings.py,sha256=ZfUnmqD1tjAuaQo2VAF8evC1oHUit7gTu4WkTF0IMYI,10628
79
+ mcp_proxy_adapter/core/ssl_utils.py,sha256=_2mhpuoiRpSbUBifnQvtuziQfBRrXQUKtB58ALWTaqU,8220
80
+ mcp_proxy_adapter/core/transport_manager.py,sha256=ppcgjO-7Ulrk1ovlzlXVM89Iw4VOGA3awKgLf7FFAJ0,9518
81
+ mcp_proxy_adapter/core/unified_config_adapter.py,sha256=cpN_VrliIFGDH3JsfRkTlFdQvLcmuMYYedq0QEzlb0Y,22857
82
+ mcp_proxy_adapter/core/utils.py,sha256=ly8Ttg2v1OBukThJLxudRvmttU1hxJFLJUfat4b2dOI,3268
83
+ mcp_proxy_adapter/examples/__init__.py,sha256=k1F-EotAFbJ3JvK_rNgiH4bUztmxIWtYn0AfbAZ1ZGs,450
84
+ mcp_proxy_adapter/examples/create_certificates_simple.py,sha256=KhP-J98e3GRfEsueEtPlACyOVNWVVxRwBZWBMged_YA,25743
85
+ mcp_proxy_adapter/examples/debug_request_state.py,sha256=x_H3NIlkmIS6lZimvEM6kCXxGdpgFw99Sdui8qa_qeU,4347
86
+ mcp_proxy_adapter/examples/debug_role_chain.py,sha256=33l2Tk5mrcnwPFwqm2NTHcrWaJrXUU2wxW2I6Y4uIg4,8344
87
+ mcp_proxy_adapter/examples/demo_client.py,sha256=inic-FP5qG8oQXUaCrtEhmhac_PDZ1pcxp-M1cxSzwA,10240
88
+ mcp_proxy_adapter/examples/generate_all_certificates.py,sha256=rgcwqIkQ1eDfEIRFRXGIOz-jOSS1w0GPBRhYvMl6Vjc,16948
89
+ mcp_proxy_adapter/examples/generate_certificates.py,sha256=A34OHUEiFvINOHrm3_JiDSbp-WG-eQXIvKCsE8JAeXQ,6616
90
+ mcp_proxy_adapter/examples/generate_certificates_and_tokens.py,sha256=J0qHm_BMY8RYqfuwf7V7xKsHcsRJx8E7x-8JxmW5sPw,15988
91
+ mcp_proxy_adapter/examples/generate_test_configs.py,sha256=NLhPrA9AfPlQ0WCbOJ1B_V9OC445tanKTmq7aAWKULU,13672
92
+ mcp_proxy_adapter/examples/proxy_registration_example.py,sha256=g59_QG2D1CCqhIXEvgy2XmgXI3toLmLyH7hL3uHZwC8,12647
93
+ mcp_proxy_adapter/examples/run_example.py,sha256=o8rcy9Xo0UuZG4MpKdex3pFWYdtAi6uW8dEBQE6Yzbw,2539
94
+ mcp_proxy_adapter/examples/run_full_test_suite.py,sha256=7Z6qDOvbndGPue1P9v-GcYZxy_XPqoC9voJ7tR8eKQ8,12428
95
+ mcp_proxy_adapter/examples/run_proxy_server.py,sha256=vkEjqREcOSw2elH_VOBLa0cFjL8gCZp9nkRa8YLsndI,5119
96
+ mcp_proxy_adapter/examples/run_security_tests.py,sha256=BFeafoRXOhorJ8ScjjnlmPdRaCG8AaPAxb-PRnSGJTM,22639
97
+ mcp_proxy_adapter/examples/run_security_tests_fixed.py,sha256=fNQsbALf9548xJ0OGPKYx5Crzg1GbcL8CSh1x_oKu_A,10540
98
+ mcp_proxy_adapter/examples/security_test_client.py,sha256=0j0-RGg9kppt_IAuYeT8cbXr3N5gqBdzEyPd3RW0bs8,35558
99
+ mcp_proxy_adapter/examples/setup_test_environment.py,sha256=fAfz1U7qERY-Z9ly15Wld8Zci-5_e9zSrvYJ56Rjowo,11839
100
+ mcp_proxy_adapter/examples/test_config.py,sha256=1X9X8lNlWOcM1ZbIzteeMvLdgxnJEK_ev1BYTZiA9ws,6451
101
+ mcp_proxy_adapter/examples/test_config_generator.py,sha256=SBKL0bv-kUwUUbwrFVbxuA_6pDvK2573Jxm9wPiyI8s,3927
102
+ mcp_proxy_adapter/examples/test_examples.py,sha256=KH095FFEQDMKYZglclr5qy3cW__t3H8VX1l8dvCkQos,12132
103
+ mcp_proxy_adapter/examples/universal_client.py,sha256=IIKGRa0__KoWVla3VnVl-RjkkG_nPpM8vglPm70pV9c,26948
104
+ mcp_proxy_adapter/examples/basic_framework/__init__.py,sha256=4aYD--R6hy9n9CUxj7Osb9HcdVUMJ6_cfpu4ujkbCwI,345
105
+ mcp_proxy_adapter/examples/basic_framework/main.py,sha256=cDmqeUN1lDBBwuwLjmnP3qIyofCZ3Jr5Ct7Im-qCsUU,1728
106
+ mcp_proxy_adapter/examples/basic_framework/commands/__init__.py,sha256=_VQNLUEdsxUG-4yt9BZI_vtOxHAdGG0OUSsP6Wj-Vz4,76
107
+ mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py,sha256=IE_EIXMnkdXuakZn7wLD9kBFyfDF5lYi56ejgiBeb-A,70
108
+ mcp_proxy_adapter/examples/commands/__init__.py,sha256=46FZSOABSeKPffw91JqIWL_UQD_RLL3nAR-ufgb2hr8,169
109
+ mcp_proxy_adapter/examples/examples/basic_framework/__init__.py,sha256=4aYD--R6hy9n9CUxj7Osb9HcdVUMJ6_cfpu4ujkbCwI,345
110
+ mcp_proxy_adapter/examples/examples/basic_framework/main.py,sha256=cDmqeUN1lDBBwuwLjmnP3qIyofCZ3Jr5Ct7Im-qCsUU,1728
111
+ mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py,sha256=_VQNLUEdsxUG-4yt9BZI_vtOxHAdGG0OUSsP6Wj-Vz4,76
112
+ mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py,sha256=IE_EIXMnkdXuakZn7wLD9kBFyfDF5lYi56ejgiBeb-A,70
113
+ mcp_proxy_adapter/examples/examples/full_application/__init__.py,sha256=AEqN_gEBzj-swBtTOvRUWqKSdXqJVk1aUtfPghVL-2o,319
114
+ mcp_proxy_adapter/examples/examples/full_application/main.py,sha256=h2d90G6XMJFbJpo2ht7M1IqITZ9nZPi9QtH6ETeE9DI,7791
115
+ mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py,sha256=-cpb0nIjzp6OltFHoZqrtFvb4wJf1dgT4WvQ2dcY6Bo,6045
116
+ mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py,sha256=yQHxVSFkAyFLUOdk42QOebUODPlQV9IbydPgF3UKsGM,217
117
+ mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py,sha256=u9_XOkoHkiFC-tn9B-yGUXfQi9OL0EDxlVVKSERI1wA,3099
118
+ mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py,sha256=fRWtegpUUVt4wWOz3yE3spMG4h1DM_xbSxg_WqlnbF0,3491
119
+ mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py,sha256=ORG4cL8cSXEMmZ0CEPz75OVuwg54pdDm2GIBpP4dtcs,200
120
+ mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py,sha256=TYXuHI-KW_mH5r8mSKgNMJCr3moeEKrqC4Eex0U298k,3457
121
+ mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py,sha256=IaskSrckZS6bE3aGxSBL8aTj-iJTSI2ysfsFjhjncyM,2975
122
+ mcp_proxy_adapter/examples/full_application/__init__.py,sha256=AEqN_gEBzj-swBtTOvRUWqKSdXqJVk1aUtfPghVL-2o,319
123
+ mcp_proxy_adapter/examples/full_application/main.py,sha256=h2d90G6XMJFbJpo2ht7M1IqITZ9nZPi9QtH6ETeE9DI,7791
124
+ mcp_proxy_adapter/examples/full_application/proxy_endpoints.py,sha256=-cpb0nIjzp6OltFHoZqrtFvb4wJf1dgT4WvQ2dcY6Bo,6045
125
+ mcp_proxy_adapter/examples/full_application/commands/__init__.py,sha256=yQHxVSFkAyFLUOdk42QOebUODPlQV9IbydPgF3UKsGM,217
126
+ mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py,sha256=u9_XOkoHkiFC-tn9B-yGUXfQi9OL0EDxlVVKSERI1wA,3099
127
+ mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py,sha256=fRWtegpUUVt4wWOz3yE3spMG4h1DM_xbSxg_WqlnbF0,3491
128
+ mcp_proxy_adapter/examples/full_application/hooks/__init__.py,sha256=ORG4cL8cSXEMmZ0CEPz75OVuwg54pdDm2GIBpP4dtcs,200
129
+ mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py,sha256=TYXuHI-KW_mH5r8mSKgNMJCr3moeEKrqC4Eex0U298k,3457
130
+ mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py,sha256=IaskSrckZS6bE3aGxSBL8aTj-iJTSI2ysfsFjhjncyM,2975
131
+ mcp_proxy_adapter/examples/scripts/config_generator.py,sha256=4qruYxQ2kGLVOukLX2JOW5kslJ06RhkNqTobAgh4rfw,32801
132
+ mcp_proxy_adapter/examples/scripts/create_certificates_simple.py,sha256=xkIvUYl6hbKlWImQmenG0k_CvIsOsc9ZHICiKY3rtI8,26380
133
+ mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py,sha256=J0qHm_BMY8RYqfuwf7V7xKsHcsRJx8E7x-8JxmW5sPw,15988
134
+ mcp_proxy_adapter/utils/config_generator.py,sha256=2dxwBh9k_nUw9kgytZso5TNOQpBqd3c-RpKSTLoHlLE,46465
135
+ mcp_proxy_adapter-6.0.1.dist-info/licenses/LICENSE,sha256=6KdtUcTwmTRbJrAmYjVn7e6S-V42ubeDJ-AiVEzZ510,1075
136
+ mcp_proxy_adapter-6.0.1.dist-info/METADATA,sha256=UYIC4jHUJrNCj-7FlIHqekZvym3C5njJhaPp8XesdXA,22347
137
+ mcp_proxy_adapter-6.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
138
+ mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
139
+ mcp_proxy_adapter-6.0.1.dist-info/top_level.txt,sha256=JZT7vPLBYrtroX-ij68JBhJYbjDdghcV-DFySRy-Nnw,18
140
+ mcp_proxy_adapter-6.0.1.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcp-proxy-adapter = mcp_proxy_adapter.__main__:main
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023-2024 Vasiliy VZ
3
+ Copyright (c) 2024 Vasiliy Zdanovskiy
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
@@ -1,146 +0,0 @@
1
- """
2
- Middleware for authentication.
3
- """
4
-
5
- import json
6
- from typing import Dict, List, Optional, Callable, Awaitable
7
-
8
- from fastapi import Request, Response
9
- from starlette.responses import JSONResponse
10
-
11
- from mcp_proxy_adapter.core.logging import logger
12
- from .base import BaseMiddleware
13
-
14
- class AuthMiddleware(BaseMiddleware):
15
- """
16
- Middleware for authenticating requests.
17
- """
18
-
19
- def __init__(self, app, api_keys: Dict[str, str] = None, public_paths: List[str] = None, auth_enabled: bool = True):
20
- """
21
- Initializes middleware for authentication.
22
-
23
- Args:
24
- app: FastAPI application
25
- api_keys: Dictionary with API keys (key: username)
26
- public_paths: List of paths accessible without authentication
27
- auth_enabled: Flag to enable/disable authentication
28
- """
29
- super().__init__(app)
30
- self.api_keys = api_keys or {}
31
- self.public_paths = public_paths or [
32
- "/docs",
33
- "/redoc",
34
- "/openapi.json",
35
- "/health"
36
- ]
37
- self.auth_enabled = auth_enabled
38
-
39
- async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
40
- """
41
- Processes request and checks authentication.
42
-
43
- Args:
44
- request: Request.
45
- call_next: Next handler.
46
-
47
- Returns:
48
- Response.
49
- """
50
- # Check if authentication is disabled
51
- if not self.auth_enabled:
52
- logger.debug("Authentication is disabled, skipping authentication check")
53
- return await call_next(request)
54
-
55
- # Check if path is public
56
- path = request.url.path
57
- if self._is_public_path(path):
58
- # If path is public, skip authentication
59
- return await call_next(request)
60
-
61
- # Check for API key in header
62
- api_key = request.headers.get("X-API-Key")
63
-
64
- if not api_key:
65
- # Check for API key in query parameters
66
- api_key = request.query_params.get("api_key")
67
-
68
- if not api_key and request.method in ["POST", "PUT", "PATCH"]:
69
- # Check for API key in JSON-RPC request body
70
- try:
71
- body = await request.body()
72
- if body:
73
- try:
74
- body_json = json.loads(body.decode("utf-8"))
75
- # Look for API key in params of JSON-RPC object
76
- if isinstance(body_json, dict) and "params" in body_json:
77
- api_key = body_json.get("params", {}).get("api_key")
78
- except json.JSONDecodeError:
79
- pass
80
- except Exception:
81
- pass
82
-
83
- # If API key not found, return error
84
- if not api_key:
85
- logger.warning(f"Authentication failed: API key not provided | Path: {path}")
86
- return self._create_error_response("API key not provided", 401)
87
-
88
- # Check if API key is valid
89
- username = self._validate_api_key(api_key)
90
- if not username:
91
- logger.warning(f"Authentication failed: Invalid API key | Path: {path}")
92
- return self._create_error_response("Invalid API key", 401)
93
-
94
- # If API key is valid, save user information in request state
95
- request.state.username = username
96
- logger.info(f"Authentication successful: {username} | Path: {path}")
97
-
98
- # Call the next middleware or main handler
99
- return await call_next(request)
100
-
101
- def _is_public_path(self, path: str) -> bool:
102
- """
103
- Checks if the path is public.
104
-
105
- Args:
106
- path: Path to check.
107
-
108
- Returns:
109
- True if path is public, False otherwise.
110
- """
111
- return any(path.startswith(public_path) for public_path in self.public_paths)
112
-
113
- def _validate_api_key(self, api_key: str) -> Optional[str]:
114
- """
115
- Validates API key.
116
-
117
- Args:
118
- api_key: API key to validate.
119
-
120
- Returns:
121
- Username if API key is valid, otherwise None.
122
- """
123
- return self.api_keys.get(api_key)
124
-
125
- def _create_error_response(self, message: str, status_code: int) -> Response:
126
- """
127
- Creates error response in JSON-RPC format.
128
-
129
- Args:
130
- message: Error message.
131
- status_code: HTTP status code.
132
-
133
- Returns:
134
- JSON response with error.
135
- """
136
- return JSONResponse(
137
- status_code=status_code,
138
- content={
139
- "jsonrpc": "2.0",
140
- "error": {
141
- "code": -32000,
142
- "message": message
143
- },
144
- "id": None
145
- }
146
- )
@@ -1,152 +0,0 @@
1
- """
2
- Middleware for rate limiting.
3
- """
4
-
5
- import time
6
- from typing import Dict, List, Callable, Awaitable
7
- from collections import defaultdict
8
-
9
- from fastapi import Request, Response
10
- from starlette.responses import JSONResponse
11
-
12
- from mcp_proxy_adapter.core.logging import logger
13
- from .base import BaseMiddleware
14
-
15
- class RateLimitMiddleware(BaseMiddleware):
16
- """
17
- Middleware for limiting request rate.
18
- """
19
-
20
- def __init__(self, app, rate_limit: int = 100, time_window: int = 60,
21
- by_ip: bool = True, by_user: bool = True,
22
- public_paths: List[str] = None):
23
- """
24
- Initializes middleware for rate limiting.
25
-
26
- Args:
27
- app: FastAPI application
28
- rate_limit: Maximum number of requests in the specified time period
29
- time_window: Time period in seconds
30
- by_ip: Limit requests by IP address
31
- by_user: Limit requests by user
32
- public_paths: List of paths for which rate limiting is not applied
33
- """
34
- super().__init__(app)
35
- self.rate_limit = rate_limit
36
- self.time_window = time_window
37
- self.by_ip = by_ip
38
- self.by_user = by_user
39
- self.public_paths = public_paths or [
40
- "/docs",
41
- "/redoc",
42
- "/openapi.json",
43
- "/health"
44
- ]
45
-
46
- # Storage for requests by IP
47
- self.ip_requests = defaultdict(list)
48
-
49
- # Storage for requests by user
50
- self.user_requests = defaultdict(list)
51
-
52
- async def dispatch(self, request: Request, call_next: Callable[[Request], Awaitable[Response]]) -> Response:
53
- """
54
- Processes request and checks rate limit.
55
-
56
- Args:
57
- request: Request.
58
- call_next: Next handler.
59
-
60
- Returns:
61
- Response.
62
- """
63
- # Check if path is public
64
- path = request.url.path
65
- if self._is_public_path(path):
66
- # If path is public, skip rate limiting
67
- return await call_next(request)
68
-
69
- # Current time
70
- current_time = time.time()
71
-
72
- # Get client IP address
73
- client_ip = request.client.host if request.client else "unknown"
74
-
75
- # Get user from request state (if any)
76
- username = getattr(request.state, "username", None)
77
-
78
- # Check limit by IP
79
- if self.by_ip and client_ip != "unknown":
80
- # Clean old requests
81
- self._clean_old_requests(self.ip_requests[client_ip], current_time)
82
-
83
- # Check number of requests
84
- if len(self.ip_requests[client_ip]) >= self.rate_limit:
85
- logger.warning(f"Rate limit exceeded for IP: {client_ip} | Path: {path}")
86
- return self._create_error_response("Rate limit exceeded", 429)
87
-
88
- # Add current request
89
- self.ip_requests[client_ip].append(current_time)
90
-
91
- # Check limit by user
92
- if self.by_user and username:
93
- # Clean old requests
94
- self._clean_old_requests(self.user_requests[username], current_time)
95
-
96
- # Check number of requests
97
- if len(self.user_requests[username]) >= self.rate_limit:
98
- logger.warning(f"Rate limit exceeded for user: {username} | Path: {path}")
99
- return self._create_error_response("Rate limit exceeded", 429)
100
-
101
- # Add current request
102
- self.user_requests[username].append(current_time)
103
-
104
- # Call the next middleware or main handler
105
- return await call_next(request)
106
-
107
- def _clean_old_requests(self, requests: List[float], current_time: float) -> None:
108
- """
109
- Cleans old requests that are outside the time window.
110
-
111
- Args:
112
- requests: List of request timestamps.
113
- current_time: Current time.
114
- """
115
- min_time = current_time - self.time_window
116
- while requests and requests[0] < min_time:
117
- requests.pop(0)
118
-
119
- def _is_public_path(self, path: str) -> bool:
120
- """
121
- Checks if the path is public.
122
-
123
- Args:
124
- path: Path to check.
125
-
126
- Returns:
127
- True if path is public, False otherwise.
128
- """
129
- return any(path.startswith(public_path) for public_path in self.public_paths)
130
-
131
- def _create_error_response(self, message: str, status_code: int) -> Response:
132
- """
133
- Creates error response in JSON-RPC format.
134
-
135
- Args:
136
- message: Error message.
137
- status_code: HTTP status code.
138
-
139
- Returns:
140
- JSON response with error.
141
- """
142
- return JSONResponse(
143
- status_code=status_code,
144
- content={
145
- "jsonrpc": "2.0",
146
- "error": {
147
- "code": -32000,
148
- "message": message
149
- },
150
- "id": None
151
- }
152
- )
@@ -1,125 +0,0 @@
1
- """
2
- Reload Settings Command
3
-
4
- This command allows reloading configuration settings from files and environment variables.
5
- """
6
-
7
- from typing import Dict, Any
8
- from mcp_proxy_adapter.commands.base import Command
9
- from mcp_proxy_adapter.core.settings import reload_settings, get_custom_settings
10
- from mcp_proxy_adapter.core.logging import get_logger
11
-
12
-
13
- class ReloadSettingsResult:
14
- """
15
- Result class for reload settings command.
16
- """
17
-
18
- def __init__(
19
- self,
20
- success: bool,
21
- message: str,
22
- custom_settings: Dict[str, Any] = None,
23
- error_message: str = None
24
- ):
25
- self.success = success
26
- self.message = message
27
- self.custom_settings = custom_settings or {}
28
- self.error_message = error_message
29
-
30
- def to_dict(self) -> Dict[str, Any]:
31
- """Convert result to dictionary."""
32
- result = {
33
- "success": self.success,
34
- "message": self.message,
35
- "custom_settings": self.custom_settings
36
- }
37
- if self.error_message:
38
- result["error_message"] = self.error_message
39
- return result
40
-
41
- def get_schema(self) -> Dict[str, Any]:
42
- """Get JSON schema for the result."""
43
- return {
44
- "type": "object",
45
- "properties": {
46
- "success": {
47
- "type": "boolean",
48
- "description": "Whether the operation was successful"
49
- },
50
- "message": {
51
- "type": "string",
52
- "description": "Operation result message"
53
- },
54
- "custom_settings": {
55
- "type": "object",
56
- "description": "Current custom settings after reload",
57
- "additionalProperties": True
58
- },
59
- "error_message": {
60
- "type": "string",
61
- "description": "Error message if operation failed"
62
- }
63
- },
64
- "required": ["success", "message", "custom_settings"]
65
- }
66
-
67
-
68
- class ReloadSettingsCommand(Command):
69
- """
70
- Command to reload configuration settings.
71
- """
72
-
73
- name = "reload_settings"
74
- description = "Reload configuration settings from files and environment variables"
75
-
76
- async def execute(self, **params) -> ReloadSettingsResult:
77
- """
78
- Execute the reload settings command.
79
-
80
- Args:
81
- **params: Command parameters (not used)
82
-
83
- Returns:
84
- ReloadSettingsResult with operation status
85
- """
86
- logger = get_logger("reload_settings_command")
87
-
88
- try:
89
- logger.info("🔄 Starting settings reload...")
90
-
91
- # Reload configuration from files and environment variables
92
- reload_settings()
93
-
94
- # Get current custom settings
95
- custom_settings = get_custom_settings()
96
-
97
- logger.info("✅ Settings reloaded successfully")
98
- logger.info(f"📋 Current custom settings: {custom_settings}")
99
-
100
- return ReloadSettingsResult(
101
- success=True,
102
- message="Settings reloaded successfully from configuration files and environment variables",
103
- custom_settings=custom_settings
104
- )
105
-
106
- except Exception as e:
107
- error_msg = f"Failed to reload settings: {str(e)}"
108
- logger.error(f"❌ {error_msg}")
109
-
110
- return ReloadSettingsResult(
111
- success=False,
112
- message="Failed to reload settings",
113
- custom_settings=get_custom_settings(),
114
- error_message=error_msg
115
- )
116
-
117
- @classmethod
118
- def get_schema(cls) -> Dict[str, Any]:
119
- """Get JSON schema for the command parameters."""
120
- return {
121
- "type": "object",
122
- "description": "Reload configuration settings from files and environment variables",
123
- "properties": {},
124
- "additionalProperties": False
125
- }