mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.6__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 (131) 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 +120 -91
  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 +7 -3
  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.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.6.dist-info/RECORD +144 -0
  125. mcp_proxy_adapter-6.3.6.dist-info/top_level.txt +2 -0
  126. mcp_proxy_adapter_issue_package/demonstrate_issue.py +178 -0
  127. mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
  128. mcp_proxy_adapter-6.3.4.dist-info/top_level.txt +0 -1
  129. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/WHEEL +0 -0
  130. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/entry_points.txt +0 -0
  131. {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.6.dist-info}/licenses/LICENSE +0 -0
@@ -20,18 +20,18 @@ from .client import UniversalClient, create_client_from_config
20
20
  class ClientManager:
21
21
  """
22
22
  Manages client connections and proxy registrations.
23
-
23
+
24
24
  This class provides functionality for:
25
25
  - Creating and managing client connections
26
26
  - Proxy registration
27
27
  - Connection pooling
28
28
  - Authentication management
29
29
  """
30
-
30
+
31
31
  def __init__(self, config: Dict[str, Any]):
32
32
  """
33
33
  Initialize client manager.
34
-
34
+
35
35
  Args:
36
36
  config: Client manager configuration
37
37
  """
@@ -39,60 +39,62 @@ class ClientManager:
39
39
  self.logger = logging.getLogger(__name__)
40
40
  self.clients: Dict[str, UniversalClient] = {}
41
41
  self.connection_pool: Dict[str, UniversalClient] = {}
42
-
42
+
43
43
  # Client manager settings
44
44
  self.max_connections = config.get("max_connections", 10)
45
45
  self.connection_timeout = config.get("connection_timeout", 30)
46
46
  self.retry_attempts = config.get("retry_attempts", 3)
47
47
  self.retry_delay = config.get("retry_delay", 1)
48
-
48
+
49
49
  self.logger.info("Client manager initialized")
50
-
50
+
51
51
  async def create_client(self, client_id: str, config_file: str) -> UniversalClient:
52
52
  """
53
53
  Create a new client instance.
54
-
54
+
55
55
  Args:
56
56
  client_id: Unique identifier for the client
57
57
  config_file: Path to client configuration file
58
-
58
+
59
59
  Returns:
60
60
  UniversalClient instance
61
61
  """
62
62
  try:
63
63
  if client_id in self.clients:
64
- self.logger.warning(f"Client {client_id} already exists, reusing existing connection")
64
+ self.logger.warning(
65
+ f"Client {client_id} already exists, reusing existing connection"
66
+ )
65
67
  return self.clients[client_id]
66
-
68
+
67
69
  client = create_client_from_config(config_file)
68
70
  self.clients[client_id] = client
69
-
71
+
70
72
  self.logger.info(f"Client {client_id} created successfully")
71
73
  return client
72
-
74
+
73
75
  except Exception as e:
74
76
  self.logger.error(f"Failed to create client {client_id}: {e}")
75
77
  raise
76
-
78
+
77
79
  async def get_client(self, client_id: str) -> Optional[UniversalClient]:
78
80
  """
79
81
  Get an existing client instance.
80
-
82
+
81
83
  Args:
82
84
  client_id: Client identifier
83
-
85
+
84
86
  Returns:
85
87
  UniversalClient instance or None if not found
86
88
  """
87
89
  return self.clients.get(client_id)
88
-
90
+
89
91
  async def remove_client(self, client_id: str) -> bool:
90
92
  """
91
93
  Remove a client instance.
92
-
94
+
93
95
  Args:
94
96
  client_id: Client identifier
95
-
97
+
96
98
  Returns:
97
99
  True if client was removed, False otherwise
98
100
  """
@@ -103,14 +105,14 @@ class ClientManager:
103
105
  self.logger.info(f"Client {client_id} removed")
104
106
  return True
105
107
  return False
106
-
108
+
107
109
  async def test_client_connection(self, client_id: str) -> bool:
108
110
  """
109
111
  Test connection for a specific client.
110
-
112
+
111
113
  Args:
112
114
  client_id: Client identifier
113
-
115
+
114
116
  Returns:
115
117
  True if connection is successful, False otherwise
116
118
  """
@@ -118,28 +120,30 @@ class ClientManager:
118
120
  if not client:
119
121
  self.logger.error(f"Client {client_id} not found")
120
122
  return False
121
-
123
+
122
124
  try:
123
125
  return await client.test_connection()
124
126
  except Exception as e:
125
127
  self.logger.error(f"Connection test failed for client {client_id}: {e}")
126
128
  return False
127
-
128
- async def register_proxy(self, client_id: str, proxy_config: Dict[str, Any]) -> Dict[str, Any]:
129
+
130
+ async def register_proxy(
131
+ self, client_id: str, proxy_config: Dict[str, Any]
132
+ ) -> Dict[str, Any]:
129
133
  """
130
134
  Register with proxy server using a specific client.
131
-
135
+
132
136
  Args:
133
137
  client_id: Client identifier
134
138
  proxy_config: Proxy registration configuration
135
-
139
+
136
140
  Returns:
137
141
  Registration result
138
142
  """
139
143
  client = await self.get_client(client_id)
140
144
  if not client:
141
145
  return {"error": f"Client {client_id} not found"}
