feat(mcp): expose scheduled task run-now#10562
1 unresolved thread · Jump to file
apps/server/src/mcp/toolkits/thread/handlers.ts · Earlier revision 97d14934 · right 74–103
Original diff
@@ -69,6 +71,36 @@ const readQuestion = Effect.fn("mcp.readQuestion")(function* (
return { ...context, request, item };
});
export const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
+ run_scheduled_task_now: (input) =>
+ Effect.gen(function* () {
+ const { caller } = yield* readMutationCaller();
+ if (
+ caller.archivedAt !== null ||
+ caller.runtimeMode !== "full-access" ||
+ caller.interactionMode !== "default"
+ )
+ return yield* new OrchestratorMcpFailure({
+ code: "capability_denied",
+ message: "Running a scheduled task requires a live full-access/default thread.",
+ });
+ const scheduler = yield* ScheduledTasks.ScheduledTaskService;
+ const { tasks } = yield* scheduler.list().pipe(Effect.mapError(unavailable));
+ if (!tasks.some((task) => task.id === input.taskId && task.projectId === caller.projectId))
+ return yield* new OrchestratorMcpFailure({
+ code: "invalid_request",
+ message: "The task was not found in the calling project.",
+ });
+ const { task } = yield* scheduler
+ .runNow({ id: input.taskId })
+ .pipe(Effect.mapError(unavailable));
+ return {
+ taskId: task.id,
+ threadId: task.threadId,
+ lastRunStatus: task.lastRunStatus,
+ runCount: task.runCount,
+ nextRunAt: task.nextRunAt,
+ };
+ }),apps/server/src/mcp/toolkits/thread/handlers.ts · right 74–103
This adds new backend behavior (a destructive tool that dispatches a scheduler run) with no focused test. Consider covering the two guard branches (non-full-access/non-default caller -> capability_denied, task outside the calling project -> invalid_request) and the happy path using the existing test-layer patterns: Layer.mock(ThreadManagement.ThreadManagementService) as in apps/server/src/mcp/toolkits/core.test.ts, or the in-memory scheduledTaskStubLayer already wired into apps/server/src/mcp/OrchestratorMcpToolkit.integration.test.ts — test layers for the external services only, no mocking of the handler logic itself.
Posted via Macroscope — Effect Service Conventions
Following the maintainer-requested test boundary: this tool calls existing ScheduledTaskService.list/runNow after a direct caller-mode and task-project filter; no scheduler execution, replay or bookkeeping implementation changes. Shared MCP registration/input/caller/error coverage remains in the stack, and ScheduledTaskService retains its isolated behavior tests. We are not adding a separate test suite merely to assert forwarding of the already-typed service call. The PR explicitly documents a new manual run per call and does not promise additional transactional authority or keyed replay.
The concern remains: no existing test invokes this handler. The caller-mode and project guards are tool-local behavior, so shared registration/input coverage and isolated service tests do not exercise them. A focused handler test for those guards and the successful delegation is still warranted.