You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(ext-tasks): server dispatch wiring — SEP-2663 runtime on the 2026 lane
Opt-in ext-tasks feature on turul-mcp-server (off by default per
SEP-2133); dispatcher design recorded in ADR-028 (2026-06-12 entry):
- .with_ext_tasks(store): advertises io.modelcontextprotocol/tasks in
discover capabilities.extensions, registers tasks/get|update|cancel
- .ext_task_tool(_required): task election per the upstream lifecycle —
declared per-request extension → durable CreateTaskResult (UUIDv4
bearer-grade id, store written BEFORE the response) + spawned worker;
undeclared → sync fallback (progressive enhancement) or -32003 with
data.requiredCapabilities.extensions for required tools
- MRTR bridge: a task tool returning McpError::InputRequired parks in
input_required; tasks/update validates keys against outstanding
requests (partial delivery keeps it parked) and resumes the worker
with responses injected through the same session-extension keys as
the sync retry leg — tool code identical under both execution models
- tasks/cancel cooperative (aborts worker, drops waiters, acks
terminal); notifications/tasks rides subscriptions/listen with
taskIds honored iff the extension is advertised (capability-map
keyed — no transport dependency on the ext crate), echoed in the ack
- turul-mcp-ext-tasks: TaskStore trait + TaskState + InMemoryTaskStore
(state machine enforced; no tokio in the public API)
9 wire e2e tests (ext_tasks_2026.rs; gates + CI steps added): discover
advertisement, create→poll→completed, sync fallback, -32003 shape,
input_required⇄update round trip incl. requestState replay, cancel,
unknown-task -32602, UUIDv4 ids, taskIds-filtered listen delivery.
Revert-and-fail recorded: neutralizing the capability check fails
declared_call_returns_task_and_polls_to_completion with a sync result.
Driver-doc Major-6 (SEP-2663) promoted to ✅ (G1 closed).
Full ci-gates.sh all green.
Copy file name to clipboardExpand all lines: CHANGELOG.md
+1Lines changed: 1 addition & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
20
20
21
21
### Added
22
22
23
+
- **Tasks-extension server runtime (2026-06-12, SEP-2663 — closes driver gap G1).** New opt-in `ext-tasks` feature on `turul-mcp-server` (off by default per SEP-2133): `.with_ext_tasks(store)` advertises `io.modelcontextprotocol/tasks` in `server/discover`'s `capabilities.extensions` and registers `tasks/get`/`tasks/update`/`tasks/cancel`; `.ext_task_tool(tool)` / `.ext_task_tool_required(tool)` mark tools for task election — a request whose per-request `_meta` `clientCapabilities.extensions` declares the extension gets a durable `CreateTaskResult` (UUIDv4 bearer-grade id, store written BEFORE the response) with a spawned worker; undeclared requests run synchronously (progressive enhancement) or, for `_required` tools, get `-32003` with the upstream `data.requiredCapabilities.extensions` shape. **MRTR bridge**: a task tool returning `McpError::InputRequired` parks its task in `input_required`; `tasks/update` validates response keys against outstanding requests (partial delivery keeps it parked) and resumes the worker with the responses injected through the same session-extension keys as the sync retry leg — tool code is identical under both execution models. `tasks/cancel` is cooperative (aborts the worker, drops input waiters, acks terminal tasks). `notifications/tasks` rides `subscriptions/listen`: the transport honors a `taskIds` filter iff the extension is advertised (keyed off the capability map — no transport dependency on the ext crate), echoes it in the ack, and delivers per-taskId. `turul-mcp-ext-tasks` gains the `TaskStore` trait + `TaskState` + `InMemoryTaskStore` (no tokio in the public API). 9 wire e2e tests (`ext_tasks_2026.rs`, wired into gates + CI); revert-and-fail recorded. Dispatcher design recorded in ADR-028 (2026-06-12 entry).
23
24
-**`turul-mcp-ext-apps` 0.1.0 scaffold (2026-06-12, SEP-1865).** Spec-neutral extension crate binding the MCP-side Apps surface: extension identifier `io.modelcontextprotocol/ui` (the ADR-028 table's `/apps` guess corrected against upstream), client capability (`UiClientCapabilities.mimeTypes` + the `text/html;profile=mcp-app` HTML-views gate), tool `_meta.ui` (`UiToolMeta`: `resourceUri`, `visibility` model/app), and UI-resource `_meta.ui` (`UiResourceMeta`: CSP domain lists, sandbox permissions, dedicated origin, `prefersBorder`). The host↔view iframe protocol is deliberately not bound (app/host SDK scope). Vendored spec pinned at `modelcontextprotocol/ext-apps@ca1d2989`; 5 wire-shape compliance tests.
24
25
- **Versioning/cancellation/elicitation P2 trio (2026-06-12).** (1) **VER-4**: the headerless-`initialize` rejection (400 + `-32001`) now carries `error.data.supported` naming this build's protocol versions — a true legacy client's only diagnostic; wire test `headerless_initialize_rejection_names_supported_versions`, red-phase recorded. (2) **PAT/G10**: dedicated `CancelledNotificationHandler` extracts `requestId` + `reason` from inbound `notifications/cancelled` into a structured log line ("Both parties SHOULD log cancellation reasons"); accepted-and-ignored semantics unchanged. (3) **CF/GAP-CF-8**: new `turul_mcp_builders::validate_elicit_content(schema, content)` validates elicited form content against the requesting schema (required/unknown keys, primitive types, string-length/numeric bounds, integer-ness, enum membership across the 2026 enum-union shapes; format assertions annotation-only by design) — central enforcement is impossible on the stateless lane (leg-1 schema not retained), so tools call it on the MRTR retry; wired into `mrtr-elicitation-server` and live-verified. Plus **BP-5** (COMPLIANCE.md §"Supported JSON Schema dialects" — the documentation the SHOULD asks for) and **UTIL/COMP-3** (relevance/fuzzy/rate-limit completion SHOULDs dispositioned: provider semantics + middleware rate limiting). Driver summary now 305 ✅ / 68 🟡 / 5 ❌ / 12 🧪 / 100 ➖ — the 5 remaining ❌ all carry recorded dispositions.
25
26
- **`turul-mcp-ext-tasks` 0.1.0 scaffold (2026-06-12, SEP-2663).** New spec-neutral extension crate per ADR-028 (2026-06-07 amendment): the `v2026_07_28` module carries the redesigned Tasks-extension surface — status-tagged `DetailedTask` (working/input_required/completed/failed/cancelled with variant fields inlined), `CreateTaskResult` (`resultType: "task"`, flat `Result & Task`), `tasks/get`/`tasks/update`/`tasks/cancel` bindings, `notifications/tasks`, `taskIds` subscription-filter fields, and capability negotiation helpers including SEP-2133 identifier validation. Upstream schema vendored from `modelcontextprotocol/ext-tasks@8966bea9` with a provenance README; 13 wire-shape compliance tests (explicit-null `ttlMs`, snake_case status strings, flat task discriminator). `protocol-2026-07-28` is the default feature; `--no-default-features` compiles empty. Server dispatch wiring and the 2025-11-25 reconciliation module are tracked as separate slices (ADR-028 revision log 2026-06-12). Partially closes driver gap **G1** (SEP-2663 row stays 🟡 until dispatch lands).
0 commit comments