mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__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 (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +12 -2
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -16,19 +16,19 @@ from mcp_proxy_adapter.core.logging import logger
16
16
  class ConfigConverter:
17
17
  """
18
18
  Converter for configuration formats.
19
-
19
+
20
20
  Provides methods to convert between mcp_proxy_adapter configuration
21
21
  and mcp_security_framework configuration formats.
22
22
  """
23
-
23
+
24
24
  @staticmethod
25
25
  def to_security_framework_config(mcp_config: Dict[str, Any]) -> Dict[str, Any]:
26
26
  """
27
27
  Convert mcp_proxy_adapter configuration to SecurityConfig format.
28
-
28
+
29
29
  Args:
30
30
  mcp_config: mcp_proxy_adapter configuration dictionary
31
-
31
+
32
32
  Returns:
33
33
  SecurityConfig compatible dictionary
34
34
  """
@@ -40,7 +40,7 @@ class ConfigConverter:
40
40
  "methods": ["api_key"],
41
41
  "api_keys": {},
42
42
  "jwt_secret": "",
43
- "jwt_algorithm": "HS256"
43
+ "jwt_algorithm": "HS256",
44
44
  },
45
45
  "ssl": {
46
46
  "enabled": False,
@@ -49,13 +49,13 @@ class ConfigConverter:
49
49
  "ca_cert": None,
50
50
  "min_tls_version": "TLSv1.2",
51
51
  "verify_client": False,
52
- "client_cert_required": False
52
+ "client_cert_required": False,
53
53
  },
54
54
  "permissions": {
55
55
  "enabled": True,
56
56
  "roles_file": "roles.json",
57
57
  "default_role": "user",
58
- "deny_by_default": True
58
+ "deny_by_default": True,
59
59
  },
60
60
  "rate_limit": {
61
61
  "enabled": True,
@@ -63,113 +63,146 @@ class ConfigConverter:
63
63
  "requests_per_hour": 1000,
64
64
  "burst_limit": 10,
65
65
  "by_ip": True,
66
- "by_user": True
67
- }
66
+ "by_user": True,
67
+ },
68
68
  }
69
-
69
+
70
70
  # Convert from security section if exists
71
71
  if "security" in mcp_config:
72
72
  security_section = mcp_config["security"]
73
-
73
+
74
74
  # Convert auth config
75
75
  if "auth" in security_section:
76
76
  auth_config = security_section["auth"]
77
- security_config["auth"].update({
78
- "enabled": auth_config.get("enabled", True),
79
- "methods": auth_config.get("methods", ["api_key"]),
80
- "api_keys": auth_config.get("api_keys", {}),
81
- "jwt_secret": auth_config.get("jwt_secret", ""),
82
- "jwt_algorithm": auth_config.get("jwt_algorithm", "HS256")
83
- })
84
-
77
+ security_config["auth"].update(
78
+ {
79
+ "enabled": auth_config.get("enabled", True),
80
+ "methods": auth_config.get("methods", ["api_key"]),
81
+ "api_keys": auth_config.get("api_keys", {}),
82
+ "jwt_secret": auth_config.get("jwt_secret", ""),
83
+ "jwt_algorithm": auth_config.get("jwt_algorithm", "HS256"),
84
+ }
85
+ )
86
+
85
87
  # Convert SSL config
86
88
  if "ssl" in security_section:
87
89
  ssl_config = security_section["ssl"]
