@softure-ai/mcp-access 0.2.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +270 -19
  3. package/dist/cli/run.d.ts +1 -1
  4. package/dist/cli/run.d.ts.map +1 -1
  5. package/dist/cli/run.js +2 -2
  6. package/dist/cli/run.js.map +1 -1
  7. package/dist/contract.d.ts +48 -2
  8. package/dist/contract.d.ts.map +1 -1
  9. package/dist/index.d.ts +96 -3
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +26 -5
  12. package/dist/index.js.map +1 -1
  13. package/dist/jobs/index.d.ts +2 -0
  14. package/dist/jobs/index.d.ts.map +1 -1
  15. package/dist/jobs/index.js +5 -2
  16. package/dist/jobs/index.js.map +1 -1
  17. package/dist/jobs/operation-state.d.ts +58 -0
  18. package/dist/jobs/operation-state.d.ts.map +1 -0
  19. package/dist/jobs/operation-state.js +68 -0
  20. package/dist/jobs/operation-state.js.map +1 -0
  21. package/dist/jobs/operation-tasks.d.ts +61 -0
  22. package/dist/jobs/operation-tasks.d.ts.map +1 -0
  23. package/dist/jobs/operation-tasks.js +161 -0
  24. package/dist/jobs/operation-tasks.js.map +1 -0
  25. package/dist/jobs/operations.d.ts +68 -0
  26. package/dist/jobs/operations.d.ts.map +1 -0
  27. package/dist/jobs/operations.js +110 -0
  28. package/dist/jobs/operations.js.map +1 -0
  29. package/dist/messages/en.d.ts +57 -1
  30. package/dist/messages/en.d.ts.map +1 -1
  31. package/dist/messages/en.js +57 -1
  32. package/dist/messages/en.js.map +1 -1
  33. package/dist/messages/index.d.ts +56 -1
  34. package/dist/messages/index.d.ts.map +1 -1
  35. package/dist/next/issue-token.d.ts +11 -2
  36. package/dist/next/issue-token.d.ts.map +1 -1
  37. package/dist/next/issue-token.js +56 -7
  38. package/dist/next/issue-token.js.map +1 -1
  39. package/dist/next/oauth-page.d.ts +6 -1
  40. package/dist/next/oauth-page.d.ts.map +1 -1
  41. package/dist/next/oauth-page.js +6 -5
  42. package/dist/next/oauth-page.js.map +1 -1
  43. package/dist/next/token-manager-props.d.ts +3 -2
  44. package/dist/next/token-manager-props.d.ts.map +1 -1
  45. package/dist/next/token-manager-props.js +12 -2
  46. package/dist/next/token-manager-props.js.map +1 -1
  47. package/dist/options.d.ts +47 -0
  48. package/dist/options.d.ts.map +1 -1
  49. package/dist/options.js +53 -0
  50. package/dist/options.js.map +1 -1
  51. package/dist/schema.d.ts +214 -0
  52. package/dist/schema.d.ts.map +1 -1
  53. package/dist/schema.js +21 -3
  54. package/dist/schema.js.map +1 -1
  55. package/dist/server/api-tokens.d.ts +64 -0
  56. package/dist/server/api-tokens.d.ts.map +1 -0
  57. package/dist/server/api-tokens.js +176 -0
  58. package/dist/server/api-tokens.js.map +1 -0
  59. package/dist/server/confirmation.d.ts +69 -0
  60. package/dist/server/confirmation.d.ts.map +1 -0
  61. package/dist/server/confirmation.js +220 -0
  62. package/dist/server/confirmation.js.map +1 -0
  63. package/dist/server/endpoint.d.ts.map +1 -1
  64. package/dist/server/endpoint.js +6 -4
  65. package/dist/server/endpoint.js.map +1 -1
  66. package/dist/server/health.d.ts.map +1 -1
  67. package/dist/server/health.js +3 -1
  68. package/dist/server/health.js.map +1 -1
  69. package/dist/server/index.d.ts +5 -2
  70. package/dist/server/index.d.ts.map +1 -1
  71. package/dist/server/index.js +4 -1
  72. package/dist/server/index.js.map +1 -1
  73. package/dist/server/oauth-http.d.ts +5 -0
  74. package/dist/server/oauth-http.d.ts.map +1 -1
  75. package/dist/server/oauth-http.js +11 -7
  76. package/dist/server/oauth-http.js.map +1 -1
  77. package/dist/server/privacy.d.ts +4 -0
  78. package/dist/server/privacy.d.ts.map +1 -1
  79. package/dist/server/privacy.js +5 -1
  80. package/dist/server/privacy.js.map +1 -1
  81. package/dist/server/prune.d.ts +5 -1
  82. package/dist/server/prune.d.ts.map +1 -1
  83. package/dist/server/prune.js +14 -4
  84. package/dist/server/prune.js.map +1 -1
  85. package/dist/server/strict-input.d.ts +3 -1
  86. package/dist/server/strict-input.d.ts.map +1 -1
  87. package/dist/server/strict-input.js +54 -8
  88. package/dist/server/strict-input.js.map +1 -1
  89. package/dist/server/tokens.d.ts +46 -11
  90. package/dist/server/tokens.d.ts.map +1 -1
  91. package/dist/server/tokens.js +46 -24
  92. package/dist/server/tokens.js.map +1 -1
  93. package/dist/server/tools.d.ts +8 -0
  94. package/dist/server/tools.d.ts.map +1 -1
  95. package/dist/server/tools.js +1 -0
  96. package/dist/server/tools.js.map +1 -1
  97. package/dist/server/writes-switch.d.ts +8 -0
  98. package/dist/server/writes-switch.d.ts.map +1 -0
  99. package/dist/server/writes-switch.js +25 -0
  100. package/dist/server/writes-switch.js.map +1 -0
  101. package/dist/stdio/serve.d.ts.map +1 -1
  102. package/dist/stdio/serve.js +5 -7
  103. package/dist/stdio/serve.js.map +1 -1
  104. package/dist/tokens/index.d.ts +6 -0
  105. package/dist/tokens/index.d.ts.map +1 -0
  106. package/dist/tokens/index.js +8 -0
  107. package/dist/tokens/index.js.map +1 -0
  108. package/dist/ui/consent-form.d.ts +2 -2
  109. package/dist/ui/consent-form.d.ts.map +1 -1
  110. package/dist/ui/consent-form.js +3 -2
  111. package/dist/ui/consent-form.js.map +1 -1
  112. package/dist/ui/index.d.ts +1 -1
  113. package/dist/ui/index.d.ts.map +1 -1
  114. package/dist/ui/index.js.map +1 -1
  115. package/dist/ui/token-manager.d.ts +18 -2
  116. package/dist/ui/token-manager.d.ts.map +1 -1
  117. package/dist/ui/token-manager.js +28 -3
  118. package/dist/ui/token-manager.js.map +1 -1
  119. package/migrations/0004_create_used_confirmations.sql +13 -0
  120. package/migrations/0005_add_api_tokens.sql +15 -0
  121. package/migrations/0006_create_operation_tasks.sql +18 -0
  122. package/module.json +10 -4
  123. package/package.json +7 -2
  124. package/src/cli/run.ts +2 -2
  125. package/src/contract.ts +60 -2
  126. package/src/index.ts +39 -4
  127. package/src/jobs/index.ts +41 -2
  128. package/src/jobs/operation-state.ts +119 -0
  129. package/src/jobs/operation-tasks.ts +229 -0
  130. package/src/jobs/operations.ts +213 -0
  131. package/src/messages/en.ts +58 -1
  132. package/src/next/issue-token.ts +64 -9
  133. package/src/next/oauth-page.tsx +12 -6
  134. package/src/next/token-manager-props.ts +15 -4
  135. package/src/options.ts +62 -0
  136. package/src/schema.ts +23 -3
  137. package/src/server/api-tokens.ts +224 -0
  138. package/src/server/confirmation.ts +316 -0
  139. package/src/server/endpoint.ts +6 -4
  140. package/src/server/health.ts +3 -1
  141. package/src/server/index.ts +33 -2
  142. package/src/server/oauth-http.ts +16 -7
  143. package/src/server/privacy.ts +9 -1
  144. package/src/server/prune.ts +17 -4
  145. package/src/server/strict-input.ts +62 -13
  146. package/src/server/tokens.ts +73 -27
  147. package/src/server/tools.ts +9 -0
  148. package/src/server/writes-switch.ts +24 -0
  149. package/src/stdio/serve.ts +5 -7
  150. package/src/tokens/index.ts +22 -0
  151. package/src/ui/consent-form.tsx +12 -8
  152. package/src/ui/index.ts +1 -0
  153. package/src/ui/token-manager.tsx +140 -3
