Repository navigation
Releases: mechubsec/rustmistmcp
Release list
v0.4.0
rustmistmcp v0.3.2
Added
- "Did you mean" suggestions for unknown operation IDs (#99, closes #96).
An operation ID not in the catalog now returns up to three similar real IDs
(e.g.listOrgInventory->getOrgInventory), and says when a suggestion
needs a different dispatcher. Nonsense IDs get no suggestions; the threshold
and cap keep this from becoming an enumeration aid.
Fixed
- Response-schema validation no longer rejects real Mist responses (#100,
#102, #95). Three vendor-drift cases captured from the live API on
2026-09-22, each relaxed for responses only — requests stay strict:searchOrgInventory/searchOrgDevicesreturn fractional epoch seconds
where the spec declaresinteger; responses now acceptnumber.getOrgStatsdeclares 15 required properties but Mist never sends
orggroup_ids;requiredis dropped for responses.searchOrgDevicesfailed on any non-empty result: removing enum
constraints erased thetypediscriminator betweenoneOfbranches, so
records matched several. Responses now useanyOf.
- Validation errors name the failing field (#98, #95). Messages include the
field path, expected type, and actual value, capped at five errors. get_mist_operation_schemadescribes any catalog operation (#98, #97).
Introspection no longer requires the execution grant; tool-level
authorization still applies.- Scope errors say what is actually wrong (#98, #97).
list_mist_wan_edges
given only asite_idno longer reports "organization is not configured or
authorized"; org-not-allowlisted, unknown site, and site-in-unconfigured-org
are now distinct.invoke_mist_read's description documents thatpathand
queryare maps.
Changed
- MSRV raised to 1.89 (#94) — family-wide decision.
- Build toolchain 1.98.0 -> 1.98.1 in full (#103): Dockerfile, release
workflow, OCI smoke script,rust-toolchain.toml. clap4.6.6 -> 4.6.7,rustix1.1.4 -> 1.1.5; CI actions
docker/setup-qemu-action4.4.0,docker/setup-buildx-action4.4.1,
docker/build-push-action7.4.0.
Full changes: v0.3.1...v0.3.2
Backfilled GitHub release for an existing tag (2026-10-07).
rustmistmcp v0.3.1
Security
- rustls 0.23.45, closing RUSTSEC-2026-0285 (#85). TLS 1.3 handshake
messages accepted across encryption-level boundaries, medium severity, CVSS
5.3. This server was on 0.23.44, which was still vulnerable. Lockfile-only
change to 0.23.45, which contains the fix.
Fixed
-
Audit flags moved to ENTRYPOINT so they cannot be silently lost (#84).
Docker replaces CMD entirely when arguments are supplied, but appends to
ENTRYPOINT. The image carried audit configuration in CMD, so any real
deployment — which must override--hostto expose the port — silently lost
the audit format, redaction rules, and HMAC key. The container started and
served normally with no indication that the audit log was unkeyed and
unredacted.The image now splits CMD and ENTRYPOINT: ENTRYPOINT holds config paths,
credentials, and security-relevant flags (device-mapping, tokens-file,
audit-format, audit-redact, audit-hmac-key-file); CMD holds only
operator-tunable flags (transport, host, port). Operators passing--host
overrides now retain audit configuration. A CI regression test asserts the
resulting argv contains all three audit flags after a typical override. -
Dockerfile trailing newline restored (#88). The file lost its final
newline in an earlier edit.
Changed
- Re-pinned the
mecmcp-*crates fromv0.21.0tov0.23.0via rmcp
3.4.0 (#87), which renamedServerInfotoServerConfig. Call sites and
literals updated accordingly. jsonschemabumped from 0.52.1 to 0.55.0 (#83).tomlbumped from 1.1.4+spec-1.1.0 to 1.1.5+spec-1.1.0 (#79).docker/setup-qemu-actionbumped from 4.2.0 to 4.3.0 in the release workflow (#80).distroless/cc-debian13:nonrootbase image updated to a newer digest (#86).
Added
- Packaging documentation (#77). Added
docs/HOW-TO-SETUP-LXC.md, which
documents how to build a rustmistmcp LXC and how to package a CI binary
without forging BUILD-INFO, completing the setup guides for both Docker and
LXC deployment methods.
Full changes: v0.3.0-rc1...v0.3.1
Backfilled GitHub release for an existing tag (2026-10-07).
rustmistmcp v0.3.0
Changed
- Systemd unit documentation (mecmcp#354). Added a comment explaining the
fleet seccomp posture:SystemCallErrorNumber=EPERMreturns EPERM rather than
raising SIGSYS and killing the process mid-request, which is what happened to
rustunifimcp during a change-set state write (mecmcp#351). An EPERM denial is
silent at the systemd layer and can become visible only if the application
stops discarding the errno.
Added (from RC)
- An approval now binds the preview it was shown. mecmcp 0.23.0 adds a v5
approval digest that carries the stored preview's digest, and this server does
store a preview, so approvals are signed with v5 rather than v4. An approver
now vouches for the exact preview they saw, not merely for the plan, and the
coordinator refuses any later write that swaps or drops that preview.
Changed
- Re-pinned the
mecmcp-*crates fromv0.21.0tov0.23.0, spanning two
minors, and updated the pinned upstream revision in the workspace contract
test fromdbae2e38tod61867d7. - The apply takes
claim_change_set_for_applyinstead of writing
Approved -> Applyingitself. 0.22.0 made the claim the only legal route onto
that edge -- it does the read and the write under one lock, so two applies
cannot both readApprovedand both issue the write -- and the plain
update_change_setthis used is now refused outright.ApplyHandle::None,
because a Mist write is synchronous and returns no pollable handle: a crash
mid-apply leaves an outcome only the service knows, which is what
apply_without_handlerecords honestly. - The drift-detection path claims before settling. It wrote
Approved -> Failed
directly, which 0.22.0's transition policy refuses; the refusal was swallowed
into an audit line, so a drifted change set stayedApprovedand its stale
approval remained spendable. It now claims first -- nothing has been sent to
Mist at that point -- which gives the settle a legalApplying -> Failedand
spends the approval, so a drifted plan cannot be retried. That claim uses
ApplyHandle::Expected, the opposite of the apply path, and for the opposite
reason: the marker decides how a crash is read back, and on this branch
nothing was sent, so recovering toFailedstates the truth. Handleless would
strand a record known not to have run. ChangeSetRecordliterals carry the newapply_without_handlefield.jsonschemabumped from 0.50.1 to 0.51.0.tomlbumped from 0.8.23 to 1.1.4+spec-1.1.0, and the workspace-contract
test now usestoml::from_strinstead ofstr::parse, as toml 1.x changed
theFromStrimplementation onValueto stop after the first table header.
Performance
-
Compiled JSON Schema validators are now cached (#59). Request and response
validation previously compiled the schema on every call — roughly 2.2 MB cloned
from the components registry, then compiled, then dropped. Measured against the
pinned catalog (1059 operations, 4.6 MB source):stage before after per call, uncached 63.25 ms 1.14 us first call ~100 ms ~100 ms Per-call validation drops from 63 ms to 1 us, a ~55,000x speedup for cached
validators. The catalog is immutable once parsed, so compiled validators are
memoised. Cache misses race harmlessly: concurrent compilations of the same
schema may occur, with the first insert winning. Compile failures are not cached,
keeping catalog defects visible rather than frozen.The cache key includes operation name, parameter location and name, and for
responses both status code and media type, ensuring distinct schemas never
share a cache entry. This addresses the known issue (#59) noted in v0.2.0.
Fixed
- Dependabot no longer attempts to bump the git-pinned mecmcp crates (#69).
Weekly cargo runs were failing because dependabot advanced the mecmcp-* refs
from pinned tags to mecmcp main, but the exact version requirements then
refused the untagged commits. The mecmcp version is deliberately moved by hand
in a single chore/mecmcp- PR that re-pins every file at once, so
dependabot is now configured to ignore those crates.
Security
- Moved off the yanked chacha20 0.10.1. The supply-chain gate went red when
chacha20 0.10.1 was yanked upstream. This is a transitive dependency through
rand -> rmcp -> mecmcp-server, so nothing here selects it directly. The
lockfile now pins the compatible 0.10.2 release.
Upgrading
- A binary-only rollback to a build pinned at mecmcp v0.21.0 will refuse to
start once any change set has been approved under this one. A v5 approval
forces the change-set state file to schema 6, which the v0.21.0 reader does
not accept -- correctly, since it cannot verify what it cannot parse. Roll the
state file back with the binary, or restore a pre-upgrade snapshot.
Full changes: v0.2.0...v0.3.0
Backfilled GitHub release for an existing tag (2026-10-07).
rustmistmcp v0.3.0-rc1
rustmistmcp 0.3.0-rc1
An approval now binds the preview it was shown: mecmcp 0.23.0 adds a v5
approval digest carrying the stored preview's digest, so an approver vouches
for the exact preview they saw and the coordinator refuses any later write
that swaps or drops it.
Apply takes claim_change_set_for_apply rather than writing Approved ->
Applying itself, so two concurrent applies cannot both read Approved. The
drift path now claims before settling; previously its Approved -> Failed write
was refused and the refusal swallowed into an audit line, leaving a drifted
change set Approved with its stale approval still spendable.
Compiled JSON Schema validators are cached: per-call validation drops from
63 ms to about 1 us.
Tagged -rc per this repository's release policy, which the pre-release
workflow enforces and scripts/test-release-policy.sh tests.
Full changes: v0.3.0...v0.3.0-rc1
Backfilled GitHub release for an existing tag (2026-10-07).
v0.2.0
Added
- SSDF evidence pipeline (mecmcp#292). Evidence is attributed to the
applying request rather than to the change set, and receipts name the
executor. An ambiguous write is reported as ambiguous, not as a failed
write.
Changed
-
The embedded catalog is parsed once instead of twice (#39). It was
parsed into aserde_json::Valueto recompute fingerprints and again into
the typed document. A 4.6 MB document costs roughly ten times its size as a
Valuetree, and glibc does not return that arena when the transient parse
is dropped, so the cost was permanent resident memory:stage before after after Catalog::embedded()90.3 MB 45.3 MB after relaxed_components()90.3 MB 63.4 MB Resident drops 90.3 MB -> 63.4 MB, a 30% cut.
Fingerprint verification moves from startup to the test gate. Be precise
about this: 0.1.1 recomputed every operation'ssource_fingerprinton each
process start, and 0.2.0 does not —Catalog::embeddednow uses
Fingerprints::Trust. The check still runs, but undercargo test/ CI, via
catalog_fingerprints_are_verified_for_the_embedded_bytes, which drives the
same bytes through the verifyingCatalog::from_jsonpath. It does not
run at startup or during a plaincargo build.That trade is sound because
include_str!freezes the catalog into the
binary at compile time, so a shipped binary's fingerprints cannot drift — but
operators should not infer a runtime enforcement that no longer exists.
Catalog::from_json, the entry point for bytes of unknown provenance, still
verifies every one. -
mecmcp0.11.0 -> 0.19.0. That is the jump from the v0.1.1 baseline;
0.17.0 existed only as an untagged intermediate commit.
Upgrade note — rolling back needs the state file, not just the binary
mecmcp-changeset state carries a schema version. v0.1.1 links 0.11.0, whose
reader accepts v1-v3 only. 0.2.0 links 0.19.0, which accepts v1-v4 and
stamps v4 on any write to a store holding a real approval.
Once this release has written such a store, reinstalling the 0.1.1 binary alone
will not start — it rejects the file with unsupported changeset state version 4. Roll back with the Proxmox snapshot, which restores /var/lib
along with the binary.
rmcp3.1.2 -> 3.1.4.- Toolchain moved to 1.98.0 in full, not just the Dockerfile.
jsonschema0.37.4 -> 0.50.0,getrandom0.2 -> 0.4.
Security
- Tier-2 hardening.
tokens.jsonmigrates to/var/liband the systemd
unit is hardened. - The legacy token store is no longer shadowed by an empty one, and the
fallback is restricted to the canonical path. Token paths compare
byte-for-byte rather than byPathequality. - An advisory scan never prevents startup. A scan failure previously took
the server down. - Packaging probes real egress enforcement rather than implying it.
Testing
- Regression coverage for the audit-capture race, not a behaviour change.
v0.1.1already carried the global-subscriber/thread-local-writer
implementation; the added guard pins it so the race cannot return. Upgrading
does not change audit behaviour. scripts/test-release-policy.shderives the expected version from
Cargo.tomlinstead of hardcoding it. It had been pinned tov0.1.1, so
every version bump silently turned both CI workflows red with "RC tag
version X does not match Cargo version Y".
Known
- #59 — every request and response validation clones the whole components
registry, roughly 37 ms and 2.2 MB per call. That is the hot-path half of
the memory story and is not addressed here.
Published retroactively from CHANGELOG.md; tagged 2026-08-25.
v0.1.1
- chore(release): 0.1.1
- build(deps): take h2 0.4.17 for RUSTSEC-2026-0258
- fix(server): carry the cache descriptor on tools/list
- docs: document audit forwarding and where the trail goes
- chore: re-pin mecmcp to v0.11.0
- fix(cli): flatten the shared CLI instead of reimplementing it
- feat: add --lab-mode
- chore(deps): mecmcp v0.10.0
- fix: --allow-insecure-bind never reached the transport
- build(deps): bump docker/login-action from 3.3.0 to 4.6.0 (#25)
- build(deps): bump actions/attest-build-provenance from 4.1.1 to 4.2.2 (#24)
- build(deps): bump docker/setup-qemu-action from 3.7.0 to 4.2.0 (#23)
Changes since v0.1.0: 14 files changed, 651 insertions(+), 122 deletions(-)
Published retroactively; summarised from the commit range, as this repository keeps no CHANGELOG. Tagged 2026-08-19.
v0.1.0
- test: keep the immutability guarantee while adopting the family tag
- test: assert a malformation that survives the wire
- test(mist): migrate integration tests to mecmcp v0.9.1
- feat!: adopt mecmcp v0.9.1 and close the silent no-auth path
- feat(wan): change-set write lifecycle for WAN edge config (#27)
- feat(wan): WAN edge config read tools (#26)
- feat(wan): SLE impact and application tools (#22)
- feat(wan): six WAN edge diagnostic tools (#21)
- chore(deps): pin mecmcp v0.8.8, retiring the preflight-audit blocker (#20)
- docs: the lab guest is 952 and protected, and mecmcp#268 is fixed upstream (#19)
- docs(ops): record the lab token's single-layer scope and 610's disposable status (#18)
- chore(deps): adopt mecmcp 0.8.7 and reconcile the record with what is deployed (#16)
- feat(catalog): classify every execute operation, and keep it classified (#15)
- fix(catalog): judge response structure, not Juniper's vocabulary (#13)
- ci: run the OCI smoke where it earns its keep, not on every push (#10)
- build(deps): bump actions/attest-build-provenance from 3.2.0 to 4.1.1 (#6)
- build(deps): bump actions/upload-artifact from 6.0.0 to 7.0.1 (#3)
- fix(ci): drop the ripgrep dependency that silently disabled two checks (#9)
- build(deps): bump docker/build-push-action from 6.18.0 to 7.3.0 (#7)
- build(deps): bump docker/metadata-action from 5.6.1 to 6.2.0 (#5)
- build(deps): bump docker/setup-buildx-action from 3.11.1 to 4.2.0 (#4)
- feat!: migrate to rmcp 3.1 and mecmcp 0.7.3, adopt the shared transport (#8)
- feat: build governed Mist MCP server v1 (#1)
- Scaffold rustmistmcp: README, MIT license, mechub branding
Published retroactively; summarised from the commit range, as this repository keeps no CHANGELOG. Tagged 2026-08-13.