88
- security_config["ssl"].update({
89
- "enabled": ssl_config.get("enabled", False),
90
- "cert_file": ssl_config.get("cert_file"),
91
- "key_file": ssl_config.get("key_file"),
92
- "ca_cert": ssl_config.get("ca_cert"),
93
- "min_tls_version": ssl_config.get("min_tls_version", "TLSv1.2"),
94
- "verify_client": ssl_config.get("verify_client", False),
95
- "client_cert_required": ssl_config.get("client_cert_required", False)
96
- })
97
-
90
+ security_config["ssl"].update(
91
+ {
92
+ "enabled": ssl_config.get("enabled", False),
93
+ "cert_file": ssl_config.get("cert_file"),
94
+ "key_file": ssl_config.get("key_file"),
95
+ "ca_cert": ssl_config.get("ca_cert"),
96
+ "min_tls_version": ssl_config.get(
97
+ "min_tls_version", "TLSv1.2"
98
+ ),
99
+ "verify_client": ssl_config.get("verify_client", False),
100
+ "client_cert_required": ssl_config.get(
101
+ "client_cert_required", False
102
+ ),
103
+ }
104
+ )
105
+
98
106
  # Convert permissions config
99
107
  if "permissions" in security_section:
100
108
  permissions_config = security_section["permissions"]
101
- security_config["permissions"].update({
102
- "enabled": permissions_config.get("enabled", True),
103
- "roles_file": permissions_config.get("roles_file", "roles.json"),
104
- "default_role": permissions_config.get("default_role", "user"),
105
- "deny_by_default": permissions_config.get("deny_by_default", True)
106
- })
107
-
109
+ security_config["permissions"].update(
110
+ {
111
+ "enabled": permissions_config.get("enabled", True),
112
+ "roles_file": permissions_config.get(
113
+ "roles_file", "roles.json"
114
+ ),
115
+ "default_role": permissions_config.get(
116
+ "default_role", "user"
117
+ ),
118
+ "deny_by_default": permissions_config.get(
119
+ "deny_by_default", True
120
+ ),
121
+ }
122
+ )
123
+
108
124
  # Convert rate limit config
109
125
  if "rate_limit" in security_section:
110
126
  rate_limit_config = security_section["rate_limit"]
111
- security_config["rate_limit"].update({
112
- "enabled": rate_limit_config.get("enabled", True),
113
- "requests_per_minute": rate_limit_config.get("requests_per_minute", 60),
114
- "requests_per_hour": rate_limit_config.get("requests_per_hour", 1000),
115
- "burst_limit": rate_limit_config.get("burst_limit", 10),
116
- "by_ip": rate_limit_config.get("by_ip", True),
117
- "by_user": rate_limit_config.get("by_user", True)
118
- })
119
-
127
+ security_config["rate_limit"].update(
128
+ {
129
+ "enabled": rate_limit_config.get("enabled", True),
130
+ "requests_per_minute": rate_limit_config.get(
131
+ "requests_per_minute", 60
132
+ ),
133
+ "requests_per_hour": rate_limit_config.get(
134
+ "requests_per_hour", 1000
135
+ ),
136
+ "burst_limit": rate_limit_config.get("burst_limit", 10),
137
+ "by_ip": rate_limit_config.get("by_ip", True),
138
+ "by_user": rate_limit_config.get("by_user", True),
139
+ }
140
+ )
141
+
120
142
  # Convert from legacy SSL config if security section doesn't exist
121
143
  elif "ssl" in mcp_config:
122
144
  ssl_config = mcp_config["ssl"]
123
- security_config["ssl"].update({
124
- "enabled": ssl_config.get("enabled", False),
125
- "cert_file": ssl_config.get("cert_file"),
126
- "key_file": ssl_config.get("key_file"),
127
- "ca_cert": ssl_config.get("ca_cert"),
128
- "min_tls_version": ssl_config.get("min_tls_version", "TLSv1.2"),
129
- "verify_client": ssl_config.get("verify_client", False),
130
- "client_cert_required": ssl_config.get("client_cert_required", False)
131
- })
132
-
145
+ security_config["ssl"].update(
146
+ {
147
+ "enabled": ssl_config.get("enabled", False),
148
+ "cert_file": ssl_config.get("cert_file"),
149
+ "key_file": ssl_config.get("key_file"),
150
+ "ca_cert": ssl_config.get("ca_cert"),
151
+ "min_tls_version": ssl_config.get("min_tls_version", "TLSv1.2"),
152
+ "verify_client": ssl_config.get("verify_client", False),
153
+ "client_cert_required": ssl_config.get(
154
+ "client_cert_required", False
155
+ ),
156
+ }
157
+ )
158
+
133
159
  # Extract API keys from legacy SSL config
