Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<PositionParams>` 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

Expand Down Expand Up @@ -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
Expand Down
52 changes: 26 additions & 26 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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. <k05h31@gmail.com>"]
Expand All @@ -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"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
3 changes: 3 additions & 0 deletions crates/mcpls-cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ See the main [README](../../README.md) for configuration examples and custom ext
| `--listen <ADDR>` | `MCPLS_LISTEN` | Bind address for HTTP transport (`transport-http` feature) |
| `--http-path <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`):
Expand Down
2 changes: 1 addition & 1 deletion skills/mcpls/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ no environment variable equivalent.
| `--config <FILE>` | `-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 <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 <ADDR>` | — | `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 <PATH>` | — | `MCPLS_HTTP_PATH` | `/mcp` | URL path the MCP service mounts at. Only meaningful with `--listen`; same `transport-http` feature gate. |

Expand Down
Loading