Merge pull request #183 from olaservo/ruby-smoke-tests

Cover the Ruby examples in the smoke tests
This commit is contained in:
Alex Akimov 2026-08-21 17:57:35 +02:00 • committed by GitHub
commit 3196b11aae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 59 additions and 9 deletions

View file

@ -41,5 +41,12 @@ jobs:
with:
go-version: "1.25"
# 3.4 is the current stable series. 3.3 is supported until March 2027; 3.2
# reached end of life in March 2026.
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.4"
- name: Run smoke tests
run: ./tests/smoke-test.sh

View file

@ -6,10 +6,10 @@ This directory contains smoke tests for the MCP quickstart examples. These tests
The smoke tests verify:
- **Servers**: Each weather server (Python, TypeScript, Rust, Go) can start, respond to MCP protocol requests, and honour the output schemas it advertises
- **Clients**: The Python and TypeScript MCP clients can connect to a mock server and list tools
- **Servers**: Each weather server (Python, TypeScript, Rust, Go, Ruby) can start, respond to MCP protocol requests, and honour the output schemas it advertises
- **Clients**: The Python, TypeScript and Ruby MCP clients can connect to a mock server and list tools
The Go and Rust clients are not covered here: 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. The Ruby examples are not covered either — the `mcp` gem cannot negotiate protocol revision `2026-07-28`.
The Go and Rust clients are not covered here: 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.
## Structured content
@ -37,6 +37,8 @@ Tool calls reach the live NWS API. When it is unreachable the tools return an er
- **Rust** stable
- **Cargo** (for Rust builds)
- **Go** 1.25+
- **Ruby** 3.4+ (3.2 and 3.3 satisfy the gems, but 3.2 is past end of life)
- **Bundler** (ships with Ruby 3.x)
## How It Works
@ -111,6 +113,9 @@ nvm install 24
# Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Ruby (via rbenv)
rbenv install 3.4
```
## Adding New Tests

View file

@ -84,11 +84,24 @@ test_weather_server_go() {
node "${TEST_CLIENT}" "${server_bin}"
}
# Test: Ruby weather server
test_weather_server_ruby() {
check_dependency ruby || return 1
check_dependency bundle || return 1
local server_dir="${PROJECT_ROOT}/weather-server-ruby"
ensure_bundled "${server_dir}" || return 1
(cd "${server_dir}" && node "${TEST_CLIENT}" bundle exec ruby weather.rb)
}
# The client tests drive the no-API-key path, where each client prints a notice
# and exits. Empty rather than unset: dotenv skips a name already present in
# ENV, so a key in the environment or a local .env would start the chat loop.
# 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
ANTHROPIC_API_KEY= uv --directory "${client_dir}" run python "${client_dir}/client.py" "${MOCK_SERVER}" >/dev/null 2>&1
}
# Test: TypeScript MCP client
@ -97,22 +110,34 @@ test_mcp_client_typescript() {
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
ANTHROPIC_API_KEY= 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}" && ANTHROPIC_API_KEY= bundle exec ruby client.rb "${MOCK_SERVER}") >/dev/null 2>&1
}
# Run all tests
#
# All four servers are covered. The Go and Rust clients are not: 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.
# 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.
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 "weather-server-ruby" test_weather_server_ruby
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 ""

View file

@ -138,3 +138,16 @@ ensure_built() {
run_build "go build in ${dir}" go build -o "server$(exe_suffix)" . || return 1
fi
}
# Ensure a Ruby project directory has its gems installed.
#
# Unlike ensure_built there is no artefact to test for -- a Ruby example has no
# build step and Gemfile.lock is gitignored -- so ask Bundler directly.
ensure_bundled() {
local dir=$1
cd "${dir}" || return 1
if ! bundle check >/dev/null 2>&1; then
run_build "bundle install in ${dir}" bundle install || return 1
fi
}