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.
- mcp_proxy_adapter/core/proxy_registration.py +100 -68
- mcp_proxy_adapter/examples/bugfix_certificate_config.py +284 -0
- mcp_proxy_adapter/examples/cert_manager_bugfix.py +203 -0
- mcp_proxy_adapter/examples/config_builder.py +574 -0
- mcp_proxy_adapter/examples/config_cli.py +283 -0
- mcp_proxy_adapter/examples/create_test_configs.py +169 -266
- mcp_proxy_adapter/examples/generate_certificates_bugfix.py +374 -0
- mcp_proxy_adapter/examples/generate_certificates_cli.py +406 -0
- mcp_proxy_adapter/examples/generate_certificates_fixed.py +313 -0
- mcp_proxy_adapter/examples/generate_certificates_framework.py +366 -0
- mcp_proxy_adapter/examples/generate_certificates_openssl.py +391 -0
- mcp_proxy_adapter/examples/required_certificates.py +210 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +117 -13
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +41 -25
- mcp_proxy_adapter/examples/security_test_client.py +333 -86
- mcp_proxy_adapter/examples/test_config_builder.py +450 -0
- mcp_proxy_adapter/examples/update_config_certificates.py +136 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/METADATA +81 -1
- {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/RECORD +23 -20
- mcp_proxy_adapter-6.4.45.dist-info/entry_points.txt +12 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +0 -661
- mcp_proxy_adapter/examples/generate_certificates.py +0 -192
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +0 -515
- mcp_proxy_adapter/examples/generate_test_configs.py +0 -393
- mcp_proxy_adapter/examples/run_security_tests.py +0 -677
- mcp_proxy_adapter/examples/scripts/config_generator.py +0 -842
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +0 -673
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +0 -515
- mcp_proxy_adapter/examples/test_config_generator.py +0 -102
- mcp_proxy_adapter-6.4.43.dist-info/entry_points.txt +0 -2
- {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.4.43.dist-info → mcp_proxy_adapter-6.4.45.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,283 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
CLI Utility for MCP Proxy Adapter Configuration Builder
|
4
|
+
Command-line interface for creating configurations with various parameters.
|
5
|
+
|
6
|
+
Author: Vasiliy Zdanovskiy
|
7
|
+
email: vasilyvz@gmail.com
|
8
|
+
"""
|
9
|
+
import argparse
|
10
|
+
import json
|
11
|
+
import sys
|
12
|
+
from pathlib import Path
|
13
|
+
from typing import Dict, Any, List, Optional
|
14
|
+
|
15
|
+
from config_builder import ConfigBuilder, ConfigFactory, Protocol, AuthMethod
|
16
|
+
|
17
|
+
|
18
|
+
def parse_protocol(protocol_str: str) -> Protocol:
|
19
|
+
"""Parse protocol string to Protocol enum."""
|
20
|
+
protocol_map = {
|
21
|
+
"http": Protocol.HTTP,
|
22
|
+
"https": Protocol.HTTPS,
|
23
|
+
"mtls": Protocol.MTLS
|
24
|
+
}
|
25
|
+
if protocol_str.lower() not in protocol_map:
|
26
|
+
raise ValueError(f"Invalid protocol: {protocol_str}. Must be one of: {list(protocol_map.keys())}")
|
27
|
+
return protocol_map[protocol_str.lower()]
|
28
|
+
|
29
|
+
|
30
|
+
def parse_auth_method(auth_str: str) -> AuthMethod:
|
31
|
+
"""Parse authentication method string to AuthMethod enum."""
|
32
|
+
auth_map = {
|
33
|
+
"none": AuthMethod.NONE,
|
34
|
+
"token": AuthMethod.TOKEN,
|
35
|
+
"basic": AuthMethod.BASIC
|
36
|
+
}
|
37
|
+
if auth_str.lower() not in auth_map:
|
38
|
+
raise ValueError(f"Invalid auth method: {auth_str}. Must be one of: {list(auth_map.keys())}")
|
39
|
+
return auth_map[auth_str.lower()]
|
40
|
+
|
41
|
+
|
42
|
+
def parse_api_keys(api_keys_str: str) -> Dict[str, str]:
|
43
|
+
"""Parse API keys from string format 'key1:value1,key2:value2'."""
|
44
|
+
if not api_keys_str:
|
45
|
+
return {}
|
46
|
+
|
47
|
+
api_keys = {}
|
48
|
+
for pair in api_keys_str.split(','):
|
49
|
+
if ':' not in pair:
|
50
|
+
raise ValueError(f"Invalid API key format: {pair}. Expected 'key:value'")
|
51
|
+
key, value = pair.split(':', 1)
|
52
|
+
api_keys[key.strip()] = value.strip()
|
53
|
+
|
54
|
+
return api_keys
|
55
|
+
|
56
|
+
|
57
|
+
def parse_roles(roles_str: str) -> Dict[str, List[str]]:
|
58
|
+
"""Parse roles from string format 'role1:perm1,perm2;role2:perm3,perm4'."""
|
59
|
+
if not roles_str:
|
60
|
+
return {}
|
61
|
+
|
62
|
+
roles = {}
|
63
|
+
for role_def in roles_str.split(';'):
|
64
|
+
if ':' not in role_def:
|
65
|
+
raise ValueError(f"Invalid role format: {role_def}. Expected 'role:perm1,perm2'")
|
66
|
+
role, perms = role_def.split(':', 1)
|
67
|
+
roles[role.strip()] = [perm.strip() for perm in perms.split(',')]
|
68
|
+
|
69
|
+
return roles
|
70
|
+
|
71
|
+
|
72
|
+
def create_custom_config(args) -> Dict[str, Any]:
|
73
|
+
"""Create custom configuration based on command line arguments."""
|
74
|
+
builder = ConfigBuilder()
|
75
|
+
|
76
|
+
# Set server configuration
|
77
|
+
builder.set_server(
|
78
|
+
host=args.host,
|
79
|
+
port=args.port,
|
80
|
+
debug=args.debug,
|
81
|
+
log_level=args.log_level
|
82
|
+
)
|
83
|
+
|
84
|
+
# Set logging configuration
|
85
|
+
builder.set_logging(
|
86
|
+
log_dir=args.log_dir,
|
87
|
+
level=args.log_level,
|
88
|
+
console_output=not args.no_console,
|
89
|
+
file_output=not args.no_file_log
|
90
|
+
)
|
91
|
+
|
92
|
+
# Set protocol
|
93
|
+
protocol = parse_protocol(args.protocol)
|
94
|
+
builder.set_protocol(
|
95
|
+
protocol,
|
96
|
+
cert_dir=args.cert_dir,
|
97
|
+
key_dir=args.key_dir
|
98
|
+
)
|
99
|
+
|
100
|
+
# Set authentication
|
101
|
+
auth_method = parse_auth_method(args.auth)
|
102
|
+
api_keys = parse_api_keys(args.api_keys) if args.api_keys else None
|
103
|
+
roles = parse_roles(args.roles) if args.roles else None
|
104
|
+
|
105
|
+
builder.set_auth(auth_method, api_keys=api_keys, roles=roles)
|
106
|
+
|
107
|
+
# Set proxy registration
|
108
|
+
if args.proxy_url:
|
109
|
+
builder.set_proxy_registration(
|
110
|
+
enabled=True,
|
111
|
+
proxy_url=args.proxy_url,
|
112
|
+
server_id=args.server_id,
|
113
|
+
cert_dir=args.cert_dir
|
114
|
+
)
|
115
|
+
|
116
|
+
# Set debug
|
117
|
+
if args.debug:
|
118
|
+
builder.set_debug(enabled=True, log_level=args.log_level)
|
119
|
+
|
120
|
+
# Set commands
|
121
|
+
if args.enabled_commands or args.disabled_commands:
|
122
|
+
enabled = args.enabled_commands.split(',') if args.enabled_commands else None
|
123
|
+
disabled = args.disabled_commands.split(',') if args.disabled_commands else None
|
124
|
+
builder.set_commands(enabled_commands=enabled, disabled_commands=disabled)
|
125
|
+
|
126
|
+
return builder.build()
|
127
|
+
|
128
|
+
|
129
|
+
def create_preset_config(preset: str, **kwargs) -> Dict[str, Any]:
|
130
|
+
"""Create preset configuration."""
|
131
|
+
preset_map = {
|
132
|
+
"http_simple": ConfigFactory.create_http_simple,
|
133
|
+
"http_token": ConfigFactory.create_http_token,
|
134
|
+
"https_simple": ConfigFactory.create_https_simple,
|
135
|
+
"https_token": ConfigFactory.create_https_token,
|
136
|
+
"mtls_simple": ConfigFactory.create_mtls_simple,
|
137
|
+
"mtls_with_roles": ConfigFactory.create_mtls_with_roles,
|
138
|
+
"mtls_with_proxy": ConfigFactory.create_mtls_with_proxy,
|
139
|
+
"full_featured": ConfigFactory.create_full_featured,
|
140
|
+
}
|
141
|
+
|
142
|
+
if preset not in preset_map:
|
143
|
+
raise ValueError(f"Invalid preset: {preset}. Must be one of: {list(preset_map.keys())}")
|
144
|
+
|
145
|
+
return preset_map[preset](**kwargs)
|
146
|
+
|
147
|
+
|
148
|
+
def list_presets():
|
149
|
+
"""List available presets."""
|
150
|
+
presets = [
|
151
|
+
("http_simple", "Simple HTTP server without authentication"),
|
152
|
+
("http_token", "HTTP server with token authentication"),
|
153
|
+
("https_simple", "Simple HTTPS server without authentication"),
|
154
|
+
("https_token", "HTTPS server with token authentication"),
|
155
|
+
("mtls_simple", "Simple mTLS server without authentication"),
|
156
|
+
("mtls_with_roles", "mTLS server with role-based access control"),
|
157
|
+
("mtls_with_proxy", "mTLS server with proxy registration"),
|
158
|
+
("full_featured", "Full-featured server with all options enabled"),
|
159
|
+
]
|
160
|
+
|
161
|
+
print("📋 Available Configuration Presets:")
|
162
|
+
print("=" * 50)
|
163
|
+
for preset, description in presets:
|
164
|
+
print(f" {preset:<20} - {description}")
|
165
|
+
|
166
|
+
|
167
|
+
def main():
|
168
|
+
"""Main CLI function."""
|
169
|
+
parser = argparse.ArgumentParser(
|
170
|
+
description="MCP Proxy Adapter Configuration Builder CLI",
|
171
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
172
|
+
epilog="""
|
173
|
+
Examples:
|
174
|
+
# Create HTTP simple configuration
|
175
|
+
python config_cli.py --preset http_simple --output configs/http_simple.json
|
176
|
+
|
177
|
+
# Create custom HTTPS configuration with token auth
|
178
|
+
python config_cli.py --protocol https --auth token --api-keys "admin:admin-key,user:user-key" --output configs/https_token.json
|
179
|
+
|
180
|
+
# Create mTLS configuration with proxy registration
|
181
|
+
python config_cli.py --protocol mtls --proxy-url "https://proxy.example.com:8080" --server-id "my_server" --output configs/mtls_proxy.json
|
182
|
+
|
183
|
+
# List all available presets
|
184
|
+
python config_cli.py --list-presets
|
185
|
+
"""
|
186
|
+
)
|
187
|
+
|
188
|
+
# Main options
|
189
|
+
parser.add_argument("--preset", help="Use a preset configuration")
|
190
|
+
parser.add_argument("--list-presets", action="store_true", help="List available presets")
|
191
|
+
parser.add_argument("--output", "-o", help="Output file path (default: stdout)")
|
192
|
+
|
193
|
+
# Server configuration
|
194
|
+
parser.add_argument("--host", default="0.0.0.0", help="Server host (default: 0.0.0.0)")
|
195
|
+
parser.add_argument("--port", type=int, default=8000, help="Server port (default: 8000)")
|
196
|
+
parser.add_argument("--debug", action="store_true", help="Enable debug mode")
|
197
|
+
parser.add_argument("--log-level", default="INFO", choices=["DEBUG", "INFO", "WARNING", "ERROR"], help="Log level (default: INFO)")
|
198
|
+
|
199
|
+
# Logging configuration
|
200
|
+
parser.add_argument("--log-dir", default="./logs", help="Log directory (default: ./logs)")
|
201
|
+
parser.add_argument("--no-console", action="store_true", help="Disable console output")
|
202
|
+
parser.add_argument("--no-file-log", action="store_true", help="Disable file logging")
|
203
|
+
|
204
|
+
# Protocol configuration
|
205
|
+
parser.add_argument("--protocol", choices=["http", "https", "mtls"], default="http", help="Protocol (default: http)")
|
206
|
+
parser.add_argument("--cert-dir", default="./certs", help="Certificate directory (default: ./certs)")
|
207
|
+
parser.add_argument("--key-dir", default="./keys", help="Key directory (default: ./keys)")
|
208
|
+
|
209
|
+
# Authentication configuration
|
210
|
+
parser.add_argument("--auth", choices=["none", "token", "basic"], default="none", help="Authentication method (default: none)")
|
211
|
+
parser.add_argument("--api-keys", help="API keys in format 'key1:value1,key2:value2'")
|
212
|
+
parser.add_argument("--roles", help="Roles in format 'role1:perm1,perm2;role2:perm3,perm4'")
|
213
|
+
|
214
|
+
# Proxy registration
|
215
|
+
parser.add_argument("--proxy-url", help="Proxy URL for registration")
|
216
|
+
parser.add_argument("--server-id", default="mcp_proxy_adapter", help="Server ID for proxy registration (default: mcp_proxy_adapter)")
|
217
|
+
|
218
|
+
# Commands configuration
|
219
|
+
parser.add_argument("--enabled-commands", help="Comma-separated list of enabled commands")
|
220
|
+
parser.add_argument("--disabled-commands", help="Comma-separated list of disabled commands")
|
221
|
+
|
222
|
+
# Preset-specific options
|
223
|
+
parser.add_argument("--preset-host", help="Host for preset configurations")
|
224
|
+
parser.add_argument("--preset-port", type=int, help="Port for preset configurations")
|
225
|
+
parser.add_argument("--preset-log-dir", help="Log directory for preset configurations")
|
226
|
+
parser.add_argument("--preset-cert-dir", help="Certificate directory for preset configurations")
|
227
|
+
parser.add_argument("--preset-key-dir", help="Key directory for preset configurations")
|
228
|
+
parser.add_argument("--preset-proxy-url", help="Proxy URL for preset configurations")
|
229
|
+
parser.add_argument("--preset-server-id", help="Server ID for preset configurations")
|
230
|
+
|
231
|
+
args = parser.parse_args()
|
232
|
+
|
233
|
+
try:
|
234
|
+
# Handle list presets
|
235
|
+
if args.list_presets:
|
236
|
+
list_presets()
|
237
|
+
return 0
|
238
|
+
|
239
|
+
# Create configuration
|
240
|
+
if args.preset:
|
241
|
+
# Use preset configuration
|
242
|
+
preset_kwargs = {}
|
243
|
+
if args.preset_host:
|
244
|
+
preset_kwargs["host"] = args.preset_host
|
245
|
+
if args.preset_port:
|
246
|
+
preset_kwargs["port"] = args.preset_port
|
247
|
+
if args.preset_log_dir:
|
248
|
+
preset_kwargs["log_dir"] = args.preset_log_dir
|
249
|
+
if args.preset_cert_dir:
|
250
|
+
preset_kwargs["cert_dir"] = args.preset_cert_dir
|
251
|
+
if args.preset_key_dir:
|
252
|
+
preset_kwargs["key_dir"] = args.preset_key_dir
|
253
|
+
if args.preset_proxy_url:
|
254
|
+
preset_kwargs["proxy_url"] = args.preset_proxy_url
|
255
|
+
if args.preset_server_id:
|
256
|
+
preset_kwargs["server_id"] = args.preset_server_id
|
257
|
+
|
258
|
+
config = create_preset_config(args.preset, **preset_kwargs)
|
259
|
+
else:
|
260
|
+
# Create custom configuration
|
261
|
+
config = create_custom_config(args)
|
262
|
+
|
263
|
+
# Output configuration
|
264
|
+
config_json = json.dumps(config, indent=2, ensure_ascii=False)
|
265
|
+
|
266
|
+
if args.output:
|
267
|
+
output_path = Path(args.output)
|
268
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
269
|
+
with open(output_path, 'w', encoding='utf-8') as f:
|
270
|
+
f.write(config_json)
|
271
|
+
print(f"✅ Configuration saved to: {output_path}")
|
272
|
+
else:
|
273
|
+
print(config_json)
|
274
|
+
|
275
|
+
return 0
|
276
|
+
|
277
|
+
except Exception as e:
|
278
|
+
print(f"❌ Error: {e}", file=sys.stderr)
|
279
|
+
return 1
|
280
|
+
|
281
|
+
|
282
|
+
if __name__ == "__main__":
|
283
|
+
sys.exit(main())
|