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.
@@ -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}")