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
Add MCP write tool(s) to resolve Operating Room (operator queue) items — answer questions, approve/deny approval requests, and (optionally) cancel pending items — so an agent or external Claude Code client can close the loop on alerts it can already read via #1101. Today the operator queue's write surface is REST-only (POST /api/operator-queue/{id}/respond, POST /api/operator-queue/{id}/cancel); the only MCP write tool in the OPS-001 family is send_notification (raise an alert). There is no MCP tool to respond to or resolve an existing item.
Context
#1101 shipped the read half of the operator-queue MCP surface (list_operator_queue, get_operator_queue_item, src/mcp-server/src/tools/operator_queue.ts) and explicitly deferred the write/respond half to a follow-up ("Write actions (respond / cancel) are intentionally deferred to a follow-up — this surface is read-only").
This is that follow-up. Read-only is the less actionable half: an agent can now see a sibling's pending approval or question but cannot act on it without a human at the web UI or a hand-curled REST call. Exposing the respond/resolve surface over MCP completes the raise → observe → respond round-trip and finishes Invariant #13 (MCP = third surface in sync) for OPS-001.
Acceptance Criteria
respond_to_operator_queue MCP tool added to src/mcp-server/src/tools/operator_queue.ts — proxies POST /api/operator-queue/{id}/respond with response (required) and optional response_text
(Optional, decide in review) cancel_operator_queue_item — proxies POST /api/operator-queue/{id}/cancel; consider leaving out of v1 given wider blast radius
Access control honored for writes: agent-scoped keys may only resolve items for {self} ∪ permitted agents — reuse the existing checkAgentAccess gate in operator_queue.ts (the backend resolves an agent-scoped key to its owner and does NOT apply agent_permissions, so the agent-to-agent gate must live in the MCP layer, same as the read tools)
Resolve the item's agent_name before gating (fetch via get/list if the caller only supplies an id) so the permission check has a target agent
State-machine errors surfaced cleanly: the backend rejects respond/cancel on a non-pending item (HTTP 400) — return a structured { error } rather than throwing
No new backend endpoints required — thin TS proxy over the existing REST routes
Technical Notes
Backend write surface already exists in src/backend/routers/operator_queue.py: POST /{item_id}/respond (body model OperatorResponse { response: str, response_text: Optional[str] }) and POST /{item_id}/cancel. Both 400 if the item is not in a respondable/cancellable state.
Mirror the existing proxy + checkAgentAccess pattern already in operator_queue.ts (read tools) — the access-control crux and helper are identical; only the verb changes.
Add the corresponding TrinityClient method(s) alongside the existing listOperatorQueue / getOperatorQueueItem in the MCP client.
Design decision for review: should an agent-scoped key be allowed to approve another (permitted) agent's approval request, or should approvals stay operator-only while questions/alerts are agent-respondable? Settle the write-permission model before merge.
Summary
Add MCP write tool(s) to resolve Operating Room (operator queue) items — answer questions, approve/deny approval requests, and (optionally) cancel pending items — so an agent or external Claude Code client can close the loop on alerts it can already read via #1101. Today the operator queue's write surface is REST-only (
POST /api/operator-queue/{id}/respond,POST /api/operator-queue/{id}/cancel); the only MCP write tool in the OPS-001 family issend_notification(raise an alert). There is no MCP tool to respond to or resolve an existing item.Context
#1101 shipped the read half of the operator-queue MCP surface (
list_operator_queue,get_operator_queue_item,src/mcp-server/src/tools/operator_queue.ts) and explicitly deferred the write/respond half to a follow-up ("Write actions (respond / cancel) are intentionally deferred to a follow-up — this surface is read-only").This is that follow-up. Read-only is the less actionable half: an agent can now see a sibling's pending approval or question but cannot act on it without a human at the web UI or a hand-curled REST call. Exposing the respond/resolve surface over MCP completes the raise → observe → respond round-trip and finishes Invariant #13 (MCP = third surface in sync) for OPS-001.
Acceptance Criteria
respond_to_operator_queueMCP tool added tosrc/mcp-server/src/tools/operator_queue.ts— proxiesPOST /api/operator-queue/{id}/respondwithresponse(required) and optionalresponse_textcancel_operator_queue_item— proxiesPOST /api/operator-queue/{id}/cancel; consider leaving out of v1 given wider blast radius{self} ∪ permittedagents — reuse the existingcheckAgentAccessgate inoperator_queue.ts(the backend resolves an agent-scoped key to its owner and does NOT applyagent_permissions, so the agent-to-agent gate must live in the MCP layer, same as the read tools)agent_namebefore gating (fetch viaget/list if the caller only supplies anid) so the permission check has a target agentpendingitem (HTTP 400) — return a structured{ error }rather than throwingarchitecture.mdoperator-queue MCP table row updated (read-only → read + respond)Technical Notes
src/backend/routers/operator_queue.py:POST /{item_id}/respond(body modelOperatorResponse { response: str, response_text: Optional[str] }) andPOST /{item_id}/cancel. Both 400 if the item is not in a respondable/cancellable state.checkAgentAccesspattern already inoperator_queue.ts(read tools) — the access-control crux and helper are identical; only the verb changes.TrinityClientmethod(s) alongside the existinglistOperatorQueue/getOperatorQueueItemin the MCP client.list→get→respondin one MCP session.