v3.11.0¶
This wave corrects the MCP surface an operator actually reads and drives: one tool per question, a per-run cancel, typed results a client can validate, in-band progress on long runs, a remote transport that serves resources and enforces its request headers, and a claim-ledger fold that answers honestly about claims that can never be released.
Behaviour changes (read before upgrading)¶
- The MCP tool surface is consolidated; every removed name stays callable for this release as a deprecated alias (#3087). Aliases are never advertised in
tools/list; an alias answers with its historical payload underresultplus a notice naming its replacement. The aliases are gated byBERNSTEIN_MCP_DEPRECATED_ALIASES(set0to drop them now) and are removed in v3.12.0. The mapping:
| Removed name | Replacement |
|---|---|
bernstein_health | bernstein_status (the response is the liveness signal) |
bernstein_tasks | bernstein_status with the status filter |
bernstein_cost | bernstein_status (cost fields) |
bernstein_create_subtask | bernstein_run with parent_task_id |
bernstein_task_handle | bernstein_run_status |
bernstein_update | bernstein_post_message |
bernstein_context | bernstein_task_capsule |
bernstein_stop | bernstein_shutdown_orchestrator |
bernstein_scenarios | bernstein_scenario with action="list" |
bernstein_scenario_status | bernstein_scenario with action="status" |
verify_chain | bernstein_verify_lineage |
A scenario run now returns the same pollable handle shape as bernstein_run, so bernstein_run_status polls it.
- The remote MCP transport now enforces
OriginandMCP-Protocol-Version(#3084). A request whoseOriginis not in the configured allow list is refused with 403 (the enforcement half of the DNS-rebinding defence the response headers alone never provided), and an unsupported protocol-version header is refused with 400 naming the supported revisions; an absent header is served as2025-03-26. Both checks ship behind a one-release opt-out,BERNSTEIN_MCP_REMOTE_HEADER_CHECKS=0, for operators whose proxies rewrite these headers. A JSON array request body (the batching removed from the MCP schema two revisions ago) is now rejected.
MCP¶
-
Per-run cancel (#3078).
bernstein_cancelcancels one task and its subtask tree throughPOST /tasks/{task_id}/canceland the orchestrator keeps running. It reads the task first: an unknown id or a non-cancellable state is refused with no state-changing request sent, and an already-terminal task is reported with its state rather than as an error. The whole-orchestrator stop now opens its description with its blast radius and points atbernstein_cancelfor the single-run case. -
Structured results with declared output schemas (#3086).
bernstein_run,bernstein_statusandbernstein_run_statusdeclare anoutputSchemaand returnstructuredContent: the run-handle fields (taskId,runId,status,journalHead,chainHead,receiptHash,pollToken) are first-class typed fields. The text content block is byte-for-byte unchanged, including the_meterenvelope, and the declared schema describes the envelope exactly as emitted for the live cost-meter state; the handle portion is generated from the wire body so it cannot drift. Nothing in the structured result's hashed region carries a wall clock: two polls of an unchanged journal are byte-identical. Moving_meterout of the result body is tracked separately. -
Progress notifications on the poll (#3085). A
bernstein_run_statuscall carrying aprogressTokenreceives anotifications/progresstick derived entirely from the chain-computed progress fold: earned steps asprogress, declared evidence producers astotal, fold counters as themessage. A tick that does not strictly advance the previous tick for that run is suppressed, so the notified sequence is monotone by construction; a failed emission never reaches the tool result, and clients that send no token see no change. -
The remote transport serves resources (#3084).
resources/list,resources/templates/listandresources/readnow answer over the streamable HTTP transport with the same resources stdio exposes: the runtime capability card, the skill discovery index, and - only whenBERNSTEIN_LINEAGE_MCP_ENABLED=1opts in - the lineage records. Resource reads pass through the same auth checks as tool calls. Theinitializeresult and the capability card now report the protocol revision actually negotiated for the connection instead of a constant.
Audit¶
- The claim fold answers honestly for unreleasable claim paths (#3072). Claim receipts minted on the MCP claim path (
claim_path="mcp_claim") are recorded against the JSON backlog, a store the task-store release receipts never touch, so they can never be released and the plain fold reported them as held forever.reconstruct_claim_holdersgains aclaim_pathsscope so a verifier folds the release-capable ledger without the acquisition-only rows (or selects exactly them);UNRELEASED_CLAIM_PATHSnames the paths with no release half, andrelease_ledger_boundarylocates the first release receipt so the pre-release-ledger region of an old chain is answered as unknown instead of confidently wrong.