diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e85fb07..35bc4c65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.3.9] - 2026-08-05 + ### Added - **`workspace.max_documents`/`workspace.max_file_size` TOML config fields** — expose `DocumentTracker`'s previously hardcoded resource limits (100 open documents, 10MB max file size) for configuration, following the existing `heuristics_max_depth` flat-field-on-`[workspace]` pattern. `0` disables either limit, matching `ResourceLimits`'s existing semantics; omitting either field preserves today's defaults unchanged. New `WorkspaceConfig::resource_limits()` maps the two fields onto `bridge::ResourceLimits`, and new `Translator::with_resource_limits` builder wires the resolved limits into `serve()`'s `Translator` construction alongside the existing `with_extensions` builder — the two builders now read each other's already-set field when rebuilding `document_tracker`, so they can be called in either order without one silently discarding the other's effect. `Error::DocumentLimitExceeded`/`FileSizeLimitExceeded` messages gained a static hint pointing at the relevant config field. Documented under "Workspace Section" in `docs/user-guide/configuration.md`. Note: `bridge::ResourceLimits` is now re-exported from `bridge` (previously private to `bridge::state`), which as a side effect makes the already-`pub` `DocumentTracker::new` constructible from outside the crate for the first time — this narrows the rationale given in the `DocumentState` encapsulation entry below (#304), which assumed `ResourceLimits`'s privacy made `DocumentTracker` uninstantiable externally; `DocumentState`'s own field privacy and invariant-enforcing methods are unaffected. (#315) @@ -50,6 +52,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **`mcp::tools`'s six position-only parameter wrappers collapsed into `PositionParams`** — `HoverParams`, `DefinitionParams`, `SignatureHelpParams`, `GoToImplementationParams`, `GoToTypeDefinitionParams`, and `CallHierarchyPrepareParams` each wrapped `PositionParams` with `#[serde(flatten)]` and added nothing: `rmcp`'s schema validation already strips the top-level `title`/`description` these wrappers carried before it reaches an MCP client, so the six were structurally identical to `PositionParams` itself. The six corresponding `#[tool]` handlers (`get_hover`, `get_definition`, `get_signature_help`, `go_to_implementation`, `go_to_type_definition`, `prepare_call_hierarchy`) now take `Parameters` directly. No client-visible schema or wire-format change. (#302) - **`bridge::translator.rs` split into `bridge/translator/` submodules** — the single 7100+ line file (setup/lifecycle, all 20 tool handlers, DTOs, and their tests) is now `mod.rs` (the `Translator` struct and setup/lifecycle methods) plus twelve sibling modules grouped by domain (`clock`, `respawn`, `routing`, `dto`, `encoding_ctx`, `navigation`, `diagnostics`, `edits`, `symbols`, `assist`, `call_hierarchy`, and a shared `testing` fixture module), matching the existing per-file test convention used by `bridge::state`/`bridge::notifications`/`bridge::encoding`. Pure code motion — `bridge::translator`'s public re-export surface (`bridge/mod.rs`'s `pub use translator::{...}` block) and every `Translator` method signature are unchanged. (#300) - **Respawn-backoff bookkeeping now goes through an injectable `Clock`** — `Translator::respawn_if_dead` and its backoff helpers (previously hardcoded to `std::time::Instant::now()`) now read time through a new `bridge::translator::clock::Clock` trait, defaulted to `SystemClock` in production. No production behavior change; this is a test-only seam (`Translator::with_clock`, `#[cfg(test)]`) that lets backoff-window tests advance a `FakeClock` deterministically instead of relying on real sleeps or incidental timing. Also switches the two call sites that used `Instant::elapsed`/`duration_since` directly to `saturating_duration_since`, for explicitness at the injection seam now that the clock reading is no longer guaranteed to be `SystemClock`; behavior is unchanged (`elapsed`/`duration_since` and `saturating_duration_since` are equivalent on current Rust). (#292) +- **`config::server`'s builtin `LspServerConfig` constructors deduplicated** — extracted a private `builtin()` helper for the six fields (`env`, `initialization_options`, `timeout_seconds`, `request_timeout_seconds`, `name`, `handles`) previously repeated verbatim across all six built-in language constructors (`rust_analyzer`, `pyright`, `typescript`, `gopls`, `clangd`, `zls`); only the per-language values remain at each call site. No behavior change. (#316) +- Bump rmcp from 2.2.0 to 3.0.0 +- Bump toml from 1.1.3+spec-1.1.0 to 1.1.4+spec-1.1.0 +- CI: bump actions/checkout from 7.0.0 to 7.0.1 +- CI: bump actions/labeler from 6 to 7 +- CI: bump cargo-bins/cargo-binstall from 1.21.0 to 1.21.1 +- CI: bump lewagon/wait-on-check-action from 1.8.1 to 1.9.0 ### Removed @@ -650,7 +659,9 @@ Add to `~/.claude/mcp.json`: - Workspace auto-discovery - LSP server auto-detection and installation -[Unreleased]: https://github.com/bug-ops/mcpls/compare/v0.3.7...HEAD +[Unreleased]: https://github.com/bug-ops/mcpls/compare/v0.3.9...HEAD +[0.3.9]: https://github.com/bug-ops/mcpls/compare/v0.3.8...v0.3.9 +[0.3.8]: https://github.com/bug-ops/mcpls/compare/v0.3.7...v0.3.8 [0.3.7]: https://github.com/bug-ops/mcpls/compare/v0.3.6...v0.3.7 [0.3.6]: https://github.com/bug-ops/mcpls/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/bug-ops/mcpls/compare/v0.3.4...v0.3.5 diff --git a/Cargo.lock b/Cargo.lock index 24084fb5..33d2eaad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b25655df2c3cdd83c5e5b293b88acd880332b2ddadd7c30ac43144fdc0033da9" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] name = "bitflags" @@ -250,9 +250,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.4" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d91e0c145792ef73a6ad36d27c75ac09f1832222a3c209689d90f534685ee5b7" +checksum = "301b56658598e48f3648647ac6fc887be7e7108eddfa4e9b63fcf3ec58c0cadf" dependencies = [ "clap_builder", "clap_derive", @@ -260,9 +260,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.2" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f09628afdcc538b57f3c6341e9c8e9970f18e4a481690a64974d7023bd33548b" +checksum = "94a65403d1a1bd28f7dc68eb8506e8874808ee5eecb59298de588e2e1407a078" dependencies = [ "anstream", "anstyle", @@ -397,13 +397,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] @@ -598,9 +598,9 @@ checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "globset" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e47d37d2ae4464254884b60ab7071be2b876a9c35b696bd018ddcc76847309cd" +checksum = "07c34a9410465b45bd9787443bc7370f37735bad04b0f0cd57ff1a3186c98988" dependencies = [ "aho-corasick", "bstr", @@ -623,9 +623,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -836,9 +836,9 @@ dependencies = [ [[package]] name = "ignore" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8a7b8211e695a1d0cd91cace480d4d0bd57667ab10277cc412c5f7f4884f83" +checksum = "00b69833ed729dc5aa7d19541d96d6cf8e9137194207a04916d658e43168402f" dependencies = [ "crossbeam-deque", "globset", @@ -897,9 +897,9 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libredox" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +checksum = "2026a5056764a10b2bf5d56488cba40da507f5493a6a429340e2004d9ed085fa" dependencies = [ "libc", ] @@ -961,7 +961,7 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "mcpls" -version = "0.3.8" +version = "0.3.9" dependencies = [ "anyhow", "assert_cmd", @@ -976,7 +976,7 @@ dependencies = [ [[package]] name = "mcpls-core" -version = "0.3.8" +version = "0.3.9" dependencies = [ "anyhow", "async-trait", @@ -1251,9 +1251,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdb36bda0c880c5931cdc7a2bcdc8ba4556847b9d912bca70bc94708711ad" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -1711,13 +1711,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6328af13490e73a9b4694030fafd93f8c8c6a9dede33e821c3fc63eddf8042ba" +checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.3", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d088732d..4100503b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = ["crates/*"] resolver = "2" [workspace.package] -version = "0.3.8" +version = "0.3.9" edition = "2024" rust-version = "1.88" authors = ["Andrei G. "] @@ -27,7 +27,7 @@ dunce = "1.0.5" futures = "0.3" ignore = "0.4" lsp-types = "0.97" -mcpls-core = { path = "crates/mcpls-core", version = "0.3.8" } +mcpls-core = { path = "crates/mcpls-core", version = "0.3.9" } predicates = "3.1" rmcp = "3.1.0" rstest = "0.26" diff --git a/README.md b/README.md index 9b7c2b03..ef73c9ec 100644 --- a/README.md +++ b/README.md @@ -239,6 +239,9 @@ project_markers = ["Cargo.toml", "rust-toolchain.toml", ".rust-version"] | `MCPLS_LOG` | Log level (trace, debug, info, warn, error) | `info` | | `MCPLS_LOG_JSON` | Output logs as JSON | `false` | +> [!NOTE] +> The two boolean flags above accept `1`/`0`, `true`/`false`, `yes`/`no`, `y`/`n`, and `on`/`off` (case-insensitive). + **Config file locations:** | Platform | Default Location | diff --git a/crates/mcpls-cli/README.md b/crates/mcpls-cli/README.md index 43f4b83a..bf157768 100644 --- a/crates/mcpls-cli/README.md +++ b/crates/mcpls-cli/README.md @@ -55,6 +55,9 @@ See the main [README](../../README.md) for configuration examples and custom ext | `--listen ` | `MCPLS_LISTEN` | Bind address for HTTP transport (`transport-http` feature) | | `--http-path ` | `MCPLS_HTTP_PATH` | URL prefix for HTTP transport (default: `/mcp`) | +> [!NOTE] +> `MCPLS_TRUST_PROJECT_CONFIG` and `MCPLS_LOG_JSON` accept `1`/`0`, `true`/`false`, `yes`/`no`, `y`/`n`, and `on`/`off` (case-insensitive). + ## Claude Code Integration Add to your Claude Code configuration (`~/.claude/claude_desktop_config.json`): diff --git a/skills/mcpls/SKILL.md b/skills/mcpls/SKILL.md index 09ef92ea..853abd4a 100644 --- a/skills/mcpls/SKILL.md +++ b/skills/mcpls/SKILL.md @@ -90,7 +90,7 @@ no environment variable equivalent. | `--config ` | `-c` | `MCPLS_CONFIG` | auto-detect | Always trusted, even a *relative* path set via the env var — naming a path is treated as consent, so this bypasses the project-config trust gate entirely (see [Config trust model](#config-trust-model)). Hard-errors at startup if the file doesn't exist — unlike auto-detection, it never falls back to defaults. | | `--trust-project-config` | — | `MCPLS_TRUST_PROJECT_CONFIG` | `false` | See [Config trust model](#config-trust-model) below. The env var accepts `1`/`0`, `true`/`false`, `yes`/`no`, `y`/`n`, and `on`/`off` (case-insensitive); any other value is a startup parse error. | | `--log-level ` | `-l` | `MCPLS_LOG` | `info` | Any `tracing-subscriber` `EnvFilter` directive works, e.g. `mcpls=debug,info`. An invalid value does **not** error — it silently falls back to `info`. | -| `--log-json` | — | `MCPLS_LOG_JSON` | `false` | Parsed and accepted, but **not currently implemented**: logging always uses the compact human-readable formatter regardless of this flag. Do not rely on JSON log output. | +| `--log-json` | — | `MCPLS_LOG_JSON` | `false` | Output logs in JSON format for structured logging. The env var accepts `1`/`0`, `true`/`false`, `yes`/`no`, `y`/`n`, and `on`/`off` (case-insensitive). | | `--listen ` | — | `MCPLS_LISTEN` | unset | HTTP transport bind address (e.g. `127.0.0.1:3000`). Only exists when built with `--features transport-http` — see [HTTP transport caveats](#registering-with-an-mcp-client). | | `--http-path ` | — | `MCPLS_HTTP_PATH` | `/mcp` | URL path the MCP service mounts at. Only meaningful with `--listen`; same `transport-http` feature gate. |