124124# Test 3: Pull gateway container image
125125log_section " Test 3: Gateway Container Image Availability"
126126count_test
127- log_info " Pulling gateway container image..."
128- if docker pull " $GATEWAY_IMAGE " > /dev/null 2>&1 ; then
127+ # Check if image exists locally first
128+ if docker image inspect " $GATEWAY_IMAGE " > /dev/null 2>&1 ; then
129+ log_info " Using local gateway image (skipping pull)"
130+ log_success " Gateway container image is available"
131+ elif docker pull " $GATEWAY_IMAGE " > /dev/null 2>&1 ; then
132+ log_info " Pulling gateway container image..."
129133 log_success " Gateway container image is available"
130134else
131135 log_error " Failed to pull gateway container image: $GATEWAY_IMAGE "
@@ -239,22 +243,63 @@ else
239243 exit 1
240244fi
241245
242- # Function to send MCP request via gateway
243- send_mcp_request () {
246+ # Session ID for MCP Streamable HTTP transport
247+ # Stored in a file to survive subshell boundaries
248+ MCP_SESSION_FILE=" $TEMP_DIR /mcp_session_id.txt"
249+ echo " " > " $MCP_SESSION_FILE "
250+
251+ # Response file for avoiding subshell variable scope issues
252+ MCP_RESPONSE_FILE=" $TEMP_DIR /mcp_response.txt"
253+
254+ # Function to get the current session ID
255+ get_session_id () {
256+ cat " $MCP_SESSION_FILE " 2> /dev/null || echo " "
257+ }
258+
259+ # Function to send MCP request and capture session ID
260+ # This writes response to MCP_RESPONSE_FILE and updates session ID file
261+ send_mcp_request_direct () {
244262 local request=" $1 "
245263 local endpoint=" http://localhost:$GATEWAY_PORT /mcp/serena"
264+ local headers_file=" $TEMP_DIR /response_headers.txt"
265+ local session_id=$( get_session_id)
266+
267+ # Run curl and save response to file
268+ if [ -n " $session_id " ]; then
269+ curl -s -X POST " $endpoint " \
270+ -H " Content-Type: application/json" \
271+ -H " Accept: application/json, text/event-stream" \
272+ -H " Authorization: $GATEWAY_API_KEY " \
273+ -H " Mcp-Session-Id: $session_id " \
274+ -D " $headers_file " \
275+ -d " $request " > " $MCP_RESPONSE_FILE " 2> /dev/null || echo ' {"error": "request failed"}' > " $MCP_RESPONSE_FILE "
276+ else
277+ curl -s -X POST " $endpoint " \
278+ -H " Content-Type: application/json" \
279+ -H " Accept: application/json, text/event-stream" \
280+ -H " Authorization: $GATEWAY_API_KEY " \
281+ -D " $headers_file " \
282+ -d " $request " > " $MCP_RESPONSE_FILE " 2> /dev/null || echo ' {"error": "request failed"}' > " $MCP_RESPONSE_FILE "
283+ fi
246284
247- curl -s -X POST " $endpoint " \
248- -H " Content-Type: application/json" \
249- -H " Accept: application/json, text/event-stream" \
250- -H " Authorization: $GATEWAY_API_KEY " \
251- -d " $request " 2> /dev/null || echo ' {"error": "request failed"}'
285+ # Capture session ID from response headers and save to file
286+ if [ -f " $headers_file " ]; then
287+ local new_session_id=$( grep -i " ^mcp-session-id:" " $headers_file " | sed ' s/^[Mm]cp-[Ss]ession-[Ii]d: *//;s/\r$//' | head -1)
288+ if [ -n " $new_session_id " ]; then
289+ echo " $new_session_id " > " $MCP_SESSION_FILE "
290+ fi
291+ fi
252292}
253293
254- # Function to send MCP request and parse response (handles SSE)
255- send_and_parse_mcp_request () {
256- local request=" $1 "
257- local raw_response=$( send_mcp_request " $request " )
294+ # Function to send MCP request and get the raw response
295+ # Call send_mcp_request_direct first, then use get_mcp_response
296+ get_mcp_response () {
297+ cat " $MCP_RESPONSE_FILE "
298+ }
299+
300+ # Function to get parsed JSON from SSE response
301+ get_mcp_response_json () {
302+ local raw_response=$( cat " $MCP_RESPONSE_FILE " )
258303
259304 # Check if response is SSE format
260305 if echo " $raw_response " | grep -q " ^event: message" ; then
@@ -266,21 +311,43 @@ send_and_parse_mcp_request() {
266311 fi
267312}
268313
314+ # Legacy function for backward compatibility
315+ send_mcp_request () {
316+ local request=" $1 "
317+ send_mcp_request_direct " $request "
318+ get_mcp_response
319+ }
320+
321+ # Legacy function for backward compatibility - parses SSE response
322+ # NOTE: Session ID is now persisted to file, so it survives subshell usage
323+ send_and_parse_mcp_request () {
324+ local request=" $1 "
325+ send_mcp_request_direct " $request "
326+ get_mcp_response_json
327+ }
328+
269329# Test 6: MCP Protocol - Initialize
270330log_section " Test 6: MCP Protocol Initialize (via Gateway)"
271331count_test
272332log_info " Sending MCP initialize request through gateway..."
273333
274334INIT_REQUEST=' {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test-client","version":"1.0.0"}}}'
275335
336+ # Send request - session ID will be captured and saved to file
276337INIT_JSON=$( send_and_parse_mcp_request " $INIT_REQUEST " )
277338
278339echo " $INIT_JSON " > " $RESULTS_DIR /initialize_response.json"
279340
341+ MCP_SESSION_ID=$( get_session_id)
280342if echo " $INIT_JSON " | grep -q ' "jsonrpc"' ; then
281343 if echo " $INIT_JSON " | grep -q ' "result"' ; then
282344 log_success " MCP initialize succeeded through gateway"
283345 log_info " Response saved to: $RESULTS_DIR /initialize_response.json"
346+ if [ -n " $MCP_SESSION_ID " ]; then
347+ log_info " MCP Session ID: $MCP_SESSION_ID "
348+ else
349+ log_warning " No MCP Session ID captured - subsequent requests may fail"
350+ fi
284351 else
285352 log_error " MCP initialize returned error through gateway"
286353 echo " $INIT_JSON " | head -5
293360# Send initialized notification to complete handshake
294361log_info " Sending initialized notification to complete MCP handshake..."
295362INITIALIZED_NOTIF=' {"jsonrpc":"2.0","method":"notifications/initialized"}'
296- send_mcp_request " $INITIALIZED_NOTIF " > /dev/null 2>&1
363+ send_mcp_request_direct " $INITIALIZED_NOTIF "
297364
298365# Give the server a moment to process the notification
299366sleep 1
0 commit comments