#!/usr/bin/env bash # Shows the sampling and elicitation messages as raw JSON-RPC over Streamable HTTP, using curl as the # "client". Needs: target/mcp-advanced-1.0.0.jar (mvn package -DskipTests), JDK 25 on PATH, curl, python3. # Output goes to output/10-wire-sampling.txt and output/11-wire-elicitation.txt. set -u cd "$(dirname "$0")/.." URL=http://localhost:8089/mcp H=(-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream') OUT=output TMP=$(mktemp -d) setsid nohup java -Dserver.port=8089 -jar target/mcp-advanced-1.0.0.jar > "$TMP/app.log" 2>&1 < /dev/null & APP_PID=$! for i in $(seq 1 60); do curl -s --noproxy '*' -o /dev/null -X POST "$URL" "${H[@]}" -d '{}' && break sleep 1 done # --- initialize, declaring BOTH sampling and elicitation --------------------------------------- curl -s --noproxy '*' -D "$TMP/init.h" -o "$TMP/init.b" -X POST "$URL" "${H[@]}" -d '{ "jsonrpc":"2.0","id":1,"method":"initialize", "params":{"protocolVersion":"2025-11-25", "capabilities":{"sampling":{},"elicitation":{}}, "clientInfo":{"name":"curl-client","version":"0"}}}' SID=$(grep -i '^mcp-session-id:' "$TMP/init.h" | awk '{print $2}' | tr -d '\r') curl -s --noproxy '*' -o /dev/null -X POST "$URL" "${H[@]}" -H "Mcp-Session-Id: $SID" \ -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' # Run one tool call, read the server's request out of the SSE stream, answer it, then show the final result. roundtrip () { # $1 = tool name $2 = arguments json $3 = answer result json $4 = output file $5 = title local call_id=7 curl -s --noproxy '*' -N -X POST "$URL" "${H[@]}" -H "Mcp-Session-Id: $SID" \ -d "{\"jsonrpc\":\"2.0\",\"id\":$call_id,\"method\":\"tools/call\",\"params\":{\"name\":\"$1\",\"arguments\":$2}}" \ > "$TMP/stream.txt" & local cpid=$! for i in $(seq 1 40); do grep -q '"method":"\(sampling/createMessage\|elicitation/create\)"' "$TMP/stream.txt" 2>/dev/null && break; sleep 0.25; done local req_line req_id req_line=$(grep '^data:' "$TMP/stream.txt" | grep -E 'sampling/createMessage|elicitation/create' | head -1 | sed 's/^data: *//') req_id=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1])["id"])' "$req_line") curl -s --noproxy '*' -o /dev/null -X POST "$URL" "${H[@]}" -H "Mcp-Session-Id: $SID" \ -d "{\"jsonrpc\":\"2.0\",\"id\":\"$req_id\",\"result\":$3}" wait $cpid { echo "# $5" echo echo "## 1. client -> server (POST, answers arrive later on the same session)" echo "tools/call $1 $2" echo echo "## 2. server -> client, on the SSE stream of that same POST" python3 -c 'import json,sys; print(json.dumps(json.loads(sys.argv[1]),indent=2))' "$req_line" echo echo "## 3. client -> server, a NEW POST carrying the answer (same id as the server's request)" python3 -c 'import json,sys; print(json.dumps({"jsonrpc":"2.0","id":sys.argv[1],"result":json.loads(sys.argv[2])},indent=2))' "$req_id" "$3" echo echo "## 4. server -> client, the original tools/call finally completes" grep '^data:' "$TMP/stream.txt" | tail -1 | sed 's/^data: *//' | python3 -c 'import json,sys; print(json.dumps(json.load(sys.stdin),indent=2))' } > "$OUT/$4" } roundtrip summarize_incident '{"incidentId":"INC-1043"}' \ '{"role":"assistant","content":{"type":"text","text":"A segment merge pushed p99 to 840ms against a 500ms SLO."},"model":"curl-model","stopReason":"endTurn"}' \ 10-wire-sampling.txt "sampling/createMessage on the wire" roundtrip restart_service '{"service":"payments-api"}' \ '{"action":"accept","content":{"confirm":true,"ticket":"CHG-2291"}}' \ 11-wire-elicitation.txt "elicitation/create on the wire" kill "$APP_PID" 2>/dev/null rm -rf "$TMP"