@@ -28,10 +28,18 @@ jest.mock("@modelcontextprotocol/sdk/client/index.js", () => ({
28
28
} ) ) ;
29
29
30
30
jest . mock ( "@modelcontextprotocol/sdk/client/sse.js" , ( ) => ( {
31
- SSEClientTransport : jest . fn ( ) ,
31
+ SSEClientTransport : jest . fn ( ( url ) => ( {
32
+ toString : ( ) => url ,
33
+ } ) ) ,
32
34
SseError : jest . fn ( ) ,
33
35
} ) ) ;
34
36
37
+ jest . mock ( "@modelcontextprotocol/sdk/client/streamableHttp.js" , ( ) => ( {
38
+ StreamableHTTPClientTransport : jest . fn ( ( url ) => ( {
39
+ toString : ( ) => url ,
40
+ } ) ) ,
41
+ } ) ) ;
42
+
35
43
jest . mock ( "@modelcontextprotocol/sdk/client/auth.js" , ( ) => ( {
36
44
auth : jest . fn ( ) . mockResolvedValue ( "AUTHORIZED" ) ,
37
45
} ) ) ;
@@ -163,4 +171,92 @@ describe("useConnection", () => {
163
171
result . current . makeRequest ( mockRequest , mockSchema ) ,
164
172
) . rejects . toThrow ( "MCP client not connected" ) ;
165
173
} ) ;
174
+
175
+ describe ( "URL Port Handling" , ( ) => {
176
+ const SSEClientTransport = jest . requireMock (
177
+ "@modelcontextprotocol/sdk/client/sse.js" ,
178
+ ) . SSEClientTransport ;
179
+ const StreamableHTTPClientTransport = jest . requireMock (
180
+ "@modelcontextprotocol/sdk/client/streamableHttp.js" ,
181
+ ) . StreamableHTTPClientTransport ;
182
+
183
+ beforeEach ( ( ) => {
184
+ jest . clearAllMocks ( ) ;
185
+ } ) ;
186
+
187
+ test ( "preserves HTTPS port number when connecting" , async ( ) => {
188
+ const props = {
189
+ ...defaultProps ,
190
+ sseUrl : "https://example.com:8443/api" ,
191
+ transportType : "sse" as const ,
192
+ } ;
193
+
194
+ const { result } = renderHook ( ( ) => useConnection ( props ) ) ;
195
+
196
+ await act ( async ( ) => {
197
+ await result . current . connect ( ) ;
198
+ } ) ;
199
+
200
+ const call = SSEClientTransport . mock . calls [ 0 ] [ 0 ] ;
201
+ expect ( call . toString ( ) ) . toContain (
202
+ "url=https%3A%2F%2Fexample.com%3A8443%2Fapi" ,
203
+ ) ;
204
+ } ) ;
205
+
206
+ test ( "preserves HTTP port number when connecting" , async ( ) => {
207
+ const props = {
208
+ ...defaultProps ,
209
+ sseUrl : "http://localhost:3000/api" ,
210
+ transportType : "sse" as const ,
211
+ } ;
212
+
213
+ const { result } = renderHook ( ( ) => useConnection ( props ) ) ;
214
+
215
+ await act ( async ( ) => {
216
+ await result . current . connect ( ) ;
217
+ } ) ;
218
+
219
+ const call = SSEClientTransport . mock . calls [ 0 ] [ 0 ] ;
220
+ expect ( call . toString ( ) ) . toContain (
221
+ "url=http%3A%2F%2Flocalhost%3A3000%2Fapi" ,
222
+ ) ;
223
+ } ) ;
224
+
225
+ test ( "uses default port for HTTPS when not specified" , async ( ) => {
226
+ const props = {
227
+ ...defaultProps ,
228
+ sseUrl : "https://example.com/api" ,
229
+ transportType : "sse" as const ,
230
+ } ;
231
+
232
+ const { result } = renderHook ( ( ) => useConnection ( props ) ) ;
233
+
234
+ await act ( async ( ) => {
235
+ await result . current . connect ( ) ;
236
+ } ) ;
237
+
238
+ const call = SSEClientTransport . mock . calls [ 0 ] [ 0 ] ;
239
+ expect ( call . toString ( ) ) . toContain ( "url=https%3A%2F%2Fexample.com%2Fapi" ) ;
240
+ expect ( call . toString ( ) ) . not . toContain ( "%3A443" ) ;
241
+ } ) ;
242
+
243
+ test ( "preserves port number in streamable-http transport" , async ( ) => {
244
+ const props = {
245
+ ...defaultProps ,
246
+ sseUrl : "https://example.com:8443/api" ,
247
+ transportType : "streamable-http" as const ,
248
+ } ;
249
+
250
+ const { result } = renderHook ( ( ) => useConnection ( props ) ) ;
251
+
252
+ await act ( async ( ) => {
253
+ await result . current . connect ( ) ;
254
+ } ) ;
255
+
256
+ const call = StreamableHTTPClientTransport . mock . calls [ 0 ] [ 0 ] ;
257
+ expect ( call . toString ( ) ) . toContain (
258
+ "url=https%3A%2F%2Fexample.com%3A8443%2Fapi" ,
259
+ ) ;
260
+ } ) ;
261
+ } ) ;
166
262
} ) ;
0 commit comments