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
Major release preparing parse-stack-next v5.0.0 with API, tooling, and infra updates. Renames the gem to parse-stack-next and updates docs/README and changelog. Introduces an ergonomic Redis cache with a ConnectionPool-backed Pool wrapper and optional cache namespacing, plus ActiveSupport cache events and graceful pool-timeout handling. Adds vector/embeddings and vector-search primitives, a GraphQL type generator for Parse::Object models (opt-in), and many model/vector/graphQL helpers. Improves Ruby 3 compatibility by replacing class variables with class-instance state guarded by mutexes/monitors, refactors LiveQuery request id generation, and tightens various validations. MCP transport and agent code add health checks, protocol-version validation, and structured tool output. Also adds MongoDB instrumentation events and a slow-query subscriber hook. Includes CI docs workflow (YARD) and a large suite of new/updated tests to cover the new features and integrations.
2.**SSE client disconnect.** When the underlying TCP connection closes (browser tab closed, network drop), Rack calls `SSEBody#close`, which trips the same cancellation token.
287
287
288
-
**Identity binding (required for `notifications/cancelled`).** The cancelling request **must** carry the same `X-MCP-Session-Id` header as the original request. The header is sanitized into `agent.correlation_id` and used as half of the registry key (the JSON-RPC `requestId` is the other half). Cancellation without a matching `X-MCP-Session-Id` is a silent no-op — this prevents an attacker who guesses sequential JSON-RPC ids from cancelling other clients' in-flight requests. Failures (no session id, no matching entry, mismatched session id) all return `202` so the response shape is not a probe oracle.
288
+
**Identity binding (required for `notifications/cancelled`).** The cancelling request **must** carry the same `Mcp-Session-Id` header as the original request. The header is sanitized into `agent.correlation_id` and used as half of the registry key (the JSON-RPC `requestId` is the other half). Cancellation without a matching `Mcp-Session-Id` is a silent no-op — this prevents an attacker who guesses sequential JSON-RPC ids from cancelling other clients' in-flight requests. Failures (no session id, no matching entry, mismatched session id) all return `202` so the response shape is not a probe oracle.
289
289
290
290
**Cooperative checkpoints.** Cancellation is observed at safe points inside tool execution, not by forcibly killing the dispatcher thread. The two checkpoints built into `Parse::Agent#execute` are:
291
291
@@ -319,7 +319,7 @@ The stream still emits the `response` SSE event before closing so clients do not
319
319
320
320
**Scope and limitations.**
321
321
- The cancellation registry is per `MCPRackApp` instance. Cancellation does not span multiple mount points within a process, nor multiple processes in a clustered deployment.
322
-
- Clients that do not set `X-MCP-Session-Id` lose cancellation but keep every other MCP feature.
322
+
- Clients that do not set `Mcp-Session-Id` lose cancellation but keep every other MCP feature.
323
323
- The standalone WEBrick-backed `MCPServer` does not support streaming and therefore does not support cancellation; calls return a single buffered response with no opportunity to interrupt.
324
324
325
325
---
@@ -1834,7 +1834,7 @@ Every tool call dispatched through `Agent#execute` fires the `"parse.agent.tool_
1834
1834
1835
1835
**Conversation correlation across multi-tool sessions.** Without correlation, individual tool-call events have no link between them — a Datadog dashboard sees "user X did query_class" and "user X did get_object" as independent points, with no way to know they belong to the same LLM turn. The dispatcher threads an optional correlation id through to every notification:
1836
1836
1837
-
-**Header path (recommended for hosted MCP):** the client sends `X-MCP-Session-Id: <opaque-id>` on every request in the conversation. `MCPRackApp` reads the header, sanitizes the value (charset `[A-Za-z0-9._-]`, max 128 chars — anything else is silently dropped to prevent log injection), and sets `agent.correlation_id` unless the factory has already supplied one. Notifications fired during that request carry the value as `payload[:correlation_id]`.
1837
+
-**Header path (recommended for hosted MCP):** the client sends `Mcp-Session-Id: <opaque-id>` on every request in the conversation (the MCP 2025-06-18 Streamable HTTP spec-canonical name). `MCPRackApp` reads the header, sanitizes the value (charset `[A-Za-z0-9._-]`, max 128 chars — anything else is silently dropped to prevent log injection), and sets `agent.correlation_id` unless the factory has already supplied one. Notifications fired during that request carry the value as `payload[:correlation_id]`.
1838
1838
1839
1839
-**Factory path (for application-bound sessions):** application code that already has an internal session identifier can override the client-supplied header by setting it inside the agent factory:
1840
1840
@@ -1853,7 +1853,7 @@ Every tool call dispatched through `Agent#execute` fires the `"parse.agent.tool_
1853
1853
1854
1854
When unset (no header, no factory assignment), `payload[:correlation_id]` is omitted entirely — the key does not appear in the payload hash.
1855
1855
1856
-
The same `X-MCP-Session-Id` header is **required** for cooperative cancellation via `notifications/cancelled` — see the Cancellation section. Clients that thread the header through every request in a conversation get both correlated audit logs and cancellation; clients that don't lose both but keep every other MCP feature.
1856
+
The same `Mcp-Session-Id` header is **required** for cooperative cancellation via `notifications/cancelled` — see the Cancellation section. Clients that thread the header through every request in a conversation get both correlated audit logs and cancellation; clients that don't lose both but keep every other MCP feature.
1857
1857
1858
1858
**Cancellation notification asymmetry.** A tool cancelled BEFORE it runs (via `agent.cancelled?` at the dispatcher's first checkpoint) does not fire `parse.agent.tool_call` — the tool never executed, so there is nothing to instrument. This matches how rate-limit and permission refusals are surfaced. A tool cancelled AFTER it returns (second checkpoint, "client cancelled while the tool's I/O was running") DOES fire the notification with `success: false, error_code: :cancelled`. Subscribers that count cancellations should expect the second shape; pre-run cancellations are visible to operators only via the wire response.
0 commit comments