134
160
  if "api_keys" in ssl_config:
135
161
  security_config["auth"]["api_keys"] = ssl_config["api_keys"]
136
-
162
+
137
163
  # Convert from legacy roles config
138
164
  if "roles" in mcp_config:
139
165
  roles_config = mcp_config["roles"]
140
- security_config["permissions"].update({
141
- "enabled": roles_config.get("enabled", True),
142
- "roles_file": roles_config.get("config_file", "roles.json"),
143
- "default_role": "user",
144
- "deny_by_default": roles_config.get("default_policy", {}).get("deny_by_default", True)
145
- })
146
-
147
- logger.info("Configuration converted to security framework format successfully")
166
+ security_config["permissions"].update(
167
+ {
168
+ "enabled": roles_config.get("enabled", True),
169
+ "roles_file": roles_config.get("config_file", "roles.json"),
170
+ "default_role": "user",
171
+ "deny_by_default": roles_config.get("default_policy", {}).get(
172
+ "deny_by_default", True
173
+ ),
174
+ }
175
+ )
176
+
177
+ logger.info(
178
+ "Configuration converted to security framework format successfully"
179
+ )
148
180
  return security_config
149
-
181
+
150
182
  except Exception as e:
151
- logger.error(f"Failed to convert configuration to security framework format: {e}")
183
+ logger.error(
184
+ f"Failed to convert configuration to security framework format: {e}"
185
+ )
152
186
  return ConfigConverter._get_default_security_config()
153
-
187
+
154
188
  @staticmethod
155
- def from_security_framework_config(security_config: Dict[str, Any]) -> Dict[str, Any]:
189
+ def from_security_framework_config(
190
+ security_config: Dict[str, Any]
191
+ ) -> Dict[str, Any]:
156
192
  """
157
193
  Convert SecurityConfig format to mcp_proxy_adapter configuration.
158
-
194
+
159
195
  Args:
160
196
  security_config: SecurityConfig compatible dictionary
161
-
197
+
162
198
  Returns:
163
199
  mcp_proxy_adapter configuration dictionary
164
200
  """
165
201
  try:
166
202
  mcp_config = {
167
- "security": {
168
- "framework": "mcp_security_framework",
169
- "enabled": True
170
- }
203
+ "security": {"framework": "mcp_security_framework", "enabled": True}
171
204
  }
172
-
205
+
173
206
  # Convert auth config
174
207
  if "auth" in security_config:
175
208
  auth_config = security_config["auth"]
@@ -178,9 +211,9 @@ class ConfigConverter:
178
211
  "methods": auth_config.get("methods", ["api_key"]),
179
212
  "api_keys": auth_config.get("api_keys", {}),
180
213
  "jwt_secret": auth_config.get("jwt_secret", ""),
181
- "jwt_algorithm": auth_config.get("jwt_algorithm", "HS256")
214
+ "jwt_algorithm": auth_config.get("jwt_algorithm", "HS256"),
182
215
  }
183
-
216
+
184
217
  # Convert SSL config
185
218
  if "ssl" in security_config:
186
219
  ssl_config = security_config["ssl"]
@@ -191,9 +224,11 @@ class ConfigConverter:
191
224
  "ca_cert": ssl_config.get("ca_cert"),
192
225
  "min_tls_version": ssl_config.get("min_tls_version", "TLSv1.2"),
193
226
  "verify_client": ssl_config.get("verify_client", False),
