Skip to content

Commit af48a2b

Browse files
authored
test: add new tests for client runtime (#29)
* tests: add new tests for client runtime * test: update workflow to test on both linux and windows * chore: disable node cache * chore: disable python cache * chore: update ci workflow * chore: disable unnecessary test on windows * chore: update ci workflow * chore: run clippy on both windows and linux * chore: fix build issue
1 parent 3fca025 commit af48a2b

File tree

3 files changed

+143
-27
lines changed

3 files changed

+143
-27
lines changed

.github/workflows/ci.yml

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,23 @@ on:
33
push:
44
branches:
55
- main
6+
# pull_request:
7+
# branches:
8+
# - "**"
69
workflow_call:
710

8-
# on:
9-
# push:
10-
# branches:
11-
# - main
12-
# pull_request:
13-
# branches:
14-
# - "**"
15-
#
16-
1711
jobs:
1812
rust_check:
19-
name: Rust check
20-
runs-on: ubuntu-latest
13+
name: Rust Checks (${{ matrix.os }})
14+
runs-on: ${{ matrix.os }}
15+
strategy:
16+
matrix:
17+
os: [ubuntu-latest, windows-latest]
18+
fail-fast: false # Continue testing other OSes even if one fails
2119
steps:
2220
- name: Checkout
2321
uses: actions/checkout@v4
22+
2423
- name: Cache Rust
2524
uses: actions/cache@v4
2625
with:
@@ -29,42 +28,77 @@ jobs:
2928
~/.cargo/registry
3029
~/.cargo/git
3130
target
32-
key: ${{ runner.os }}-rust-${{ steps.toolchain.outputs.cachekey }}
33-
restore-keys: ${{ runner.os }}-rust-
31+
key: ${{ matrix.os }}-rust-${{ hashFiles('Cargo.lock') }}
32+
restore-keys: ${{ matrix.os }}-rust-
3433

3534
- name: Install Rust Toolchain
3635
uses: dtolnay/rust-toolchain@master
3736
with:
3837
toolchain: stable
39-
components: rustfmt
38+
components: rustfmt, clippy
4039

41-
- uses: davidB/rust-cargo-make@v1
42-
- uses: taiki-e/install-action@nextest
40+
- name: Install cargo-make
41+
uses: davidB/rust-cargo-make@v1
42+
43+
- name: Install nextest
44+
uses: taiki-e/install-action@nextest
4345

4446
- name: Run Clippy
45-
run: |
46-
cargo make clippy
47+
run: cargo make clippy
48+
continue-on-error: false
4749

4850
- name: Run Rustfmt
49-
run: |
50-
cargo make fmt
51+
run: cargo make fmt -- --check
52+
if: matrix.os == 'ubuntu-latest' # Run fmt only on Linux
5153

5254
- name: Run cargo doc
55+
env:
56+
RUSTDOCFLAGS: "-Dwarnings"
5357
run: cargo doc --no-deps
58+
if: matrix.os == 'ubuntu-latest' # Run doc only on Linux
5459

5560
- name: Spell Check
56-
env:
57-
RUSTDOCFLAGS: "-Dwarnings"
5861
uses: crate-ci/typos@master
62+
if: matrix.os == 'ubuntu-latest' # Run typos only on Linux
5963

60-
- name: Audit
64+
- name: Audit Dependencies
6165
uses: actions-rust-lang/audit@v1
6266
with:
6367
token: ${{ secrets.GITHUB_TOKEN }}
68+
if: matrix.os == 'ubuntu-latest' # Run audit only on Linux
69+
70+
# install nodejs that is required for tests
71+
- name: Setup Node.js
72+
uses: actions/setup-node@v4
73+
with:
74+
node-version: "20" # Stable Node.js version
75+
# Verify npx is available
76+
- name: Verify npx
77+
run: npx --version
78+
shell: bash
79+
80+
- name: Install server-everything globally
81+
run: npm install -g @modelcontextprotocol/server-everything
82+
shell: bash
83+
84+
# install Python and uvx that is required for tests
85+
- name: Setup Python
86+
uses: actions/setup-python@v5
87+
with:
88+
python-version: "3.11" # Stable Python version
89+
90+
- name: Install uv
91+
run: pip install uv
92+
shell: bash
93+
94+
- name: Verify uvx
95+
run: uvx --version
96+
shell: bash
6497

6598
- name: Run Tests
66-
run: |
67-
cargo make test
99+
run: cargo make test
100+
shell: bash # Ensure consistent shell
101+
68102
- name: Run Doc Tests
69-
run: |
70-
cargo make doc-test
103+
run: cargo make doc-test
104+
shell: bash # Ensure consistent shell
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use async_trait::async_trait;
2+
use rust_mcp_schema::{
3+
ClientCapabilities, Implementation, InitializeRequestParams, JSONRPC_VERSION,
4+
};
5+
use rust_mcp_sdk::mcp_client::ClientHandler;
6+
7+
pub const NPX_SERVER_EVERYTHING: &str = "@modelcontextprotocol/server-everything";
8+
9+
#[cfg(unix)]
10+
pub const UVX_SERVER_GIT: &str = "mcp-server-git";
11+
12+
pub fn test_client_info() -> InitializeRequestParams {
13+
InitializeRequestParams {
14+
capabilities: ClientCapabilities::default(),
15+
client_info: Implementation {
16+
name: "test-rust-mcp-client".into(),
17+
version: "0.1.0".into(),
18+
},
19+
protocol_version: JSONRPC_VERSION.into(),
20+
}
21+
}
22+
23+
pub struct TestClientHandler;
24+
25+
#[async_trait]
26+
impl ClientHandler for TestClientHandler {}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use common::{test_client_info, TestClientHandler, NPX_SERVER_EVERYTHING};
2+
use rust_mcp_sdk::{mcp_client::client_runtime, McpClient, StdioTransport, TransportOptions};
3+
4+
#[cfg(unix)]
5+
use common::UVX_SERVER_GIT;
6+
7+
#[path = "common/common.rs"]
8+
pub mod common;
9+
10+
#[tokio::test]
11+
async fn tets_client_launch_npx_server() {
12+
// NPM based MCP servers should launch successfully using `npx`
13+
let transport = StdioTransport::create_with_server_launch(
14+
"npx",
15+
vec!["-y".into(), NPX_SERVER_EVERYTHING.into()],
16+
None,
17+
TransportOptions::default(),
18+
)
19+
.unwrap();
20+
21+
let client = client_runtime::create_client(test_client_info(), transport, TestClientHandler {});
22+
23+
client.clone().start().await.unwrap();
24+
25+
let server_capabilities = client.server_capabilities().unwrap();
26+
let server_info = client.server_info().unwrap();
27+
28+
assert!(server_info.server_info.name.len() > 0);
29+
assert!(server_info.server_info.version.len() > 0);
30+
assert!(server_capabilities.tools.is_some());
31+
}
32+
33+
#[cfg(unix)]
34+
#[tokio::test]
35+
async fn tets_client_launch_uvx_server() {
36+
// The Python-based MCP server should launch successfully
37+
// provided that `uvx` is installed and accessible in the system's PATH
38+
let transport = StdioTransport::create_with_server_launch(
39+
"uvx",
40+
vec![UVX_SERVER_GIT.into()],
41+
None,
42+
TransportOptions::default(),
43+
)
44+
.unwrap();
45+
46+
let client = client_runtime::create_client(test_client_info(), transport, TestClientHandler {});
47+
48+
client.clone().start().await.unwrap();
49+
50+
let server_capabilities = client.server_capabilities().unwrap();
51+
let server_info = client.server_info().unwrap();
52+
53+
assert!(server_info.server_info.name.len() > 0);
54+
assert!(server_info.server_info.version.len() > 0);
55+
assert!(server_capabilities.tools.is_some());
56+
}

0 commit comments

Comments
 (0)