Skip to content

Guide MCP clients to serialize FocusRelay reads and triage bounded slices #221

Description

@deverman

Scheduling

Post-release backlog. Do not start this work or change the frozen release candidate until the current release verification is complete.

User outcome

When a supported MCP client asks FocusRelay to review a large due or flagged workload, it processes one bounded slice at a time instead of launching overlapping Bridge reads or falling back to another OmniFocus server.

Validation impact

server-wire — this changes the MCP Initialize instructions visible to clients, not query semantics or transport architecture.

User-facing acceptance journey

  1. In OpenCode, the user asks to review an overwhelming due or flagged workload.
  2. The assistant requests one bounded FocusRelay list slice of 10–15 tasks and waits for the response.
  3. It helps the user process or summarize that slice before requesting another.
  4. If FocusRelay returns bridge_busy or bridge_queue_timeout, it waits for retryAfterMilliseconds and retries only the rejected read.
  5. It stays with FocusRelay rather than switching to another OmniFocus server.

Sanitized reproduction evidence

On 2026-08-17, OpenCode issued four FocusRelay count calls concurrently in one assistant turn:

  • The first completed in 12.16 seconds.
  • The second waited 10.84 seconds, then hit the 45-second Bridge timeout while processing.
  • The remaining two hit the Bridge queue timeout after about 43 seconds.
  • OpenCode then fell back to a legacy OmniFocus MCP, whose JXA request also timed out after 30 seconds.

The unrelated background OpenCode session did not call OmniFocus. General system load may have amplified latency, but the direct failure was parallel fan-out inside the FocusRelay client session.

A sequential read-only reproduction succeeded:

  • Bridge health: 0.27 seconds
  • Flagged count: 10.56 seconds
  • Exact due count: 8.43 seconds
  • Bounded list of 15 due tasks: 2.80 seconds

Bounded implementation

  • Add one compact MCP server instruction to the Initialize result.
  • Tell clients to run FocusRelay calls sequentially and wait for each response.
  • For due/flagged reviews, prefer one bounded 10–15 item list slice at a time; use counts only when the user actually asks for a count.
  • On bridge_busy or bridge_queue_timeout, honor retryAfterMilliseconds and retry only the rejected read.
  • Tell clients not to switch to another OmniFocus server after a FocusRelay timeout.
  • Add direct MCP Initialize wire coverage for the instruction.
  • Verify that the public tool count, schemas, and catalog remain unchanged.
  • Add prompt-specific guidance only if OpenCode does not surface or follow the global server instruction; avoid duplicated context.

A candidate compact instruction is:

Run FocusRelay tool calls sequentially and wait for each response. For due or flagged reviews, process one bounded 10–15 item slice at a time and use counts only when requested. On bridge_busy or bridge_queue_timeout, wait retryAfterMilliseconds and retry only the rejected read. Do not switch to another OmniFocus server.

UAT

Using the current supported OpenCode version:

  1. Ask to review a large due/flagged workload.
  2. Inspect the transcript and confirm FocusRelay calls do not overlap.
  3. Confirm the first response uses one bounded slice rather than multiple counts or broad lists.
  4. Confirm a rejected read observes the retry delay and does not duplicate successful reads.
  5. Confirm no fallback to a legacy OmniFocus server.

Acceptance criteria

  • MCP Initialize exposes concise client guidance without adding a tool.
  • Direct server-wire tests verify the guidance and unchanged tool catalog.
  • The OpenCode UAT transcript shows sequential FocusRelay calls and bounded-slice processing.
  • Retry guidance is explicit and applies only to rejected read calls.
  • No production query, caching, admission-control, or Bridge dispatch behavior changes.
  • The issue begins only after the current release completes.

Non-goals

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions