quickstart-resources/tests/smoke-test.sh
olaservo 75796e0c98 Cover the Ruby MCP client in the smoke tests
CI installed no Ruby toolchain and the suite ran no Ruby example, so
nothing under mcp-client-ruby or weather-server-ruby was exercised by a
green build. A dependency change there -- #177 removes the base64 gem
now that the anthropic gem declares it -- merges on the strength of a
check that never resolved its Gemfile.

The client is drivable without credentials: it connects before it looks
for ANTHROPIC_API_KEY and exits 0 when there is none, the same shape the
Python and TypeScript clients already rely on for their coverage.

The Ruby weather server stays uncovered. The mcp gem's server does not
emit the resultType field that protocol revision 2026-07-28 makes
mandatory, so the test client rejects its responses; that is a fix for
the gem rather than something an example can work around. The README
said the gem could not negotiate the revision at all, which stopped
being true at 1.1.0 -- it negotiates, then answers incompletely.

Ruby 3.4 rather than the 3.2.0 floor the anthropic gem declares: 3.2
reached end of life in March 2026, and a gem's floor says what it
tolerates, not what an example should tell people to run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-09 21:11:42 -07:00

151 lines
4.4 KiB
Shell
Executable file

#!/bin/bash
set -e
# Source utilities
source "$(dirname "$0")/utils.sh"
print_header "MCP Quickstart Smoke Tests"
# Get project root
PROJECT_ROOT=$(get_project_root)
TESTS_DIR="${PROJECT_ROOT}/tests"
# Setup common test variables
TEST_CLIENT="${PROJECT_ROOT}/tests/helpers/build/mcp-test-client.js"
MOCK_SERVER="${PROJECT_ROOT}/tests/helpers/build/mock-mcp-server.js"
# Track test results
FAILED_TESTS=()
PASSED_TESTS=()
# Build test helpers
ensure_helpers_built
# Helper function to run a test and track results
run_test() {
local test_name=$1
echo ""
print_header "Testing ${test_name}"
if "${@:2}"; then
PASSED_TESTS+=("${test_name}")
print_success "${test_name} test passed"
else
FAILED_TESTS+=("${test_name}")
print_error "${test_name} test failed"
fi
}
# Test: Python weather server
test_weather_server_python() {
check_dependency uv || return 1
local server_dir="${PROJECT_ROOT}/weather-server-python"
node "${TEST_CLIENT}" uv --directory "${server_dir}" run weather.py
}
# Test: TypeScript weather server
test_weather_server_typescript() {
check_dependency node || return 1
check_dependency npm || return 1
local server_dir="${PROJECT_ROOT}/weather-server-typescript"
ensure_built "${server_dir}" || return 1
node "${TEST_CLIENT}" node "${server_dir}/build/index.js"
}
# Test: Rust weather server
test_weather_server_rust() {
check_dependency cargo || return 1
local server_dir="${PROJECT_ROOT}/weather-server-rust"
ensure_built "${server_dir}" || return 1
# Determine which binary to use
local server_bin
server_bin=$(resolve_binary "${server_dir}/target/release/weather" \
|| resolve_binary "${server_dir}/target/debug/weather") || {
print_error "no weather binary found in ${server_dir}/target"
return 1
}
node "${TEST_CLIENT}" "${server_bin}"
}
# Test: Go weather server
test_weather_server_go() {
check_dependency go || return 1
local server_dir="${PROJECT_ROOT}/weather-server-go"
ensure_built "${server_dir}" || return 1
local server_bin
server_bin=$(resolve_binary "${server_dir}/server") || {
print_error "no server binary found in ${server_dir}"
return 1
}
node "${TEST_CLIENT}" "${server_bin}"
}
# Test: Python MCP client
test_mcp_client_python() {
check_dependency uv || return 1
local client_dir="${PROJECT_ROOT}/mcp-client-python"
uv --directory "${client_dir}" run python "${client_dir}/client.py" "${MOCK_SERVER}" >/dev/null 2>&1
}
# Test: TypeScript MCP client
test_mcp_client_typescript() {
check_dependency node || return 1
check_dependency npm || return 1
local client_dir="${PROJECT_ROOT}/mcp-client-typescript"
ensure_built "${client_dir}" || return 1
node "${client_dir}/build/index.js" "${MOCK_SERVER}" >/dev/null 2>&1
}
# Test: Ruby MCP client
test_mcp_client_ruby() {
check_dependency ruby || return 1
check_dependency bundle || return 1
local client_dir="${PROJECT_ROOT}/mcp-client-ruby"
ensure_bundled "${client_dir}" || return 1
(cd "${client_dir}" && bundle exec ruby client.rb "${MOCK_SERVER}") >/dev/null 2>&1
}
# Run all tests
#
# The Go and Rust clients are not covered: on main both abort when no .env file
# is present, so they cannot be driven without credentials. Making them start
# credential-free is a change in their own directories, so their coverage lands
# with those changes rather than here.
#
# Nor is the Ruby weather server: the mcp gem does not stamp the resultType
# field that 2026-07-28 requires, so the test client rejects its responses.
print_header "Running smoke tests"
run_test "weather-server-python" test_weather_server_python
run_test "weather-server-typescript" test_weather_server_typescript
run_test "weather-server-rust" test_weather_server_rust
run_test "weather-server-go" test_weather_server_go
run_test "mcp-client-python" test_mcp_client_python
run_test "mcp-client-typescript" test_mcp_client_typescript
run_test "mcp-client-ruby" test_mcp_client_ruby
# Print summary
echo ""
print_header "Test Summary"
echo "Passed: ${#PASSED_TESTS[@]}"
for test in "${PASSED_TESTS[@]}"; do
print_success "${test}"
done
if [ ${#FAILED_TESTS[@]} -gt 0 ]; then
echo ""
echo "Failed: ${#FAILED_TESTS[@]}"
for test in "${FAILED_TESTS[@]}"; do
print_error "${test}"
done
echo ""
print_error "Some tests failed"
exit 1
else
echo ""
print_success "All tests passed!"
exit 0
fi