mcp-proxy-adapter 6.4.43__py3-none-any.whl → 6.4.45__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 (33) hide show
  1. mcp_proxy_adapter/core/proxy_registration.py +100 -68
  2. mcp_proxy_adapter/examples/bugfix_certificate_config.py +284 -0
  3. mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
  4. mcp_proxy_adapter/examples/config_builder.py +574 -0
  5. mcp_proxy_adapter/examples/config_cli.py +283 -0
  6. mcp_proxy_adapter/examples/create_test_configs.py +169 -266
  7. mcp_proxy_adapter/examples/generate_certificates_bugfix.py +374 -0
  8. mcp_proxy_adapter/examples/generate_certificates_cli.py +406 -0
  9. mcp_proxy_adapter/examples/generate_certificates_fixed.py +313 -0
  10. mcp_proxy_adapter/examples/generate_certificates_framework.py +366 -0
  11. mcp_proxy_adapter/examples/generate_certificates_openssl.py +391 -0
  12. mcp_proxy_adapter/examples/required_certificates.py +210 -0
  13. mcp_proxy_adapter/examples/run_full_test_suite.py +117 -13
  14. mcp_proxy_adapter/examples/run_security_tests_fixed.py +41 -25
  15. mcp_proxy_adapter/examples/security_test_client.py +333 -86
  16. mcp_proxy_adapter/examples/test_config_builder.py +450 -0
  17. mcp_proxy_adapter/examples/update_config_certificates.py +136 -0
  18. mcp_proxy_adapter/version.py +1 -1
  19. {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/METADATA +81 -1
  20. {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/RECORD +23 -20
  21. mcp_proxy_adapter-6.4.45.dist-info/entry_points.txt +12 -0
  22. mcp_proxy_adapter/examples/create_certificates_simple.py +0 -661
  23. mcp_proxy_adapter/examples/generate_certificates.py +0 -192
  24. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +0 -515
  25. mcp_proxy_adapter/examples/generate_test_configs.py +0 -393
  26. mcp_proxy_adapter/examples/run_security_tests.py +0 -677
  27. mcp_proxy_adapter/examples/scripts/config_generator.py +0 -842
  28. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +0 -673
  29. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +0 -515
  30. mcp_proxy_adapter/examples/test_config_generator.py +0 -102
  31. mcp_proxy_adapter-6.4.43.dist-info/entry_points.txt +0 -2
  32. {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/WHEEL +0 -0
  33. {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/top_level.txt +0 -0
@@ -1,317 +1,220 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  Test Configuration Generator
4
- Creates test configurations by copying the comprehensive config and enabling/disabling specific options.
4
+ Creates test configurations using the advanced ConfigBuilder utility.
5
5
  Author: Vasiliy Zdanovskiy
6
6
  email: vasilyvz@gmail.com
7
7
  """
8
8
  import json
9
- import shutil
10
9
  import uuid
11
10
  from pathlib import Path
12
11
  from typing import Dict, Any, Optional
13
12
 
13
+ from config_builder import ConfigBuilder, ConfigFactory, Protocol, AuthMethod
14
+
14
15
 
15
16
  class TestConfigGenerator:
16
- """Generator for test configurations based on comprehensive config."""
17
+ """Generator for test configurations using ConfigBuilder."""
17
18
 
18
- def __init__(self, comprehensive_config_path: str, output_dir: str = "configs"):
19
+ def __init__(self, output_dir: str = "configs"):
19
20
  """
20
21
  Initialize the generator.
21
22
 
22
23
  Args:
23
- comprehensive_config_path: Path to the comprehensive configuration file
24
24
  output_dir: Directory to output test configurations
25
25
  """
26
- self.comprehensive_config_path = Path(comprehensive_config_path)
27
26
  self.output_dir = Path(output_dir)
28
27
  self.output_dir.mkdir(exist_ok=True)
29
28
 
30
- # Load the comprehensive config
31
- with open(self.comprehensive_config_path, 'r', encoding='utf-8') as f:
32
- self.base_config = json.load(f)
33
-
34
- def create_config(self, name: str, modifications: Dict[str, Any]) -> Path:
35
- """
36
- Create a test configuration with specific modifications.
37
-
38
- Args:
39
- name: Name of the configuration (without .json extension)
40
- modifications: Dictionary of modifications to apply
41
-
42
- Returns:
43
- Path to the created configuration file
44
- """
45
- # Deep copy the base config
46
- config = json.loads(json.dumps(self.base_config))
47
-
48
- # Add UUID if not present
49
- if "uuid" not in config:
50
- config["uuid"] = str(uuid.uuid4())
51
-
52
- # Apply modifications
53
- for key, value in modifications.items():
54
- self._set_nested_value(config, key, value)
55
-
56
- # Save the configuration
29
+ def _save_config(self, name: str, config: Dict[str, Any]) -> Path:
30
+ """Save configuration to file."""
57
31
  output_path = self.output_dir / f"{name}.json"
58
32
  with open(output_path, 'w', encoding='utf-8') as f:
59
33
  json.dump(config, f, indent=2, ensure_ascii=False)
60
-
61
34
  print(f"✅ Created test config: {output_path}")
62
35
  return output_path
63
36
 
64
- def _set_nested_value(self, config: Dict, key: str, value: Any):
65
- """Set a nested value in the configuration using dot notation."""
66
- keys = key.split('.')
67
- current = config
68
-
69
- for k in keys[:-1]:
70
- if k not in current:
71
- current[k] = {}
72
- current = current[k]
73
-
74
- current[keys[-1]] = value
75
-
76
37
  def create_all_test_configs(self):
77
- """Create all standard test configurations."""
78
- print("🔧 Creating test configurations from comprehensive config...")
38
+ """Create all standard test configurations using ConfigFactory."""
39
+ print("🔧 Creating test configurations using ConfigBuilder...")
79
40
 
80
- # 1. HTTP Simple
81
- self.create_config("http_simple", {
82
- "server.port": 20020, # Dedicated port for basic_http
83
- "ssl.enabled": False,
84
- "security.enabled": False,
85
- "proxy_registration.enabled": False,
86
- "protocols.allowed_protocols": ["http"],
87
- "protocols.default_protocol": "http"
88
- })
41
+ # Create output directory
42
+ self.output_dir.mkdir(exist_ok=True)
89
43
 
90
- # 2. HTTP with Auth (renamed to http_token for security tests)
91
- self.create_config("http_token", {
92
- "server.port": 20021, # Dedicated port for http_token
93
- "ssl.enabled": False,
94
- "security.enabled": True,
95
- "security.auth.enabled": True,
96
- "security.auth.methods": ["api_key"],
97
- "security.auth.api_keys": {
98
- "admin": "admin-secret-key",
99
- "user": "user-secret-key"
100
- },
101
- "proxy_registration.enabled": True,
102
- "proxy_registration.auth_method": "token",
103
- "proxy_registration.server_url": "https://127.0.0.1:20005/register",
104
- "proxy_registration.proxy_url": "https://127.0.0.1:20005",
105
- "proxy_registration.server_id": "http_token_server",
106
- "proxy_registration.server_name": "HTTP Token Server",
107
- "proxy_registration.description": "HTTP server with token authentication",
108
- "proxy_registration.version": "1.0.0",
109
- "proxy_registration.token.enabled": True,
110
- "proxy_registration.token.token": "http_token_123",
111
- "proxy_registration.heartbeat.enabled": True,
112
- "proxy_registration.heartbeat.interval": 30,
113
- "proxy_registration.heartbeat.timeout": 10,
114
- "proxy_registration.heartbeat.retry_attempts": 3,
115
- "proxy_registration.heartbeat.retry_delay": 5,
116
- "protocols.allowed_protocols": ["http"],
117
- "protocols.default_protocol": "http"
118
- })
44
+ # 1. HTTP Simple
45
+ config = ConfigFactory.create_http_simple(port=20020, log_dir=str(self.output_dir.parent / "logs"))
46
+ self._save_config("http_simple", config)
119
47
 
120
- # 3. HTTPS with Auth (renamed to https_token for security tests)
121
- self.create_config("https_token", {
122
- "server.port": 20023, # Dedicated port for https_token
123
- "ssl.enabled": True,
124
- "ssl.cert_file": "certs/mcp_proxy_adapter_server.crt",
125
- "ssl.key_file": "certs/mcp_proxy_adapter_server.key",
126
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
127
- "security.enabled": True,
128
- "security.auth.enabled": True,
129
- "security.auth.methods": ["api_key"],
130
- "security.auth.api_keys": {
48
+ # 2. HTTP with Token Auth
49
+ api_keys = {
131
50
  "admin": "admin-secret-key",
132
51
  "user": "user-secret-key"
133
- },
134
- "proxy_registration.enabled": True,
135
- "proxy_registration.auth_method": "token",
136
- "proxy_registration.server_url": "https://127.0.0.1:20005/register",
137
- "proxy_registration.proxy_url": "https://127.0.0.1:20005",
138
- "proxy_registration.server_id": "https_token_server",
139
- "proxy_registration.server_name": "HTTPS Token Server",
140
- "proxy_registration.description": "HTTPS server with token authentication",
141
- "proxy_registration.version": "1.0.0",
142
- "proxy_registration.token.enabled": True,
143
- "proxy_registration.token.token": "https_token_123",
144
- "proxy_registration.heartbeat.enabled": True,
145
- "proxy_registration.heartbeat.interval": 30,
146
- "proxy_registration.heartbeat.timeout": 10,
147
- "proxy_registration.heartbeat.retry_attempts": 3,
148
- "proxy_registration.heartbeat.retry_delay": 5,
149
- "protocols.allowed_protocols": ["https"],
150
- "protocols.default_protocol": "https"
151
- })
152
-
153
- # 4. HTTPS Simple (without auth)
154
- self.create_config("https_simple", {
155
- "server.port": 20022, # Dedicated port for https_simple
156
- "ssl.enabled": True,
157
- "ssl.cert_file": "certs/mcp_proxy_adapter_server.crt",
158
- "ssl.key_file": "certs/mcp_proxy_adapter_server.key",
159
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
160
- "security.enabled": False,
161
- "proxy_registration.enabled": False,
162
- "protocols.allowed_protocols": ["https"],
163
- "protocols.default_protocol": "https"
164
- })
52
+ }
53
+ config = ConfigFactory.create_http_token(port=20021, log_dir=str(self.output_dir.parent / "logs"), api_keys=api_keys)
54
+ self._save_config("http_token", config)
55
+
56
+ # 3. HTTPS Simple
57
+ config = ConfigFactory.create_https_simple(
58
+ port=20022,
59
+ log_dir=str(self.output_dir.parent / "logs"),
60
+ cert_dir=str(self.output_dir.parent / "certs"),
61
+ key_dir=str(self.output_dir.parent / "keys")
62
+ )
63
+ self._save_config("https_simple", config)
64
+
65
+ # 4. HTTPS with Token Auth
66
+ config = ConfigFactory.create_https_token(
67
+ port=20023,
68
+ log_dir=str(self.output_dir.parent / "logs"),
69
+ cert_dir=str(self.output_dir.parent / "certs"),
70
+ key_dir=str(self.output_dir.parent / "keys"),
71
+ api_keys=api_keys
72
+ )
73
+ self._save_config("https_token", config)
165
74
 
166
75
  # 5. mTLS Simple
167
- self.create_config("mtls_simple", {
168
- "server.port": 20025, # Different port for mtls_simple
169
- "ssl.enabled": True,
170
- "ssl.cert_file": "certs/localhost_server.crt",
171
- "ssl.key_file": "keys/server_key.pem",
172
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
173
- "ssl.verify_client": True,
174
- "security.enabled": True,
175
- "security.auth.enabled": True,
176
- "security.auth.methods": ["certificate"],
177
- "proxy_registration.enabled": False,
178
- "protocols.allowed_protocols": ["https", "mtls"],
179
- "protocols.default_protocol": "mtls"
180
- })
76
+ config = ConfigFactory.create_mtls_simple(
77
+ port=20024,
78
+ log_dir=str(self.output_dir.parent / "logs"),
79
+ cert_dir=str(self.output_dir.parent / "certs"),
80
+ key_dir=str(self.output_dir.parent / "keys")
81
+ )
82
+ self._save_config("mtls_simple", config)
181
83
 
182
84
  # 6. mTLS with Roles
183
- self.create_config("mtls_with_roles", {
184
- "server.port": 20026, # Different port for mtls_with_roles
185
- "ssl.enabled": True,
186
- "ssl.cert_file": "certs/localhost_server.crt",
187
- "ssl.key_file": "keys/server_key.pem",
188
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
189
- "ssl.verify_client": True,
190
- "security.enabled": True,
191
- "security.auth.enabled": True,
192
- "security.auth.methods": ["certificate"],
193
- "security.permissions.enabled": True,
194
- "security.permissions.roles_file": "configs/roles.json",
195
- "proxy_registration.enabled": False,
196
- "protocols.allowed_protocols": ["https", "mtls"],
197
- "protocols.default_protocol": "mtls"
198
- })
199
-
200
- # 6a. mTLS without Roles (for security tests)
201
- self.create_config("mtls_no_roles", {
202
- "server.port": 20024, # Dedicated port for mtls
203
- "ssl.enabled": True,
204
- "ssl.cert_file": "certs/localhost_server.crt",
205
- "ssl.key_file": "keys/server_key.pem",
206
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
207
- "ssl.verify_client": True,
208
- "security.enabled": True,
209
- "security.auth.enabled": True,
210
- "security.auth.methods": ["certificate"],
211
- "security.permissions.enabled": False,
212
- "proxy_registration.enabled": False,
213
- "protocols.allowed_protocols": ["https", "mtls"],
214
- "protocols.default_protocol": "mtls"
215
- })
85
+ roles = {
86
+ "admin": ["read", "write", "delete", "admin"],
87
+ "user": ["read", "write"],
88
+ "guest": ["read"]
89
+ }
90
+ config = ConfigFactory.create_mtls_with_roles(
91
+ port=20025,
92
+ log_dir=str(self.output_dir.parent / "logs"),
93
+ cert_dir=str(self.output_dir.parent / "certs"),
94
+ key_dir=str(self.output_dir.parent / "keys"),
95
+ roles=roles
96
+ )
97
+ self._save_config("mtls_with_roles", config)
216
98
 
217
99
  # 7. mTLS with Proxy Registration
218
- self.create_config("mtls_with_proxy", {
219
- "server.port": 8007,
220
- "ssl.enabled": True,
221
- "ssl.cert_file": "certs/localhost_server.crt",
222
- "ssl.key_file": "keys/localhost_server.key",
223
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
224
- "ssl.verify_client": True,
225
- "security.enabled": True,
226
- "security.auth.enabled": True,
227
- "security.auth.methods": ["certificate"],
228
- "proxy_registration.enabled": True,
229
- "proxy_registration.proxy_url": "http://127.0.0.1:3006",
230
- "proxy_registration.server_id": "mcp_test_server",
231
- "proxy_registration.server_name": "MCP Test Server",
232
- "protocols.allowed_protocols": ["https", "mtls"]
233
- })
234
-
235
- # 8. HTTP with Token Auth (for security tests) - REMOVED DUPLICATE
236
- # This is already created above with correct port 20021
237
-
238
- # 9. HTTPS with Token Auth (for security tests) - REMOVED DUPLICATE
239
- # This is already created above with correct port 20023
240
-
241
- # 10. Full Featured (everything enabled)
242
- self.create_config("full_featured", {
243
- "server.port": 8008,
244
- "ssl.enabled": True,
245
- "ssl.cert_file": "certs/localhost_server.crt",
246
- "ssl.key_file": "keys/localhost_server.key",
247
- "ssl.ca_cert": "certs/mcp_proxy_adapter_ca_ca.crt",
248
- "ssl.verify_client": True,
249
- "security.enabled": True,
250
- "security.auth.enabled": True,
251
- "security.auth.methods": ["certificate", "api_key"],
252
- "security.auth.api_keys": {
253
- "admin": "admin-secret-key",
254
- "user": "user-secret-key"
100
+ config = ConfigFactory.create_mtls_with_proxy(
101
+ port=20026,
102
+ log_dir=str(self.output_dir.parent / "logs"),
103
+ cert_dir=str(self.output_dir.parent / "certs"),
104
+ key_dir=str(self.output_dir.parent / "keys"),
105
+ proxy_url="https://127.0.0.1:20005",
106
+ server_id="mcp_test_server"
107
+ )
108
+ self._save_config("mtls_with_proxy", config)
109
+
110
+ # 8. Full Featured Configuration
111
+ config = ConfigFactory.create_full_featured(
112
+ port=20027,
113
+ log_dir=str(self.output_dir.parent / "logs"),
114
+ cert_dir=str(self.output_dir.parent / "certs"),
115
+ key_dir=str(self.output_dir.parent / "keys"),
116
+ proxy_url="https://127.0.0.1:20005",
117
+ server_id="mcp_full_server"
118
+ )
119
+ self._save_config("full_featured", config)
120
+
121
+ # 9. Additional configurations for comprehensive testing
122
+
123
+ # mTLS No Roles (for testing without role-based access)
124
+ config = ConfigFactory.create_mtls_simple(
125
+ port=20028,
126
+ log_dir=str(self.output_dir.parent / "logs"),
127
+ cert_dir=str(self.output_dir.parent / "certs"),
128
+ key_dir=str(self.output_dir.parent / "keys")
129
+ )
130
+ self._save_config("mtls_no_roles", config)
131
+
132
+ print(f"✅ Created {len(list(self.output_dir.glob('*.json')))} test configurations in {self.output_dir}/")
133
+
134
+ # Create roles.json file for role-based configurations
135
+ self._create_roles_file(roles)
136
+
137
+ def _create_roles_file(self, roles: Dict[str, list]):
138
+ """Create roles.json file for role-based access control."""
139
+ roles_config = {
140
+ "enabled": True,
141
+ "default_policy": {
142
+ "deny_by_default": False,
143
+ "require_role_match": False,
144
+ "case_sensitive": False,
145
+ "allow_wildcard": False
255
146
  },
256
- "security.permissions.enabled": True,
257
- "security.permissions.roles_file": "configs/roles.json",
258
- "security.rate_limit.enabled": True,
259
- "proxy_registration.enabled": True,
260
- "proxy_registration.proxy_url": "http://127.0.0.1:3006",
261
- "proxy_registration.server_id": "mcp_full_server",
262
- "proxy_registration.server_name": "MCP Full Featured Server",
263
- "protocols.allowed_protocols": ["http", "https", "mtls", "jsonrpc"]
264
- })
147
+ "roles": roles,
148
+ "permissions": {
149
+ "read": ["GET"],
150
+ "write": ["POST", "PUT", "PATCH"],
151
+ "delete": ["DELETE"],
152
+ "admin": ["*"]
153
+ }
154
+ }
265
155
 
266
- print(f"✅ Created {10} test configurations in {self.output_dir}")
156
+ roles_path = self.output_dir / "roles.json"
157
+ with open(roles_path, 'w', encoding='utf-8') as f:
158
+ json.dump(roles_config, f, indent=2, ensure_ascii=False)
159
+ print(f"✅ Created roles.json: {roles_path}")
160
+
161
+ def create_custom_config(self, name: str, protocol: str, auth: str = "none",
162
+ port: int = 8000, **kwargs) -> Path:
163
+ """
164
+ Create a custom configuration.
165
+
166
+ Args:
167
+ name: Configuration name
168
+ protocol: Protocol (http, https, mtls)
169
+ auth: Authentication method (none, token, basic)
170
+ port: Server port
171
+ **kwargs: Additional configuration parameters
172
+
173
+ Returns:
174
+ Path to created configuration file
175
+ """
176
+ builder = ConfigBuilder()
177
+
178
+ # Set basic server configuration
179
+ builder.set_server(port=port, **kwargs.get('server', {}))
180
+
181
+ # Set protocol
182
+ protocol_enum = Protocol(protocol.lower())
183
+ cert_dir = kwargs.get('cert_dir', str(self.output_dir.parent / "certs"))
184
+ key_dir = kwargs.get('key_dir', str(self.output_dir.parent / "keys"))
185
+ builder.set_protocol(protocol_enum, cert_dir=cert_dir, key_dir=key_dir)
186
+
187
+ # Set authentication
188
+ auth_enum = AuthMethod(auth.lower())
189
+ api_keys = kwargs.get('api_keys')
190
+ roles = kwargs.get('roles')
191
+ builder.set_auth(auth_enum, api_keys=api_keys, roles=roles)
192
+
193
+ # Set proxy registration if specified
194
+ if kwargs.get('proxy_registration', False):
195
+ proxy_url = kwargs.get('proxy_url', 'https://127.0.0.1:20005')
196
+ server_id = kwargs.get('server_id', f'{name}_server')
197
+ builder.set_proxy_registration(enabled=True, proxy_url=proxy_url, server_id=server_id, cert_dir=cert_dir)
198
+
199
+ # Set debug if specified
200
+ if kwargs.get('debug', False):
201
+ builder.set_debug(enabled=True)
202
+
203
+ config = builder.build()
204
+ return self._save_config(name, config)
267
205
 
268
206
 
269
207
  def main():
270
- """Main entry point."""
271
- import argparse
272
-
273
- parser = argparse.ArgumentParser(description="Generate test configurations")
274
- parser.add_argument(
275
- "--comprehensive-config",
276
- default="comprehensive_config.json",
277
- help="Path to comprehensive configuration file"
278
- )
279
- parser.add_argument(
280
- "--output-dir",
281
- default="configs",
282
- help="Output directory for test configurations"
283
- )
284
- parser.add_argument(
285
- "--config-name",
286
- help="Create a specific configuration (http_simple, https_auth, mtls_with_roles, etc.)"
287
- )
288
- parser.add_argument(
289
- "--modifications",
290
- help="JSON string of modifications to apply (for custom configs)"
291
- )
292
-
293
- args = parser.parse_args()
208
+ """Main function to create all test configurations."""
209
+ print("🔧 Creating Test Configurations")
210
+ print("=" * 40)
294
211
 
295
- generator = TestConfigGenerator(args.comprehensive_config, args.output_dir)
212
+ generator = TestConfigGenerator()
213
+ generator.create_all_test_configs()
296
214
 
297
- if args.config_name:
298
- # Create a specific configuration
299
- if args.modifications:
300
- modifications = json.loads(args.modifications)
301
- else:
302
- # Use predefined modifications
303
- predefined = {
304
- "http_simple": {"server.port": 8001, "ssl.enabled": False, "security.enabled": False},
305
- "https_simple": {"server.port": 8003, "ssl.enabled": True},
306
- "mtls_simple": {"server.port": 8005, "ssl.enabled": True, "ssl.verify_client": True},
307
- }
308
- modifications = predefined.get(args.config_name, {})
309
-
310
- generator.create_config(args.config_name, modifications)
311
- else:
312
- # Create all test configurations
313
- generator.create_all_test_configs()
215
+ print("\n🎉 All test configurations created successfully!")
216
+ print(f"📁 Output directory: {generator.output_dir}")
314
217
 
315
218
 
316
219
  if __name__ == "__main__":
317
- main()
220
+ main()