Skip to content

feat(mcp): respond to / resolve Operator Queue items over MCP (#1101 follow-up) #1104

Description

@vybe

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 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
  • MCP tool count + architecture.md operator-queue MCP table row updated (read-only → read + respond)
  • 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.
  • Pairs with feat(mcp): MCP tools to read Operator Queue (OPS alerts) — broad or by agent name #1101 — keep the read and write tools coherent so an agent can list → get → respond in one MCP session.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions