Skip to content

1.3.0

Latest

Choose a tag to compare

@jwcarman jwcarman released this 04 Aug 12:29
· 9 commits to main since this release

No breaking changes. 1.3.0 adds a distributed, durable TaskStore for the MCP Tasks extension and fixes two serialization defects surfaced while building it.

Added

  • Substrate-backed TaskStore (mocapi-tasks-substrate) — a distributed, durable TaskStore for the MCP Tasks extension, backed by Substrate Atoms (token compare-and-set) across any of Substrate's nine backends (ADR-0040). Add the module, a Substrate backend, and codec-jackson to your app and it activates automatically once an AtomFactory bean exists, backing off the InMemoryTaskStore default with no other code changes. Configurable backend key prefix via mocapi.tasks.substrate.key-prefix (default mocapi:tasks:). Verified with the same TaskStoreContractTest TCK InMemoryTaskStore is held to (in-memory Atom SPI + real Redis via Testcontainers), a full autoconfiguration-chain proof test, and end-to-end lifecycle runs — including a mid-task elicitation task through working → input_required → tasks/update → completed — on both a live JVM and a genuine GraalVM native image. See the Tasks guide. The Substrate baseline is 0.8.1, which ships the upstream fix for the codec/substrate auto-configuration ordering bug this work surfaced; mocapi's SubstrateOrderingAutoConfiguration shim is retained as defense-in-depth for applications pinned to Substrate 0.8.0. A runnable Redis-backed example (examples/tasks-redis) demonstrates kill-and-resume: Spring Boot's Docker Compose support starts Redis, the app is killed at input_required, and after a restart the elicitation answer resumes the task via MRTR replay through the store.

Fixed

  • PrimitiveSchemaDefinition deserialization routing (mocapi-model). The sealed elicitation-schema hierarchy had no deserialization routing at all, breaking tasks/get with -32603 for any task whose inputRequests held a pending elicitation's requestedSchema, through any serializing TaskStore. PrimitiveSchemaDefinitionDeserializer now shape-sniffs the wire payload to route to the correct one of the eight leaf types per the pinned 2026-07-28 schema, including the documented LegacyTitledEnumSchema (no enumNames) vs UntitledSingleSelectEnumSchema wire ambiguity, resolved toward the non-deprecated variant. Wire serialization is unchanged; the released 1.2.0 wire path was not affected, since RequestStateCodec only ever carries response ledgers, never schema definitions.
  • InMemoryTaskStore now serializes records (mocapi-tasks). Records are held as JSON strings and round-tripped on every read/write instead of as live object graphs, giving the shipped default the same serialization coverage as every external store (closing the blind spot the fix above hid behind) and removing an aliasing hazard where a caller could mutate a returned record's JsonNode and corrupt stored state. The sweeper is hardened against a malformed stored entry (logged and skipped, rather than killing the sweeper thread). Public constructors are unchanged.

Requirements

  • Building from source now requires a running Docker daemon: mocapi-tasks-substrate's Redis Testcontainers IT runs during mvn verify. Consuming the published artifacts requires nothing new.