diff --git a/apps/server/src/mcp/toolkits/core.test.ts b/apps/server/src/mcp/toolkits/core.test.ts index 0e9b5cb557d41..81614e5eb4274 100644 --- a/apps/server/src/mcp/toolkits/core.test.ts +++ b/apps/server/src/mcp/toolkits/core.test.ts @@ -1126,6 +1126,54 @@ it.effect.each([ ), ); +it.effect("run_scheduled_task_now reports why a started run failed to dispatch", () => + Effect.gen(function* () { + const server = yield* McpServer.McpServer; + const result = yield* server + .callTool({ name: "run_scheduled_task_now", arguments: { taskId: "task-full-access" } }) + .pipe( + Effect.provideService( + McpInvocationContext.McpInvocationContext, + clientScope("full-access"), + ), + Effect.provideService(McpSchema.McpServerClient, client), + ); + expect(result.isError).toBe(false); + expect(result.structuredContent).toMatchObject({ + threadId: null, + lastRunStatus: "failed", + lastRunError: "the provider is disabled", + }); + }).pipe( + Effect.provide( + McpHttpServer.layerThreadToolkit.pipe( + Layer.provideMerge(McpHttpServer.layerInProcessMcpServer), + Layer.provide(NodeCrypto.layer), + Layer.provide(Layer.mock(ThreadManagement.ThreadManagementService)({})), + Layer.provide(Layer.mock(ThreadSearch.ThreadSearch)({})), + Layer.provide(Layer.mock(PeerForwarding.PeerForwarding)({})), + Layer.provide(Layer.mock(PeerLinkRequests.PeerLinkRequests)({})), + Layer.provide(Layer.mock(PeerLinks.PeerLinks)({})), + Layer.provide( + Layer.mock(ScheduledTaskService.ScheduledTaskService)({ + list: () => + Effect.succeed({ tasks: [scheduledTask("task-full-access", "full-access")] }), + runNow: () => + Effect.succeed({ + threadId: null, + task: { + ...(scheduledTask("task-full-access", "full-access") as object), + lastRunStatus: "failed" as const, + lastRunError: "the provider is disabled", + }, + } as never), + }), + ), + ), + ), + ), +); + function scheduledTask(id: string, runtimeMode: "auto" | "full-access"): never { return { id, diff --git a/apps/server/src/mcp/toolkits/thread/handlers.ts b/apps/server/src/mcp/toolkits/thread/handlers.ts index 03b796c6da892..972174638e10f 100644 --- a/apps/server/src/mcp/toolkits/thread/handlers.ts +++ b/apps/server/src/mcp/toolkits/thread/handlers.ts @@ -134,6 +134,7 @@ export const layer = McpToolAccess.toLayer(ThreadToolkit, { link: McpInvocationContext.threadLinkFor(scope, threadId), }), lastRunStatus: task.lastRunStatus, + lastRunError: task.lastRunError, runCount: task.runCount, nextRunAt: task.nextRunAt, }; diff --git a/apps/server/src/mcp/toolkits/thread/tools.ts b/apps/server/src/mcp/toolkits/thread/tools.ts index bea03c83c8465..d6c9a34565ddb 100644 --- a/apps/server/src/mcp/toolkits/thread/tools.ts +++ b/apps/server/src/mcp/toolkits/thread/tools.ts @@ -232,6 +232,7 @@ const ScheduledTaskRunTool = Tool.make("run_scheduled_task_now", { threadId: ScheduledTask.fields.threadId, link: Schema.optional(Schema.String), lastRunStatus: ScheduledTask.fields.lastRunStatus, + lastRunError: ScheduledTask.fields.lastRunError, runCount: NonNegativeInt, nextRunAt: ScheduledTask.fields.nextRunAt, }),