feat(mcp): expose existing queued message commands#10555

merged2
agents/mcp-thin/thread-organization
agents/mcp-thin/queue
openedSep 7, 2026byJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 3d ago

Part 5/16 of the shared-core and MCP stack. Based on #10554. Next: #10556.

Expose queued message list/read/edit/cancel/reorder/promote through ThreadManagementService and the existing queue commands.

Output text is bounded by Unicode code points. Paging is a live offset. Queue ordering, dispatch and replay semantics remain in the existing services.

MCP-only rebuild of #8699, preserving attribution to Julius Marminge's original work. Original branches remain available for separate service follow-ups.

Validation: The composed stack passes 94 tests across 12 focused files, including shared core MCP and real MCP/V2 integration, attachment intake, project RPC/service contracts, and client model command selection. Server/contracts/shared/client-runtime typechecks and targeted format/lint/diff checks pass. New behavior coverage lives with the shared operation; no per-tool mock suite was added. Current-head CI is shown below.

Layer size: 6 files, +191/-6. No domain-service production implementation or documentation files change in this MCP layer.

Prepared with Codex in the OpenAI agent runtime.

Note

Expose six queued-message MCP tools in ThreadToolkit

  • Adds t3_queue_list, t3_queue_read, t3_queue_edit, t3_queue_cancel, t3_queue_reorder, and t3_queue_promote_to_steer MCP tools for managing queued thread runs
  • List entries cap message text at 1,000 characters; direct reads cap at 16,000 characters, both using Unicode-code-point counting via Array.from
  • Mutation handlers dispatch existing orchestration commands through a shared dispatch helper that maps failures to the unavailable MCP error
  • Registers t3_queue_list and t3_queue_read in CLAUDE_READ_ONLY_T3_MCP_ALLOWED_TOOLS and adds display names in the shared presentation registry
  • Risk: queueEntry helper in handlers.ts returns undefined for non-queued or unmatched runs, causing t3_queue_read to return invalid_request — callers passing a run ID that is not currently queued will see this failure

Macroscope summarized 0a74c93.

Synced from GitHub

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR adds six production MCP queue tools, including destructive mutations, and expands Claude's default read-only tool allowlist. The integration coverage is useful but does not fully exercise the new handler command and failure paths.

No code changes detected at 0a74c93. Prior analysis still applies.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Thread transfer impact

⚠️ The latest CI run did not produce a thread transfer result for 0a74c93.

This comment will update automatically after the next completed run.

apps/server/src/mcp/toolkits/thread/handlers.tsline 40Outdated · 2a263e9Open thread
……@@ -1,10 +1,95 @@
37+});
38+
739export const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
40+ t3_queue_list: (input) =>
MmacroscopeappBoton line 40Sep 7, 2026

These six new handlers change backend behavior (queue paging via cursor/limit, queueEntry truncation at 1000/16000 characters, not found failure mapping, and command construction for edit/cancel/reorder/promote) but no focused tests were added — toolkits/core.test.ts only covers t3_thread_organize. Consider adding handler tests in the same style as core.test.ts, using Layer.mock(ThreadManagementService) as the test layer for the external service and asserting the real handler output (page shape/nextCursor, truncation flag, and the invalid_request path for an unknown queuedRunId).

Posted via Macroscope — Effect Service Conventions

Fixed in 90adc5c8bff1c16a8a878c1cce733d8a1e1b3e1c. CommandId is a normal top-level type import. The existing real MCP/V2 integration now follows both queue pages, verifies the 1,000/16,000 Unicode-code-point output windows, and checks an unknown queued run's invalid_request result. The fixture uses an existing queued run and cleanup path rather than adding six service mocks or duplicating queue execution tests. Integration 2/2 and server typecheck passed; the full stack core/integration batch is 6/6.

apps/server/src/mcp/toolkits/thread/handlers.tsline 28Outdated · 2a263e9Open thread
……@@ -1,10 +1,95 @@
25+const dispatch = Effect.fn("mcp.dispatchThreadCommand")(function* (
26+ threadId: ThreadId | undefined,
27+ command: (common: {
28+ commandId: import("@t3tools/contracts").CommandId;
MmacroscopeappBoton line 28Sep 7, 2026

thread/handlers.ts:28

An inline import("@t3tools/contracts").CommandId type expression bypasses the module's import block. Consider adding type CommandId to the existing top-level named import from @t3tools/contracts (lines 1-7) and referencing it as commandId: CommandId; here.

No longer relevant as of 90adc5c8bff1c16a8a878c1cce733d8a1e1b3e1c

Fixed in 90adc5c8bff1c16a8a878c1cce733d8a1e1b3e1c. CommandId is a normal top-level type import. The existing real MCP/V2 integration now follows both queue pages, verifies the 1,000/16,000 Unicode-code-point output windows, and checks an unknown queued run's invalid_request result. The fixture uses an existing queued run and cleanup path rather than adding six service mocks or duplicating queue execution tests. Integration 2/2 and server typecheck passed; the full stack core/integration batch is 6/6.

Added 2 commits

  • test(mcp): cover queue output in the shared integration0a74c93
  • feat(mcp): expose existing queued message operationsc1d4b34