@@ -0,0 +1,161 @@
1
+ // Long operations as MCP Tasks (#977): the Tasks extension `io.modelcontextprotocol/tasks` of protocol revision
2
+ // 2026-07-28. A client that declares the extension on a tool call gets a task instead of an operation id and follows it
3
+ // through `tasks/get`; every other client keeps the polling tools (`get_operation`, `cancel_operation`) of #952.
4
+ //
5
+ // registerOperationTasks(server, { ctx, identity, readResult: (job) => findRenderUrl(job.id) });
6
+ // server.registerTool("render_video", { inputSchema }, (args, request) =>
7
+ // startOperation(ctx, identity, { queue: "video.render", payload: args, taskRequest: request }));
8
+ //
9
+ // A task id is random (the spec requires ids nobody can guess) and lives in `mcp.operation_tasks` with its owner, the
10
+ // operation's job and an expiry. Every task request checks the owner too, and reads the job's state as it is now.
11
+ import { randomBytes } from "node:crypto";
12
+ import { CLIENT_CAPABILITIES_META_KEY, MissingRequiredClientCapabilityError, ProtocolError, ProtocolErrorCode, } from "@modelcontextprotocol/server";
13
+ import { requestJobCancel } from "@softure-ai/jobs/server";
14
+ import { and, eq, sql } from "drizzle-orm";
15
+ import { z } from "zod";
16
+ import { operationTasks } from "../schema.js";
17
+ import { getMcpAccessMessages } from "../server/options.js";
18
+ import { toolResult } from "../server/tools.js";
19
+ import { describeOperation, findOwnedJob, getOperationStatus, getPollAfterSeconds, } from "./operation-state.js";
20
+ /** The extension's identifier, in the client's per-request capabilities and the server's `capabilities.extensions`. */
21
+ export const TASKS_EXTENSION = "io.modelcontextprotocol/tasks";
22
+ export const DEFAULT_TASK_TTL_SECONDS = 86_400;
23
+ export const MIN_TASK_TTL_SECONDS = 60;
24
+ /** Thirty days: a task outlives its operation only so long. */
25
+ export const MAX_TASK_TTL_SECONDS = 2_592_000;
26
+ const TASK_ID_BYTES = 32;
27
+ const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
28
+ const TASK_NOT_FOUND = "Failed to retrieve task: Task not found";
29
+ const TASK_EXPIRED = "Failed to retrieve task: Task has expired";
30
+ const CANCEL_NEEDS_WRITE = "Cancelling a task needs a token with write access";
31
+ const taskIdParams = z.looseObject({ taskId: z.string() });
32
+ const taskResult = z.looseObject({});
33
+ const clientCapabilities = z.looseObject({ extensions: z.record(z.string(), z.unknown()).optional() });
34
+ /** True when the request's client declared the Tasks extension in its per-request capabilities (revision 2026-07-28). */
35
+ export function isTasksRequest(request) {
36
+ const envelope = { ...request.mcpReq.envelope };
37
+ const capabilities = clientCapabilities.safeParse(envelope[CLIENT_CAPABILITIES_META_KEY]);
38
+ return capabilities.success && capabilities.data.extensions?.[TASKS_EXTENSION] !== undefined;
39
+ }
40
+ export function isTaskTtlValid(seconds) {
41
+ return Number.isInteger(seconds) && seconds >= MIN_TASK_TTL_SECONDS && seconds <= MAX_TASK_TTL_SECONDS;
42
+ }
43
+ /**
44
+ * The tool's answer as a task (`resultType: "task"`) for the operation's job: stores the task before answering, as the
45
+ * spec requires, and gives the same account the same task id for the same job.
46
+ */
47
+ export async function answerOperationTask(ctx, identity, input) {
48
+ const row = await storeTask(ctx, identity, input);
49
+ const job = await findOwnedJob(ctx, identity, input.jobId);
50
+ if (job === null)
51
+ throw new Error(`answerOperationTask: job ${input.jobId} is not an operation of this account`);
52
+ const task = await describeTask(ctx, row, job, input.poll === undefined ? {} : { poll: input.poll });
53
+ // On revision 2026-07-28 the SDK passes a tool's own `resultType` through; its `CallToolResult` type does not know
54
+ // the extension's task shape, and the `content` it would add anyway is ignored by clients.
55
+ return { content: [], ...task, resultType: "task" };
56
+ }
57
+ /** The caller's task with its operation's state now; `null` when unknown, another account's, or its job is gone. */
58
+ export async function getOperationTask(ctx, identity, taskId, options = {}) {
59
+ const found = await findTask(ctx, identity, taskId);
60
+ if (found === null || found === "expired")
61
+ return found;
62
+ return describeTask(ctx, found.row, found.job, options);
63
+ }
64
+ /**
65
+ * Serves the Tasks extension on the app's server: declares the capability and answers `tasks/get`, `tasks/update` and
66
+ * `tasks/cancel` for the request's account. Register it on every server whose tools pass `taskRequest`.
67
+ */
68
+ export function registerOperationTasks(server, options) {
69
+ const { ctx, identity } = options;
70
+ const describeOptions = { ...(options.readResult === undefined ? {} : { readResult: options.readResult }), ...(options.poll === undefined ? {} : { poll: options.poll }) };
71
+ server.server.registerCapabilities({ extensions: { [TASKS_EXTENSION]: {} } });
72
+ server.server.setRequestHandler("tasks/get", { params: taskIdParams, result: taskResult }, async ({ taskId }, request) => {
73
+ requireTasksCapability(request);
74
+ return { ...(await requireTask(ctx, identity, taskId, describeOptions)) };
75
+ });
76
+ // Operations never ask for input, so there is nothing to update; an owned task is acknowledged, as the spec asks.
77
+ server.server.setRequestHandler("tasks/update", { params: taskIdParams, result: taskResult }, async ({ taskId }, request) => {
78
+ requireTasksCapability(request);
79
+ await requireTask(ctx, identity, taskId, describeOptions);
80
+ return {};
81
+ });
82
+ server.server.setRequestHandler("tasks/cancel", { params: taskIdParams, result: taskResult }, async ({ taskId }, request) => {
83
+ requireTasksCapability(request);
84
+ const found = await findTask(ctx, identity, taskId);
85
+ if (found === null)
86
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, TASK_NOT_FOUND);
87
+ if (found === "expired")
88
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, TASK_EXPIRED);
89
+ if (!identity.canWrite)
90
+ throw new ProtocolError(ProtocolErrorCode.InvalidRequest, CANCEL_NEEDS_WRITE);
91
+ // Cancelling is cooperative: an operation that has already ended is acknowledged all the same.
92
+ await requestJobCancel(ctx, found.job.id);
93
+ return {};
94
+ });
95
+ }
96
+ async function storeTask(ctx, identity, input) {
97
+ const now = ctx.clock.now();
98
+ const expiresAt = new Date(now.getTime() + (input.ttlSeconds ?? DEFAULT_TASK_TTL_SECONDS) * 1000);
99
+ // One task per account and job: joining a running operation answers its task again, kept alive at least as long.
100
+ const [row] = await ctx.db
101
+ .insert(operationTasks)
102
+ .values({ taskId: randomBytes(TASK_ID_BYTES).toString("base64url"), userId: identity.userId, jobId: BigInt(input.jobId), createdAt: now, expiresAt })
103
+ .onConflictDoUpdate({
104
+ target: [operationTasks.userId, operationTasks.jobId],
105
+ set: { expiresAt: sql `greatest(${operationTasks.expiresAt}, excluded.expires_at)` },
106
+ })
107
+ .returning();
108
+ if (row === undefined)
109
+ throw new Error(`answerOperationTask: no task row for job ${input.jobId}`);
110
+ return row;
111
+ }
112
+ async function findTask(ctx, identity, taskId) {
113
+ if (!UUID.test(identity.userId))
114
+ return null;
115
+ const [row] = await ctx.db
116
+ .select()
117
+ .from(operationTasks)
118
+ .where(and(eq(operationTasks.taskId, taskId), eq(operationTasks.userId, identity.userId)))
119
+ .limit(1);
120
+ if (row === undefined)
121
+ return null;
122
+ if (row.expiresAt.getTime() <= ctx.clock.now().getTime())
123
+ return "expired";
124
+ const job = await findOwnedJob(ctx, identity, row.jobId.toString());
125
+ return job === null ? null : { row, job };
126
+ }
127
+ async function requireTask(ctx, identity, taskId, options) {
128
+ const task = await getOperationTask(ctx, identity, taskId, options);
129
+ if (task === null)
130
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, TASK_NOT_FOUND);
131
+ if (task === "expired")
132
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, TASK_EXPIRED);
133
+ return task;
134
+ }
135
+ /** The spec's rule for `tasks/*`: a client that did not declare the extension on this request gets `-32021`. */
136
+ function requireTasksCapability(request) {
137
+ if (!isTasksRequest(request))
138
+ throw new MissingRequiredClientCapabilityError({ requiredCapabilities: { extensions: { [TASKS_EXTENSION]: {} } } });
139
+ }
140
+ async function describeTask(ctx, row, job, options) {
141
+ const messages = getMcpAccessMessages(ctx.config).operations;
142
+ const status = getOperationStatus(job);
143
+ const base = {
144
+ taskId: row.taskId,
145
+ createdAt: row.createdAt.toISOString(),
146
+ lastUpdatedAt: job.updatedAt.toISOString(),
147
+ ttlMs: row.expiresAt.getTime() - row.createdAt.getTime(),
148
+ };
149
+ if (status === "queued" || status === "running") {
150
+ const ageSeconds = (ctx.clock.now().getTime() - job.createdAt.getTime()) / 1000;
151
+ const statusMessage = job.cancelRequestedAt !== null ? messages.taskCancelRequested : status === "queued" ? messages.taskQueued : messages.taskRunning;
152
+ return { ...base, status: "working", statusMessage, pollIntervalMs: getPollAfterSeconds(ageSeconds, options.poll) * 1000 };
153
+ }
154
+ if (status === "cancelled")
155
+ return { ...base, status: "cancelled", statusMessage: messages.cancelled };
156
+ // A failed job is a tool-level failure, not a JSON-RPC error: the spec makes it `completed` with `isError`.
157
+ const answer = await describeOperation(ctx, job, options);
158
+ const result = status === "failed" ? { ...toolResult(answer), isError: true } : toolResult(answer);
159
+ return { ...base, status: "completed", statusMessage: answer.message, result };
160
+ }
161
+ //# sourceMappingURL=operation-tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-tasks.js","sourceRoot":"","sources":["../../src/jobs/operation-tasks.ts"],"names":[],"mappings":"AAAA,gHAAgH;AAChH,wHAAwH;AACxH,iHAAiH;AACjH,EAAE;AACF,mGAAmG;AACnG,4EAA4E;AAC5E,sGAAsG;AACtG,EAAE;AACF,sHAAsH;AACtH,kHAAkH;AAClH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EACL,4BAA4B,EAC5B,oCAAoC,EACpC,aAAa,EACb,iBAAiB,GAGlB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,gBAAgB,EAAoB,MAAM,yBAAyB,CAAC;AAC7E,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,GAGpB,MAAM,sBAAsB,CAAC;AAE9B,uHAAuH;AACvH,MAAM,CAAC,MAAM,eAAe,GAAG,+BAA+B,CAAC;AAC/D,MAAM,CAAC,MAAM,wBAAwB,GAAG,MAAM,CAAC;AAC/C,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,+DAA+D;AAC/D,MAAM,CAAC,MAAM,oBAAoB,GAAG,SAAS,CAAC;AAE9C,MAAM,aAAa,GAAG,EAAE,CAAC;AACzB,MAAM,IAAI,GAAG,iEAAiE,CAAC;AAC/E,MAAM,cAAc,GAAG,yCAAyC,CAAC;AACjE,MAAM,YAAY,GAAG,2CAA2C,CAAC;AACjE,MAAM,kBAAkB,GAAG,mDAAmD,CAAC;AA0C/E,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC3D,MAAM,UAAU,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACrC,MAAM,kBAAkB,GAAG,CAAC,CAAC,WAAW,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;AAEvG,yHAAyH;AACzH,MAAM,UAAU,cAAc,CAAC,OAA6B;IAC1D,MAAM,QAAQ,GAAqC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAClF,MAAM,YAAY,GAAG,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,CAAC;IAC1F,OAAO,YAAY,CAAC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,eAAe,CAAC,KAAK,SAAS,CAAC;AAC/F,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe;IAC5C,OAAO,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,OAAO,IAAI,oBAAoB,IAAI,OAAO,IAAI,oBAAoB,CAAC;AACzG,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,GAAgB,EAAE,QAA2B,EAAE,KAA+B;IACtH,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;IAC3D,IAAI,GAAG,KAAK,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,KAAK,CAAC,KAAK,sCAAsC,CAAC,CAAC;IACjH,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACrG,mHAAmH;IACnH,2FAA2F;IAC3F,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC;AACtD,CAAC;AAED,oHAAoH;AACpH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAgB,EAChB,QAA2B,EAC3B,MAAc,EACd,UAA8D,EAAE;IAEhE,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACpD,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxD,OAAO,YAAY,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAiB,EAAE,OAA8B;IACtF,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC;IAClC,MAAM,eAAe,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;IAC3K,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,UAAU,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAE9E,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;QACvH,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,EAAE,GAAG,CAAC,MAAM,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,kHAAkH;IAClH,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;QAC1H,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;QAC1D,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,EAAE;QAC1H,sBAAsB,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,IAAI;YAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAC7F,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;QAChG,IAAI,CAAC,QAAQ,CAAC,QAAQ;YAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;QACtG,+FAA+F;QAC/F,MAAM,gBAAgB,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC1C,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,KAAK,UAAU,SAAS,CAAC,GAAgB,EAAE,QAA2B,EAAE,KAA+B;IACrG,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,UAAU,IAAI,wBAAwB,CAAC,GAAG,IAAI,CAAC,CAAC;IAClG,iHAAiH;IACjH,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;SACvB,MAAM,CAAC,cAAc,CAAC;SACtB,MAAM,CAAC,EAAE,MAAM,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;SACpJ,kBAAkB,CAAC;QAClB,MAAM,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,cAAc,CAAC,KAAK,CAAC;QACrD,GAAG,EAAE,EAAE,SAAS,EAAE,GAAG,CAAA,YAAY,cAAc,CAAC,SAAS,wBAAwB,EAAE;KACpF,CAAC;SACD,SAAS,EAAE,CAAC;IACf,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAClG,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,GAAgB,EAAE,QAA2B,EAAE,MAAc;IACnF,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IAC7C,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,GAAG,CAAC,EAAE;SACvB,MAAM,EAAE;SACR,IAAI,CAAC,cAAc,CAAC;SACpB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;SACzF,KAAK,CAAC,CAAC,CAAC,CAAC;IACZ,IAAI,GAAG,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE;QAAE,OAAO,SAAS,CAAC;IAC3E,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;IACpE,OAAO,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAC5C,CAAC;AAED,KAAK,UAAU,WAAW,CACxB,GAAgB,EAChB,QAA2B,EAC3B,MAAc,EACd,OAA2D;IAE3D,MAAM,IAAI,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IACpE,IAAI,IAAI,KAAK,IAAI;QAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;IAC5F,IAAI,IAAI,KAAK,SAAS;QAAE,MAAM,IAAI,aAAa,CAAC,iBAAiB,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC/F,OAAO,IAAI,CAAC;AACd,CAAC;AAED,gHAAgH;AAChH,SAAS,sBAAsB,CAAC,OAA6B;IAC3D,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;QAAE,MAAM,IAAI,oCAAoC,CAAC,EAAE,oBAAoB,EAAE,EAAE,UAAU,EAAE,EAAE,CAAC,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AACpJ,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,GAAgB,EAAE,GAAY,EAAE,GAAQ,EAAE,OAA2D;IAC/H,MAAM,QAAQ,GAAG,oBAAoB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC;IAC7D,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG;QACX,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;QACtC,aAAa,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;QAC1C,KAAK,EAAE,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE;KACzD,CAAC;IACF,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,GAAG,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC;QAChF,MAAM,aAAa,GAAG,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC;QACvJ,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;IAC7H,CAAC;IACD,IAAI,MAAM,KAAK,WAAW;QAAE,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC;IACvG,4GAA4G;IAC5G,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,MAAM,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACnG,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;AACjF,CAAC"}
@@ -0,0 +1,68 @@
1
+ import type { CallToolResult, McpServer } from "@modelcontextprotocol/server";
2
+ import { type Err, type Ok } from "@softure-ai/core";
3
+ import { type JobsContext } from "@softure-ai/jobs/server";
4
+ import type { McpServerIdentity } from "../contract.js";
5
+ import { type OperationTaskRequest } from "./operation-tasks.js";
6
+ import { type GetOperationOptions, type OperationAnswer, type OperationErrorCode, type OperationPollOptions, type ReadOperationResult } from "./operation-state.js";
7
+ export { getOperationStatus, getPollAfterSeconds, MAX_OPERATION_DEDUP_KEY_LENGTH, OPERATION_CANCEL_TOOL_NAME, OPERATION_ORIGIN, OPERATION_STATUS_TOOL_NAME, OPERATION_STATUSES, type GetOperationOptions, type OperationAnswer, type OperationErrorCode, type OperationJob, type OperationPollOptions, type OperationStatus, type ReadOperationResult, } from "./operation-state.js";
8
+ export interface StartOperationInput {
9
+ /** A queue defined in `jobs({ queues })`. */
10
+ readonly queue: string;
11
+ /** The handler's payload, as `enqueueJob` takes it: ids, not personal data. */
12
+ readonly payload: unknown;
13
+ /**
14
+ * While an operation of this account and queue with the same key runs, starting again joins it (the answer carries
15
+ * its id and status). At most 150 characters. Default: a new operation every time.
16
+ */
17
+ readonly dedupKey?: string;
18
+ /** The status tool the answer tells the assistant to call. Default `get_operation`. */
19
+ readonly statusToolName?: string;
20
+ readonly poll?: OperationPollOptions;
21
+ /**
22
+ * The tool handler's request context (its second argument). When the client declared the MCP Tasks extension on
23
+ * this request, the answer is a task (`resultType: "task"`) instead of an operation id; any other client gets the
24
+ * operation id as before. Pair it with `registerOperationTasks` on the same server, which serves `tasks/get`.
25
+ */
26
+ readonly taskRequest?: OperationTaskRequest;
27
+ /** How long a task can be read after it was created, in seconds. Default 86 400 (a day). */
28
+ readonly taskTtlSeconds?: number;
29
+ }
30
+ interface OperationToolOptions {
31
+ /** `{ db, clock, config }` of the request. */
32
+ readonly ctx: JobsContext;
33
+ /** The request's identity: operations are scoped to `identity.userId`. */
34
+ readonly identity: McpServerIdentity;
35
+ /** Default: the module dictionary's description. */
36
+ readonly description?: string;
37
+ }
38
+ export interface OperationStatusToolOptions extends OperationToolOptions {
39
+ /** Default `get_operation`. */
40
+ readonly name?: string;
41
+ readonly readResult?: ReadOperationResult;
42
+ readonly poll?: OperationPollOptions;
43
+ }
44
+ export interface OperationCancelToolOptions extends OperationToolOptions {
45
+ /** Default `cancel_operation`. */
46
+ readonly name?: string;
47
+ /** The status tool the answer points to. Default `get_operation`. */
48
+ readonly statusToolName?: string;
49
+ readonly poll?: OperationPollOptions;
50
+ }
51
+ /**
52
+ * For a tool handler: enqueues the operation's job and answers its id with the fixed sentence (ask the status tool,
53
+ * do not start again). Throws on an unknown queue or a dedup key over 150 characters (a bug in the caller); database
54
+ * failures propagate, so call it inside `withToolErrors` or let the SDK answer the error.
55
+ */
56
+ export declare function startOperation(ctx: JobsContext, identity: McpServerIdentity, input: StartOperationInput): Promise<CallToolResult>;
57
+ /** The caller's operation as `get_operation` answers it; `mcp-access.operation_not_found` for any other id. */
58
+ export declare function getOperation(ctx: JobsContext, identity: McpServerIdentity, operationId: string, options?: GetOperationOptions): Promise<Ok<OperationAnswer> | Err<"mcp-access.operation_not_found">>;
59
+ /**
60
+ * Cancels the caller's operation: a queued one ends at once, a running one is asked to stop (its handler's `signal`
61
+ * aborts on the next heartbeat). `mcp-access.operation_finished` once it has ended.
62
+ */
63
+ export declare function cancelOperation(ctx: JobsContext, identity: McpServerIdentity, operationId: string, options?: Omit<GetOperationOptions, "readResult">): Promise<Ok<OperationAnswer> | Err<OperationErrorCode>>;
64
+ /** Registers the read-only status tool (`get_operation`) for the request's account. */
65
+ export declare function registerOperationStatusTool(server: McpServer, options: OperationStatusToolOptions): void;
66
+ /** Registers the cancel tool (`cancel_operation`), a write: nothing is registered without `identity.canWrite`. */
67
+ export declare function registerOperationCancelTool(server: McpServer, options: OperationCancelToolOptions): void;
68
+ //# sourceMappingURL=operations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.d.ts","sourceRoot":"","sources":["../../src/jobs/operations.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,110 @@
1
+ // Long operations as MCP tools (#952), on top of `@softure-ai/jobs`. A tool whose work takes minutes cannot hold the
2
+ // call open (JSON mode drops mid-call notifications, proxies cut long responses, assistants time out), so it starts a
3
+ // job and answers an operation id at once; the assistant then asks `get_operation` until the operation ends, and may
4
+ // stop it with `cancel_operation`.
5
+ //
6
+ // server.registerTool("render_video", { inputSchema }, (args) => startOperation(ctx, identity, { queue: "video.render", payload: args }));
7
+ // registerOperationStatusTool(server, { ctx, identity, readResult: (job) => findRenderUrl(job.id) });
8
+ // registerOperationCancelTool(server, { ctx, identity });
9
+ //
10
+ // Ownership rides on the job itself: its origin is `mcp` and its dedup key `mcp:<userId>:<key>`, which the jobs table
11
+ // keeps after the job ends. Any other job, or another account's, is "not found".
12
+ import { randomUUID } from "node:crypto";
13
+ import { err, ok } from "@softure-ai/core";
14
+ import { enqueueJob, requestJobCancel } from "@softure-ai/jobs/server";
15
+ import { z } from "zod";
16
+ import { getMcpAccessMessages } from "../server/options.js";
17
+ import { toolResult, withToolErrors } from "../server/tools.js";
18
+ import { answerOperationTask, isTasksRequest, isTaskTtlValid, MAX_TASK_TTL_SECONDS } from "./operation-tasks.js";
19
+ import { describeOperation, fillToolName, findOwnedJob, getOwnerPrefix, getPollMin, MAX_OPERATION_DEDUP_KEY_LENGTH, OPERATION_ORIGIN, OPERATION_STATUS_TOOL_NAME, OPERATION_CANCEL_TOOL_NAME, } from "./operation-state.js";
20
+ export { getOperationStatus, getPollAfterSeconds, MAX_OPERATION_DEDUP_KEY_LENGTH, OPERATION_CANCEL_TOOL_NAME, OPERATION_ORIGIN, OPERATION_STATUS_TOOL_NAME, OPERATION_STATUSES, } from "./operation-state.js";
21
+ const operationInput = z.object({ operationId: z.string().min(1).max(100) });
22
+ /**
23
+ * For a tool handler: enqueues the operation's job and answers its id with the fixed sentence (ask the status tool,
24
+ * do not start again). Throws on an unknown queue or a dedup key over 150 characters (a bug in the caller); database
25
+ * failures propagate, so call it inside `withToolErrors` or let the SDK answer the error.
26
+ */
27
+ export async function startOperation(ctx, identity, input) {
28
+ if (input.dedupKey !== undefined && (input.dedupKey.length === 0 || input.dedupKey.length > MAX_OPERATION_DEDUP_KEY_LENGTH)) {
29
+ throw new Error(`startOperation: the dedup key of queue ${input.queue} must have 1 to ${String(MAX_OPERATION_DEDUP_KEY_LENGTH)} characters`);
30
+ }
31
+ if (input.taskTtlSeconds !== undefined && !isTaskTtlValid(input.taskTtlSeconds)) {
32
+ throw new Error(`startOperation: the task lifetime of queue ${input.queue} must be whole seconds from 60 to ${String(MAX_TASK_TTL_SECONDS)}`);
33
+ }
34
+ const enqueued = await enqueueJob(ctx, {
35
+ queue: input.queue,
36
+ payload: input.payload,
37
+ origin: OPERATION_ORIGIN,
38
+ dedupKey: getOwnerPrefix(identity.userId) + (input.dedupKey ?? randomUUID()),
39
+ });
40
+ const options = { ...(input.poll === undefined ? {} : { poll: input.poll }), statusToolName: input.statusToolName ?? OPERATION_STATUS_TOOL_NAME };
41
+ if (input.taskRequest !== undefined && isTasksRequest(input.taskRequest)) {
42
+ return answerOperationTask(ctx, identity, { jobId: enqueued.id, ...(input.taskTtlSeconds === undefined ? {} : { ttlSeconds: input.taskTtlSeconds }), ...(input.poll === undefined ? {} : { poll: input.poll }) });
43
+ }
44
+ if (enqueued.isDuplicate) {
45
+ const joined = await getOperation(ctx, identity, enqueued.id, options);
46
+ if (joined.ok)
47
+ return toolResult(joined.value);
48
+ }
49
+ const messages = getMcpAccessMessages(ctx.config).operations;
50
+ const answer = {
51
+ operationId: enqueued.id,
52
+ status: "queued",
53
+ progress: null,
54
+ pollAfterSeconds: getPollMin(input.poll),
55
+ message: fillToolName(messages.started, options.statusToolName),
56
+ };
57
+ return toolResult(answer);
58
+ }
59
+ /** The caller's operation as `get_operation` answers it; `mcp-access.operation_not_found` for any other id. */
60
+ export async function getOperation(ctx, identity, operationId, options = {}) {
61
+ const job = await findOwnedJob(ctx, identity, operationId);
62
+ if (job === null)
63
+ return err("mcp-access.operation_not_found");
64
+ return ok(await describeOperation(ctx, job, options));
65
+ }
66
+ /**
67
+ * Cancels the caller's operation: a queued one ends at once, a running one is asked to stop (its handler's `signal`
68
+ * aborts on the next heartbeat). `mcp-access.operation_finished` once it has ended.
69
+ */
70
+ export async function cancelOperation(ctx, identity, operationId, options = {}) {
71
+ const owned = await findOwnedJob(ctx, identity, operationId);
72
+ if (owned === null)
73
+ return err("mcp-access.operation_not_found");
74
+ const cancelled = await requestJobCancel(ctx, owned.id);
75
+ if (!cancelled.ok)
76
+ return err(cancelled.error === "jobs.not_found" ? "mcp-access.operation_not_found" : "mcp-access.operation_finished");
77
+ return ok(await describeOperation(ctx, cancelled.value, options));
78
+ }
79
+ /** Registers the read-only status tool (`get_operation`) for the request's account. */
80
+ export function registerOperationStatusTool(server, options) {
81
+ const name = options.name ?? OPERATION_STATUS_TOOL_NAME;
82
+ const messages = getMcpAccessMessages(options.ctx.config).operations;
83
+ const getOptions = {
84
+ statusToolName: name,
85
+ ...(options.readResult === undefined ? {} : { readResult: options.readResult }),
86
+ ...(options.poll === undefined ? {} : { poll: options.poll }),
87
+ };
88
+ server.registerTool(name, {
89
+ description: options.description ?? messages.statusToolDescription,
90
+ inputSchema: operationInput,
91
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
92
+ }, ({ operationId }) => withToolErrors(() => getOperation(options.ctx, options.identity, operationId, getOptions), { hints: getOperationHints(messages), label: name }));
93
+ }
94
+ /** Registers the cancel tool (`cancel_operation`), a write: nothing is registered without `identity.canWrite`. */
95
+ export function registerOperationCancelTool(server, options) {
96
+ if (!options.identity.canWrite)
97
+ return;
98
+ const name = options.name ?? OPERATION_CANCEL_TOOL_NAME;
99
+ const messages = getMcpAccessMessages(options.ctx.config).operations;
100
+ const cancelOptions = { statusToolName: options.statusToolName ?? OPERATION_STATUS_TOOL_NAME, ...(options.poll === undefined ? {} : { poll: options.poll }) };
101
+ server.registerTool(name, {
102
+ description: options.description ?? messages.cancelToolDescription,
103
+ inputSchema: operationInput,
104
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false },
105
+ }, ({ operationId }) => withToolErrors(() => cancelOperation(options.ctx, options.identity, operationId, cancelOptions), { hints: getOperationHints(messages), label: name }));
106
+ }
107
+ function getOperationHints(messages) {
108
+ return { "mcp-access.operation_not_found": messages.notFound, "mcp-access.operation_finished": messages.finished };
109
+ }
110
+ //# sourceMappingURL=operations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operations.js","sourceRoot":"","sources":["../../src/jobs/operations.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,28 @@ export declare const en: {
20
20
  pending: string;
