feat(mcp): expose pending user questions#10556

merged1
agents/mcp-thin/queue
agents/mcp-thin/questions
openedSep 7, 2026byJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 3d ago
1 unresolved thread · Jump to file
Selected thread: apps/server/src/mcp/toolkits/thread/handlers.ts:92 — These three handlers add new backend behavior (pending-request filtering, question lookup failure, and a `runtime-request.respond` dispatch), but no test exercises them — the thread toolkit currently has no test module and the integration test only invokes `t3_thread_organize`. Consider adding a focused test alongside the existing toolkit tests (`apps/server/src/mcp/toolkits/core.test.ts` or `OrchestratorMcpToolkit.integration.test.ts`) covering at least the respond path and the `invalid_request` case for a non-pending/unknown `requestId`, using test layers for `ThreadManagementService` rather than mocking the handler logic itself. <sup>Posted via Macroscope — <a href="https://github.com/pingdotgg/t3code/runs/101847601547">Effect Service Conventions</a></sup> <!-- macroscope-meta: {"kind":"check_run","config":".macroscope/check-run-agents/effect-service-conventions.md","check":"Effect Service Conventions"} -->
0 / 4 viewed4 files changedLine totals unavailable

apps/server/src/mcp/toolkits/thread/handlers.ts · Earlier revision 61205e4f · right 65–92

Original diff
@@ -36,7 +37,59 @@ const dispatch = Effect.fn("mcp.dispatchThreadCommand")(function* (
   return { sequence: result.sequence };
 });
 
+const readQuestion = Effect.fn("mcp.readQuestion")(function* (
+  input: {
+    threadId?: ThreadId | undefined;
+    requestId: RuntimeRequestId;
+  },
+  writable = false,
+) {
+  const context = yield* writable ? readWritableThread(input.threadId) : readThread(input.threadId);
+  const request = context.projection.runtimeRequests.find(
+    (request) =>
+      request.id === input.requestId &&
+      request.kind === "user_input" &&
+      request.status === "pending",
+  );
+  const item = context.projection.turnItems.find(
+    (item) => item.type === "user_input_request" && item.requestId === input.requestId,
+  );
+  if (request === undefined || item?.type !== "user_input_request")
+    return yield* new OrchestratorMcpFailure({
+      code: "invalid_request",
+      message: "The pending user-input request was not found.",
+    });
+  return { ...context, request, item };
+});
 export const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
+  t3_pending_request_list: (input) =>
+    Effect.gen(function* () {
+      const { projection } = yield* readThread(input.threadId);
+      return {
+        requestIds: projection.runtimeRequests
+          .filter((request) => request.kind === "user_input" && request.status === "pending")
+          .map((request) => request.id),
+      };
+    }),
+  t3_pending_request_read: (input) =>
+    Effect.gen(function* () {
+      const { item } = yield* readQuestion(input);
+      return { requestId: input.requestId, questions: item.questions };
+    }),
+  t3_pending_request_respond: (input) =>
+    Effect.gen(function* () {
+      const { threads, projection } = yield* readQuestion(input, true);
+      const result = yield* threads
+        .dispatch({
+          type: "runtime-request.respond",
+          threadId: projection.thread.id,
+          commandId: yield* newCommandId(),
+          requestId: input.requestId,
+          answers: input.answers,
+        })
+        .pipe(Effect.mapError(unavailable));
+      return { sequence: result.sequence };
+    }),

apps/server/src/mcp/toolkits/thread/handlers.ts · right 65–92

M
macroscopeappBotSep 7, 2026

These three handlers add new backend behavior (pending-request filtering, question lookup failure, and a runtime-request.respond dispatch), but no test exercises them — the thread toolkit currently has no test module and the integration test only invokes t3_thread_organize. Consider adding a focused test alongside the existing toolkit tests (apps/server/src/mcp/toolkits/core.test.ts or OrchestratorMcpToolkit.integration.test.ts) covering at least the respond path and the invalid_request case for a non-pending/unknown requestId, using test layers for ThreadManagementService rather than mocking the handler logic itself.

Posted via Macroscope — Effect Service Conventions

J
Julius MarmingeSep 7, 2026

The maintainer explicitly requested shared MCP coverage rather than per-tool service-test duplication for this rebuild. These handlers reuse readThread/readWritableThread for scope and ceilings, the existing ProviderUserInputAnswers contract, and the existing runtime-request.respond command. The filter/lookup only selects pending user_input records; no response execution or provider state machine is introduced. Shared production registration/schema/capability/error tests and the existing real MCP/V2 integration remain in the stack; runtime response behavior remains tested with the service. No concrete faulty behavior was identified here, so no wrapper-only dispatch mock suite is being added.

M
macroscopeappBotSep 7, 2026

The service-layer coverage does not exercise these MCP handlers. Current shared MCP tests cover infrastructure only, and the integration suite does not invoke the pending-request tools. The requested focused MCP test—especially invalid_request plus the respond dispatch path—remains warranted.