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