Skip to content

Releases: 4lador/leantime-mcp

v2.8.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 19:12
chore: v2.8.0 — P1 batch (envelopes, readonly profile, retention, man…

v2.7.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 17:52
feat: idempotency keys on creation tools — safe agent retries

An optional idempotencyKey on the six creation tools lets an agent
retry a call whose response was lost on its side (harness timeout,
session restart, retry loop): a retried call with an already-succeeded
key returns the original result, marked idempotentReplay: true, with
zero write requests.

- journal: one file per instance profile (idempotency.json, 0600,
  atomic temp+rename writes, TTL 7 days — LEANTIME_MCP_IDEMPOTENCY_TTL_DAYS,
  0 disables expiry — capped at 10k live entries with an actionable
  error); survives process restarts; corrupt files read as empty rather
  than breaking mutations
- scoping: (instance, tool, key) — cross-tool reuse is refused with an
  actionable error instead of a false hit; failed mutations do not
  consume their key; dry runs ignore keys entirely (and consume nothing)
- gate placement: replay short-circuits before any API call, including
  validation reads — a replay costs zero requests
- honest scope (in the CHANGELOG and the module doc): keys cover
  agent-driven retries, NOT Ambiguous 5xx outcomes — a lost server
  response leaves nothing to journal, those still instruct verify-first
- client: with_idempotency_dir() pins the journal base; the serve
  command resolves it from the active instance profile (keyring root
  fallback when running on pure env credentials)

Also in this release (separate commit): CI contract tests against
Leantime :latest for API drift detection.

Tests: 5 unit (validation bounds, round-trip hit/miss/mismatch, TTL,
corrupt-file recovery, on-disk parseability) + 5 integration via
mockito (replay = exactly one mutation wire-wide, failure doesn't
consume the key, cross-tool reuse refused, dry-run ignores keys, bulk
batch replays as a whole).

v2.6.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 15:44
chore: v2.6.0 — 5xx ambiguity fix + documentation honesty pass + READ…

v2.5.4

Choose a tag to compare

@github-actions github-actions released this 08 Sep 05:01
docs: overhaul — What's new removed for good, v1.x migration in its o…

v2.5.3

Choose a tag to compare

@github-actions github-actions released this 08 Sep 04:28
fix: publish job needs the crates-io-auth-action — cargo does no OIDC…

v2.5.2

Choose a tag to compare

@github-actions github-actions released this 08 Sep 04:10
chore: v2.5.2 — CI verification release

First end-to-end run of the tag-triggered publish job: crates.io via
keyless trusted publishing, MCP Registry via OIDC. No functional
changes — exists to prove the automation before a genuine release
depends on it.

v2.5.1

Choose a tag to compare

@github-actions github-actions released this 08 Sep 03:09
chore: v2.5.1 — docs-only release, sync the crates.io README

The crates.io page renders the README embedded at publish time; the
consolidated What's-new and badges landed after the 2.5.0 upload. This
patch release republishes with current docs. server.json follows to
2.5.1.

v2.5.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 01:16
feat: concurrent comment harvesting for --full backups

LEANTIME_MCP_BACKUP_CONCURRENCY (1-8, default 1): the per-ticket
comment calls run with bounded concurrency through the shared HTTP
pool. Default stays sequential — on rate-limited instances concurrency
buys nothing (the reactive 429 backoff governs throughput regardless,
live-observed: C=4 on a 10/min instance is slower from retry
collisions); on generous instances N>1 removes round-trip latency.

Results are collected in INPUT order — the backup file is identical
whatever the concurrency (live-verified C=1 vs C=4, same comments in
the same order).

To keep the sequential and concurrent paths from ever diverging, the
request/retry policy (429 <=5 with server-hinted delays, 502/503/504
<=2, 64 MB response cap) was extracted into request_with_retries over
rpc_roundtrip — one implementation shared by call() and the spawned
concurrent requests.

Tests: order preservation under concurrency, measured speedup via a
minimal delay HTTP server (mockito can't delay), C=1 serialization
floor, per-ticket 429 retry.

v2.4.0

Choose a tag to compare

@github-actions github-actions released this 08 Sep 00:33
feat: date-window pagination — completeness fetches immune to the API…

v2.3.3

Choose a tag to compare

@github-actions github-actions released this 07 Sep 23:56
fix: list_tickets status label filter resolved the wrong result set

The label was passed raw to the API, which intval()s it: "New" became 0
and silently filtered on status ID 0 — asking for New returned every
Done ticket on the local test project (175 items, live-reproduced).

Labels now resolve to IDs server-side against the project's cached
status map (case-insensitive); CSV lists resolve token by token; unknown
labels error with the project's valid statuses (id + name); the server's
magic done/not_done values and numeric IDs pass through untouched.

Live-verified: status="New" → 101 New items (was 175 Done); unknown
label → actionable error listing valid statuses.