mcp-proxy-adapter 6.0.0__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 (212) hide show
  1. mcp_proxy_adapter/__main__.py +27 -7
  2. mcp_proxy_adapter/api/app.py +209 -79
  3. mcp_proxy_adapter/api/handlers.py +16 -5
  4. mcp_proxy_adapter/api/middleware/__init__.py +14 -9
  5. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
  6. mcp_proxy_adapter/api/middleware/factory.py +36 -12
  7. mcp_proxy_adapter/api/middleware/protocol_middleware.py +84 -18
  8. mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
  9. mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
  10. mcp_proxy_adapter/commands/__init__.py +7 -1
  11. mcp_proxy_adapter/commands/base.py +7 -4
  12. mcp_proxy_adapter/commands/builtin_commands.py +8 -2
  13. mcp_proxy_adapter/commands/command_registry.py +8 -0
  14. mcp_proxy_adapter/commands/echo_command.py +81 -0
  15. mcp_proxy_adapter/commands/health_command.py +1 -1
  16. mcp_proxy_adapter/commands/help_command.py +21 -14
  17. mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
  18. mcp_proxy_adapter/commands/role_test_command.py +141 -0
  19. mcp_proxy_adapter/commands/security_command.py +488 -0
  20. mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
  21. mcp_proxy_adapter/commands/token_management_command.py +1 -1
  22. mcp_proxy_adapter/config.py +323 -40
  23. mcp_proxy_adapter/core/app_factory.py +410 -0
  24. mcp_proxy_adapter/core/app_runner.py +272 -0
  25. mcp_proxy_adapter/core/certificate_utils.py +291 -73
  26. mcp_proxy_adapter/core/client.py +574 -0
  27. mcp_proxy_adapter/core/client_manager.py +284 -0
  28. mcp_proxy_adapter/core/client_security.py +384 -0
  29. mcp_proxy_adapter/core/logging.py +8 -3
  30. mcp_proxy_adapter/core/mtls_asgi.py +156 -0
  31. mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
  32. mcp_proxy_adapter/core/protocol_manager.py +169 -10
  33. mcp_proxy_adapter/core/proxy_client.py +602 -0
  34. mcp_proxy_adapter/core/proxy_registration.py +299 -47
  35. mcp_proxy_adapter/core/security_adapter.py +12 -15
  36. mcp_proxy_adapter/core/security_integration.py +286 -0
  37. mcp_proxy_adapter/core/server_adapter.py +282 -0
  38. mcp_proxy_adapter/core/server_engine.py +270 -0
  39. mcp_proxy_adapter/core/ssl_utils.py +13 -12
  40. mcp_proxy_adapter/core/transport_manager.py +5 -5
  41. mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
  42. mcp_proxy_adapter/examples/__init__.py +13 -4
  43. mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
  44. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  45. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  46. mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
  47. mcp_proxy_adapter/examples/commands/__init__.py +5 -0
  48. mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
  49. mcp_proxy_adapter/examples/debug_request_state.py +112 -0
  50. mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
  51. mcp_proxy_adapter/examples/demo_client.py +275 -0
  52. mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
  53. mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
  54. mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
  55. mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
  56. mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
  57. mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
  58. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
  59. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  60. mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
  61. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
  62. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  63. mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
  64. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
  65. mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
  66. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  67. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
  68. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
  69. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  70. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
  71. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
  72. mcp_proxy_adapter/examples/full_application/main.py +173 -0
  73. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  74. mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
  75. mcp_proxy_adapter/examples/generate_certificates.py +177 -0
  76. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  77. mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
  78. mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
  79. mcp_proxy_adapter/examples/run_example.py +59 -0
  80. mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
  81. mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
  82. mcp_proxy_adapter/examples/run_security_tests.py +544 -0
  83. mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
  84. mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
  85. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
  86. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
  87. mcp_proxy_adapter/examples/security_test_client.py +782 -0
  88. mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
  89. mcp_proxy_adapter/examples/test_config.py +148 -0
  90. mcp_proxy_adapter/examples/test_config_generator.py +86 -0
  91. mcp_proxy_adapter/examples/test_examples.py +281 -0
  92. mcp_proxy_adapter/examples/universal_client.py +620 -0
  93. mcp_proxy_adapter/main.py +66 -148
  94. mcp_proxy_adapter/utils/config_generator.py +1008 -0
  95. mcp_proxy_adapter/version.py +5 -2
  96. mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
  97. mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
  98. mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
  99. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
  100. mcp_proxy_adapter/api/middleware/auth.py +0 -146
  101. mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
  102. mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
  103. mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
  104. mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
  105. mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
  106. mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
  107. mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
  108. mcp_proxy_adapter/api/middleware/security.py +0 -376
  109. mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
  110. mcp_proxy_adapter/examples/README.md +0 -124
  111. mcp_proxy_adapter/examples/basic_server/README.md +0 -60
  112. mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
  113. mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
  114. mcp_proxy_adapter/examples/basic_server/config.json +0 -70
  115. mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
  116. mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
  117. mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
  118. mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
  119. mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
  120. mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
  121. mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
  122. mcp_proxy_adapter/examples/basic_server/server.py +0 -114
  123. mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
  124. mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
  125. mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
  126. mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
  127. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
  128. mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
  129. mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
  130. mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
  131. mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
  132. mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
  133. mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
  134. mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
  135. mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
  136. mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
  137. mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
  138. mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
  139. mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
  140. mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
  141. mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
  142. mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
  143. mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
  144. mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
  145. mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
  146. mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
  147. mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
  148. mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
  149. mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
  150. mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
  151. mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
  152. mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
  153. mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
  154. mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
  155. mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
  156. mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
  157. mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
  158. mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
  159. mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
  160. mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
  161. mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
  162. mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
  163. mcp_proxy_adapter/examples/deployment/README.md +0 -49
  164. mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
  165. mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
  166. mcp_proxy_adapter/examples/deployment/config.json +0 -29
  167. mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
  168. mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
  169. mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
  170. mcp_proxy_adapter/examples/deployment/run.sh +0 -43
  171. mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
  172. mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
  173. mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
  174. mcp_proxy_adapter/schemas/base_schema.json +0 -114
  175. mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
  176. mcp_proxy_adapter/schemas/roles_schema.json +0 -162
  177. mcp_proxy_adapter/tests/__init__.py +0 -0
  178. mcp_proxy_adapter/tests/api/__init__.py +0 -3
  179. mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
  180. mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
  181. mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
  182. mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
  183. mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
  184. mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
  185. mcp_proxy_adapter/tests/commands/__init__.py +0 -3
  186. mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
  187. mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
  188. mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
  189. mcp_proxy_adapter/tests/conftest.py +0 -131
  190. mcp_proxy_adapter/tests/functional/__init__.py +0 -3
  191. mcp_proxy_adapter/tests/functional/test_api.py +0 -253
  192. mcp_proxy_adapter/tests/integration/__init__.py +0 -3
  193. mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
  194. mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
  195. mcp_proxy_adapter/tests/performance/__init__.py +0 -3
  196. mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
  197. mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
  198. mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
  199. mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
  200. mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
  201. mcp_proxy_adapter/tests/test_base_command.py +0 -123
  202. mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
  203. mcp_proxy_adapter/tests/test_command_registry.py +0 -281
  204. mcp_proxy_adapter/tests/test_config.py +0 -127
  205. mcp_proxy_adapter/tests/test_utils.py +0 -65
  206. mcp_proxy_adapter/tests/unit/__init__.py +0 -3
  207. mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
  208. mcp_proxy_adapter/tests/unit/test_config.py +0 -270
  209. mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
  210. mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
  211. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
  212. {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -1,278 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Proxy Connection Manager
4
-
5
- Manages connection to the proxy server with regular health checks
6
- and automatic re-registration when needed.
7
- """
8
-
9
- import asyncio
10
- import time
11
- import logging
12
- from typing import Optional, Dict, Any
13
- from datetime import datetime, timedelta
14
-
15
- from mcp_proxy_adapter.core.proxy_registration import register_with_proxy, unregister_from_proxy
16
- from mcp_proxy_adapter.config import config
17
- from mcp_proxy_adapter.core.logging import get_logger
18
-
19
-
20
- class ProxyConnectionManager:
21
- """
22
- Manages connection to proxy server with health monitoring and auto-reconnection.
23
- """
24
-
25
- def __init__(self, check_interval: int = 30, max_retries: int = 3):
26
- """
27
- Initialize proxy connection manager.
28
-
29
- Args:
30
- check_interval: Interval between health checks in seconds
31
- max_retries: Maximum number of retry attempts
32
- """
33
- self.logger = get_logger("proxy_connection_manager")
34
- self.check_interval = check_interval
35
- self.max_retries = max_retries
36
- self.is_running = False
37
- self.last_registration = None
38
- self.registration_count = 0
39
- self.failed_attempts = 0
40
- self.server_url = None
41
- self.server_id = None
42
-
43
- # Get configuration
44
- proxy_config = config.get("proxy_registration", {})
45
- self.proxy_url = proxy_config.get("proxy_url", "http://localhost:3004")
46
- self.server_id = proxy_config.get("server_id", "mcp_proxy_adapter_custom")
47
-
48
- # Get server configuration
49
- server_config = config.get("server", {})
50
- server_host = server_config.get("host", "0.0.0.0")
51
- server_port = server_config.get("port", 8000)
52
-
53
- # Use localhost for external access if host is 0.0.0.0
54
- if server_host == "0.0.0.0":
55
- server_host = "localhost"
56
-
57
- self.server_url = f"http://{server_host}:{server_port}"
58
-
59
- self.logger.info(f"Proxy Connection Manager initialized:")
60
- self.logger.info(f" • Server URL: {self.server_url}")
61
- self.logger.info(f" • Proxy URL: {self.proxy_url}")
62
- self.logger.info(f" • Server ID: {self.server_id}")
63
- self.logger.info(f" • Check interval: {check_interval}s")
64
- self.logger.info(f" • Max retries: {max_retries}")
65
-
66
- async def start(self) -> None:
67
- """
68
- Start the proxy connection manager.
69
- """
70
- if self.is_running:
71
- self.logger.warning("Proxy Connection Manager is already running")
72
- return
73
-
74
- self.is_running = True
75
- self.logger.info("🚀 Starting Proxy Connection Manager")
76
-
77
- # Initial registration
78
- await self.register_with_proxy()
79
-
80
- # Start monitoring loop
81
- asyncio.create_task(self._monitoring_loop())
82
-
83
- async def stop(self) -> None:
84
- """
85
- Stop the proxy connection manager.
86
- """
87
- if not self.is_running:
88
- return
89
-
90
- self.is_running = False
91
- self.logger.info("🛑 Stopping Proxy Connection Manager")
92
-
93
- # Unregister from proxy
94
- await self.unregister_from_proxy()
95
-
96
- async def register_with_proxy(self) -> bool:
97
- """
98
- Register server with proxy.
99
-
100
- Returns:
101
- True if registration was successful, False otherwise
102
- """
103
- try:
104
- self.logger.info(f"📡 Attempting to register server with proxy at {self.proxy_url}")
105
-
106
- success = await register_with_proxy(self.server_url)
107
-
108
- if success:
109
- self.last_registration = datetime.now()
110
- self.registration_count += 1
111
- self.failed_attempts = 0
112
- self.logger.info(f"✅ Successfully registered with proxy (attempt #{self.registration_count})")
113
- return True
114
- else:
115
- self.failed_attempts += 1
116
- self.logger.warning(f"⚠️ Failed to register with proxy (attempt #{self.failed_attempts})")
117
- return False
118
-
119
- except Exception as e:
120
- self.failed_attempts += 1
121
- self.logger.error(f"❌ Error registering with proxy: {e}")
122
- return False
123
-
124
- async def unregister_from_proxy(self) -> bool:
125
- """
126
- Unregister server from proxy.
127
-
128
- Returns:
129
- True if unregistration was successful, False otherwise
130
- """
131
- try:
132
- self.logger.info("📡 Unregistering from proxy")
133
-
134
- success = await unregister_from_proxy()
135
-
136
- if success:
137
- self.logger.info("✅ Successfully unregistered from proxy")
138
- else:
139
- self.logger.warning("⚠️ Failed to unregister from proxy")
140
-
141
- return success
142
-
143
- except Exception as e:
144
- self.logger.error(f"❌ Error unregistering from proxy: {e}")
145
- return False
146
-
147
- async def check_proxy_health(self) -> bool:
148
- """
149
- Check if proxy is accessible and server is registered.
150
-
151
- Returns:
152
- True if proxy is healthy, False otherwise
153
- """
154
- try:
155
- import httpx
156
-
157
- # Check if proxy is accessible
158
- async with httpx.AsyncClient(timeout=5.0) as client:
159
- response = await client.get(f"{self.proxy_url}/health")
160
-
161
- if response.status_code == 200:
162
- self.logger.debug("✅ Proxy health check passed")
163
- return True
164
- else:
165
- self.logger.warning(f"⚠️ Proxy health check failed: {response.status_code}")
166
- return False
167
-
168
- except Exception as e:
169
- self.logger.warning(f"⚠️ Proxy health check error: {e}")
170
- return False
171
-
172
- async def _monitoring_loop(self) -> None:
173
- """
174
- Main monitoring loop that checks proxy health and re-registers if needed.
175
- """
176
- self.logger.info("🔄 Starting proxy monitoring loop")
177
-
178
- while self.is_running:
179
- try:
180
- # Check if we need to re-register
181
- should_reregister = False
182
-
183
- # Check if last registration was too long ago (more than 5 minutes)
184
- if self.last_registration:
185
- time_since_registration = datetime.now() - self.last_registration
186
- if time_since_registration > timedelta(minutes=5):
187
- self.logger.info("⏰ Last registration was more than 5 minutes ago, re-registering")
188
- should_reregister = True
189
-
190
- # Check proxy health
191
- proxy_healthy = await self.check_proxy_health()
192
-
193
- if not proxy_healthy:
194
- self.logger.warning("⚠️ Proxy health check failed, attempting re-registration")
195
- should_reregister = True
196
-
197
- # Re-register if needed
198
- if should_reregister:
199
- if self.failed_attempts >= self.max_retries:
200
- self.logger.error(f"❌ Max retries ({self.max_retries}) reached, stopping re-registration attempts")
201
- break
202
-
203
- await self.register_with_proxy()
204
-
205
- # Log status
206
- if self.last_registration:
207
- time_since = datetime.now() - self.last_registration
208
- self.logger.info(f"📊 Status: Registered {time_since.total_seconds():.0f}s ago, "
209
- f"attempts: {self.registration_count}, "
210
- f"failed: {self.failed_attempts}")
211
-
212
- # Wait for next check
213
- await asyncio.sleep(self.check_interval)
214
-
215
- except asyncio.CancelledError:
216
- self.logger.info("🛑 Monitoring loop cancelled")
217
- break
218
- except Exception as e:
219
- self.logger.error(f"❌ Error in monitoring loop: {e}")
220
- await asyncio.sleep(self.check_interval)
221
-
222
- self.logger.info("🔄 Proxy monitoring loop stopped")
223
-
224
- def get_status(self) -> Dict[str, Any]:
225
- """
226
- Get current status of the connection manager.
227
-
228
- Returns:
229
- Dictionary with status information
230
- """
231
- status = {
232
- "is_running": self.is_running,
233
- "server_url": self.server_url,
234
- "proxy_url": self.proxy_url,
235
- "server_id": self.server_id,
236
- "registration_count": self.registration_count,
237
- "failed_attempts": self.failed_attempts,
238
- "check_interval": self.check_interval,
239
- "max_retries": self.max_retries
240
- }
241
-
242
- if self.last_registration:
243
- time_since = datetime.now() - self.last_registration
244
- status["last_registration"] = self.last_registration.isoformat()
245
- status["time_since_registration"] = time_since.total_seconds()
246
- else:
247
- status["last_registration"] = None
248
- status["time_since_registration"] = None
249
-
250
- return status
251
-
252
-
253
- # Global instance
254
- proxy_manager = ProxyConnectionManager()
255
-
256
-
257
- async def start_proxy_manager() -> None:
258
- """
259
- Start the global proxy connection manager.
260
- """
261
- await proxy_manager.start()
262
-
263
-
264
- async def stop_proxy_manager() -> None:
265
- """
266
- Stop the global proxy connection manager.
267
- """
268
- await proxy_manager.stop()
269
-
270
-
271
- def get_proxy_manager_status() -> Dict[str, Any]:
272
- """
273
- Get status of the global proxy connection manager.
274
-
275
- Returns:
276
- Dictionary with status information
277
- """
278
- return proxy_manager.get_status()
@@ -1,252 +0,0 @@
1
- """
2
- Custom Commands Server Example
3
-
4
- This example demonstrates a MCP Proxy Adapter server
5
- with custom commands: echo, custom help, and custom health.
6
- Includes hooks for before and after command processing.
7
- """
8
-
9
- import asyncio
10
- import uvicorn
11
- import sys
12
- import os
13
- sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
14
-
15
- from mcp_proxy_adapter import create_app
16
- from mcp_proxy_adapter.core.logging import get_logger, setup_logging
17
- from mcp_proxy_adapter.core.settings import (
18
- Settings,
19
- get_server_host,
20
- get_server_port,
21
- get_server_debug,
22
- get_setting,
23
- get_custom_setting_value
24
- )
25
- from mcp_proxy_adapter.core.ssl_utils import SSLUtils
26
- from mcp_proxy_adapter.core.transport_manager import transport_manager
27
- from custom_settings_manager import CustomSettingsManager, get_app_name, is_feature_enabled
28
-
29
- # Import custom commands and hooks
30
- from custom_help_command import CustomHelpCommand
31
- from custom_health_command import CustomHealthCommand
32
- from data_transform_command import DataTransformCommand
33
- from intercept_command import InterceptCommand
34
- from advanced_hooks import register_advanced_hooks
35
-
36
- # Import auto-registered commands
37
- from auto_commands.auto_echo_command import AutoEchoCommand
38
- from auto_commands.auto_info_command import AutoInfoCommand
39
-
40
- # Import manual registration example
41
- from manual_echo_command import ManualEchoCommand
42
-
43
- # Import echo command
44
- from echo_command import EchoCommand
45
-
46
- # Import custom OpenAPI generator
47
- from custom_openapi_generator import custom_openapi_generator
48
-
49
- # Import command registry for manual registration
50
- from mcp_proxy_adapter.commands.command_registry import registry
51
- from mcp_proxy_adapter.config import config
52
- from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
53
-
54
-
55
- async def initialize_commands():
56
- """
57
- Initialize commands using the unified system initialization logic.
58
- This function is used both at startup and during reload.
59
-
60
- Returns:
61
- Number of commands discovered.
62
- """
63
- # Use the unified reload method from registry
64
- result = await registry.reload_system()
65
- return result["total_commands"]
66
-
67
-
68
- def custom_commands_hook(registry):
69
- """Hook function for registering custom commands."""
70
- logger = get_logger("custom_commands")
71
- logger.info("Registering custom commands via hook...")
72
-
73
- # Get custom commands configuration from custom settings
74
- custom_commands_config = get_custom_setting_value("custom_commands", {})
75
-
76
- # Register echo command (only if not already registered)
77
- if not registry.command_exists("echo"):
78
- registry.register_custom(EchoCommand)
79
- logger.info("Registered: echo command")
80
- else:
81
- logger.debug("Command 'echo' is already registered, skipping")
82
-
83
- # Register custom help command (will override built-in)
84
- if custom_commands_config.get("help", {}).get("enabled", True):
85
- registry.register_custom(CustomHelpCommand)
86
- logger.info("Registered: custom help command")
87
-
88
- # Register custom health command (will override built-in)
89
- if custom_commands_config.get("health", {}).get("enabled", True):
90
- registry.register_custom(CustomHealthCommand)
91
- logger.info("Registered: custom health command")
92
-
93
- # Register advanced demonstration commands
94
- if custom_commands_config.get("data_transform", {}).get("enabled", True):
95
- registry.register_custom(DataTransformCommand)
96
- logger.info("Registered: data_transform command")
97
-
98
- if custom_commands_config.get("intercept", {}).get("enabled", True):
99
- registry.register_custom(InterceptCommand)
100
- logger.info("Registered: intercept command")
101
-
102
- # Register manually registered commands
103
- if custom_commands_config.get("manual_echo", {}).get("enabled", True):
104
- registry.register_custom(ManualEchoCommand)
105
- logger.info("Registered: manual_echo command")
106
-
107
- logger.info(f"Total custom commands registered: {len(registry.get_commands_by_type()['custom'])}")
108
-
109
-
110
- def setup_hooks():
111
- """Setup hooks for command processing."""
112
- logger = get_logger("custom_commands")
113
- logger.info("Setting up hooks...")
114
-
115
- # Register custom commands hook
116
- from mcp_proxy_adapter.commands.hooks import register_custom_commands_hook
117
- register_custom_commands_hook(custom_commands_hook)
118
-
119
- logger.info("Registered: custom commands hook")
120
-
121
-
122
- def main():
123
- """Run the custom commands server example with hooks."""
124
- # Load configuration from config.json in the same directory
125
- config_path = os.path.join(os.path.dirname(__file__), "config.json")
126
- if os.path.exists(config_path):
127
- from mcp_proxy_adapter.config import config
128
- config.load_from_file(config_path)
129
- print(f"✅ Loaded configuration from: {config_path}")
130
- else:
131
- print(f"⚠️ Configuration file not found: {config_path}")
132
- print(" Using default configuration")
133
- from mcp_proxy_adapter.config import config
134
- config.load_config()
135
-
136
- # Setup logging with configuration
137
- setup_logging()
138
- logger = get_logger("custom_commands")
139
-
140
- # Initialize custom settings manager
141
- custom_settings_manager = CustomSettingsManager("custom_settings.json")
142
-
143
- # Print custom settings summary
144
- custom_settings_manager.print_settings_summary()
145
-
146
- # Get settings from configuration
147
- server_settings = Settings.get_server_settings()
148
- logging_settings = Settings.get_logging_settings()
149
- commands_settings = Settings.get_commands_settings()
150
- custom_settings = Settings.get_custom_setting("custom", {})
151
-
152
- # Load transport configuration
153
- if not transport_manager.load_config(config.config_data):
154
- logger.error("Failed to load transport configuration")
155
- return
156
-
157
- # Validate transport configuration
158
- if not transport_manager.validate_config():
159
- logger.error("Transport configuration validation failed")
160
- return
161
-
162
- # Print server header and description
163
- print("=" * 80)
164
- print("🔧 ADVANCED MCP PROXY ADAPTER SERVER WITH HOOKS")
165
- print("=" * 80)
166
- print("📋 Description:")
167
- print(f" {get_app_name()} - Advanced server with custom settings management")
168
- print()
169
- # Get transport info
170
- transport_info = transport_manager.get_transport_info()
171
-
172
- print("⚙️ Configuration:")
173
- print(f" • Server: {server_settings['host']}:{transport_manager.get_port()}")
174
- print(f" • Transport: {transport_info['type']}")
175
- print(f" • Debug: {server_settings['debug']}")
176
- print(f" • Log Level: {logging_settings['level']}")
177
- print(f" • Log Directory: {logging_settings['log_dir']}")
178
- print(f" • Auto Discovery: {commands_settings['auto_discovery']}")
179
- print(f" • SSL Enabled: {transport_info['ssl_enabled']}")
180
- if transport_info['ssl_enabled']:
181
- ssl_config = transport_info['ssl_config']
182
- print(f" • SSL Cert: {ssl_config.get('cert_file', 'Not specified')}")
183
- print(f" • Client Verification: {ssl_config.get('verify_client', False)}")
184
- print()
185
- print("🔧 Available Commands:")
186
- print(" • help - Custom help command (overrides built-in)")
187
- print(" • health - Custom health command (overrides built-in)")
188
- print(" • config - Built-in config command")
189
- print(" • reload - Built-in reload command")
190
- print(" • settings - Built-in settings command")
191
- print(" • load - Built-in load command")
192
- print(" • unload - Built-in unload command")
193
- print(" • plugins - Built-in plugins command")
194
- print(" • echo - Custom echo command")
195
- print(" • data_transform - Data transformation command")
196
- print(" • intercept - Command interception example")
197
- print(" • manual_echo - Manually registered echo command")
198
- print(" • test - Remote command (loaded from plugin server)")
199
- print()
200
- print("🎯 Features:")
201
- print(" • Advanced JSON-RPC API")
202
- print(" • Custom commands with hooks")
203
- print(" • Data transformation hooks")
204
- print(" • Command interception hooks")
205
- print(" • Auto-registration and manual registration")
206
- print(" • Custom OpenAPI schema generation")
207
- print(" • Configuration-driven settings")
208
- print(" • Custom settings management")
209
- print("=" * 80)
210
- print()
211
-
212
- logger.info("Starting Advanced Custom Commands MCP Proxy Adapter Server with Hooks...")
213
- logger.info(f"Server configuration: {server_settings}")
214
- logger.info(f"Logging configuration: {logging_settings}")
215
- logger.info(f"Commands configuration: {commands_settings}")
216
- logger.info(f"Transport configuration: {transport_info}")
217
- logger.info("This server demonstrates custom commands with hooks and remote plugin loading:")
218
- logger.info("• Custom commands: echo, help, health, data_transform, intercept, manual_echo")
219
- logger.info("• Built-in commands: config, reload, settings, load, unload, plugins")
220
- logger.info("• Remote commands: test (loaded from plugin server)")
221
- logger.info("With advanced hooks for data transformation and command interception")
222
-
223
- # Setup hooks for command processing
224
- setup_hooks()
225
-
226
- # Initialize commands
227
- import asyncio
228
- asyncio.run(initialize_commands())
229
-
230
- # Create application with settings from configuration
231
- app = create_app(
232
- title=get_app_name(),
233
- description="Advanced MCP Proxy Adapter server with custom settings management, demonstrating hook capabilities including data transformation, command interception, conditional processing, and smart interception hooks. Features custom commands with enhanced functionality and comprehensive settings management.",
234
- version="2.1.0"
235
- )
236
-
237
- # Get uvicorn configuration from transport manager
238
- uvicorn_config = transport_manager.get_uvicorn_config()
239
- uvicorn_config["host"] = server_settings['host']
240
- uvicorn_config["log_level"] = server_settings['log_level'].lower()
241
-
242
- logger.info(f"Starting server with uvicorn config: {uvicorn_config}")
243
-
244
- # Run the server with configuration settings
245
- uvicorn.run(
246
- app,
247
- **uvicorn_config
248
- )
249
-
250
-
251
- if __name__ == "__main__":
252
- main()
@@ -1,75 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Simple server with fixed OpenAPI generator.
4
- """
5
-
6
- import uvicorn
7
- import asyncio
8
- import sys
9
- import os
10
- from pathlib import Path
11
-
12
- # Add current directory to path for imports
13
- sys.path.insert(0, os.getcwd())
14
-
15
- from fastapi import FastAPI
16
- from mcp_proxy_adapter.custom_openapi import CustomOpenAPIGenerator
17
- from mcp_proxy_adapter.commands.command_registry import registry
18
-
19
- # Create FastAPI app
20
- app = FastAPI(
21
- title="Extended MCP Proxy Server",
22
- description="Advanced MCP Proxy Adapter server with custom commands and hooks",
23
- version="2.1.0"
24
- )
25
-
26
- async def generate_openapi_schema():
27
- """Generate OpenAPI schema with custom commands."""
28
- # Initialize commands
29
- await registry.reload_system()
30
-
31
- # Load custom commands
32
- custom_commands = [
33
- "echo_command",
34
- "custom_help_command",
35
- "custom_health_command",
36
- "manual_echo_command"
37
- ]
38
-
39
- for cmd_name in custom_commands:
40
- try:
41
- module = __import__(cmd_name)
42
- if hasattr(module, 'EchoCommand'):
43
- registry.register_custom(module.EchoCommand())
44
- elif hasattr(module, 'CustomHelpCommand'):
45
- registry.register_custom(module.CustomHelpCommand())
46
- elif hasattr(module, 'CustomHealthCommand'):
47
- registry.register_custom(module.CustomHealthCommand())
48
- elif hasattr(module, 'ManualEchoCommand'):
49
- registry.register_custom(module.ManualEchoCommand())
50
- except Exception as e:
51
- print(f"Warning: Failed to load {cmd_name}: {e}")
52
-
53
- # Generate schema
54
- generator = CustomOpenAPIGenerator()
55
- return generator.generate(
56
- title="Extended MCP Proxy Server",
57
- description="Advanced MCP Proxy Adapter server with custom commands and hooks",
58
- version="2.1.0"
59
- )
60
-
61
- # Set custom OpenAPI generator
62
- @app.on_event("startup")
63
- async def startup_event():
64
- """Initialize OpenAPI schema on startup."""
65
- app.openapi_schema = await generate_openapi_schema()
66
-
67
- @app.get("/openapi.json")
68
- async def get_openapi_schema():
69
- """Returns OpenAPI schema."""
70
- if not hasattr(app, 'openapi_schema'):
71
- app.openapi_schema = await generate_openapi_schema()
72
- return app.openapi_schema
73
-
74
- if __name__ == "__main__":
75
- uvicorn.run(app, host="0.0.0.0", port=8000)