Skip to content

Commit 3196b11

Browse files
authored
Merge pull request #183 from olaservo/ruby-smoke-tests
Cover the Ruby examples in the smoke tests
2 parents d06b6ac + cfda589 commit 3196b11

4 files changed

Lines changed: 59 additions & 9 deletions

File tree

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,12 @@ jobs:
4141
with:
4242
go-version: "1.25"
4343

44+
# 3.4 is the current stable series. 3.3 is supported until March 2027; 3.2
45+
# reached end of life in March 2026.
46+
- name: Set up Ruby
47+
uses: ruby/setup-ruby@v1
48+
with:
49+
ruby-version: "3.4"
50+
4451
- name: Run smoke tests
4552
run: ./tests/smoke-test.sh

tests/README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ This directory contains smoke tests for the MCP quickstart examples. These tests
66

77
The smoke tests verify:
88

9-
- **Servers**: Each weather server (Python, TypeScript, Rust, Go) can start, respond to MCP protocol requests, and honour the output schemas it advertises
10-
- **Clients**: The Python and TypeScript MCP clients can connect to a mock server and list tools
9+
- **Servers**: Each weather server (Python, TypeScript, Rust, Go, Ruby) can start, respond to MCP protocol requests, and honour the output schemas it advertises
10+
- **Clients**: The Python, TypeScript and Ruby MCP clients can connect to a mock server and list tools
1111

12-
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`.
12+
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.
1313

1414
## Structured content
1515

@@ -37,6 +37,8 @@ Tool calls reach the live NWS API. When it is unreachable the tools return an er
3737
- **Rust** stable
3838
- **Cargo** (for Rust builds)
3939
- **Go** 1.25+
40+
- **Ruby** 3.4+ (3.2 and 3.3 satisfy the gems, but 3.2 is past end of life)
41+
- **Bundler** (ships with Ruby 3.x)
4042

4143
## How It Works
4244

@@ -111,6 +113,9 @@ nvm install 24
111113

112114
# Rust
113115
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
116+
117+
# Ruby (via rbenv)
118+
rbenv install 3.4
114119
```
115120

116121
## Adding New Tests

tests/smoke-test.sh

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,24 @@ test_weather_server_go() {
8484
node "${TEST_CLIENT}" "${server_bin}"
8585
}
8686

87+
# Test: Ruby weather server
88+
test_weather_server_ruby() {
89+
check_dependency ruby || return 1
90+
check_dependency bundle || return 1
91+
local server_dir="${PROJECT_ROOT}/weather-server-ruby"
92+
ensure_bundled "${server_dir}" || return 1
93+
(cd "${server_dir}" && node "${TEST_CLIENT}" bundle exec ruby weather.rb)
94+
}
95+
96+
# The client tests drive the no-API-key path, where each client prints a notice
97+
# and exits. Empty rather than unset: dotenv skips a name already present in
98+
# ENV, so a key in the environment or a local .env would start the chat loop.
99+
87100
# Test: Python MCP client
88101
test_mcp_client_python() {
89102
check_dependency uv || return 1
90103
local client_dir="${PROJECT_ROOT}/mcp-client-python"
91-
uv --directory "${client_dir}" run python "${client_dir}/client.py" "${MOCK_SERVER}" >/dev/null 2>&1
104+
ANTHROPIC_API_KEY= uv --directory "${client_dir}" run python "${client_dir}/client.py" "${MOCK_SERVER}" >/dev/null 2>&1
92105
}
93106

94107
# Test: TypeScript MCP client
@@ -97,22 +110,34 @@ test_mcp_client_typescript() {
97110
check_dependency npm || return 1
98111
local client_dir="${PROJECT_ROOT}/mcp-client-typescript"
99112
ensure_built "${client_dir}" || return 1
100-
node "${client_dir}/build/index.js" "${MOCK_SERVER}" >/dev/null 2>&1
113+
ANTHROPIC_API_KEY= node "${client_dir}/build/index.js" "${MOCK_SERVER}" >/dev/null 2>&1
114+
}
115+
116+
# Test: Ruby MCP client
117+
test_mcp_client_ruby() {
118+
check_dependency ruby || return 1
119+
check_dependency bundle || return 1
120+
local client_dir="${PROJECT_ROOT}/mcp-client-ruby"
121+
ensure_bundled "${client_dir}" || return 1
122+
(cd "${client_dir}" && ANTHROPIC_API_KEY= bundle exec ruby client.rb "${MOCK_SERVER}") >/dev/null 2>&1
101123
}
102124

103125
# Run all tests
104126
#
105-
# All four servers are covered. The Go and Rust clients are not: on main both
106-
# abort when no .env file is present, so they cannot be driven without
107-
# credentials. Making them start credential-free is a change in their own
108-
# directories, so their coverage lands with those changes rather than here.
127+
# The Go and Rust clients are not covered: on main both abort when no .env file
128+
# is present, so they cannot be driven without credentials. Making them start
129+
# credential-free is a change in their own directories, so their coverage lands
130+
# with those changes rather than here.
131+
109132
print_header "Running smoke tests"
110133
run_test "weather-server-python" test_weather_server_python
111134
run_test "weather-server-typescript" test_weather_server_typescript
112135
run_test "weather-server-rust" test_weather_server_rust
113136
run_test "weather-server-go" test_weather_server_go
137+
run_test "weather-server-ruby" test_weather_server_ruby
114138
run_test "mcp-client-python" test_mcp_client_python
115139
run_test "mcp-client-typescript" test_mcp_client_typescript
140+
run_test "mcp-client-ruby" test_mcp_client_ruby
116141

117142
# Print summary
118143
echo ""

tests/utils.sh

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,3 +138,16 @@ ensure_built() {
138138
run_build "go build in ${dir}" go build -o "server$(exe_suffix)" . || return 1
139139
fi
140140
}
141+
142+
# Ensure a Ruby project directory has its gems installed.
143+
#
144+
# Unlike ensure_built there is no artefact to test for -- a Ruby example has no
145+
# build step and Gemfile.lock is gitignored -- so ask Bundler directly.
146+
ensure_bundled() {
147+
local dir=$1
148+
cd "${dir}" || return 1
149+
150+
if ! bundle check >/dev/null 2>&1; then
151+
run_build "bundle install in ${dir}" bundle install || return 1
152+
fi
153+
}

0 commit comments

Comments
 (0)