194
- "client_cert_required": ssl_config.get("client_cert_required", False)
227
+ "client_cert_required": ssl_config.get(
228
+ "client_cert_required", False
229
+ ),
195
230
  }
196
-
231
+
197
232
  # Convert permissions config
198
233
  if "permissions" in security_config:
199
234
  permissions_config = security_config["permissions"]
@@ -201,74 +236,84 @@ class ConfigConverter:
201
236
  "enabled": permissions_config.get("enabled", True),
202
237
  "roles_file": permissions_config.get("roles_file", "roles.json"),
203
238
  "default_role": permissions_config.get("default_role", "user"),
204
- "deny_by_default": permissions_config.get("deny_by_default", True)
239
+ "deny_by_default": permissions_config.get("deny_by_default", True),
205
240
  }
206
-
241
+
207
242
  # Convert rate limit config
208
243
  if "rate_limit" in security_config:
209
244
  rate_limit_config = security_config["rate_limit"]
210
245
  mcp_config["security"]["rate_limit"] = {
211
246
  "enabled": rate_limit_config.get("enabled", True),
212
- "requests_per_minute": rate_limit_config.get("requests_per_minute", 60),
213
- "requests_per_hour": rate_limit_config.get("requests_per_hour", 1000),
247
+ "requests_per_minute": rate_limit_config.get(
248
+ "requests_per_minute", 60
249
+ ),
250
+ "requests_per_hour": rate_limit_config.get(
251
+ "requests_per_hour", 1000
252
+ ),
214
253
  "burst_limit": rate_limit_config.get("burst_limit", 10),
215
254
  "by_ip": rate_limit_config.get("by_ip", True),
216
- "by_user": rate_limit_config.get("by_user", True)
255
+ "by_user": rate_limit_config.get("by_user", True),
217
256
  }
218
-
219
- logger.info("Configuration converted from security framework format successfully")
257
+
258
+ logger.info(
259
+ "Configuration converted from security framework format successfully"
260
+ )
220
261
  return mcp_config
221
-
262
+
222
263
  except Exception as e:
223
- logger.error(f"Failed to convert configuration from security framework format: {e}")
264
+ logger.error(
265
+ f"Failed to convert configuration from security framework format: {e}"
266
+ )
224
267
  return ConfigConverter._get_default_mcp_config()
225
-
268
+
226
269
  @staticmethod
227
- def migrate_legacy_config(config_path: str, output_path: Optional[str] = None) -> bool:
270
+ def migrate_legacy_config(
271
+ config_path: str, output_path: Optional[str] = None
272
+ ) -> bool:
228
273
  """
229
274
  Migrate legacy configuration to new security framework format.
230
-
275
+
231
276
  Args:
232
277
  config_path: Path to legacy configuration file
233
278
  output_path: Path to output migrated configuration file (optional)
234
-
279
+
235
280
  Returns:
236
281
  True if migration successful, False otherwise
237
282
  """
238
283
  try:
239
284
  # Read legacy configuration
240
- with open(config_path, 'r', encoding='utf-8') as f:
285
+ with open(config_path, "r", encoding="utf-8") as f:
241
286
  legacy_config = json.load(f)
242
-
287
+
243
288
  # Convert to new format
244
289
  new_config = ConfigConverter.to_security_framework_config(legacy_config)
245
-
290
+
246
291
  # Add security section to legacy config
247
292
  legacy_config["security"] = new_config
248
-
293
+
249
294
  # Determine output path
250
295
  if output_path is None:
251
- output_path = config_path.replace('.json', '_migrated.json')
252
-
296
+ output_path = config_path.replace(".json", "_migrated.json")
297
+
253
298
  # Write migrated configuration
254
- with open(output_path, 'w', encoding='utf-8') as f:
299
+ with open(output_path, "w", encoding="utf-8") as f:
255
300
  json.dump(legacy_config, f, indent=2, ensure_ascii=False)
