From 3537626bfe0e685394cfa17e08fca403c9c031ed Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 08:06:05 +0000 Subject: [PATCH 1/7] Initial plan From 1e761d2827c3e90bc3c6eac9f9d58eb583688773 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 08:31:35 +0000 Subject: [PATCH 2/7] fix: use tools/list instead of ping in check_mcp_servers.sh to ensure backends are ready Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/sh/check_mcp_servers.sh | 16 +++++++++++----- actions/setup/sh/check_mcp_servers_test.sh | 8 ++++---- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/actions/setup/sh/check_mcp_servers.sh b/actions/setup/sh/check_mcp_servers.sh index 8d72f14c5f..78c6c36d92 100755 --- a/actions/setup/sh/check_mcp_servers.sh +++ b/actions/setup/sh/check_mcp_servers.sh @@ -6,8 +6,11 @@ # Resilience Features: # - Progressive timeout: 10s, 20s, 30s across retry attempts # - Progressive delay: 2s, 4s between retry attempts -# - Up to 3 retry attempts per server ping request +# - Up to 3 retry attempts per server tools/list request # - Accommodates slow-starting MCP servers (gateway may take 40-50 seconds to start) +# Note: We use tools/list instead of ping because ping may be handled by the gateway +# itself without being forwarded to the backend. tools/list must be forwarded to the +# backend container, ensuring the backend is truly ready (not just the gateway proxy). set -e @@ -115,8 +118,11 @@ while IFS= read -r SERVER_NAME; do AUTH_HEADER=$(echo "$SERVER_CONFIG" | jq -r '.headers.Authorization' 2>/dev/null) fi - # Send MCP ping request with retry logic - PING_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"ping"}' + # Send MCP tools/list request with retry logic + # Use tools/list instead of ping: tools/list must be forwarded to the backend + # container by the gateway, whereas ping may be handled by the gateway proxy itself + # without reaching the backend. This ensures the backend is truly ready. + TOOLS_LIST_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"tools/list"}' # Retry logic for slow-starting servers RETRY_COUNT=0 @@ -141,11 +147,11 @@ while IFS= read -r SERVER_NAME; do PING_RESPONSE=$(curl -s -w "\n%{http_code}" --max-time $TIMEOUT -X POST "$SERVER_URL" \ -H "Content-Type: application/json" \ -H "Authorization: $AUTH_HEADER" \ - -d "$PING_PAYLOAD" 2>&1 || echo -e "\n000") + -d "$TOOLS_LIST_PAYLOAD" 2>&1 || echo -e "\n000") else PING_RESPONSE=$(curl -s -w "\n%{http_code}" --max-time $TIMEOUT -X POST "$SERVER_URL" \ -H "Content-Type: application/json" \ - -d "$PING_PAYLOAD" 2>&1 || echo -e "\n000") + -d "$TOOLS_LIST_PAYLOAD" 2>&1 || echo -e "\n000") fi PING_HTTP_CODE=$(echo "$PING_RESPONSE" | tail -n 1) diff --git a/actions/setup/sh/check_mcp_servers_test.sh b/actions/setup/sh/check_mcp_servers_test.sh index c3c242e330..12bee8d914 100755 --- a/actions/setup/sh/check_mcp_servers_test.sh +++ b/actions/setup/sh/check_mcp_servers_test.sh @@ -314,11 +314,11 @@ test_validation_functions_exist() { print_result "mcpServers parsing validation missing" "FAIL" fi - # Check for ping request (replacing initialize and tools/list) - if grep -q "method.*ping" "$SCRIPT_PATH"; then - print_result "Ping request logic exists" "PASS" + # Check for tools/list request (used instead of ping to verify backend connectivity) + if grep -q 'method.*tools/list' "$SCRIPT_PATH"; then + print_result "tools/list request logic exists" "PASS" else - print_result "Ping request logic missing" "FAIL" + print_result "tools/list request logic missing" "FAIL" fi # Check for gateway config authentication logic From bbab4fc86c8e04a66774b01af9ea131b783b5fea Mon Sep 17 00:00:00 2001 From: Codex Bot Date: Sat, 21 Feb 2026 11:30:02 +0000 Subject: [PATCH 3/7] Add changeset [skip-ci] --- .changeset/patch-check-mcp-servers-tools-list.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/patch-check-mcp-servers-tools-list.md diff --git a/.changeset/patch-check-mcp-servers-tools-list.md b/.changeset/patch-check-mcp-servers-tools-list.md new file mode 100644 index 0000000000..cba7c69dc1 --- /dev/null +++ b/.changeset/patch-check-mcp-servers-tools-list.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Ensure `check_mcp_servers.sh` uses `tools/list` instead of `ping` so the readiness probe waits for the backend containers to become available. From 17ffad7021af2e4073164cd4df16a3b7c44bd476 Mon Sep 17 00:00:00 2001 From: Claude Smoke Test Date: Sat, 21 Feb 2026 11:32:13 +0000 Subject: [PATCH 4/7] test: Add smoke test file for run 22255965551 --- tmp-smoke-test-22255965551.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 tmp-smoke-test-22255965551.txt diff --git a/tmp-smoke-test-22255965551.txt b/tmp-smoke-test-22255965551.txt new file mode 100644 index 0000000000..70ac4518ed --- /dev/null +++ b/tmp-smoke-test-22255965551.txt @@ -0,0 +1 @@ +Test file for PR push - smoke test run 22255965551 From e73f270fab5682be4cd9e6d24984e69338e61f07 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 11:59:29 +0000 Subject: [PATCH 5/7] fix: implement MCP initialize+session protocol in check_mcp_servers.sh Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/sh/check_mcp_servers.sh | 85 +++++++++++++--------- actions/setup/sh/check_mcp_servers_test.sh | 14 ++++ 2 files changed, 63 insertions(+), 36 deletions(-) diff --git a/actions/setup/sh/check_mcp_servers.sh b/actions/setup/sh/check_mcp_servers.sh index 78c6c36d92..80f01071ed 100755 --- a/actions/setup/sh/check_mcp_servers.sh +++ b/actions/setup/sh/check_mcp_servers.sh @@ -1,16 +1,17 @@ #!/usr/bin/env bash # Check MCP Server Functionality # This script performs basic functionality checks on MCP servers configured by the MCP gateway -# It sends a ping message to each server to verify connectivity +# It sends an MCP initialize + tools/list request to each server to verify backend connectivity # # Resilience Features: # - Progressive timeout: 10s, 20s, 30s across retry attempts # - Progressive delay: 2s, 4s between retry attempts -# - Up to 3 retry attempts per server tools/list request +# - Up to 3 retry attempts per server # - Accommodates slow-starting MCP servers (gateway may take 40-50 seconds to start) -# Note: We use tools/list instead of ping because ping may be handled by the gateway -# itself without being forwarded to the backend. tools/list must be forwarded to the -# backend container, ensuring the backend is truly ready (not just the gateway proxy). +# Note: MCP protocol requires initialize before tools/list. We use tools/list (not ping) because +# ping may be handled by the gateway itself without being forwarded to the backend. tools/list must +# be forwarded to the backend container, ensuring the backend is truly ready. The Mcp-Session-Id +# header returned by initialize is passed to tools/list when present. set -e @@ -118,15 +119,15 @@ while IFS= read -r SERVER_NAME; do AUTH_HEADER=$(echo "$SERVER_CONFIG" | jq -r '.headers.Authorization' 2>/dev/null) fi - # Send MCP tools/list request with retry logic - # Use tools/list instead of ping: tools/list must be forwarded to the backend - # container by the gateway, whereas ping may be handled by the gateway proxy itself - # without reaching the backend. This ensures the backend is truly ready. - TOOLS_LIST_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"tools/list"}' + # MCP protocol requires initialize before tools/list. + # initialize establishes protocol version and may return a Mcp-Session-Id header + # that must be included in subsequent requests (for stateful HTTP transports). + INIT_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"check-mcp-servers","version":"1.0.0"},"protocolVersion":"2024-11-05"}}' + TOOLS_LIST_PAYLOAD='{"jsonrpc":"2.0","id":2,"method":"tools/list"}' # Retry logic for slow-starting servers RETRY_COUNT=0 - PING_SUCCESS=false + CHECK_SUCCESS=false LAST_ERROR="" while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do @@ -142,42 +143,54 @@ while IFS= read -r SERVER_NAME; do echo " Attempting connection (timeout: ${TIMEOUT}s)..." fi - # Make the request with proper headers and progressive timeout - if [ -n "$AUTH_HEADER" ]; then - PING_RESPONSE=$(curl -s -w "\n%{http_code}" --max-time $TIMEOUT -X POST "$SERVER_URL" \ - -H "Content-Type: application/json" \ - -H "Authorization: $AUTH_HEADER" \ - -d "$TOOLS_LIST_PAYLOAD" 2>&1 || echo -e "\n000") - else - PING_RESPONSE=$(curl -s -w "\n%{http_code}" --max-time $TIMEOUT -X POST "$SERVER_URL" \ - -H "Content-Type: application/json" \ - -d "$TOOLS_LIST_PAYLOAD" 2>&1 || echo -e "\n000") + # Step 1: Send MCP initialize request, capturing response headers for Mcp-Session-Id + CURL_ARGS=(-s -D - --max-time "$TIMEOUT" -X POST "$SERVER_URL" + -H "Content-Type: application/json") + [ -n "$AUTH_HEADER" ] && CURL_ARGS+=(-H "Authorization: $AUTH_HEADER") + CURL_ARGS+=(-d "$INIT_PAYLOAD") + INIT_RESPONSE=$(curl "${CURL_ARGS[@]}" 2>&1 || true) + + INIT_HTTP_CODE=$(echo "$INIT_RESPONSE" | grep -m1 '^HTTP/' | awk '{print $2}') + SESSION_ID=$(echo "$INIT_RESPONSE" | grep -i '^Mcp-Session-Id:' | awk '{print $2}' | tr -d '\r') + + if [ "$INIT_HTTP_CODE" != "200" ]; then + LAST_ERROR="Initialize failed: HTTP ${INIT_HTTP_CODE:-000}" + RETRY_COUNT=$((RETRY_COUNT + 1)) + continue fi - PING_HTTP_CODE=$(echo "$PING_RESPONSE" | tail -n 1) - PING_BODY=$(echo "$PING_RESPONSE" | head -n -1) + # Step 2: Send tools/list, including Mcp-Session-Id header if returned by initialize + CURL_ARGS=(-s -w "\n%{http_code}" --max-time "$TIMEOUT" -X POST "$SERVER_URL" + -H "Content-Type: application/json") + [ -n "$AUTH_HEADER" ] && CURL_ARGS+=(-H "Authorization: $AUTH_HEADER") + [ -n "$SESSION_ID" ] && CURL_ARGS+=(-H "Mcp-Session-Id: $SESSION_ID") + CURL_ARGS+=(-d "$TOOLS_LIST_PAYLOAD") + CHECK_RESPONSE=$(curl "${CURL_ARGS[@]}" 2>&1 || echo -e "\n000") + + CHECK_HTTP_CODE=$(echo "$CHECK_RESPONSE" | tail -n 1) + CHECK_BODY=$(echo "$CHECK_RESPONSE" | head -n -1) - # Check if ping succeeded - if [ "$PING_HTTP_CODE" = "200" ]; then + # Check if tools/list succeeded + if [ "$CHECK_HTTP_CODE" = "200" ]; then # Check for JSON-RPC error in response - if ! echo "$PING_BODY" | jq -e '.error' >/dev/null 2>&1; then - PING_SUCCESS=true + if ! echo "$CHECK_BODY" | jq -e '.error' >/dev/null 2>&1; then + CHECK_SUCCESS=true break else - LAST_ERROR="JSON-RPC error: $(echo "$PING_BODY" | jq -r '.error.message // .error' 2>/dev/null)" + LAST_ERROR="JSON-RPC error: $(echo "$CHECK_BODY" | jq -r '.error.message // .error' 2>/dev/null)" fi else - LAST_ERROR="HTTP ${PING_HTTP_CODE}" - if [ "$PING_HTTP_CODE" = "000" ]; then + LAST_ERROR="HTTP ${CHECK_HTTP_CODE}" + if [ "$CHECK_HTTP_CODE" = "000" ]; then # Connection error or timeout - if echo "$PING_BODY" | grep -q "Connection refused"; then + if echo "$CHECK_BODY" | grep -q "Connection refused"; then LAST_ERROR="Connection refused" - elif echo "$PING_BODY" | grep -q "timed out"; then + elif echo "$CHECK_BODY" | grep -q "timed out"; then LAST_ERROR="Connection timeout" - elif echo "$PING_BODY" | grep -q "Could not resolve host"; then + elif echo "$CHECK_BODY" | grep -q "Could not resolve host"; then LAST_ERROR="DNS resolution failed" else - LAST_ERROR="Connection error: $(echo "$PING_BODY" | head -c 100)" + LAST_ERROR="Connection error: $(echo "$CHECK_BODY" | head -c 100)" fi fi fi @@ -185,7 +198,7 @@ while IFS= read -r SERVER_NAME; do RETRY_COUNT=$((RETRY_COUNT + 1)) done - if [ "$PING_SUCCESS" = true ]; then + if [ "$CHECK_SUCCESS" = true ]; then echo "✓ $SERVER_NAME: connected" SERVERS_SUCCEEDED=$((SERVERS_SUCCEEDED + 1)) else @@ -208,7 +221,7 @@ if [ $SERVERS_FAILED -gt 0 ]; then echo "ERROR: $SERVERS_FAILED of $SERVERS_CHECKED server(s) failed connectivity check" echo "Succeeded: $SERVERS_SUCCEEDED, Failed: $SERVERS_FAILED, Skipped: $SERVERS_SKIPPED" echo "" - echo "This indicates that one or more MCP servers failed to respond to ping requests" + echo "This indicates that one or more MCP servers failed to respond to MCP initialize/tools/list requests" echo "after multiple retry attempts with progressive timeouts (10s, 20s, 30s)." echo "" echo "Common causes:" diff --git a/actions/setup/sh/check_mcp_servers_test.sh b/actions/setup/sh/check_mcp_servers_test.sh index 12bee8d914..12f1f62f37 100755 --- a/actions/setup/sh/check_mcp_servers_test.sh +++ b/actions/setup/sh/check_mcp_servers_test.sh @@ -321,6 +321,20 @@ test_validation_functions_exist() { print_result "tools/list request logic missing" "FAIL" fi + # Check for MCP initialize before tools/list (per MCP protocol) + if grep -q 'method.*initialize' "$SCRIPT_PATH"; then + print_result "MCP initialize request logic exists" "PASS" + else + print_result "MCP initialize request logic missing" "FAIL" + fi + + # Check for Mcp-Session-Id handling + if grep -q 'Mcp-Session-Id' "$SCRIPT_PATH"; then + print_result "Mcp-Session-Id session tracking exists" "PASS" + else + print_result "Mcp-Session-Id session tracking missing" "FAIL" + fi + # Check for gateway config authentication logic if grep -q "Authorization" "$SCRIPT_PATH"; then print_result "Gateway config authentication logic exists" "PASS" From 88da7ae5d6a653011a4703c78d1824b8e148fc49 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 21 Feb 2026 12:07:19 +0000 Subject: [PATCH 6/7] =?UTF-8?q?fix:=20add=20ping=20as=20first=20step=20in?= =?UTF-8?q?=20MCP=20protocol=20sequence=20(ping=20=E2=86=92=20initialize?= =?UTF-8?q?=20=E2=86=92=20tools/list)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/sh/check_mcp_servers.sh | 38 +++++++++++++++------- actions/setup/sh/check_mcp_servers_test.sh | 7 ++++ 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/actions/setup/sh/check_mcp_servers.sh b/actions/setup/sh/check_mcp_servers.sh index 80f01071ed..0f1bffe53f 100755 --- a/actions/setup/sh/check_mcp_servers.sh +++ b/actions/setup/sh/check_mcp_servers.sh @@ -1,17 +1,16 @@ #!/usr/bin/env bash # Check MCP Server Functionality # This script performs basic functionality checks on MCP servers configured by the MCP gateway -# It sends an MCP initialize + tools/list request to each server to verify backend connectivity +# It sends an MCP ping + initialize + tools/list request to each server to verify backend connectivity # # Resilience Features: # - Progressive timeout: 10s, 20s, 30s across retry attempts # - Progressive delay: 2s, 4s between retry attempts # - Up to 3 retry attempts per server # - Accommodates slow-starting MCP servers (gateway may take 40-50 seconds to start) -# Note: MCP protocol requires initialize before tools/list. We use tools/list (not ping) because -# ping may be handled by the gateway itself without being forwarded to the backend. tools/list must -# be forwarded to the backend container, ensuring the backend is truly ready. The Mcp-Session-Id -# header returned by initialize is passed to tools/list when present. +# Protocol: ping verifies basic connectivity; initialize establishes the session (capturing +# Mcp-Session-Id); tools/list confirms the backend container is truly ready (must be forwarded +# by the gateway, unlike ping which may be handled at the proxy layer). set -e @@ -119,11 +118,14 @@ while IFS= read -r SERVER_NAME; do AUTH_HEADER=$(echo "$SERVER_CONFIG" | jq -r '.headers.Authorization' 2>/dev/null) fi - # MCP protocol requires initialize before tools/list. + # MCP protocol sequence: ping → initialize → tools/list. + # ping verifies basic connectivity (may be handled by the gateway proxy). # initialize establishes protocol version and may return a Mcp-Session-Id header # that must be included in subsequent requests (for stateful HTTP transports). - INIT_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"check-mcp-servers","version":"1.0.0"},"protocolVersion":"2024-11-05"}}' - TOOLS_LIST_PAYLOAD='{"jsonrpc":"2.0","id":2,"method":"tools/list"}' + # tools/list must be forwarded to the backend container, confirming the backend is ready. + PING_PAYLOAD='{"jsonrpc":"2.0","id":1,"method":"ping"}' + INIT_PAYLOAD='{"jsonrpc":"2.0","id":2,"method":"initialize","params":{"capabilities":{},"clientInfo":{"name":"check-mcp-servers","version":"1.0.0"},"protocolVersion":"2024-11-05"}}' + TOOLS_LIST_PAYLOAD='{"jsonrpc":"2.0","id":3,"method":"tools/list"}' # Retry logic for slow-starting servers RETRY_COUNT=0 @@ -143,7 +145,21 @@ while IFS= read -r SERVER_NAME; do echo " Attempting connection (timeout: ${TIMEOUT}s)..." fi - # Step 1: Send MCP initialize request, capturing response headers for Mcp-Session-Id + # Step 1: Send ping to verify basic connectivity + CURL_ARGS=(-s -w "\n%{http_code}" --max-time "$TIMEOUT" -X POST "$SERVER_URL" + -H "Content-Type: application/json") + [ -n "$AUTH_HEADER" ] && CURL_ARGS+=(-H "Authorization: $AUTH_HEADER") + CURL_ARGS+=(-d "$PING_PAYLOAD") + PING_RESPONSE=$(curl "${CURL_ARGS[@]}" 2>&1 || echo -e "\n000") + PING_HTTP_CODE=$(echo "$PING_RESPONSE" | tail -n 1) + + if [ "$PING_HTTP_CODE" != "200" ]; then + LAST_ERROR="Ping failed: HTTP ${PING_HTTP_CODE:-000}" + RETRY_COUNT=$((RETRY_COUNT + 1)) + continue + fi + + # Step 2: Send MCP initialize request, capturing response headers for Mcp-Session-Id CURL_ARGS=(-s -D - --max-time "$TIMEOUT" -X POST "$SERVER_URL" -H "Content-Type: application/json") [ -n "$AUTH_HEADER" ] && CURL_ARGS+=(-H "Authorization: $AUTH_HEADER") @@ -159,7 +175,7 @@ while IFS= read -r SERVER_NAME; do continue fi - # Step 2: Send tools/list, including Mcp-Session-Id header if returned by initialize + # Step 3: Send tools/list, including Mcp-Session-Id header if returned by initialize CURL_ARGS=(-s -w "\n%{http_code}" --max-time "$TIMEOUT" -X POST "$SERVER_URL" -H "Content-Type: application/json") [ -n "$AUTH_HEADER" ] && CURL_ARGS+=(-H "Authorization: $AUTH_HEADER") @@ -221,7 +237,7 @@ if [ $SERVERS_FAILED -gt 0 ]; then echo "ERROR: $SERVERS_FAILED of $SERVERS_CHECKED server(s) failed connectivity check" echo "Succeeded: $SERVERS_SUCCEEDED, Failed: $SERVERS_FAILED, Skipped: $SERVERS_SKIPPED" echo "" - echo "This indicates that one or more MCP servers failed to respond to MCP initialize/tools/list requests" + echo "This indicates that one or more MCP servers failed to respond to MCP ping/initialize/tools/list requests" echo "after multiple retry attempts with progressive timeouts (10s, 20s, 30s)." echo "" echo "Common causes:" diff --git a/actions/setup/sh/check_mcp_servers_test.sh b/actions/setup/sh/check_mcp_servers_test.sh index 12f1f62f37..561a88f733 100755 --- a/actions/setup/sh/check_mcp_servers_test.sh +++ b/actions/setup/sh/check_mcp_servers_test.sh @@ -321,6 +321,13 @@ test_validation_functions_exist() { print_result "tools/list request logic missing" "FAIL" fi + # Check for MCP ping as first step (per MCP protocol) + if grep -q 'method.*ping' "$SCRIPT_PATH"; then + print_result "MCP ping request logic exists" "PASS" + else + print_result "MCP ping request logic missing" "FAIL" + fi + # Check for MCP initialize before tools/list (per MCP protocol) if grep -q 'method.*initialize' "$SCRIPT_PATH"; then print_result "MCP initialize request logic exists" "PASS" From a587be03afb9ae542ed2213a2c86b41e922362e7 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 21 Feb 2026 12:12:27 +0000 Subject: [PATCH 7/7] Add changeset [skip-ci] --- .changeset/patch-fix-mcp-handshake-readiness.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/patch-fix-mcp-handshake-readiness.md diff --git a/.changeset/patch-fix-mcp-handshake-readiness.md b/.changeset/patch-fix-mcp-handshake-readiness.md new file mode 100644 index 0000000000..dce7626f22 --- /dev/null +++ b/.changeset/patch-fix-mcp-handshake-readiness.md @@ -0,0 +1,5 @@ +--- +"gh-aw": patch +--- + +Ensure `check_mcp_servers.sh` runs the full MCP handshake (ping → initialize → tools/list) with the session ID so the readiness probe waits for backend containers.