mcp-proxy-adapter 6.4.10__py3-none-any.whl → 6.4.12__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/examples/basic_framework/main.py +3 -2
- mcp_proxy_adapter/examples/create_test_configs.py +301 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +180 -20
- mcp_proxy_adapter/version.py +1 -1
- mcp_proxy_adapter-6.4.12.dist-info/METADATA +156 -0
- {mcp_proxy_adapter-6.4.10.dist-info → mcp_proxy_adapter-6.4.12.dist-info}/RECORD +9 -16
- mcp_proxy_adapter-6.4.12.dist-info/top_level.txt +1 -0
- mcp_proxy_adapter/examples/basic_framework/roles.json +0 -21
- mcp_proxy_adapter/examples/full_application/roles.json +0 -21
- mcp_proxy_adapter/examples/generate_comprehensive_config.py +0 -177
- mcp_proxy_adapter/examples/test_mcp_adapter.py +0 -207
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/utils/config_generator.py +0 -1167
- mcp_proxy_adapter-6.4.10.dist-info/METADATA +0 -680
- mcp_proxy_adapter-6.4.10.dist-info/top_level.txt +0 -2
- mcp_proxy_adapter_issue_package/demonstrate_issue.py +0 -208
- {mcp_proxy_adapter-6.4.10.dist-info → mcp_proxy_adapter-6.4.12.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.4.10.dist-info → mcp_proxy_adapter-6.4.12.dist-info}/entry_points.txt +0 -0
@@ -1,208 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Demonstration script showing the mcp_proxy_adapter SSL verification issue.
|
4
|
-
This script reproduces the problem where verify_server: false is ignored.
|
5
|
-
|
6
|
-
Author: Vasiliy Zdanovskiy
|
7
|
-
email: vasilyvz@gmail.com
|
8
|
-
"""
|
9
|
-
import ssl
|
10
|
-
import asyncio
|
11
|
-
import aiohttp
|
12
|
-
import logging
|
13
|
-
from pathlib import Path
|
14
|
-
|
15
|
-
# Setup logging
|
16
|
-
logging.basicConfig(
|
17
|
-
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
|
18
|
-
)
|
19
|
-
logger = logging.getLogger(__name__)
|
20
|
-
|
21
|
-
|
22
|
-
class MockSSLConfig:
|
23
|
-
"""Mock SSL configuration to demonstrate the issue."""
|
24
|
-
|
25
|
-
def __init__(self, verify_server=True):
|
26
|
-
self.verify_server = verify_server
|
27
|
-
self.ca_cert_file = "certs/mtls/truststore.pem"
|
28
|
-
self.client_cert_file = "certs/mtls/client/embedding-service.pem"
|
29
|
-
self.client_key_file = "certs/mtls/client/embedding-service.key"
|
30
|
-
|
31
|
-
|
32
|
-
def create_client_ssl_context_broken(ssl_config: MockSSLConfig) -> ssl.SSLContext:
|
33
|
-
"""
|
34
|
-
BROKEN: This is how mcp_proxy_adapter currently works.
|
35
|
-
It hardcodes CERT_REQUIRED, ignoring the verify_server setting.
|
36
|
-
"""
|
37
|
-
logger.info("🔴 Creating SSL context (BROKEN - current mcp_proxy_adapter behavior)")
|
38
|
-
logger.info(f" Configuration: verify_server={ssl_config.verify_server}")
|
39
|
-
|
40
|
-
try:
|
41
|
-
ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
42
|
-
|
43
|
-
# Load CA certificate if provided
|
44
|
-
if ssl_config.ca_cert_file and Path(ssl_config.ca_cert_file).exists():
|
45
|
-
ssl_context.load_verify_locations(ssl_config.ca_cert_file)
|
46
|
-
logger.info(f" ✅ Loaded CA certificate: {ssl_config.ca_cert_file}")
|
47
|
-
|
48
|
-
# Load client certificate if provided
|
49
|
-
if (
|
50
|
-
ssl_config.client_cert_file
|
51
|
-
and ssl_config.client_key_file
|
52
|
-
and Path(ssl_config.client_cert_file).exists()
|
53
|
-
and Path(ssl_config.client_key_file).exists()
|
54
|
-
):
|
55
|
-
ssl_context.load_cert_chain(
|
56
|
-
ssl_config.client_cert_file, ssl_config.client_key_file
|
57
|
-
)
|
58
|
-
logger.info(
|
59
|
-
f" ✅ Loaded client certificate: {ssl_config.client_cert_file}"
|
60
|
-
)
|
61
|
-
|
62
|
-
# PROBLEM: This line hardcodes CERT_REQUIRED, ignoring configuration
|
63
|
-
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
64
|
-
logger.info(" ❌ HARDCODED: ssl_context.verify_mode = ssl.CERT_REQUIRED")
|
65
|
-
logger.info(" ❌ IGNORES: verify_server=False configuration!")
|
66
|
-
|
67
|
-
return ssl_context
|
68
|
-
except Exception as e:
|
69
|
-
logger.error(f" ❌ Failed to create SSL context: {e}")
|
70
|
-
return ssl.create_default_context()
|
71
|
-
|
72
|
-
|
73
|
-
def create_client_ssl_context_fixed(ssl_config: MockSSLConfig) -> ssl.SSLContext:
|
74
|
-
"""
|
75
|
-
FIXED: This is how mcp_proxy_adapter should work.
|
76
|
-
It respects the verify_server configuration setting.
|
77
|
-
"""
|
78
|
-
logger.info("🟢 Creating SSL context (FIXED - proposed solution)")
|
79
|
-
logger.info(f" Configuration: verify_server={ssl_config.verify_server}")
|
80
|
-
|
81
|
-
try:
|
82
|
-
ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
|
83
|
-
|
84
|
-
# Load CA certificate if provided
|
85
|
-
if ssl_config.ca_cert_file and Path(ssl_config.ca_cert_file).exists():
|
86
|
-
ssl_context.load_verify_locations(ssl_config.ca_cert_file)
|
87
|
-
logger.info(f" ✅ Loaded CA certificate: {ssl_config.ca_cert_file}")
|
88
|
-
|
89
|
-
# Load client certificate if provided
|
90
|
-
if (
|
91
|
-
ssl_config.client_cert_file
|
92
|
-
and ssl_config.client_key_file
|
93
|
-
and Path(ssl_config.client_cert_file).exists()
|
94
|
-
and Path(ssl_config.client_key_file).exists()
|
95
|
-
):
|
96
|
-
ssl_context.load_cert_chain(
|
97
|
-
ssl_config.client_cert_file, ssl_config.client_key_file
|
98
|
-
)
|
99
|
-
logger.info(
|
100
|
-
f" ✅ Loaded client certificate: {ssl_config.client_cert_file}"
|
101
|
-
)
|
102
|
-
|
103
|
-
# FIX: Respect the verify_server configuration
|
104
|
-
if not ssl_config.verify_server:
|
105
|
-
ssl_context.check_hostname = False # Must be set BEFORE verify_mode
|
106
|
-
ssl_context.verify_mode = ssl.CERT_NONE
|
107
|
-
logger.info(" ✅ RESPECTS: ssl_context.check_hostname = False")
|
108
|
-
logger.info(
|
109
|
-
" ✅ RESPECTS: ssl_context.verify_mode = ssl.CERT_NONE (verify_server=False)"
|
110
|
-
)
|
111
|
-
else:
|
112
|
-
ssl_context.verify_mode = ssl.CERT_REQUIRED
|
113
|
-
logger.info(
|
114
|
-
" ✅ RESPECTS: ssl_context.verify_mode = ssl.CERT_REQUIRED (verify_server=True)"
|
115
|
-
)
|
116
|
-
|
117
|
-
return ssl_context
|
118
|
-
except Exception as e:
|
119
|
-
logger.error(f" ❌ Failed to create SSL context: {e}")
|
120
|
-
return ssl.create_default_context()
|
121
|
-
|
122
|
-
|
123
|
-
async def test_connection(ssl_context: ssl.SSLContext, url: str, description: str):
|
124
|
-
"""Test connection with the given SSL context."""
|
125
|
-
logger.info(f"\n🧪 Testing connection: {description}")
|
126
|
-
logger.info(f" URL: {url}")
|
127
|
-
|
128
|
-
try:
|
129
|
-
connector = aiohttp.TCPConnector(ssl=ssl_context)
|
130
|
-
async with aiohttp.ClientSession(connector=connector) as session:
|
131
|
-
async with session.get(
|
132
|
-
url, timeout=aiohttp.ClientTimeout(total=5)
|
133
|
-
) as response:
|
134
|
-
logger.info(f" ✅ SUCCESS: HTTP {response.status}")
|
135
|
-
return True
|
136
|
-
except ssl.SSLCertVerificationError as e:
|
137
|
-
logger.error(f" ❌ SSL VERIFICATION ERROR: {e}")
|
138
|
-
return False
|
139
|
-
except Exception as e:
|
140
|
-
logger.error(f" ❌ CONNECTION ERROR: {e}")
|
141
|
-
return False
|
142
|
-
|
143
|
-
|
144
|
-
async def main():
|
145
|
-
"""Main demonstration function."""
|
146
|
-
logger.info("🚀 mcp_proxy_adapter SSL Verification Issue Demonstration")
|
147
|
-
logger.info("=" * 70)
|
148
|
-
|
149
|
-
# Test URL with self-signed certificate
|
150
|
-
test_url = "https://127.0.0.1:3004/health"
|
151
|
-
|
152
|
-
# Configuration with verify_server=False (should be respected)
|
153
|
-
config = MockSSLConfig(verify_server=False)
|
154
|
-
|
155
|
-
logger.info(f"\n📋 Test Configuration:")
|
156
|
-
logger.info(f" URL: {test_url}")
|
157
|
-
logger.info(f" verify_server: {config.verify_server}")
|
158
|
-
logger.info(f" CA cert: {config.ca_cert_file}")
|
159
|
-
logger.info(f" Client cert: {config.client_cert_file}")
|
160
|
-
|
161
|
-
# Test 1: Current broken behavior
|
162
|
-
logger.info(f"\n" + "=" * 50)
|
163
|
-
logger.info("TEST 1: Current mcp_proxy_adapter behavior (BROKEN)")
|
164
|
-
logger.info("=" * 50)
|
165
|
-
|
166
|
-
broken_ssl_context = create_client_ssl_context_broken(config)
|
167
|
-
broken_result = await test_connection(
|
168
|
-
broken_ssl_context, test_url, "BROKEN - ignores verify_server=False"
|
169
|
-
)
|
170
|
-
|
171
|
-
# Test 2: Proposed fixed behavior
|
172
|
-
logger.info(f"\n" + "=" * 50)
|
173
|
-
logger.info("TEST 2: Proposed fixed behavior")
|
174
|
-
logger.info("=" * 50)
|
175
|
-
|
176
|
-
fixed_ssl_context = create_client_ssl_context_fixed(config)
|
177
|
-
fixed_result = await test_connection(
|
178
|
-
fixed_ssl_context, test_url, "FIXED - respects verify_server=False"
|
179
|
-
)
|
180
|
-
|
181
|
-
# Summary
|
182
|
-
logger.info(f"\n" + "=" * 50)
|
183
|
-
logger.info("SUMMARY")
|
184
|
-
logger.info("=" * 50)
|
185
|
-
logger.info(
|
186
|
-
f"🔴 Current behavior (broken): {'FAILED' if not broken_result else 'SUCCESS'}"
|
187
|
-
)
|
188
|
-
logger.info(f"🟢 Proposed fix: {'SUCCESS' if fixed_result else 'FAILED'}")
|
189
|
-
|
190
|
-
if not broken_result and fixed_result:
|
191
|
-
logger.info("\n✅ DEMONSTRATION SUCCESSFUL!")
|
192
|
-
logger.info(" The issue is confirmed: verify_server=False is ignored")
|
193
|
-
logger.info(" The proposed fix works: verify_server=False is respected")
|
194
|
-
elif broken_result and not fixed_result:
|
195
|
-
logger.info("\n❓ UNEXPECTED RESULT")
|
196
|
-
logger.info(" Both approaches failed - may be a different issue")
|
197
|
-
else:
|
198
|
-
logger.info("\n❓ INCONCLUSIVE")
|
199
|
-
logger.info(" Results don't clearly demonstrate the issue")
|
200
|
-
|
201
|
-
|
202
|
-
if __name__ == "__main__":
|
203
|
-
try:
|
204
|
-
asyncio.run(main())
|
205
|
-
except KeyboardInterrupt:
|
206
|
-
logger.info("\n🛑 Demonstration interrupted by user")
|
207
|
-
except Exception as e:
|
208
|
-
logger.error(f"\n❌ Demonstration error: {e}")
|
File without changes
|
File without changes
|