256
-
301
+
257
302
  logger.info(f"Configuration migrated successfully to {output_path}")
258
303
  return True
259
-
304
+
260
305
  except Exception as e:
261
306
  logger.error(f"Failed to migrate configuration: {e}")
262
307
  return False
263
-
308
+
264
309
  @staticmethod
265
310
  def validate_security_config(config: Dict[str, Any]) -> bool:
266
311
  """
267
312
  Validate security configuration format.
268
-
313
+
269
314
  Args:
270
315
  config: Configuration dictionary to validate
271
-
316
+
272
317
  Returns:
273
318
  True if configuration is valid, False otherwise
274
319
  """
@@ -277,64 +322,66 @@ class ConfigConverter:
277
322
  if "security" not in config:
278
323
  logger.error("Security section not found in configuration")
279
324
  return False
280
-
325
+
281
326
  security_section = config["security"]
282
-
327
+
283
328
  # Validate required fields
284
329
  required_sections = ["auth", "ssl", "permissions", "rate_limit"]
285
330
  for section in required_sections:
286
331
  if section not in security_section:
287
- logger.error(f"Required section '{section}' not found in security configuration")
332
+ logger.error(
333
+ f"Required section '{section}' not found in security configuration"
334
+ )
288
335
  return False
289
-
336
+
290
337
  if not isinstance(security_section[section], dict):
291
338
  logger.error(f"Section '{section}' must be a dictionary")
292
339
  return False
293
-
340
+
294
341
  # Validate auth configuration
295
342
  auth_config = security_section["auth"]
296
343
  if not isinstance(auth_config.get("methods", []), list):
297
344
  logger.error("Auth methods must be a list")
298
345
  return False
299
-
346
+
300
347
  if not isinstance(auth_config.get("api_keys", {}), dict):
301
348
  logger.error("API keys must be a dictionary")
302
349
  return False
303
-
350
+
304
351
  # Validate SSL configuration
305
352
  ssl_config = security_section["ssl"]
306
353
  if not isinstance(ssl_config.get("enabled", False), bool):
307
354
  logger.error("SSL enabled must be a boolean")
308
355
  return False
309
-
356
+
310
357
  # Validate permissions configuration
311
358
  permissions_config = security_section["permissions"]
312
359
  if not isinstance(permissions_config.get("enabled", True), bool):
313
360
  logger.error("Permissions enabled must be a boolean")
314
361
  return False
315
-
362
+
316
363
  # Validate rate limit configuration
317
364
  rate_limit_config = security_section["rate_limit"]
318
365
  if not isinstance(rate_limit_config.get("enabled", True), bool):
319
366
  logger.error("Rate limit enabled must be a boolean")
320
367
  return False
321
-
368
+
322
369
  if not isinstance(rate_limit_config.get("requests_per_minute", 60), int):
323
370
  logger.error("Requests per minute must be an integer")
324
371
  return False
325
-
372
+
326
373
  logger.info("Security configuration validation passed")
327
374
  return True
328
-
375
+
329
376
  except Exception as e:
330
377
  logger.error(f"Configuration validation failed: {e}")
331
378
  return False
332
-
379
+
333
380
  @staticmethod
334
381
  def _get_default_security_config() -> Dict[str, Any]:
335
382
  """
336
383
  Get default security framework configuration.
337
-
384
+
338
385
  Returns:
339
386
  Default security framework configuration
340
387
  """
@@ -344,7 +391,7 @@ class ConfigConverter:
344
391
  "methods": ["api_key"],
345
392
  "api_keys": {},
346
393
  "jwt_secret": "",
347
- "jwt_algorithm": "HS256"
394
+ "jwt_algorithm": "HS256",
348
395
  },
349
396
  "ssl": {
350
397
  "enabled": False,
@@ -353,13 +400,13 @@ class ConfigConverter:
353
400
  "ca_cert": None,
354
401
  "min_tls_version": "TLSv1.2",
355
402
  "verify_client": False,
356
- "client_cert_required": False
403
+ "client_cert_required": False,
357
404
  },