142
-
146
+
143
147
  try:
144
148
  result = await client.register_proxy(proxy_config)
145
149
  self.logger.info(f"Proxy registration completed for client {client_id}")
@@ -147,23 +151,25 @@ class ClientManager:
147
151
  except Exception as e:
148
152
  self.logger.error(f"Proxy registration failed for client {client_id}: {e}")
149
153
  return {"error": str(e)}
150
-
151
- async def execute_command(self, client_id: str, command: str, params: Dict[str, Any] = None) -> Dict[str, Any]:
154
+
155
+ async def execute_command(
156
+ self, client_id: str, command: str, params: Dict[str, Any] = None
157
+ ) -> Dict[str, Any]:
152
158
  """
153
159
  Execute a command using a specific client.
154
-
160
+
155
161
  Args:
156
162
  client_id: Client identifier
157
163
  command: Command name
158
164
  params: Command parameters
159
-
165
+
160
166
  Returns:
161
167
  Command result
162
168
  """
163
169
  client = await self.get_client(client_id)
164
170
  if not client:
165
171
  return {"error": f"Client {client_id} not found"}
166
-
172
+
167
173
  try:
168
174
  result = await client.execute_command(command, params or {})
169
175
  self.logger.info(f"Command {command} executed for client {client_id}")
@@ -171,61 +177,61 @@ class ClientManager:
171
177
  except Exception as e:
172
178
  self.logger.error(f"Command execution failed for client {client_id}: {e}")
173
179
  return {"error": str(e)}
174
-
180
+
175
181
  async def get_client_status(self, client_id: str) -> Dict[str, Any]:
176
182
  """
177
183
  Get status information for a specific client.
178
-
184
+
179
185
  Args:
180
186
  client_id: Client identifier
181
-
187
+
182
188
  Returns:
183
189
  Client status information
184
190
  """
185
191
  client = await self.get_client(client_id)
186
192
  if not client:
187
193
  return {"error": f"Client {client_id} not found"}
188
-
194
+
189
195
  try:
190
196
  # Test connection
191
197
  connection_ok = await client.test_connection()
192
-
198
+
193
199
  # Test security features
194
200
  security_features = await client.test_security_features()
195
-
201
+
196
202
  status = {
197
203
  "client_id": client_id,
198
204
  "base_url": client.base_url,
199
205
  "auth_method": client.auth_method,
200
206
  "connection_ok": connection_ok,
201
207
  "security_features": security_features,
202
- "session_active": client.session is not None
208
+ "session_active": client.session is not None,
203
209
  }
204
-
210
+
205
211
  return status
206
212
  except Exception as e:
207
213
  self.logger.error(f"Failed to get status for client {client_id}: {e}")
208
214
  return {"error": str(e)}
209
-
215
+
210
216
  async def list_clients(self) -> List[str]:
211
217
  """
212
218
  Get list of all client identifiers.
213
-
219
+
214
220
  Returns:
215
221
  List of client identifiers
216
222
  """
217
223
  return list(self.clients.keys())
218
-
224
+
219
225
  async def cleanup(self):
220
226
  """Clean up all client connections."""
221
227
  for client_id in list(self.clients.keys()):
222
228
  await self.remove_client(client_id)
223
229
  self.logger.info("All client connections cleaned up")
224
-
230
+
225
231
  async def __aenter__(self):
226
232
  """Async context manager entry."""
227
233
  return self
228
-
234
+
229
235
  async def __aexit__(self, exc_type, exc_val, exc_tb):
230
236
  """Async context manager exit."""
231
237
  await self.cleanup()
@@ -234,10 +240,10 @@ class ClientManager:
234
240
  def create_client_manager(config: Dict[str, Any]) -> ClientManager:
235
241
  """
236
242
  Create a ClientManager instance.
237
-
243
+
238
244
  Args:
239
245
  config: Client manager configuration
240
-
246
+
241
247
  Returns:
242
248
  ClientManager instance
243
249
  """
@@ -252,30 +258,30 @@ async def test_client_manager():
252
258
  "max_connections": 5,
253
259
  "connection_timeout": 30,
254
260
  "retry_attempts": 3,
255
- "retry_delay": 1
261
+ "retry_delay": 1,
256
262
  }
257
-
263
+
258
264
  async with ClientManager(config) as manager:
259
265
  # Create a client
260
266
  client_id = "test_client"
261
267
  config_file = "configs/http_simple.json"
262
-
268
+
263
269
  try:
264
270
  client = await manager.create_client(client_id, config_file)
265
271
  print(f"✅ Client {client_id} created successfully")
266
-
272
+
267
273
  # Test connection
268
274
  connection_ok = await manager.test_client_connection(client_id)
269
275
  print(f"✅ Connection test: {connection_ok}")
270
-
276
+
271
277
  # Get status
272
278
  status = await manager.get_client_status(client_id)
273
279
  print(f"✅ Client status: {json.dumps(status, indent=2)}")
274
-
280
+
275
281
  # Execute command
276
282
  result = await manager.execute_command(client_id, "help")
277
283
  print(f"✅ Command result: {json.dumps(result, indent=2)}")
278
-
284
+
279
285
  except Exception as e:
280
286
  print(f"❌ Test failed: {e}")
281
287