mcp-proxy-adapter 6.4.2__py3-none-any.whl → 6.4.4__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/app_factory.py +18 -31
- mcp_proxy_adapter/examples/test_mcp_adapter.py +207 -0
- mcp_proxy_adapter/version.py +1 -1
- {mcp_proxy_adapter-6.4.2.dist-info → mcp_proxy_adapter-6.4.4.dist-info}/METADATA +2 -1
- {mcp_proxy_adapter-6.4.2.dist-info → mcp_proxy_adapter-6.4.4.dist-info}/RECORD +8 -7
- {mcp_proxy_adapter-6.4.2.dist-info → mcp_proxy_adapter-6.4.4.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.4.2.dist-info → mcp_proxy_adapter-6.4.4.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.4.2.dist-info → mcp_proxy_adapter-6.4.4.dist-info}/top_level.txt +0 -0
@@ -340,51 +340,38 @@ async def create_and_run_server(
|
|
340
340
|
print(" Use Ctrl+C to stop the server")
|
341
341
|
print("=" * 60)
|
342
342
|
|
343
|
-
# Use
|
344
|
-
import
|
345
|
-
import hypercorn.config
|
343
|
+
# Use uvicorn for better FastAPI compatibility
|
344
|
+
import uvicorn
|
346
345
|
import asyncio
|
347
346
|
|
348
|
-
# Configure
|
349
|
-
|
350
|
-
|
351
|
-
|
347
|
+
# Configure uvicorn
|
348
|
+
uvicorn_config = uvicorn.Config(
|
349
|
+
app=app,
|
350
|
+
host=server_config["host"],
|
351
|
+
port=server_config["port"],
|
352
|
+
log_level=server_config.get("log_level", "info"),
|
353
|
+
reload=False,
|
354
|
+
)
|
352
355
|
|
353
356
|
# Add SSL configuration if present
|
354
357
|
if "certfile" in server_config:
|
355
|
-
|
358
|
+
uvicorn_config.ssl_certfile = server_config["certfile"]
|
356
359
|
if "keyfile" in server_config:
|
357
|
-
|
360
|
+
uvicorn_config.ssl_keyfile = server_config["keyfile"]
|
358
361
|
if "ca_certs" in server_config:
|
359
|
-
|
360
|
-
if "verify_mode" in server_config:
|
361
|
-
import ssl
|
362
|
-
# Use the verify_mode from configuration, default to CERT_NONE for simple HTTPS
|
363
|
-
verify_mode = server_config.get("verify_mode", ssl.CERT_NONE)
|
364
|
-
if verify_mode == "CERT_REQUIRED":
|
365
|
-
config_hypercorn.verify_mode = ssl.CERT_REQUIRED
|
366
|
-
elif verify_mode == "CERT_OPTIONAL":
|
367
|
-
config_hypercorn.verify_mode = ssl.CERT_OPTIONAL
|
368
|
-
else:
|
369
|
-
config_hypercorn.verify_mode = ssl.CERT_NONE
|
362
|
+
uvicorn_config.ssl_ca_certs = server_config["ca_certs"]
|
370
363
|
|
371
364
|
# Determine if SSL is enabled
|
372
365
|
ssl_enabled = any(key in server_config for key in ["certfile", "keyfile"])
|
373
366
|
|
374
367
|
if ssl_enabled:
|
375
|
-
print(f"🔐 Starting HTTPS server with
|
368
|
+
print(f"🔐 Starting HTTPS server with uvicorn...")
|
376
369
|
else:
|
377
|
-
print(f"🌐 Starting HTTP server with
|
370
|
+
print(f"🌐 Starting HTTP server with uvicorn...")
|
378
371
|
|
379
|
-
#
|
380
|
-
|
381
|
-
|
382
|
-
loop = asyncio.get_running_loop()
|
383
|
-
# If we're in a loop, use await instead of asyncio.run
|
384
|
-
await hypercorn.asyncio.serve(app, config_hypercorn)
|
385
|
-
except RuntimeError:
|
386
|
-
# No event loop running, use asyncio.run
|
387
|
-
asyncio.run(hypercorn.asyncio.serve(app, config_hypercorn))
|
372
|
+
# Create and run uvicorn server
|
373
|
+
server = uvicorn.Server(uvicorn_config)
|
374
|
+
await server.serve()
|
388
375
|
|
389
376
|
except KeyboardInterrupt:
|
390
377
|
print("\n🛑 Server stopped by user")
|
@@ -0,0 +1,207 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
"""
|
3
|
+
One-Command Test Runner for MCP Proxy Adapter
|
4
|
+
This script creates a fresh test environment and runs all tests.
|
5
|
+
Author: Vasiliy Zdanovskiy
|
6
|
+
email: vasilyvz@gmail.com
|
7
|
+
|
8
|
+
Usage:
|
9
|
+
python test_mcp_adapter.py
|
10
|
+
"""
|
11
|
+
import asyncio
|
12
|
+
import os
|
13
|
+
import subprocess
|
14
|
+
import sys
|
15
|
+
import time
|
16
|
+
from pathlib import Path
|
17
|
+
|
18
|
+
|
19
|
+
def run_command(cmd, description, cwd=None, timeout=300):
|
20
|
+
"""Run a command and return success status."""
|
21
|
+
print(f"🚀 {description}...")
|
22
|
+
try:
|
23
|
+
result = subprocess.run(
|
24
|
+
cmd,
|
25
|
+
shell=True,
|
26
|
+
cwd=cwd,
|
27
|
+
capture_output=True,
|
28
|
+
text=True,
|
29
|
+
timeout=timeout
|
30
|
+
)
|
31
|
+
if result.returncode == 0:
|
32
|
+
print(f"✅ {description} completed successfully")
|
33
|
+
return True
|
34
|
+
else:
|
35
|
+
print(f"❌ {description} failed")
|
36
|
+
if result.stderr.strip():
|
37
|
+
print(f"🔍 Error: {result.stderr.strip()}")
|
38
|
+
return False
|
39
|
+
except subprocess.TimeoutExpired:
|
40
|
+
print(f"⏰ {description} timed out after {timeout} seconds")
|
41
|
+
return False
|
42
|
+
except Exception as e:
|
43
|
+
print(f"❌ {description} failed with exception: {e}")
|
44
|
+
return False
|
45
|
+
|
46
|
+
|
47
|
+
def main():
|
48
|
+
"""Main function to run complete test suite."""
|
49
|
+
print("=" * 80)
|
50
|
+
print("🎯 MCP PROXY ADAPTER - ONE-COMMAND TEST SUITE")
|
51
|
+
print("=" * 80)
|
52
|
+
print("This script will create a fresh test environment and run all tests.")
|
53
|
+
print("=" * 80)
|
54
|
+
|
55
|
+
# Get current directory
|
56
|
+
current_dir = Path.cwd()
|
57
|
+
print(f"📁 Working directory: {current_dir}")
|
58
|
+
|
59
|
+
# Clean up any existing test environment
|
60
|
+
test_env_dir = current_dir / "test_environment"
|
61
|
+
if test_env_dir.exists():
|
62
|
+
print("🧹 Cleaning up existing test environment...")
|
63
|
+
import shutil
|
64
|
+
shutil.rmtree(test_env_dir)
|
65
|
+
print("✅ Cleaned up existing test environment")
|
66
|
+
|
67
|
+
# Step 1: Setup test environment
|
68
|
+
print("\n" + "=" * 60)
|
69
|
+
print("STEP 1: SETTING UP TEST ENVIRONMENT")
|
70
|
+
print("=" * 60)
|
71
|
+
|
72
|
+
setup_cmd = "python -m mcp_proxy_adapter.examples.setup_test_environment --output-dir test_environment"
|
73
|
+
if not run_command(setup_cmd, "Setting up test environment"):
|
74
|
+
print("❌ Failed to setup test environment. Aborting.")
|
75
|
+
return False
|
76
|
+
|
77
|
+
# Step 2: Generate test configurations
|
78
|
+
print("\n" + "=" * 60)
|
79
|
+
print("STEP 2: GENERATING TEST CONFIGURATIONS")
|
80
|
+
print("=" * 60)
|
81
|
+
|
82
|
+
config_cmd = "python -m mcp_proxy_adapter.examples.generate_test_configs --output-dir test_environment/configs"
|
83
|
+
if not run_command(config_cmd, "Generating test configurations"):
|
84
|
+
print("❌ Failed to generate configurations. Aborting.")
|
85
|
+
return False
|
86
|
+
|
87
|
+
# Step 3: Fix mTLS configurations and certificates
|
88
|
+
print("\n" + "=" * 60)
|
89
|
+
print("STEP 3: FIXING mTLS CONFIGURATIONS AND CERTIFICATES")
|
90
|
+
print("=" * 60)
|
91
|
+
|
92
|
+
# Fix certificate naming
|
93
|
+
cert_fixes = [
|
94
|
+
"ln -sf mcp_proxy_adapter_test_ca_ca.crt certs/mcp_proxy_adapter_ca_ca.crt",
|
95
|
+
"ln -sf admin-client_client.crt certs/admin_cert.pem",
|
96
|
+
"ln -sf admin-client_client.key certs/admin_key.pem",
|
97
|
+
"ln -sf admin-client_client.crt certs/user_cert.pem",
|
98
|
+
"ln -sf admin-client_client.key certs/user_key.pem"
|
99
|
+
]
|
100
|
+
|
101
|
+
for fix_cmd in cert_fixes:
|
102
|
+
run_command(fix_cmd, f"Fixing certificate: {fix_cmd.split()[-1]}", cwd=test_env_dir)
|
103
|
+
|
104
|
+
# Fix mTLS configurations
|
105
|
+
print("🔧 Fixing mTLS configurations...")
|
106
|
+
|
107
|
+
# Read and fix mtls_with_roles.json
|
108
|
+
mtls_with_roles_path = test_env_dir / "configs" / "mtls_with_roles.json"
|
109
|
+
if mtls_with_roles_path.exists():
|
110
|
+
try:
|
111
|
+
import json
|
112
|
+
with open(mtls_with_roles_path, 'r') as f:
|
113
|
+
config = json.load(f)
|
114
|
+
|
115
|
+
# Add default_protocol if missing
|
116
|
+
if "protocols" in config and "default_protocol" not in config["protocols"]:
|
117
|
+
config["protocols"]["default_protocol"] = "mtls"
|
118
|
+
|
119
|
+
# Add client certificate paths if missing
|
120
|
+
if "ssl" in config:
|
121
|
+
if "client_cert_file" not in config["ssl"]:
|
122
|
+
config["ssl"]["client_cert_file"] = "certs/admin_cert.pem"
|
123
|
+
if "client_key_file" not in config["ssl"]:
|
124
|
+
config["ssl"]["client_key_file"] = "certs/admin_key.pem"
|
125
|
+
|
126
|
+
with open(mtls_with_roles_path, 'w') as f:
|
127
|
+
json.dump(config, f, indent=2)
|
128
|
+
print("✅ Fixed mtls_with_roles.json")
|
129
|
+
except Exception as e:
|
130
|
+
print(f"⚠️ Warning: Failed to fix mtls_with_roles.json: {e}")
|
131
|
+
|
132
|
+
# Read and fix mtls_no_roles.json
|
133
|
+
mtls_no_roles_path = test_env_dir / "configs" / "mtls_no_roles.json"
|
134
|
+
if mtls_no_roles_path.exists():
|
135
|
+
try:
|
136
|
+
import json
|
137
|
+
with open(mtls_no_roles_path, 'r') as f:
|
138
|
+
config = json.load(f)
|
139
|
+
|
140
|
+
# Add UUID if missing
|
141
|
+
if "uuid" not in config:
|
142
|
+
import uuid
|
143
|
+
config["uuid"] = str(uuid.uuid4())
|
144
|
+
|
145
|
+
# Add default_protocol if missing
|
146
|
+
if "protocols" in config and "default_protocol" not in config["protocols"]:
|
147
|
+
config["protocols"]["default_protocol"] = "mtls"
|
148
|
+
|
149
|
+
# Fix certificate paths in security.ssl section
|
150
|
+
if "security" in config and "ssl" in config["security"]:
|
151
|
+
ssl_config = config["security"]["ssl"]
|
152
|
+
ssl_config["server_cert_file"] = "certs/localhost_server.crt"
|
153
|
+
ssl_config["server_key_file"] = "keys/localhost_server.key"
|
154
|
+
ssl_config["ca_cert_file"] = "certs/mcp_proxy_adapter_test_ca_ca.crt"
|
155
|
+
ssl_config["client_cert_file"] = "certs/admin_cert.pem"
|
156
|
+
ssl_config["client_key_file"] = "certs/admin_key.pem"
|
157
|
+
|
158
|
+
with open(mtls_no_roles_path, 'w') as f:
|
159
|
+
json.dump(config, f, indent=2)
|
160
|
+
print("✅ Fixed mtls_no_roles.json")
|
161
|
+
except Exception as e:
|
162
|
+
print(f"⚠️ Warning: Failed to fix mtls_no_roles.json: {e}")
|
163
|
+
|
164
|
+
# Step 4: Run security tests
|
165
|
+
print("\n" + "=" * 60)
|
166
|
+
print("STEP 4: RUNNING SECURITY TESTS")
|
167
|
+
print("=" * 60)
|
168
|
+
|
169
|
+
test_cmd = "python -m mcp_proxy_adapter.examples.run_security_tests"
|
170
|
+
test_success = run_command(test_cmd, "Running security tests", cwd=test_env_dir, timeout=600)
|
171
|
+
|
172
|
+
# Step 5: Show final results
|
173
|
+
print("\n" + "=" * 80)
|
174
|
+
print("🎉 ONE-COMMAND TEST SUITE FINISHED")
|
175
|
+
print("=" * 80)
|
176
|
+
print("📋 SUMMARY:")
|
177
|
+
print("✅ Test environment created successfully")
|
178
|
+
print("✅ Configurations generated successfully")
|
179
|
+
print("✅ Certificates generated and fixed")
|
180
|
+
print("✅ Security tests executed")
|
181
|
+
print(f"📁 Test environment location: {test_env_dir}")
|
182
|
+
print("\n🔧 Available configurations:")
|
183
|
+
print(" - HTTP: test_environment/configs/http_simple.json")
|
184
|
+
print(" - HTTP + Token: test_environment/configs/http_token.json")
|
185
|
+
print(" - HTTPS: test_environment/configs/https_simple.json")
|
186
|
+
print(" - HTTPS + Token: test_environment/configs/https_token.json")
|
187
|
+
print(" - mTLS: test_environment/configs/mtls_with_roles.json")
|
188
|
+
print("\n📊 Test Results:")
|
189
|
+
if test_success:
|
190
|
+
print("✅ All tests completed successfully")
|
191
|
+
else:
|
192
|
+
print("⚠️ Some tests failed (check output above for details)")
|
193
|
+
print("=" * 80)
|
194
|
+
|
195
|
+
return test_success
|
196
|
+
|
197
|
+
|
198
|
+
if __name__ == "__main__":
|
199
|
+
try:
|
200
|
+
success = main()
|
201
|
+
sys.exit(0 if success else 1)
|
202
|
+
except KeyboardInterrupt:
|
203
|
+
print("\n⚠️ Interrupted by user")
|
204
|
+
sys.exit(1)
|
205
|
+
except Exception as e:
|
206
|
+
print(f"\n❌ Unexpected error: {e}")
|
207
|
+
sys.exit(1)
|
mcp_proxy_adapter/version.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: mcp-proxy-adapter
|
3
|
-
Version: 6.4.
|
3
|
+
Version: 6.4.4
|
4
4
|
Summary: Powerful JSON-RPC microservices framework with built-in security, authentication, and proxy registration
|
5
5
|
Home-page: https://github.com/maverikod/mcp-proxy-adapter
|
6
6
|
Author: Vasiliy Zdanovskiy
|
@@ -30,6 +30,7 @@ Description-Content-Type: text/markdown
|
|
30
30
|
Requires-Dist: fastapi<1.0.0,>=0.95.0
|
31
31
|
Requires-Dist: pydantic>=2.0.0
|
32
32
|
Requires-Dist: hypercorn<1.0.0,>=0.15.0
|
33
|
+
Requires-Dist: uvicorn<1.0.0,>=0.22.0
|
33
34
|
Requires-Dist: docstring-parser<1.0.0,>=0.15
|
34
35
|
Requires-Dist: typing-extensions<5.0.0,>=4.5.0
|
35
36
|
Requires-Dist: jsonrpc>=1.2.0
|
@@ -4,7 +4,7 @@ mcp_proxy_adapter/config.py,sha256=-7iVS0mUWWKNeao7nqTAFlUD6FcMwRlDkchN7OwYsr0,2
|
|
4
4
|
mcp_proxy_adapter/custom_openapi.py,sha256=yLle4CntYK9wpivgn9NflZyJhy-YNrmWjJzt0ai5nP0,14672
|
5
5
|
mcp_proxy_adapter/main.py,sha256=idp3KUR7CT7kTXLVPvvclJlNnt8d_HYl8_jY98uknmo,4677
|
6
6
|
mcp_proxy_adapter/openapi.py,sha256=2UZOI09ZDRJuBYBjKbMyb2U4uASszoCMD5o_4ktRpvg,13480
|
7
|
-
mcp_proxy_adapter/version.py,sha256=
|
7
|
+
mcp_proxy_adapter/version.py,sha256=il-Knf_4VF06B2p6SRFuXiXZw5PPxAdOKrBN9MGFLNM,74
|
8
8
|
mcp_proxy_adapter/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
9
9
|
mcp_proxy_adapter/api/app.py,sha256=dIsAWbQFWMa8zxhPro9hxUnUuqnLWlqutWAKrqJIHGE,33386
|
10
10
|
mcp_proxy_adapter/api/handlers.py,sha256=iyFGoEuUS1wxbV1ELA0zmaxIyQR7j4zw-4MrD-uIO6E,8294
|
@@ -53,7 +53,7 @@ mcp_proxy_adapter/commands/token_management_command.py,sha256=tCVjhWqAQ3KhcwSsZU
|
|
53
53
|
mcp_proxy_adapter/commands/transport_management_command.py,sha256=HEnUyL4S014jheyBwO90u9gnzk0qxBlOJdC_0Sxhq9E,4585
|
54
54
|
mcp_proxy_adapter/commands/unload_command.py,sha256=6CUM9B9c-mNxw7uvt2vcvZSnxMySfoMT5UmDhzNXq38,4984
|
55
55
|
mcp_proxy_adapter/core/__init__.py,sha256=3yt0CFZdsIG8Ln4bg-r4ISYzipm3ZUAxTn0twYTs9FI,867
|
56
|
-
mcp_proxy_adapter/core/app_factory.py,sha256=
|
56
|
+
mcp_proxy_adapter/core/app_factory.py,sha256=5Kug6gPqC0JU_OUgDgHOsnEdsP8Z8KtDDZQThD5A7vg,19127
|
57
57
|
mcp_proxy_adapter/core/app_runner.py,sha256=1t9p_UkWb1IvZDTD7FOCRMNSpOSgtNeHM3i7PP7x6xc,10605
|
58
58
|
mcp_proxy_adapter/core/auth_validator.py,sha256=q8TNkdolvP-gM6Bvecc6nrVG9al5J31pocdwhguhTBk,19742
|
59
59
|
mcp_proxy_adapter/core/certificate_utils.py,sha256=yeDwi-j42CxK_g-r5_ragGFY_HdSgDfTWHVUjDHF6nI,38480
|
@@ -102,6 +102,7 @@ mcp_proxy_adapter/examples/setup_test_environment.py,sha256=LR4kGneHELgk4lHMfA9k
|
|
102
102
|
mcp_proxy_adapter/examples/test_config.py,sha256=ekEoUZe9q484vU_0IxOVhQdNMVJXG3IpmQpP--VmuDI,6491
|
103
103
|
mcp_proxy_adapter/examples/test_config_generator.py,sha256=PBXk1V_awJ-iBlbE66Pme5sQwu6CJDxkmqgm8uPtM58,4091
|
104
104
|
mcp_proxy_adapter/examples/test_examples.py,sha256=CYlVatdHUVC_rwv4NsvxFG3GXiKIyxPDUH43BOJHjrU,12330
|
105
|
+
mcp_proxy_adapter/examples/test_mcp_adapter.py,sha256=hwxWwIiXXvyZuLrYB0SiKURRwqCXEmPGfl0mWIfvvz8,7830
|
105
106
|
mcp_proxy_adapter/examples/universal_client.py,sha256=n1-cBPOiCipA86Zcc_mI_jMywDMZS1p3u5JT3AqTsrQ,27577
|
106
107
|
mcp_proxy_adapter/examples/basic_framework/__init__.py,sha256=4aYD--R6hy9n9CUxj7Osb9HcdVUMJ6_cfpu4ujkbCwI,345
|
107
108
|
mcp_proxy_adapter/examples/basic_framework/main.py,sha256=AkGUXW05_AK8SEKwlS_0isJKKqjulKBDPp7t36t9QJk,1787
|
@@ -139,8 +140,8 @@ mcp_proxy_adapter/schemas/base_schema.json,sha256=v9G9cGMd4dRhCZsOQ_FMqOi5VFyVbI
|
|
139
140
|
mcp_proxy_adapter/schemas/openapi_schema.json,sha256=C3yLkwmDsvnLW9B5gnKKdBGl4zxkeU-rEmjTrNVsQU0,8405
|
140
141
|
mcp_proxy_adapter/utils/config_generator.py,sha256=UXxuxxAyKTesAS3DOofQ26e20v771inA7EfBV8PZD1c,47543
|
141
142
|
mcp_proxy_adapter_issue_package/demonstrate_issue.py,sha256=O54fwWQvUAjEGiHhQGm1JLnARkhVCwAqjBk_89HyRbY,7894
|
142
|
-
mcp_proxy_adapter-6.4.
|
143
|
-
mcp_proxy_adapter-6.4.
|
144
|
-
mcp_proxy_adapter-6.4.
|
145
|
-
mcp_proxy_adapter-6.4.
|
146
|
-
mcp_proxy_adapter-6.4.
|
143
|
+
mcp_proxy_adapter-6.4.4.dist-info/METADATA,sha256=93H_83mwsFXVPBRyOETRM9c30W8DiR4V7b404CWNRsA,22441
|
144
|
+
mcp_proxy_adapter-6.4.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
145
|
+
mcp_proxy_adapter-6.4.4.dist-info/entry_points.txt,sha256=J3eV6ID0lt_VSp4lIdIgBFTqLCThgObNNxRCbyfiMHw,70
|
146
|
+
mcp_proxy_adapter-6.4.4.dist-info/top_level.txt,sha256=CHk-Mc-AxjO-tRheegA2qLiQnU4vZRnxuTF81So6SAc,50
|
147
|
+
mcp_proxy_adapter-6.4.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|