358
405
  "permissions": {
359
406
  "enabled": True,
360
407
  "roles_file": "roles.json",
361
408
  "default_role": "user",
362
- "deny_by_default": True
409
+ "deny_by_default": True,
363
410
  },
364
411
  "rate_limit": {
365
412
  "enabled": True,
@@ -367,15 +414,15 @@ class ConfigConverter:
367
414
  "requests_per_hour": 1000,
368
415
  "burst_limit": 10,
369
416
  "by_ip": True,
370
- "by_user": True
371
- }
417
+ "by_user": True,
418
+ },
372
419
  }
373
-
420
+
374
421
  @staticmethod
375
422
  def _get_default_mcp_config() -> Dict[str, Any]:
376
423
  """
377
424
  Get default mcp_proxy_adapter configuration.
378
-
425
+
379
426
  Returns:
380
427
  Default mcp_proxy_adapter configuration
381
428
  """
@@ -383,23 +430,9 @@ class ConfigConverter:
383
430
  "security": {
384
431
  "framework": "mcp_security_framework",
385
432
  "enabled": True,
386
- "auth": {
387
- "enabled": True,
388
- "methods": ["api_key"],
389
- "api_keys": {}
390
- },
391
- "ssl": {
392
- "enabled": False,
393
- "cert_file": None,
394
- "key_file": None
395
- },
396
- "permissions": {
397
- "enabled": True,
398
- "roles_file": "roles.json"
399
- },
400
- "rate_limit": {
401
- "enabled": True,
402
- "requests_per_minute": 60
403
- }
433
+ "auth": {"enabled": True, "methods": ["api_key"], "api_keys": {}},
434
+ "ssl": {"enabled": False, "cert_file": None, "key_file": None},
435
+ "permissions": {"enabled": True, "roles_file": "roles.json"},
436
+ "rate_limit": {"enabled": True, "requests_per_minute": 60},
404
437
  }
405
438
  }
@@ -173,7 +173,9 @@ class ConfigValidator:
173
173
  if auth_config.get("enabled", False):
174
174
  api_keys = auth_config.get("api_keys", {})
175
175
  if not api_keys:
176
- self.errors.append("API keys are required when authentication is enabled")
176
+ self.errors.append(
177
+ "API keys are required when authentication is enabled"
178
+ )
177
179
  return False
178
180
 
179
181
  # Validate API key format
@@ -192,7 +194,9 @@ class ConfigValidator:
192
194
  if commands_config.get("auto_discovery", True):
193
195
  commands_dir = commands_config.get("commands_directory", "./commands")
194
196
  if not os.path.exists(commands_dir):
195
- self.warnings.append(f"Commands directory does not exist: {commands_dir}")
197
+ self.warnings.append(
198
+ f"Commands directory does not exist: {commands_dir}"
199
+ )
196
200
 
197
201
  return True
198
202
 
@@ -207,7 +211,9 @@ class ConfigValidator:
207
211
  key_file = ssl_config.get("key_file")
208
212
 
209
213
  if not cert_file or not key_file:
210
- self.errors.append("SSL certificate and key files are required when SSL is enabled")
214
+ self.errors.append(
215
+ "SSL certificate and key files are required when SSL is enabled"
216
+ )
211
217
  return False
212
218
 
213
219
  if not os.path.exists(cert_file):
@@ -226,7 +232,9 @@ class ConfigValidator:
226
232
  if roles_enabled:
227
233
  config_file = roles_config.get("config_file")
228
234
  if not config_file:
229
- self.errors.append("Roles config file is required when roles are enabled")
235
+ self.errors.append(
236
+ "Roles config file is required when roles are enabled"
237
+ )
230
238
  return False
231
239
 
232
240
  if not os.path.exists(config_file):