diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d9bc4d..7161d62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- **`rmcp` bumped from 3.0.0 to 3.1.0.** Breaking-for-affected-clients: `transport-http`'s stateless (non-`initialize`) POST handling now unconditionally rejects a `/mcp` request carrying `MCP-Protocol-Version: 2026-07-28` or later that omits `_meta.protocolVersion`/`_meta.clientCapabilities` from the request body, returning `HTTP 400` / JSON-RPC `-32602` where 3.0.0 accepted it; this check is not gated by `rmcp`'s new `stateless_protocol_metadata_required` option, which mcpls does not set (default `false`). Scope: only a hand-rolled or non-`rmcp` HTTP client sending a `2026-07-28`+ protocol header without `_meta` is affected — `rmcp`-based clients at that protocol version already attach `_meta`, `2025-11-25` and earlier protocol headers are unaffected, and `transport-http` is an opt-in, off-by-default feature. (#296) - **`DocumentState`'s six fields (`uri`, `language_id`, `version`, `content`, `disk`, `synced`) are now private** — internal encapsulation improvement, not an externally-reachable breaking change: `DocumentTracker::new`'s only parameter, `ResourceLimits`, is not re-exported outside `bridge::state`, so no code outside that module could construct a `DocumentTracker` (and therefore never obtain a `DocumentState`) either before or after this change. Previously the type had no constructor and let any caller writing a struct literal inside `bridge::state` violate its documented invariants (monotonic `version`, `disk` provenance, per-server `synced` tracking) by touching fields directly; those invariants are now enforced by the type itself, via internal methods (`apply_local_edit`, `commit_reload`, `set_disk`, `mark_synced`, `forget_server`) rather than documentation alone. Read access is now via `#[must_use]` getters: `uri()`, `language_id()`, `version()`, `content()`, `synced_version(&ServerId) -> Option` (there is no public `disk()`, since it would leak the crate-internal `DiskSync` type). (#304) - Sort `[workspace.dependencies]` in root `Cargo.toml` alphabetically (#232) - **`bridge::translator`'s fixed `DEFAULT_LSP_TIMEOUT`/`COMPLETIONS_LSP_TIMEOUT` constants (added in #231 below) removed** in favor of the new per-server `request_timeout_seconds` config field (see Added) — all 17 call sites now read `client.request_timeout()`/`client.completion_timeout()`. Breaking change: `LspServerConfig` gained a field, so existing `LspServerConfig { .. }` struct-literal construction (not behind `#[non_exhaustive]`) must add `request_timeout_seconds`. Also breaking: `ServerConfig::validate()` now rejects `timeout_seconds == 0` in addition to the new `request_timeout_seconds == 0` check — no working config could previously set `timeout_seconds` to 0 (it made `initialize` fail instantly), so no functioning setup is affected. (#267) diff --git a/Cargo.lock b/Cargo.lock index e98f6b0..24084fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1274,9 +1274,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "rmcp" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcd2b6dd3b18129368955f32661a7718969e8c152c7d8866434c09cf15a512e0" +checksum = "ad26b216c966e987e80e86daf784a455c039c43d98575ceed57b8faa259e5695" dependencies = [ "async-trait", "base64", @@ -1305,9 +1305,9 @@ dependencies = [ [[package]] name = "rmcp-macros" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1aa4b9345795260a43fc23d6d05e096407c8b953903f673af7c4404b49fb2d6" +checksum = "41bc748630c2be2a71b614c2f40d27bc0df0060696d224e1692c72345b7e0b79" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 15538f1..d088732 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ ignore = "0.4" lsp-types = "0.97" mcpls-core = { path = "crates/mcpls-core", version = "0.3.8" } predicates = "3.1" -rmcp = "3.0.0" +rmcp = "3.1.0" rstest = "0.26" schemars = "1.2" serde = "1.0" diff --git a/crates/mcpls-core/src/transport.rs b/crates/mcpls-core/src/transport.rs index 65a067e..730e639 100644 --- a/crates/mcpls-core/src/transport.rs +++ b/crates/mcpls-core/src/transport.rs @@ -359,7 +359,7 @@ const HTTP_GRACEFUL_SHUTDOWN_TIMEOUT: std::time::Duration = std::time::Duration: /// Enforcement lives here, at the `SessionManager` layer, rather than in Axum /// middleware sniffing request headers, because that is the only place /// guaranteed to run exactly when — and only when — a session is actually -/// created. `rmcp` 3.0.0's `StreamableHttpService::handle_post` calls +/// created. `rmcp` 3.1.0's `StreamableHttpService::handle_post` calls /// `create_session` solely on legacy-mode POSTs with no `Mcp-Session-Id` /// header (the `initialize` handshake); modern-protocol POSTs (SEP-2567, /// protocol `>= 2026-07-28`, which removes sessions entirely) and