feat(mcp): add batch summaries with read-only detail retrieval

Add opt-in response_detail=summary with step and change counts, compact state, warnings, and actionable errors or prompts. Return an ocs_read batch_result request for full cached details without resuming mutations.

Keep compact/full behavior and idempotent batch retries intact. Preserve active-step context and report unavailable cached results explicitly. Document cache scope and retention; update schemas and digest.

Validation: 47 MCP unit tests, live stdio smoke test, rustfmt, and diff checks passed.
This commit is contained in:
Karim Jerbi committed 2026-10-12 09:39:54 +01:00
1 parent f4b33d5cde
commit 7b68d274ad
3 files changed
+322 -10

No files matched your search

+16
View File
@@ -191,6 +191,22 @@ Use `batch` when the steps are already known. OCS supplies each step with the st
Execute responses use `response_detail: "compact"` by default and return only the state needed for the next edit. Use `changed_entities` to receive the current geometry of affected handles in the same response, or `full` when the complete editor state is needed.
For large batches, use `response_detail: "summary"`. It omits the full step
results and change list, returning step counts, `failed_steps`, `change_count`,
compact final state and a `details` tool request. `change_count` counts change
records, not unique entities. Warnings, failed or waiting-input steps in
`attention`, and any `active_step` are retained so the next action remains clear.
For non-batch operations, `summary` behaves like `compact`.
To inspect the retained full result, call the tool and arguments in `details`:
`ocs_read` with the same `ocs_session_id`, `op: "batch_result"`, and
`parameters: {"request_id": "<original batch request_id>"}`. This reads a cached
snapshot without executing or resuming any step. Results are retained in the
originating MCP connection, for up to 64 batches per session; after eviction or
reconnection the read fails explicitly. Do not replay a mutation merely to
retrieve expired details. A `running` snapshot is not completion; resume work
through the existing batch retry/task workflow.
`ocs_read` query accepts exact handles, type/layer filters, field projection, world-XY bounds, nearest-curve ranking, closed-curve containment, and exact intersections between two planar curves. `detail: "full"` adds the complete serialized entity properties. Nearest points, containment, curve length, area, and intersections are calculated by the geometry kernel:
```json
+11
View File
@@ -51,6 +51,8 @@ def legacy(server: Path) -> None:
definitions = {tool["name"]: tool for tool in tools["result"]["tools"]}
names = set(definitions)
assert names == TOOLS, names
assert "summary" in definitions["ocs_execute"]["inputSchema"]["properties"]["response_detail"]["enum"]
assert "batch_result" in definitions["ocs_read"]["inputSchema"]["properties"]["op"]["enum"]
execute_request = definitions["ocs_execute"]["inputSchema"]["properties"]["request"]
variants = execute_request.get("anyOf") or execute_request.get("oneOf")
# Resolve local references from the complete tool input schema.
@@ -103,6 +105,15 @@ def legacy(server: Path) -> None:
"params": {"name": "ocs_sessions", "arguments": {"launch_if_none": False}},
})
assert not sessions["result"].get("isError"), sessions
missing_batch = request(process, {
"jsonrpc": "2.0", "id": 4, "method": "tools/call",
"params": {"name": "ocs_read", "arguments": {
"ocs_session_id": "missing", "op": "batch_result",
"parameters": {"request_id": "expired-batch"},
}},
})
assert missing_batch["result"]["isError"] is True
assert "absent or expired" in missing_batch["result"]["content"][0]["text"]
close(process)