21
21
  limit: string;
22
22
  };
23
+ apiScopes: {
24
+ title: string;
25
+ lead: string;
26
+ read: string;
27
+ write: string;
28
+ writeUnavailable: string;
29
+ };
30
+ apiIssue: {
31
+ title: string;
32
+ name: string;
33
+ nameHint: string;
34
+ scopes: string;
35
+ submit: string;
36
+ pending: string;
37
+ };
38
+ apiIssued: {
39
+ title: string;
40
+ once: string;
41
+ scopes: string;
42
+ tokenTitle: string;
43
+ headerTitle: string;
44
+ };
23
45
  issued: {
24
46
  title: string;
25
47
  once: string;
@@ -42,6 +64,8 @@ export declare const en: {
42
64
  };
43
65
  list: {
44
66
  title: string;
67
+ kindMcp: string;
68
+ kindApi: string;
45
69
  empty: string;
46
70
  readOnly: string;
47
71
  readWrite: string;
@@ -70,7 +94,8 @@ export declare const en: {
70
94
  title: string;
71
95
  lead: string;
72
96
  app: string;
73
- returnsTo: string;
97
+ redirectLabel: string;
98
+ redirectHint: string;
74
99
  account: string;
75
100
  access: string;
76
101
  readAccess: string;
@@ -90,9 +115,37 @@ export declare const en: {
90
115
  noFields: string;
91
116
  fieldRenamed: string;
92
117
  };
118
+ confirmation: {
119
+ ask: string;
120
+ fieldDescription: string;
121
+ invalid: string;
122
+ otherTool: string;
123
+ otherAccount: string;
124
+ expired: string;
125
+ argumentsChanged: string;
126
+ estimateChanged: string;
127
+ used: string;
128
+ };
93
129
  serverInfoTool: {
94
130
  description: string;
95
131
  };
132
+ operations: {
133
+ statusToolDescription: string;
134
+ cancelToolDescription: string;
135
+ started: string;
136
+ queued: string;
137
+ running: string;
138
+ cancelRequested: string;
139
+ succeeded: string;
140
+ failed: string;
141
+ cancelled: string;
142
+ notFound: string;
143
+ finished: string;
144
+ /** The `statusMessage` of an MCP task (#977) while its operation has not ended. */
145
+ taskQueued: string;
146
+ taskRunning: string;
147
+ taskCancelRequested: string;
148
+ };
96
149
  errors: {
97
150
  "mcp-access": {
98
151
  name_required: string;
@@ -102,6 +155,9 @@ export declare const en: {
102
155
  grant_not_found: string;
103
156
  issue_refused: string;
104
157
  write_refused: string;
158
+ api_disabled: string;
159
+ scope_required: string;
160
+ scope_unknown: string;
105
161
  };
106
162
  auth: {
107
163
  unauthenticated: string;
@@ -1 +1 @@
1
- {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkHd,CAAC"}
1
+ {"version":3,"file":"en.d.ts","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiJX,mFAAmF;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BtF,CAAC"}
@@ -20,6 +20,28 @@ export const en = {
20
20
  pending: "Creating…",
21
21
  limit: "You can hold up to {max} active tokens.",
22
22
  },
23
+ apiScopes: {
24
+ title: "What a token for other apps can do",
25
+ lead: "Tokens for other apps, such as a phone Shortcut, an automation tool or a script, call this app's HTTP routes. Each one gets only the access you tick.",
26
+ read: "Reads",
27
+ write: "Changes data",
28
+ writeUnavailable: "Changes data (turned off in this app)",
29
+ },
30
+ apiIssue: {
31
+ title: "New token for other apps",
32
+ name: "Name",
33
+ nameHint: "Where you will use it, e.g. iPhone Shortcut or Make.",
34
+ scopes: "Access",
35
+ submit: "Create token",
36
+ pending: "Creating…",
37
+ },
38
+ apiIssued: {
39
+ title: "Token created: {name}",
40
+ once: "Copy it now. It is shown only once; after you leave this page, only its name remains.",
41
+ scopes: "Access: {scopes}.",
42
+ tokenTitle: "Token",
43
+ headerTitle: "Authorization header",
44
+ },
23
45
  issued: {
24
46
  title: "Token created: {name}",
25
47
  once: "Copy it now. It is shown only once; after you leave this page, only its name remains.",
@@ -42,6 +64,8 @@ export const en = {
42
64
  },
43
65
  list: {
44
66
  title: "Your tokens",
67
+ kindMcp: "AI assistant",
68
+ kindApi: "Other apps",
45
69
  empty: "You have no tokens yet.",
46
70
  readOnly: "Read only",
47
71
  readWrite: "Read and change",
@@ -70,7 +94,8 @@ export const en = {
70
94
  title: "{client} wants access to your account",
71
95
  lead: "The assistant can answer questions with your data in this app. You can disconnect it at any time on the AI assistant access page.",
72
96
  app: "App",
73
- returnsTo: "returns to {target}",
97
+ redirectLabel: "Access code goes to",
98
+ redirectHint: "The app chose its own name; this address is the one part it cannot fake. Allow only if you recognise it.",
74
99
  account: "Account",
75
100
  access: "Access",
76
101
  readAccess: "Read your data",
@@ -90,9 +115,37 @@ export const en = {
90
115
  noFields: "none",
91
116
  fieldRenamed: "input.field_renamed: the field \"{field}\" is now \"{renamed}\". Send it as \"{renamed}\".",
92
117
  },
118
+ confirmation: {
119
+ ask: "Nothing was done yet. Show the person this estimate and ask whether to go ahead. Only after they agree in the chat, call the tool again with the same arguments and \"confirmation\" set to the value above, before {expiresAt}.",
120
+ fieldDescription: "Leave it out on the first call. Set it only to the confirmation the first call answered, after the person agreed to its estimate.",
121
+ invalid: "input.confirmation_invalid: this is not a confirmation this tool issued. Call the tool again without \"confirmation\" for a new estimate.",
122
+ otherTool: "input.confirmation_other_tool: the confirmation was issued for another tool. Call this tool without \"confirmation\" for its own estimate.",
123
+ otherAccount: "input.confirmation_other_account: the confirmation was issued to another account or access token. Call the tool again without \"confirmation\" for a new estimate.",
124
+ expired: "input.confirmation_expired: the confirmation has expired. Call the tool again without \"confirmation\" for a new estimate and ask the person again.",
125
+ argumentsChanged: "input.confirmation_arguments_changed: the arguments differ from the ones the person agreed to. Call the tool again without \"confirmation\" for an estimate of these arguments and ask the person again.",
126
+ estimateChanged: "input.confirmation_estimate_changed: the estimate has changed since the person agreed. Call the tool again without \"confirmation\" for the new estimate and ask the person again.",
127
+ used: "input.confirmation_used: the confirmation was used already; nothing was done again. Call the tool again without \"confirmation\" if the person wants it done once more.",
128
+ },
93
129
  serverInfoTool: {
94
130
  description: "Tells which build of this server answers: its name and version (the version changes whenever a tool changes), the release, the commit, when it was built and started, and the changelog when the app publishes one. Use it to check that a change is live.",
95
131
  },
132
+ operations: {
133
+ statusToolDescription: "Tells how a long operation started by another tool is going: queued, running (with its progress), succeeded (with its result), failed (with an error code) or cancelled. Call it again after pollAfterSeconds while the operation runs.",
134
+ cancelToolDescription: "Stops a long operation started by another tool. A queued one ends at once; a running one stops at its next safe point.",
135
+ started: "The operation has started and runs in the background. Call {tool} with this operationId after pollAfterSeconds to follow it. Do not call the starting tool again.",
136
+ queued: "The operation is waiting to start. Call {tool} again after pollAfterSeconds.",
137
+ running: "The operation is running. Call {tool} again after pollAfterSeconds.",
138
+ cancelRequested: "The operation was asked to stop and will end shortly. Call {tool} again after pollAfterSeconds.",
139
+ succeeded: "The operation has finished.",
140
+ failed: "The operation failed. Tell the user; start it again only if they ask.",
141
+ cancelled: "The operation was cancelled.",
142
+ notFound: "No operation with this id belongs to this account.",
143
+ finished: "The operation has already ended, so it cannot be cancelled.",
144
+ /** The `statusMessage` of an MCP task (#977) while its operation has not ended. */
145
+ taskQueued: "The operation is waiting to start.",
146
+ taskRunning: "The operation is running.",
147
+ taskCancelRequested: "The operation was asked to stop and will end shortly.",
148
+ },
96
149
  errors: {
97
150
  "mcp-access": {
98
151
  name_required: "Give the token a name, so you can tell it from the others.",
@@ -102,6 +155,9 @@ export const en = {
102
155
  grant_not_found: "This app is no longer connected.",
103
156
  issue_refused: "Your account cannot create tokens right now.",
104
157
  write_refused: "Your account cannot create tokens with write access. Create a read-only token instead.",
158
+ api_disabled: "This app does not offer tokens for other apps.",
159
+ scope_required: "Tick at least one kind of access.",
160
+ scope_unknown: "This app does not offer that access. Reload the page and try again.",
105
161
  },
106
162
  auth: {
107
163
  unauthenticated: "Your session has ended. Log in again.",
@@ -1 +1 @@
1
- {"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"en.js","sourceRoot":"","sources":["../../src/messages/en.ts"],"names":[],"mappings":"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"}