diff --git a/CHANGELOG.md b/CHANGELOG.md index a7227ab..64317dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,7 +14,7 @@ All notable user-facing changes to Rustwright are documented in this file. - Moved actionability waits for supported, optionless `AsyncPage.click()` and `AsyncPage.fill()` calls into the Rust core while preserving trusted browser input and a single action deadline. - Centralized evaluation value decoding in the Rust core for the Go/C-ABI and native Rust surfaces, and added structured timeout, closed, crashed, and disconnected errors for the Python API. -- Promoted the native Rust MCP server (`mcp-rs/`) into the open-source tree as the canonical `rustwright-mcp` implementation; documentation now targets it. +- Promoted the native Rust MCP server (`mcp-rs/`) into the open-source tree as the canonical `rustwright-mcp` implementation; documentation now targets it, the `rustwright mcp` CLI verb launches it, and its cargo package and binary are named `rustwright-mcp` to match the npm distribution. ### Deprecated diff --git a/CODE_ARCHITECTURE.md b/CODE_ARCHITECTURE.md index 0f73ea1..f94daca 100644 --- a/CODE_ARCHITECTURE.md +++ b/CODE_ARCHITECTURE.md @@ -71,7 +71,8 @@ C-ABI bindings. | `python/rustwright/pytest_plugin.py` | Pytest fixtures. | | `python/playwright/*`, `python/patchright/*`, `python/cloakbrowser/*` | Compatibility import packages. Public alpha compatibility imports should be enabled only through opt-in compatibility mode. | | `rust-native/` | Native Rust facade crate over `rustwright-core` (crates.io `rustwright`); also the facade `mcp-rs/` consumes. | -| `mcp-rs/` | Native Rust MCP stdio server on the promoted engine facade. | +| `mcp-rs/` | `rustwright-mcp`: the canonical native Rust MCP stdio server on the promoted engine facade, with its npm packaging under `mcp-rs/npm/`. | +| `mcp/` | Deprecated Python MCP server (present in the public tree only, outside the sync map); superseded by `mcp-rs/` and removed once the native tool set reaches parity. | | `node/` | napi-rs binding (in-process, links `rustwright-core` directly). | | `capi/` | Shared C ABI (`librustwright_capi`) over `rustwright-core`; the boundary for the Go/Java/C#/Ruby/PHP bindings. | | `go/`, `java/`, `csharp/`, `ruby/`, `php/` | C-ABI language bindings (alpha surface) + per-language conformance runners. | diff --git a/README.md b/README.md index 636e162..632b4e2 100644 --- a/README.md +++ b/README.md @@ -130,10 +130,10 @@ compact accessibility snapshots and inline PNG screenshots. It lives in From source (needs a Rust toolchain): ```bash -cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs +cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp ``` -This installs the server binary as `mcp-rs`. An npm package (`rustwright-mcp`, +This installs the server binary as `rustwright-mcp`. An npm package (`rustwright-mcp`, prebuilt binaries via `npx rustwright-mcp`) is on the way. If Chrome or Chromium is already installed, point Rustwright at it with @@ -156,7 +156,7 @@ Open `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS { "mcpServers": { "rustwright": { - "command": "mcp-rs" + "command": "rustwright-mcp" } } } @@ -168,7 +168,7 @@ Open `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS { "mcpServers": { "rustwright": { - "command": "mcp-rs" + "command": "rustwright-mcp" } } } diff --git a/mcp-rs/Cargo.lock b/mcp-rs/Cargo.lock index b675c3c..f55dc89 100644 --- a/mcp-rs/Cargo.lock +++ b/mcp-rs/Cargo.lock @@ -675,18 +675,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" -[[package]] -name = "mcp-rs" -version = "0.1.0" -dependencies = [ - "base64", - "rmcp", - "rustwright", - "serde", - "serde_json", - "tokio", -] - [[package]] name = "memchr" version = "2.8.3" @@ -1103,6 +1091,18 @@ dependencies = [ "url", ] +[[package]] +name = "rustwright-mcp" +version = "0.1.0" +dependencies = [ + "base64", + "rmcp", + "rustwright", + "serde", + "serde_json", + "tokio", +] + [[package]] name = "ryu" version = "1.0.15" diff --git a/mcp-rs/Cargo.toml b/mcp-rs/Cargo.toml index 7e53a73..a70a919 100644 --- a/mcp-rs/Cargo.toml +++ b/mcp-rs/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mcp-rs" +name = "rustwright-mcp" version = "0.1.0" edition = "2024" publish = false diff --git a/mcp-rs/README.md b/mcp-rs/README.md index 56ea72f..a5b9552 100644 --- a/mcp-rs/README.md +++ b/mcp-rs/README.md @@ -15,10 +15,10 @@ new capabilities land here only. From source (needs a Rust toolchain): ```bash -cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs +cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp ``` -The server binary is installed as `mcp-rs`. An npm distribution +The server binary is installed as `rustwright-mcp`. An npm distribution (`rustwright-mcp`, prebuilt per-platform binaries, run with `npx rustwright-mcp`) is prepared under [`npm/`](npm/) and is on the way. @@ -48,7 +48,7 @@ other MCP client: { "mcpServers": { "rustwright": { - "command": "mcp-rs", + "command": "rustwright-mcp", "env": { "RUSTWRIGHT_CHROMIUM": "/path/to/chrome-or-chromium" } diff --git a/mcp-rs/npm/main/platforms.json b/mcp-rs/npm/main/platforms.json index f10f761..4e344d6 100644 --- a/mcp-rs/npm/main/platforms.json +++ b/mcp-rs/npm/main/platforms.json @@ -1,22 +1,22 @@ { "darwin-arm64": { "package": "@skyvernai/rustwright-mcp-darwin-arm64", - "binary": "mcp-rs" + "binary": "rustwright-mcp" }, "darwin-x64": { "package": "@skyvernai/rustwright-mcp-darwin-x64", - "binary": "mcp-rs" + "binary": "rustwright-mcp" }, "linux-x64": { "package": "@skyvernai/rustwright-mcp-linux-x64-gnu", - "binary": "mcp-rs" + "binary": "rustwright-mcp" }, "linux-arm64": { "package": "@skyvernai/rustwright-mcp-linux-arm64-gnu", - "binary": "mcp-rs" + "binary": "rustwright-mcp" }, "win32-x64": { "package": "@skyvernai/rustwright-mcp-win32-x64", - "binary": "mcp-rs.exe" + "binary": "rustwright-mcp.exe" } } diff --git a/mcp-rs/npm/scripts/build-npm.mjs b/mcp-rs/npm/scripts/build-npm.mjs index efd70d8..dd24cd7 100755 --- a/mcp-rs/npm/scripts/build-npm.mjs +++ b/mcp-rs/npm/scripts/build-npm.mjs @@ -28,7 +28,7 @@ function crateVersion() { const manifest = fs.readFileSync(path.join(crateDirectory, 'Cargo.toml'), 'utf8'); const packageSection = manifest.match(/\[package\]([\s\S]*?)(?=\n\[|$)/); const version = packageSection?.[1].match(/^version\s*=\s*"([^"]+)"\s*$/m)?.[1]; - if (!version) fail('could not read the mcp-rs package version from Cargo.toml'); + if (!version) fail('could not read the rustwright-mcp package version from Cargo.toml'); return version; } diff --git a/mcp-rs/npm/targets.json b/mcp-rs/npm/targets.json index 75a5f46..bb02851 100644 --- a/mcp-rs/npm/targets.json +++ b/mcp-rs/npm/targets.json @@ -5,7 +5,7 @@ "rustTarget": "aarch64-apple-darwin", "os": "darwin", "cpu": "arm64", - "binary": "mcp-rs", + "binary": "rustwright-mcp", "package": "@skyvernai/rustwright-mcp-darwin-arm64", "runner": "macos-15", "cross": false @@ -16,7 +16,7 @@ "rustTarget": "x86_64-apple-darwin", "os": "darwin", "cpu": "x64", - "binary": "mcp-rs", + "binary": "rustwright-mcp", "package": "@skyvernai/rustwright-mcp-darwin-x64", "runner": "macos-15-intel", "cross": false @@ -28,7 +28,7 @@ "os": "linux", "cpu": "x64", "libc": "glibc", - "binary": "mcp-rs", + "binary": "rustwright-mcp", "package": "@skyvernai/rustwright-mcp-linux-x64-gnu", "runner": "ubuntu-24.04", "zig": true, @@ -42,7 +42,7 @@ "os": "linux", "cpu": "arm64", "libc": "glibc", - "binary": "mcp-rs", + "binary": "rustwright-mcp", "package": "@skyvernai/rustwright-mcp-linux-arm64-gnu", "runner": "ubuntu-24.04", "zig": true, @@ -55,7 +55,7 @@ "rustTarget": "x86_64-pc-windows-msvc", "os": "win32", "cpu": "x64", - "binary": "mcp-rs.exe", + "binary": "rustwright-mcp.exe", "package": "@skyvernai/rustwright-mcp-win32-x64", "runner": "windows-2022", "cross": false diff --git a/mcp-rs/src/server.rs b/mcp-rs/src/server.rs index bbda7d4..492ffdf 100644 --- a/mcp-rs/src/server.rs +++ b/mcp-rs/src/server.rs @@ -162,7 +162,10 @@ fn output_content( impl ServerHandler for BrowserServer { fn get_info(&self) -> ServerInfo { ServerInfo::new(ServerCapabilities::builder().enable_tools().build()) - .with_server_info(Implementation::new("mcp-rs", env!("CARGO_PKG_VERSION"))) + .with_server_info(Implementation::new( + "rustwright-mcp", + env!("CARGO_PKG_VERSION"), + )) .with_instructions("Browser commands execute in order on one dedicated owner thread.") } diff --git a/mcp-rs/tests/stdio_e2e.rs b/mcp-rs/tests/stdio_e2e.rs index 54609b7..66fc91f 100644 --- a/mcp-rs/tests/stdio_e2e.rs +++ b/mcp-rs/tests/stdio_e2e.rs @@ -351,7 +351,7 @@ impl ServerProcess { remote: Option<(&str, &Value, u64)>, environment: &[(&str, &str)], ) -> Self { - let mut command = Command::new(env!("CARGO_BIN_EXE_mcp-rs")); + let mut command = Command::new(env!("CARGO_BIN_EXE_rustwright-mcp")); command .env_remove("RUSTWRIGHT_MCP_CDP_ENDPOINT") .env_remove("RUSTWRIGHT_MCP_CDP_HEADERS") diff --git a/mcp-rs/tests/validation_p1b_remote.rs b/mcp-rs/tests/validation_p1b_remote.rs index a4a4f6e..7c8fc30 100644 --- a/mcp-rs/tests/validation_p1b_remote.rs +++ b/mcp-rs/tests/validation_p1b_remote.rs @@ -175,7 +175,7 @@ struct ServerProcess { impl ServerProcess { fn spawn_remote(endpoint: &str, headers: &Value) -> Self { - let mut child = Command::new(env!("CARGO_BIN_EXE_mcp-rs")) + let mut child = Command::new(env!("CARGO_BIN_EXE_rustwright-mcp")) .env_remove("RUSTWRIGHT_MCP_CDP_ENDPOINT") .env_remove("RUSTWRIGHT_MCP_CDP_HEADERS") .env_remove("RUSTWRIGHT_MCP_CDP_TIMEOUT_MS") diff --git a/python/rustwright/cli.py b/python/rustwright/cli.py index 5a015e1..4a3790c 100644 --- a/python/rustwright/cli.py +++ b/python/rustwright/cli.py @@ -1481,7 +1481,7 @@ def _mcp_main(argv: Sequence[str], *, program: str) -> int: if binary is None: print( "rustwright mcp requires the native rustwright-mcp server binary; " - "install it with: cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs\n" + "install it with: cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp\n" "or install the rustwright-mcp npm package once it is published", file=sys.stderr, ) @@ -1554,7 +1554,7 @@ def _print_mcp_help(program: str) -> None: print( f"usage: {program} mcp [args...]\n\n" "Run the native MCP stdio server (requires the rustwright-mcp binary).\n" - "Install with: cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs" + "Install with: cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp" ) diff --git a/tests/test_cli_mcp_integration.py b/tests/test_cli_mcp_integration.py index 3215ed8..d8e5bf7 100644 --- a/tests/test_cli_mcp_integration.py +++ b/tests/test_cli_mcp_integration.py @@ -19,9 +19,10 @@ def _native_server_binary(): if found: return Path(found) for profile in ("debug", "release"): - candidate = REPOSITORY / "mcp-rs" / "target" / profile / "mcp-rs" - if candidate.is_file() and os.access(candidate, os.X_OK): - return candidate + for name in ("rustwright-mcp", "mcp-rs"): + candidate = REPOSITORY / "mcp-rs" / "target" / profile / name + if candidate.is_file() and os.access(candidate, os.X_OK): + return candidate return None @@ -122,7 +123,7 @@ def read_stdout(): assert "error" not in initialize_response initialize_result = initialize_response["result"] assert initialize_result["protocolVersion"] == "2024-11-05" - assert initialize_result["serverInfo"]["name"] == "mcp-rs" + assert initialize_result["serverInfo"]["name"] == "rustwright-mcp" _send_message( process, diff --git a/tests/test_cli_mcp_verb.py b/tests/test_cli_mcp_verb.py index d469e59..708cbe8 100644 --- a/tests/test_cli_mcp_verb.py +++ b/tests/test_cli_mcp_verb.py @@ -63,7 +63,7 @@ def test_mcp_missing_binary_prints_install_help_without_traceback( captured = capsys.readouterr() assert captured.out == "" assert ( - "cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs" + "cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp" in captured.err ) assert len(captured.err.splitlines()) == 2 @@ -97,4 +97,4 @@ def test_help_mcp_prints_usage_and_install_hint(capsys): captured = capsys.readouterr() assert captured.err == "" assert "usage: rustwright mcp [args...]" in captured.out - assert "cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs" in captured.out + assert "cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp" in captured.out diff --git a/tests/test_validation_mcp_verb.py b/tests/test_validation_mcp_verb.py index 957ddad..8fbd214 100644 --- a/tests/test_validation_mcp_verb.py +++ b/tests/test_validation_mcp_verb.py @@ -54,7 +54,7 @@ def test_validation_missing_binary_is_clean_two_line_error( assert captured.out == "" assert captured.err.splitlines() == [ "rustwright mcp requires the native rustwright-mcp server binary; " - "install it with: cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs", + "install it with: cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp", "or install the rustwright-mcp npm package once it is published", ] assert "Traceback" not in captured.err @@ -96,7 +96,7 @@ def test_validation_help_mcp_succeeds(capsys): assert captured.err == "" assert "usage: rustwright mcp [args...]" in captured.out assert ( - "cargo install --git https://github.com/Skyvern-AI/rustwright mcp-rs" + "cargo install --git https://github.com/Skyvern-AI/rustwright rustwright-mcp" in captured.out )