mcp-proxy-adapter 6.9.17__py3-none-any.whl → 6.9.18__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mcp_proxy_adapter/api/app.py +52 -52
- mcp_proxy_adapter/api/handlers.py +5 -5
- mcp_proxy_adapter/api/middleware/__init__.py +8 -8
- mcp_proxy_adapter/api/middleware/base.py +14 -14
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +7 -7
- mcp_proxy_adapter/api/middleware/error_handling.py +9 -9
- mcp_proxy_adapter/api/middleware/factory.py +17 -17
- mcp_proxy_adapter/api/middleware/logging.py +6 -6
- mcp_proxy_adapter/api/middleware/performance.py +3 -3
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +19 -19
- mcp_proxy_adapter/api/middleware/transport_middleware.py +3 -3
- mcp_proxy_adapter/api/middleware/unified_security.py +11 -11
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +21 -21
- mcp_proxy_adapter/api/tool_integration.py +3 -2
- mcp_proxy_adapter/api/tools.py +4 -3
- mcp_proxy_adapter/commands/auth_validation_command.py +6 -5
- mcp_proxy_adapter/commands/base.py +10 -10
- mcp_proxy_adapter/commands/builtin_commands.py +6 -6
- mcp_proxy_adapter/commands/catalog_manager.py +74 -74
- mcp_proxy_adapter/commands/cert_monitor_command.py +13 -12
- mcp_proxy_adapter/commands/certificate_management_command.py +20 -19
- mcp_proxy_adapter/commands/command_registry.py +68 -67
- mcp_proxy_adapter/commands/config_command.py +3 -1
- mcp_proxy_adapter/commands/dependency_manager.py +10 -10
- mcp_proxy_adapter/commands/help_command.py +21 -20
- mcp_proxy_adapter/commands/hooks.py +27 -27
- mcp_proxy_adapter/commands/key_management_command.py +19 -18
- mcp_proxy_adapter/commands/plugins_command.py +2 -1
- mcp_proxy_adapter/commands/protocol_management_command.py +6 -6
- mcp_proxy_adapter/commands/proxy_registration_command.py +9 -9
- mcp_proxy_adapter/commands/registration_status_command.py +4 -4
- mcp_proxy_adapter/commands/reload_command.py +5 -5
- mcp_proxy_adapter/commands/role_test_command.py +2 -1
- mcp_proxy_adapter/commands/roles_management_command.py +9 -8
- mcp_proxy_adapter/commands/security_command.py +3 -2
- mcp_proxy_adapter/commands/ssl_setup_command.py +7 -6
- mcp_proxy_adapter/commands/token_management_command.py +12 -11
- mcp_proxy_adapter/commands/transport_management_command.py +2 -2
- mcp_proxy_adapter/config.py +3 -3
- mcp_proxy_adapter/core/__init__.py +1 -1
- mcp_proxy_adapter/core/app_runner.py +3 -3
- mcp_proxy_adapter/core/auth_validator.py +9 -9
- mcp_proxy_adapter/core/certificate_utils.py +27 -27
- mcp_proxy_adapter/core/client_manager.py +13 -13
- mcp_proxy_adapter/core/client_security.py +26 -26
- mcp_proxy_adapter/core/config_converter.py +18 -18
- mcp_proxy_adapter/core/config_validator.py +5 -1
- mcp_proxy_adapter/core/crl_utils.py +22 -22
- mcp_proxy_adapter/core/logging.py +21 -13
- mcp_proxy_adapter/core/mtls_asgi.py +7 -7
- mcp_proxy_adapter/core/mtls_asgi_app.py +9 -9
- mcp_proxy_adapter/core/mtls_proxy.py +9 -9
- mcp_proxy_adapter/core/mtls_server.py +18 -18
- mcp_proxy_adapter/core/protocol_manager.py +29 -29
- mcp_proxy_adapter/core/proxy_registration.py +67 -67
- mcp_proxy_adapter/core/security_adapter.py +18 -18
- mcp_proxy_adapter/core/security_factory.py +16 -16
- mcp_proxy_adapter/core/security_integration.py +6 -6
- mcp_proxy_adapter/core/server_adapter.py +12 -12
- mcp_proxy_adapter/core/server_engine.py +17 -17
- mcp_proxy_adapter/core/signal_handler.py +12 -12
- mcp_proxy_adapter/core/ssl_utils.py +12 -12
- mcp_proxy_adapter/core/transport_manager.py +14 -14
- mcp_proxy_adapter/core/unified_config_adapter.py +6 -6
- mcp_proxy_adapter/core/utils.py +5 -5
- mcp_proxy_adapter/custom_openapi.py +7 -7
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +2 -2
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +6 -5
- mcp_proxy_adapter/examples/full_application/commands/echo_command.py +44 -0
- mcp_proxy_adapter/examples/full_application/commands/help_command.py +66 -0
- mcp_proxy_adapter/examples/full_application/commands/list_command.py +64 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +21 -21
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +6 -6
- mcp_proxy_adapter/examples/full_application/main.py +28 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +38 -38
- mcp_proxy_adapter/examples/test_framework_complete.py +35 -35
- mcp_proxy_adapter/examples/test_mcp_server.py +2 -2
- mcp_proxy_adapter/examples/validate_generator_compatibility.py +386 -0
- mcp_proxy_adapter/examples/validate_generator_compatibility_simple.py +248 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.9.18.dist-info/RECORD +149 -0
- mcp_proxy_adapter-6.9.17.dist-info/RECORD +0 -144
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.9.17.dist-info → mcp_proxy_adapter-6.9.18.dist-info}/top_level.txt +0 -0
@@ -19,7 +19,7 @@ sys.path.insert(0, str(project_root))
|
|
19
19
|
import aiohttp
|
20
20
|
from aiohttp import ClientTimeout, TCPConnector
|
21
21
|
import ssl
|
22
|
-
from mcp_proxy_adapter.core.logging import
|
22
|
+
from mcp_proxy_adapter.core.logging import get_global_logger
|
23
23
|
|
24
24
|
|
25
25
|
class ProxyRegistrationExample:
|
@@ -112,15 +112,15 @@ class ProxyRegistrationExample:
|
|
112
112
|
"method": "proxy_registration",
|
113
113
|
"params": {"operation": "register", **server_data},
|
114
114
|
}
|
115
|
-
|
116
|
-
|
115
|
+
get_global_logger().info(f"Testing registration for server: {server_data['server_id']}")
|
116
|
+
get_global_logger().debug(f"Request data: {json.dumps(request_data, indent=2)}")
|
117
117
|
# Make request
|
118
118
|
async with self.session.post(
|
119
119
|
f"{self.server_url}/cmd", json=request_data, headers=self._get_headers()
|
120
120
|
) as response:
|
121
121
|
result = await response.json()
|
122
|
-
|
123
|
-
|
122
|
+
get_global_logger().info(f"Response status: {response.status}")
|
123
|
+
get_global_logger().debug(f"Response: {json.dumps(result, indent=2)}")
|
124
124
|
return {
|
125
125
|
"success": response.status == 200,
|
126
126
|
"status_code": response.status,
|
@@ -128,7 +128,7 @@ class ProxyRegistrationExample:
|
|
128
128
|
"server_id": server_data["server_id"],
|
129
129
|
}
|
130
130
|
except Exception as e:
|
131
|
-
|
131
|
+
get_global_logger().error(f"Registration test failed: {e}")
|
132
132
|
return {
|
133
133
|
"success": False,
|
134
134
|
"error": str(e),
|
@@ -149,21 +149,21 @@ class ProxyRegistrationExample:
|
|
149
149
|
"method": "proxy_registration",
|
150
150
|
"params": {"operation": "discover"},
|
151
151
|
}
|
152
|
-
|
152
|
+
get_global_logger().info("Testing discovery operation")
|
153
153
|
# Make request
|
154
154
|
async with self.session.post(
|
155
155
|
f"{self.server_url}/cmd", json=request_data, headers=self._get_headers()
|
156
156
|
) as response:
|
157
157
|
result = await response.json()
|
158
|
-
|
159
|
-
|
158
|
+
get_global_logger().info(f"Response status: {response.status}")
|
159
|
+
get_global_logger().debug(f"Response: {json.dumps(result, indent=2)}")
|
160
160
|
return {
|
161
161
|
"success": response.status == 200,
|
162
162
|
"status_code": response.status,
|
163
163
|
"result": result,
|
164
164
|
}
|
165
165
|
except Exception as e:
|
166
|
-
|
166
|
+
get_global_logger().error(f"Discovery test failed: {e}")
|
167
167
|
return {"success": False, "error": str(e)}
|
168
168
|
|
169
169
|
async def test_heartbeat(self, server_key: str) -> Dict[str, Any]:
|
@@ -187,14 +187,14 @@ class ProxyRegistrationExample:
|
|
187
187
|
"status": "healthy",
|
188
188
|
},
|
189
189
|
}
|
190
|
-
|
190
|
+
get_global_logger().info(f"Testing heartbeat for server: {server_key}")
|
191
191
|
# Make request
|
192
192
|
async with self.session.post(
|
193
193
|
f"{self.server_url}/cmd", json=request_data, headers=self._get_headers()
|
194
194
|
) as response:
|
195
195
|
result = await response.json()
|
196
|
-
|
197
|
-
|
196
|
+
get_global_logger().info(f"Response status: {response.status}")
|
197
|
+
get_global_logger().debug(f"Response: {json.dumps(result, indent=2)}")
|
198
198
|
return {
|
199
199
|
"success": response.status == 200,
|
200
200
|
"status_code": response.status,
|
@@ -202,13 +202,13 @@ class ProxyRegistrationExample:
|
|
202
202
|
"server_key": server_key,
|
203
203
|
}
|
204
204
|
except Exception as e:
|
205
|
-
|
205
|
+
get_global_logger().error(f"Heartbeat test failed: {e}")
|
206
206
|
return {"success": False, "error": str(e), "server_key": server_key}
|
207
207
|
|
208
208
|
|
209
209
|
async def run_proxy_registration_example():
|
210
210
|
"""Run proxy registration example."""
|
211
|
-
|
211
|
+
get_global_logger().info("🚀 Starting proxy registration example")
|
212
212
|
# Test configurations
|
213
213
|
test_configs = [
|
214
214
|
{
|
@@ -229,9 +229,9 @@ async def run_proxy_registration_example():
|
|
229
229
|
]
|
230
230
|
results = []
|
231
231
|
for config in test_configs:
|
232
|
-
|
233
|
-
|
234
|
-
|
232
|
+
get_global_logger().info(f"\n📋 Testing: {config['name']}")
|
233
|
+
get_global_logger().info(f"Server URL: {config['server_url']}")
|
234
|
+
get_global_logger().info(f"Auth Token: {config['auth_token']}")
|
235
235
|
async with ProxyRegistrationExample(
|
236
236
|
config["server_url"], config["auth_token"]
|
237
237
|
) as client:
|
@@ -263,7 +263,7 @@ async def run_proxy_registration_example():
|
|
263
263
|
{"test": f"{config['name']} - Discovery", **discovery_result}
|
264
264
|
)
|
265
265
|
# Test without authentication
|
266
|
-
|
266
|
+
get_global_logger().info(f"\n📋 Testing: No Authentication")
|
267
267
|
async with ProxyRegistrationExample("http://localhost:8002") as client:
|
268
268
|
for server_data in client.test_servers:
|
269
269
|
result = await client.test_registration(server_data)
|
@@ -275,40 +275,40 @@ async def run_proxy_registration_example():
|
|
275
275
|
}
|
276
276
|
)
|
277
277
|
# Print results
|
278
|
-
|
279
|
-
|
280
|
-
|
278
|
+
get_global_logger().info("\n" + "=" * 80)
|
279
|
+
get_global_logger().info("📊 EXAMPLE RESULTS")
|
280
|
+
get_global_logger().info("=" * 80)
|
281
281
|
passed = 0
|
282
282
|
failed = 0
|
283
283
|
for result in results:
|
284
284
|
status = "✅ PASS" if result["success"] else "❌ FAIL"
|
285
|
-
|
285
|
+
get_global_logger().info(f"{status} {result['test']}")
|
286
286
|
if result["success"]:
|
287
287
|
passed += 1
|
288
288
|
else:
|
289
289
|
failed += 1
|
290
290
|
if "error" in result:
|
291
|
-
|
291
|
+
get_global_logger().error(f" Error: {result['error']}")
|
292
292
|
elif "result" in result:
|
293
293
|
result_data = result["result"]
|
294
294
|
if "error" in result_data:
|
295
|
-
|
295
|
+
get_global_logger().error(f" API Error: {result_data['error']}")
|
296
296
|
elif "result" in result_data:
|
297
297
|
api_result = result_data["result"]
|
298
298
|
if "server_key" in api_result:
|
299
|
-
|
299
|
+
get_global_logger().info(f" Server Key: {api_result['server_key']}")
|
300
300
|
if "message" in api_result:
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
301
|
+
get_global_logger().info(f" Message: {api_result['message']}")
|
302
|
+
get_global_logger().info("\n" + "=" * 80)
|
303
|
+
get_global_logger().info(f"📈 SUMMARY: {passed} passed, {failed} failed")
|
304
|
+
get_global_logger().info("=" * 80)
|
305
305
|
return passed, failed
|
306
306
|
|
307
307
|
|
308
308
|
def main():
|
309
309
|
"""Main function for the example."""
|
310
|
-
|
311
|
-
|
310
|
+
get_global_logger().info("🔧 MCP Proxy Adapter - Proxy Registration Example")
|
311
|
+
get_global_logger().info("=" * 60)
|
312
312
|
# Check if server is running
|
313
313
|
import socket
|
314
314
|
|
@@ -316,15 +316,15 @@ def main():
|
|
316
316
|
result = sock.connect_ex(("localhost", 8002))
|
317
317
|
sock.close()
|
318
318
|
if result != 0:
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
319
|
+
get_global_logger().error("❌ Server is not running on localhost:8002")
|
320
|
+
get_global_logger().info("💡 Please start the server first:")
|
321
|
+
get_global_logger().info(" cd mcp_proxy_adapter/examples")
|
322
|
+
get_global_logger().info(
|
323
323
|
" python -m mcp_proxy_adapter.main --config server_configs/config_proxy_registration.json"
|
324
324
|
)
|
325
325
|
sys.exit(1)
|
326
|
-
|
327
|
-
|
326
|
+
get_global_logger().info("✅ Server is running on localhost:8002")
|
327
|
+
get_global_logger().info("🚀 Starting proxy registration example...")
|
328
328
|
# Run example
|
329
329
|
passed, failed = asyncio.run(run_proxy_registration_example())
|
330
330
|
# Exit with appropriate code
|
@@ -32,8 +32,8 @@ class FrameworkTester:
|
|
32
32
|
|
33
33
|
async def test_all_protocols(self):
|
34
34
|
"""Test all protocols with real MCP server registration."""
|
35
|
-
|
36
|
-
|
35
|
+
get_global_logger().info("🧪 Starting Complete Framework Testing")
|
36
|
+
get_global_logger().info("=" * 60)
|
37
37
|
|
38
38
|
# Test configurations
|
39
39
|
test_configs = [
|
@@ -43,8 +43,8 @@ class FrameworkTester:
|
|
43
43
|
]
|
44
44
|
|
45
45
|
for config_file, protocol, port in test_configs:
|
46
|
-
|
47
|
-
|
46
|
+
get_global_logger().info(f"\n🔧 Testing {protocol} (port {port})")
|
47
|
+
get_global_logger().info("-" * 40)
|
48
48
|
|
49
49
|
try:
|
50
50
|
# Start proxy adapter server
|
@@ -68,10 +68,10 @@ class FrameworkTester:
|
|
68
68
|
proxy_process.terminate()
|
69
69
|
await asyncio.sleep(1)
|
70
70
|
|
71
|
-
|
71
|
+
get_global_logger().info(f"✅ {protocol} testing completed successfully")
|
72
72
|
|
73
73
|
except Exception as e:
|
74
|
-
|
74
|
+
get_global_logger().error(f"❌ {protocol} testing failed: {e}")
|
75
75
|
self.test_results.append({
|
76
76
|
"protocol": protocol,
|
77
77
|
"status": "failed",
|
@@ -86,10 +86,10 @@ class FrameworkTester:
|
|
86
86
|
config_path = self.configs_dir / config_file
|
87
87
|
|
88
88
|
if not config_path.exists():
|
89
|
-
|
89
|
+
get_global_logger().error(f"❌ Config file not found: {config_path}")
|
90
90
|
return None
|
91
91
|
|
92
|
-
|
92
|
+
get_global_logger().info(f"🚀 Starting proxy server with {config_file}")
|
93
93
|
|
94
94
|
try:
|
95
95
|
# Start server in background
|
@@ -102,12 +102,12 @@ class FrameworkTester:
|
|
102
102
|
return process
|
103
103
|
|
104
104
|
except Exception as e:
|
105
|
-
|
105
|
+
get_global_logger().error(f"❌ Failed to start server: {e}")
|
106
106
|
return None
|
107
107
|
|
108
108
|
async def _test_server_registration(self, protocol: str, port: int):
|
109
109
|
"""Test MCP server registration."""
|
110
|
-
|
110
|
+
get_global_logger().info(f"📝 Testing server registration for {protocol}")
|
111
111
|
|
112
112
|
base_url = f"http://localhost:{port}" if protocol == "HTTP" else f"https://localhost:{port}"
|
113
113
|
|
@@ -135,17 +135,17 @@ class FrameworkTester:
|
|
135
135
|
)
|
136
136
|
|
137
137
|
if response.status_code == 200:
|
138
|
-
|
138
|
+
get_global_logger().info("✅ Server registration successful")
|
139
139
|
else:
|
140
|
-
|
140
|
+
get_global_logger().warning(f"⚠️ Registration returned status {response.status_code}")
|
141
141
|
|
142
142
|
except Exception as e:
|
143
|
-
|
143
|
+
get_global_logger().error(f"❌ Registration failed: {e}")
|
144
144
|
raise
|
145
145
|
|
146
146
|
async def _test_mcp_communication(self, protocol: str, port: int):
|
147
147
|
"""Test MCP communication through proxy."""
|
148
|
-
|
148
|
+
get_global_logger().info(f"🔗 Testing MCP communication for {protocol}")
|
149
149
|
|
150
150
|
base_url = f"http://localhost:{port}" if protocol == "HTTP" else f"https://localhost:{port}"
|
151
151
|
|
@@ -175,19 +175,19 @@ class FrameworkTester:
|
|
175
175
|
if response.status_code == 200:
|
176
176
|
result = response.json()
|
177
177
|
if "result" in result:
|
178
|
-
|
178
|
+
get_global_logger().info("✅ MCP communication successful")
|
179
179
|
else:
|
180
|
-
|
180
|
+
get_global_logger().warning(f"⚠️ MCP response: {result}")
|
181
181
|
else:
|
182
|
-
|
182
|
+
get_global_logger().warning(f"⚠️ MCP call returned status {response.status_code}")
|
183
183
|
|
184
184
|
except Exception as e:
|
185
|
-
|
185
|
+
get_global_logger().error(f"❌ MCP communication failed: {e}")
|
186
186
|
raise
|
187
187
|
|
188
188
|
async def _test_security_features(self, protocol: str, port: int):
|
189
189
|
"""Test security features."""
|
190
|
-
|
190
|
+
get_global_logger().info(f"🔒 Testing security features for {protocol}")
|
191
191
|
|
192
192
|
base_url = f"http://localhost:{port}" if protocol == "HTTP" else f"https://localhost:{port}"
|
193
193
|
|
@@ -206,43 +206,43 @@ class FrameworkTester:
|
|
206
206
|
)
|
207
207
|
|
208
208
|
if response.status_code == 200:
|
209
|
-
|
209
|
+
get_global_logger().info("✅ Health check successful")
|
210
210
|
else:
|
211
|
-
|
211
|
+
get_global_logger().warning(f"⚠️ Health check returned status {response.status_code}")
|
212
212
|
|
213
213
|
except Exception as e:
|
214
|
-
|
214
|
+
get_global_logger().error(f"❌ Security test failed: {e}")
|
215
215
|
raise
|
216
216
|
|
217
217
|
def _print_summary(self):
|
218
218
|
"""Print test summary."""
|
219
|
-
|
220
|
-
|
221
|
-
|
219
|
+
get_global_logger().info("\n" + "=" * 60)
|
220
|
+
get_global_logger().info("📊 FRAMEWORK TESTING SUMMARY")
|
221
|
+
get_global_logger().info("=" * 60)
|
222
222
|
|
223
223
|
total_tests = len(self.test_results)
|
224
224
|
successful_tests = len([r for r in self.test_results if r["status"] == "success"])
|
225
225
|
|
226
|
-
|
227
|
-
|
228
|
-
|
226
|
+
get_global_logger().info(f"Total tests: {total_tests}")
|
227
|
+
get_global_logger().info(f"Successful: {successful_tests}")
|
228
|
+
get_global_logger().info(f"Failed: {total_tests - successful_tests}")
|
229
229
|
|
230
230
|
if total_tests > 0:
|
231
231
|
success_rate = (successful_tests / total_tests) * 100
|
232
|
-
|
232
|
+
get_global_logger().info(f"Success rate: {success_rate:.1f}%")
|
233
233
|
|
234
234
|
if success_rate == 100:
|
235
|
-
|
235
|
+
get_global_logger().info("🎉 All tests passed! Framework is working correctly.")
|
236
236
|
elif success_rate >= 80:
|
237
|
-
|
237
|
+
get_global_logger().info("✅ Most tests passed. Framework is mostly functional.")
|
238
238
|
else:
|
239
|
-
|
239
|
+
get_global_logger().info("⚠️ Many tests failed. Framework needs attention.")
|
240
240
|
|
241
|
-
|
241
|
+
get_global_logger().info("=" * 60)
|
242
242
|
|
243
243
|
async def cleanup(self):
|
244
244
|
"""Cleanup server processes."""
|
245
|
-
|
245
|
+
get_global_logger().info("🧹 Cleaning up server processes...")
|
246
246
|
|
247
247
|
for process in self.server_processes:
|
248
248
|
try:
|
@@ -252,7 +252,7 @@ class FrameworkTester:
|
|
252
252
|
except subprocess.TimeoutExpired:
|
253
253
|
process.kill()
|
254
254
|
except Exception as e:
|
255
|
-
|
255
|
+
get_global_logger().warning(f"Warning: Failed to cleanup process: {e}")
|
256
256
|
|
257
257
|
self.server_processes.clear()
|
258
258
|
|
@@ -77,7 +77,7 @@ class TestMCPServer:
|
|
77
77
|
@self.server.call_tool()
|
78
78
|
async def call_tool(name: str, arguments: Dict[str, Any]) -> List[types.TextContent]:
|
79
79
|
"""Handle tool calls."""
|
80
|
-
|
80
|
+
get_global_logger().info(f"Tool called: {name} with args: {arguments}")
|
81
81
|
|
82
82
|
if name == "echo":
|
83
83
|
message = arguments.get("message", "")
|
@@ -173,7 +173,7 @@ class TestMCPServer:
|
|
173
173
|
|
174
174
|
async def main():
|
175
175
|
"""Main server function."""
|
176
|
-
|
176
|
+
get_global_logger().info("Starting Test MCP Server...")
|
177
177
|
|
178
178
|
server_instance = TestMCPServer()
|
179
179
|
|