@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
package/dist/index.d.ts CHANGED
@@ -1,4 +1,10 @@
1
1
  export declare const MODULE_ID = "mcp-access";
2
+ /**
3
+ * Name of the runtime switch that turns writes off without a deploy. Defined in
4
+ * `@softure-ai/feature-switches`, writes need it on as well as `allowWrites` and the token's write access;
5
+ * not defined, `allowWrites` alone decides.
6
+ */
7
+ export declare const WRITES_ENABLED_SWITCH = "mcp-access.writes_enabled";
2
8
  /**
3
9
  * The rate limit bucket of `POST /api/mcp`, to spread into `security({ buckets })`: requests per
4
10
  * client address, counted before the token is verified. Every request counts, so the limit is for
@@ -21,6 +27,23 @@ export declare const MCP_RATE_LIMIT_BUCKETS: {
21
27
  readonly key: "ip";
22
28
  };
23
29
  };
30
+ /**
31
+ * The rate limit buckets of `requireApiToken`, to spread into `security({ buckets })` when the app sets
32
+ * `apiTokens`: `api` counts requests per client address before the token is looked up (guessing),
33
+ * `api-token` counts requests per verified token (one script or Shortcut cannot flood a route).
34
+ */
35
+ export declare const API_TOKEN_RATE_LIMIT_BUCKETS: {
36
+ readonly api: {
37
+ readonly limit: 300;
38
+ readonly windowMinutes: 15;
39
+ readonly key: "ip";
40
+ };
41
+ readonly "api-token": {
42
+ readonly limit: 120;
43
+ readonly windowMinutes: 15;
44
+ readonly key: "subject";
45
+ };
46
+ };
24
47
  /**
25
48
  * Enables MCP access in `softure.config.ts` (after `security` and `auth`):
26
49
  * `mcpAccess({ serverName: "acme", tools: [{ name: "list_orders", access: "read", description: { en: "Lists your orders." } }] })`.
@@ -54,6 +77,28 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
54
77
  pending: string;
55
78
  limit: string;
56
79
  };
80
+ apiScopes: {
81
+ title: string;
82
+ lead: string;
83
+ read: string;
84
+ write: string;
85
+ writeUnavailable: string;
86
+ };
87
+ apiIssue: {
88
+ title: string;
89
+ name: string;
90
+ nameHint: string;
91
+ scopes: string;
92
+ submit: string;
93
+ pending: string;
94
+ };
95
+ apiIssued: {
96
+ title: string;
97
+ once: string;
98
+ scopes: string;
99
+ tokenTitle: string;
100
+ headerTitle: string;
101
+ };
57
102
  issued: {
58
103
  title: string;
59
104
  once: string;
@@ -76,6 +121,8 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
76
121
  };
77
122
  list: {
78
123
  title: string;
124
+ kindMcp: string;
125
+ kindApi: string;
79
126
  empty: string;
80
127
  readOnly: string;
81
128
  readWrite: string;
@@ -104,7 +151,8 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
104
151
  title: string;
105
152
  lead: string;
106
153
  app: string;
107
- returnsTo: string;
154
+ redirectLabel: string;
155
+ redirectHint: string;
108
156
  account: string;
109
157
  access: string;
110
158
  readAccess: string;
@@ -124,9 +172,36 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
124
172
  noFields: string;
125
173
  fieldRenamed: string;
126
174
  };
175
+ confirmation: {
176
+ ask: string;
177
+ fieldDescription: string;
178
+ invalid: string;
179
+ otherTool: string;
180
+ otherAccount: string;
181
+ expired: string;
182
+ argumentsChanged: string;
183
+ estimateChanged: string;
184
+ used: string;
185
+ };
127
186
  serverInfoTool: {
128
187
  description: string;
129
188
  };
189
+ operations: {
190
+ statusToolDescription: string;
191
+ cancelToolDescription: string;
192
+ started: string;
193
+ queued: string;
194
+ running: string;
195
+ cancelRequested: string;
196
+ succeeded: string;
197
+ failed: string;
198
+ cancelled: string;
199
+ notFound: string;
200
+ finished: string;
201
+ taskQueued: string;
202
+ taskRunning: string;
203
+ taskCancelRequested: string;
204
+ };
130
205
  errors: {
131
206
  "mcp-access": {
132
207
  name_required: string;
@@ -136,6 +211,9 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
136
211
  grant_not_found: string;
137
212
  issue_refused: string;
138
213
  write_refused: string;
214
+ api_disabled: string;
215
+ scope_required: string;
216
+ scope_unknown: string;
139
217
  };
140
218
  auth: {
141
219
  unauthenticated: string;
@@ -180,11 +258,26 @@ export declare const mcpAccess: import("@softure-ai/core").ModuleFactory<{
180
258
  protectedResource: import("zod").ZodOptional<import("zod").ZodUnion<readonly [import("zod").ZodCustom<(origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>, (origins: import("./origins.js").McpOrigins) => Readonly<Record<string, unknown>>>, import("zod").ZodRecord<import("zod").ZodString, import("zod").ZodUnknown>]>>;
181
259
  }, import("zod/v4/core").$strict>>;
182
260
  }, import("zod/v4/core").$strict>>;
261
+ apiTokens: import("zod").ZodOptional<import("zod").ZodObject<{
262
+ prefix: import("zod").ZodDefault<import("zod").ZodString>;
263
+ scopes: import("zod").ZodArray<import("zod").ZodObject<{
264
+ name: import("zod").ZodString;
265
+ access: import("zod").ZodEnum<{
266
+ read: "read";
267
+ write: "write";
268
+ }>;
269
+ description: import("zod").ZodRecord<import("zod").ZodString & import("zod").ZodType<string, string, import("zod/v4/core").$ZodTypeInternals<string, string>>, import("zod").ZodString>;
270
+ }, import("zod/v4/core").$strict>>;
271
+ examples: import("zod").ZodDefault<import("zod").ZodArray<import("zod").ZodObject<{
272
+ title: import("zod").ZodRecord<import("zod").ZodString & import("zod").ZodType<string, string, import("zod/v4/core").$ZodTypeInternals<string, string>>, import("zod").ZodString>;
273
+ text: import("zod").ZodRecord<import("zod").ZodString & import("zod").ZodType<string, string, import("zod/v4/core").$ZodTypeInternals<string, string>>, import("zod").ZodString>;
274
+ }, import("zod/v4/core").$strict>>>;
275
+ }, import("zod/v4/core").$strict>>;
183
276
  }, import("zod/v4/core").$strict>>;
184
277
  export { getAuthorizationHeader, getClaudeCodeCommand, getClaudeCodeLink, getDesktopConfig, getJsonConfig, getMcpClientSetup, type McpClientSetupInput, } from "./client-setup.js";
185
- export type { AccessTokenStatus, AccessTokenView, IssuedToken, IssueTokenFormState, McpAccessErrorCode, McpIssueRefusal, McpIssueRefusalCode, McpClientSetup, McpServerIdentity, OAuthGrantView, RevokeGrantFormState, RevokeTokenFormState, TokenFormErrorCode, } from "./contract.js";
278
+ export type { AccessTokenKind, AccessTokenStatus, AccessTokenView, ApiTokenErrorCode, ApiTokenExample, ApiTokenIdentity, ApiTokenRefusal, IssuedApiTokenView, IssuedToken, IssueTokenFormState, McpAccessErrorCode, McpIssueRefusal, McpIssueRefusalCode, McpClientSetup, McpServerIdentity, OAuthGrantView, RevokeGrantFormState, RevokeTokenFormState, TokenFormErrorCode, } from "./contract.js";
186
279
  export { getTokenErrorMessage, mcpAccessMessages, type McpAccessMessages } from "./messages/index.js";
187
- export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, type McpAccessOptions, type McpAccessOptionsInput, type McpAppOriginResolver, type McpMetadataExtension, type McpOAuthOptions, type McpToolAccess, type McpToolDefinition, type McpToolDefinitionInput, } from "./options.js";
280
+ export { API_SCOPE_PATTERN, API_TOKEN_PREFIX_PATTERN, MAX_API_TOKEN_SCOPES, MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, type ApiScopeDefinition, type ApiTokenOptions, type ApiTokenOptionsInput, type McpAccessOptions, type McpAccessOptionsInput, type McpAppOriginResolver, type McpMetadataExtension, type McpOAuthOptions, type McpToolAccess, type McpToolDefinition, type McpToolDefinitionInput, } from "./options.js";
188
281
  export { DEFAULT_MCP_ACCESS_ROUTES } from "./routes.js";
189
282
  export { readRequestOrigin, type McpOriginRequest, type McpOrigins } from "./origins.js";
190
283
  export { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants, type OAuthClientRow, type OAuthTokenEndpointAuthMethod } from "./schema.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;IAEjC;;;;OAIG;;;;;;CAE8D,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCA4BpB,CAAC;AAEH,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,mCAAmC,EACnC,iCAAiC,EACjC,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,4BAA4B,EAAE,MAAM,aAAa,CAAC;AACvJ,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,SAAS,eAAe,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,8BAA8B,CAAC;AAEjE;;;;GAIG;AACH,eAAO,MAAM,sBAAsB;;;;;;IAEjC;;;;OAIG;;;;;;CAE8D,CAAC;AAEpE;;;;GAIG;AACH,eAAO,MAAM,4BAA4B;;;;;;;;;;;CAG0B,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kCAkCpB,CAAC;AAEH,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,KAAK,mBAAmB,GACzB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtG,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACxB,oBAAoB,EACpB,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,mCAAmC,EACnC,iCAAiC,EACjC,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,KAAK,cAAc,EAAE,KAAK,4BAA4B,EAAE,MAAM,aAAa,CAAC;AACvJ,OAAO,EAAE,oBAAoB,EAAE,KAAK,wBAAwB,EAAE,MAAM,mBAAmB,CAAC"}
package/dist/index.js CHANGED
@@ -9,6 +9,12 @@ import { DEFAULT_MCP_ACCESS_ROUTES } from "./routes.js";
9
9
  import { checkAccessTokensTable } from "./server/health.js";
10
10
  import { mcpAccessPrivacyContributor } from "./server/privacy.js";
11
11
  export const MODULE_ID = "mcp-access";
12
+ /**
13
+ * Name of the runtime switch that turns writes off without a deploy. Defined in
14
+ * `@softure-ai/feature-switches`, writes need it on as well as `allowWrites` and the token's write access;
15
+ * not defined, `allowWrites` alone decides.
16
+ */
17
+ export const WRITES_ENABLED_SWITCH = "mcp-access.writes_enabled";
12
18
  /**
13
19
  * The rate limit bucket of `POST /api/mcp`, to spread into `security({ buckets })`: requests per
14
20
  * client address, counted before the token is verified. Every request counts, so the limit is for
@@ -23,6 +29,15 @@ export const MCP_RATE_LIMIT_BUCKETS = {
23
29
  */
24
30
  "mcp-oauth": { limit: 60, windowMinutes: 15, key: "ip" },
25
31
  };
32
+ /**
33
+ * The rate limit buckets of `requireApiToken`, to spread into `security({ buckets })` when the app sets
34
+ * `apiTokens`: `api` counts requests per client address before the token is looked up (guessing),
35
+ * `api-token` counts requests per verified token (one script or Shortcut cannot flood a route).
36
+ */
37
+ export const API_TOKEN_RATE_LIMIT_BUCKETS = {
38
+ api: { limit: 300, windowMinutes: 15, key: "ip" },
39
+ "api-token": { limit: 120, windowMinutes: 15, key: "subject" },
40
+ };
26
41
  /**
27
42
  * Enables MCP access in `softure.config.ts` (after `security` and `auth`):
28
43
  * `mcpAccess({ serverName: "acme", tools: [{ name: "list_orders", access: "read", description: { en: "Lists your orders." } }] })`.
@@ -30,12 +45,18 @@ export const MCP_RATE_LIMIT_BUCKETS = {
30
45
  export const mcpAccess = defineModule({
31
46
  manifest: {
32
47
  id: MODULE_ID,
33
- version: "0.2.8",
48
+ version: "0.3.0",
34
49
  dependsOn: { security: "^0.2.0", auth: "^0.2.0", jobs: "^0.1.1?", ops: "^0.2.0?" },
35
50
  dbSchema: "mcp",
36
- tables: ["access_tokens", "oauth_clients", "oauth_authorization_codes", "oauth_grants", "oauth_registration_window"],
37
- env: [],
38
- switches: [],
51
+ tables: ["access_tokens", "oauth_clients", "oauth_authorization_codes", "oauth_grants", "oauth_registration_window", "used_confirmations", "operation_tasks"],
52
+ env: [
53
+ {
54
+ name: "MCP_CONFIRMATION_SECRET",
55
+ required: false,
56
+ description: "Signs and verifies the confirmation tokens of confirmed tool calls (withConfirmation), at least 32 characters; required only by an app that confirms tool calls. Changing it voids the tokens in flight.",
57
+ },
58
+ ],
59
+ switches: [WRITES_ENABLED_SWITCH],
39
60
  routes: { ...DEFAULT_MCP_ACCESS_ROUTES },
40
61
  mount: [
41
62
  { kind: "page", path: "app/account/mcp/page.tsx", export: "McpAccessPage" },
@@ -58,7 +79,7 @@ export const mcpAccess = defineModule({
58
79
  });
59
80
  export { getAuthorizationHeader, getClaudeCodeCommand, getClaudeCodeLink, getDesktopConfig, getJsonConfig, getMcpClientSetup, } from "./client-setup.js";
60
81
  export { getTokenErrorMessage, mcpAccessMessages } from "./messages/index.js";
61
- export { MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, } from "./options.js";
82
+ export { API_SCOPE_PATTERN, API_TOKEN_PREFIX_PATTERN, MAX_API_TOKEN_SCOPES, MAX_PRESENTED_TOKEN_LENGTH, MAX_TOKEN_NAME_LENGTH, SERVER_NAME_PATTERN, TOOL_NAME_PATTERN, GENERATED_AUTHORIZATION_SERVER_KEYS, GENERATED_PROTECTED_RESOURCE_KEYS, } from "./options.js";
62
83
  export { DEFAULT_MCP_ACCESS_ROUTES } from "./routes.js";
63
84
  export { readRequestOrigin } from "./origins.js";
64
85
  export { accessTokens, oauthAuthorizationCodes, oauthClients, oauthGrants } from "./schema.js";
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,kGAAkG;AAClG,kGAAkG;AAClG,mDAAmD;AACnD,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAElE,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AAEtC;;;;GAIG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,GAAG,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;IACjD;;;;OAIG;IACH,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE;CACS,CAAC;AAEpE;;;GAGG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;IACpC,QAAQ,EAAE;QACR,EAAE,EAAE,SAAS;QACb,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE;QAClF,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,CAAC,eAAe,EAAE,eAAe,EAAE,2BAA2B,EAAE,cAAc,EAAE,2BAA2B,CAAC;QACpH,GAAG,EAAE,EAAE;QACP,QAAQ,EAAE,EAAE;QACZ,MAAM,EAAE,EAAE,GAAG,yBAAyB,EAAE;QACxC,KAAK,EAAE;YACL,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,0BAA0B,EAAE,MAAM,EAAE,eAAe,EAAE;YAC3E,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,sBAAsB,EAAE,MAAM,EAAE,gBAAgB,EAAE;YACjF,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,8BAA8B,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClF,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,kCAAkC,EAAE,MAAM,EAAE,+BAA+B,EAAE;YAC5G,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,8BAA8B,EAAE,MAAM,EAAE,yBAAyB,EAAE;YAClG,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,iCAAiC,EAAE,MAAM,EAAE,0BAA0B,EAAE;YACtG,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,qDAAqD,EAAE,MAAM,EAAE,qCAAqC,EAAE;YACrI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,mDAAmD,EAAE,MAAM,EAAE,mCAAmC,EAAE;YACjI,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,2DAA2D,EAAE,MAAM,EAAE,mCAAmC,EAAE;SAC1I;QACD,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE;KAC1C;IACD,QAAQ,EAAE,iBAAiB;IAC3B,OAAO,EAAE,sBAAsB;IAC/B,UAAU,EAAE,EAAE,GAAG,EAAE,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE;IAC5E,OAAO,EAAE,2BAA2B;IACpC,MAAM,EAAE,sBAAsB;CAC/B,CAAC,CAAC;AAEH,OAAO,EACL,sBAAsB,EACtB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,iBAAiB,GAElB,MAAM,mBAAmB,CAAC;AAgB3B,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAA0B,MAAM,qBAAqB,CAAC;AACtG,OAAO,EACL,0BAA0B,EAC1B,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,mCAAmC,EACnC,iCAAiC,GASlC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAA0C,MAAM,cAAc,CAAC;AACzF,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAA0D,MAAM,aAAa,CAAC;AACvJ,OAAO,EAAE,oBAAoB,EAAiC,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -9,4 +9,6 @@ export declare const mcpAccessJobSchedules: {
9
9
  every: string;
10
10
  };
11
11
  };
12
+ export { cancelOperation, getOperation, getOperationStatus, getPollAfterSeconds, MAX_OPERATION_DEDUP_KEY_LENGTH, OPERATION_CANCEL_TOOL_NAME, OPERATION_ORIGIN, OPERATION_STATUS_TOOL_NAME, OPERATION_STATUSES, registerOperationCancelTool, registerOperationStatusTool, startOperation, type GetOperationOptions, type OperationAnswer, type OperationCancelToolOptions, type OperationErrorCode, type OperationJob, type OperationPollOptions, type OperationStatus, type OperationStatusToolOptions, type ReadOperationResult, type StartOperationInput, } from "./operations.js";
13
+ export { DEFAULT_TASK_TTL_SECONDS, getOperationTask, isTasksRequest, MAX_TASK_TTL_SECONDS, MIN_TASK_TTL_SECONDS, registerOperationTasks, TASKS_EXTENSION, type OperationTask, type OperationTaskRequest, type OperationTasksOptions, type OperationTaskStatus, } from "./operation-tasks.js";
12
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAOA,wEAAwE;AACxE,eAAO,MAAM,oBAAoB;IAC/B,+EAA+E;;CAQ1D,CAAC;AAExB,gFAAgF;AAChF,eAAO,MAAM,qBAAqB;;;;CAEL,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAQA,wEAAwE;AACxE,eAAO,MAAM,oBAAoB;IAC/B,+EAA+E;;CAQ1D,CAAC;AAExB,gFAAgF;AAChF,eAAO,MAAM,qBAAqB;;;;CAEL,CAAC;AAE9B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,8BAA8B,EAC9B,0BAA0B,EAC1B,gBAAgB,EAChB,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,cAAc,EACd,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,GACzB,MAAM,sBAAsB,CAAC"}
@@ -1,5 +1,6 @@
1
- // The jobs adapter of @softure-ai/mcp-access: its daily cleanup as a `@softure-ai/jobs` handler and schedule (an
2
- // optional peer dependency; only apps that import this entry need it).
1
+ // The jobs adapter of @softure-ai/mcp-access: its daily cleanup as a `@softure-ai/jobs` handler and schedule, and long
2
+ // operations as MCP tools (`startOperation`, `get_operation`, `cancel_operation`) or as MCP Tasks
3
+ // (`registerOperationTasks`). Jobs is an optional peer dependency; only apps that import this entry need it.
3
4
  import { ok } from "@softure-ai/core";
4
5
  import { defineJobHandler } from "@softure-ai/jobs";
5
6
  import { z } from "zod";
@@ -19,4 +20,6 @@ export const mcpAccessJobHandlers = {
19
20
  export const mcpAccessJobSchedules = {
20
21
  "mcp-access.prune": { every: "1d" },
21
22
  };
23
+ export { cancelOperation, getOperation, getOperationStatus, getPollAfterSeconds, MAX_OPERATION_DEDUP_KEY_LENGTH, OPERATION_CANCEL_TOOL_NAME, OPERATION_ORIGIN, OPERATION_STATUS_TOOL_NAME, OPERATION_STATUSES, registerOperationCancelTool, registerOperationStatusTool, startOperation, } from "./operations.js";
24
+ export { DEFAULT_TASK_TTL_SECONDS, getOperationTask, isTasksRequest, MAX_TASK_TTL_SECONDS, MIN_TASK_TTL_SECONDS, registerOperationTasks, TASKS_EXTENSION, } from "./operation-tasks.js";
22
25
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,iHAAiH;AACjH,uEAAuE;AACvE,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAA4C,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,wEAAwE;AACxE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,+EAA+E;IAC/E,kBAAkB,EAAE,gBAAgB,CAAC;QACnC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;YAC3B,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;YAC1B,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;KACF,CAAC;CACmB,CAAC;AAExB,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;CACR,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,uHAAuH;AACvH,kGAAkG;AAClG,6GAA6G;AAC7G,OAAO,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AACtC,OAAO,EAAE,gBAAgB,EAA4C,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,wEAAwE;AACxE,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,+EAA+E;IAC/E,kBAAkB,EAAE,gBAAgB,CAAC;QACnC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACrB,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,EAAE;YAC3B,MAAM,cAAc,CAAC,GAAG,CAAC,CAAC;YAC1B,OAAO,EAAE,EAAE,CAAC;QACd,CAAC;KACF,CAAC;CACmB,CAAC;AAExB,gFAAgF;AAChF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,kBAAkB,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE;CACR,CAAC;AAE9B,OAAO,EACL,eAAe,EACf,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,8BAA8B,EAC9B,0BAA0B,EAC1B,gBAAgB,EAChB,0BAA0B,EAC1B,kBAAkB,EAClB,2BAA2B,EAC3B,2BAA2B,EAC3B,cAAc,GAWf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,EACd,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,eAAe,GAKhB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,58 @@
1
+ import { type Job, type JobProgress } from "@softure-ai/jobs";
2
+ import { type JobsContext } from "@softure-ai/jobs/server";
3
+ import type { McpServerIdentity } from "../contract.js";
4
+ /** The origin of every operation's job: the jobs admin page and run log show where it came from. */
5
+ export declare const OPERATION_ORIGIN = "mcp";
6
+ export declare const OPERATION_STATUS_TOOL_NAME = "get_operation";
7
+ export declare const OPERATION_CANCEL_TOOL_NAME = "cancel_operation";
8
+ /** The longest dedup key an app may pass: the column holds 200 characters and the owner's prefix takes 42. */
9
+ export declare const MAX_OPERATION_DEDUP_KEY_LENGTH = 150;
10
+ export declare const OPERATION_STATUSES: readonly ["queued", "running", "succeeded", "failed", "cancelled"];
11
+ /** An operation's status as the assistant reads it: a retrying job is `running`, since the operation has not ended. */
12
+ export type OperationStatus = (typeof OPERATION_STATUSES)[number];
13
+ export type OperationErrorCode = "mcp-access.operation_not_found" | "mcp-access.operation_finished";
14
+ /** How often the assistant is told to ask again: between `minSeconds` (default 2) and `maxSeconds` (default 30). */
15
+ export interface OperationPollOptions {
16
+ readonly minSeconds?: number;
17
+ readonly maxSeconds?: number;
18
+ }
19
+ /** The job behind an operation, as `readResult` receives it. */
20
+ export interface OperationJob {
21
+ readonly id: string;
22
+ readonly queue: string;
23
+ readonly payload: unknown;
24
+ readonly finishedAt: Date | null;
25
+ }
26
+ /** The app's result of a succeeded operation (a URL, an id, counts), read from its own tables; never a secret. */
27
+ export type ReadOperationResult = (job: OperationJob) => unknown;
28
+ /** What `get_operation` answers. `pollAfterSeconds` only while the operation runs, `result` and `errorCode` once ended. */
29
+ export interface OperationAnswer {
30
+ readonly operationId: string;
31
+ readonly status: OperationStatus;
32
+ /** The running attempt's progress (`context.reportProgress`): codes and counts only. */
33
+ readonly progress: JobProgress | null;
34
+ readonly pollAfterSeconds?: number;
35
+ /** True once someone asked a running operation to stop and it has not ended yet. */
36
+ readonly cancelRequested?: boolean;
37
+ readonly result?: unknown;
38
+ /** The failure's code (`lastError`), `jobs.cancelled` for a cancelled operation. */
39
+ readonly errorCode?: string;
40
+ /** What the assistant should do next, in a sentence. */
41
+ readonly message: string;
42
+ }
43
+ export interface GetOperationOptions {
44
+ readonly readResult?: ReadOperationResult;
45
+ readonly poll?: OperationPollOptions;
46
+ readonly statusToolName?: string;
47
+ }
48
+ /** The operation's status: a pending job that has used an attempt is waiting for a retry, so it is `running`. */
49
+ export declare function getOperationStatus(job: Pick<Job, "status" | "attempts">): OperationStatus;
50
+ /** Seconds until the next status call: a quarter of the operation's age, clamped to the poll bounds. */
51
+ export declare function getPollAfterSeconds(ageSeconds: number, poll?: OperationPollOptions): number;
52
+ export declare function describeOperation(ctx: JobsContext, job: Job, options: GetOperationOptions): Promise<OperationAnswer>;
53
+ /** The job behind the caller's operation, or null: not a job, not an operation, or another account's. */
54
+ export declare function findOwnedJob(ctx: JobsContext, identity: McpServerIdentity, operationId: string): Promise<Job | null>;
55
+ export declare function getOwnerPrefix(userId: string): string;
56
+ export declare function getPollMin(poll?: OperationPollOptions): number;
57
+ export declare function fillToolName(text: string, toolName: string): string;
58
+ //# sourceMappingURL=operation-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-state.d.ts","sourceRoot":"","sources":["../../src/jobs/operation-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ // The state of a long operation (#952) as both answers read it: the polling tools (`get_operation`) and MCP Tasks
2
+ // (#977). An operation is a job of origin `mcp` whose dedup key starts with `mcp:<userId>:`.
3
+ import { JOB_CANCELLED_CODE } from "@softure-ai/jobs";
4
+ import { getJob } from "@softure-ai/jobs/server";
5
+ import { getMcpAccessMessages } from "../server/options.js";
6
+ /** The origin of every operation's job: the jobs admin page and run log show where it came from. */
7
+ export const OPERATION_ORIGIN = "mcp";
8
+ export const OPERATION_STATUS_TOOL_NAME = "get_operation";
9
+ export const OPERATION_CANCEL_TOOL_NAME = "cancel_operation";
10
+ /** The longest dedup key an app may pass: the column holds 200 characters and the owner's prefix takes 42. */
11
+ export const MAX_OPERATION_DEDUP_KEY_LENGTH = 150;
12
+ const DEFAULT_MIN_POLL_SECONDS = 2;
13
+ const DEFAULT_MAX_POLL_SECONDS = 30;
14
+ /** The wait grows with the operation's age: a quarter of the seconds since it started. */
15
+ const POLL_AGE_FACTOR = 0.25;
16
+ export const OPERATION_STATUSES = ["queued", "running", "succeeded", "failed", "cancelled"];
17
+ /** The operation's status: a pending job that has used an attempt is waiting for a retry, so it is `running`. */
18
+ export function getOperationStatus(job) {
19
+ if (job.status === "pending")
20
+ return job.attempts === 0 ? "queued" : "running";
21
+ return job.status;
22
+ }
23
+ /** Seconds until the next status call: a quarter of the operation's age, clamped to the poll bounds. */
24
+ export function getPollAfterSeconds(ageSeconds, poll = {}) {
25
+ const min = getPollMin(poll);
26
+ const max = Math.max(min, poll.maxSeconds ?? DEFAULT_MAX_POLL_SECONDS);
27
+ return Math.min(max, Math.max(min, Math.round(Math.max(0, ageSeconds) * POLL_AGE_FACTOR)));
28
+ }
29
+ export async function describeOperation(ctx, job, options) {
30
+ const messages = getMcpAccessMessages(ctx.config).operations;
31
+ const status = getOperationStatus(job);
32
+ const statusToolName = options.statusToolName ?? OPERATION_STATUS_TOOL_NAME;
33
+ const base = { operationId: job.id, status, progress: status === "running" ? job.progress : null };
34
+ if (status === "queued" || status === "running") {
35
+ const ageSeconds = (ctx.clock.now().getTime() - job.createdAt.getTime()) / 1000;
36
+ const cancelRequested = job.cancelRequestedAt !== null;
37
+ return {
38
+ ...base,
39
+ pollAfterSeconds: getPollAfterSeconds(ageSeconds, options.poll),
40
+ ...(cancelRequested ? { cancelRequested } : {}),
41
+ message: fillToolName(cancelRequested ? messages.cancelRequested : messages[status], statusToolName),
42
+ };
43
+ }
44
+ if (status === "succeeded") {
45
+ const result = options.readResult === undefined ? undefined : await options.readResult({ id: job.id, queue: job.queue, payload: job.payload, finishedAt: job.finishedAt });
46
+ return { ...base, ...(result === undefined ? {} : { result }), message: messages.succeeded };
47
+ }
48
+ if (status === "cancelled")
49
+ return { ...base, errorCode: JOB_CANCELLED_CODE, message: messages.cancelled };
50
+ return { ...base, ...(job.lastError === null ? {} : { errorCode: job.lastError }), message: messages.failed };
51
+ }
52
+ /** The job behind the caller's operation, or null: not a job, not an operation, or another account's. */
53
+ export async function findOwnedJob(ctx, identity, operationId) {
54
+ const job = await getJob(ctx, operationId);
55
+ if (job === null || job.origin !== OPERATION_ORIGIN || job.dedupKey?.startsWith(getOwnerPrefix(identity.userId)) !== true)
56
+ return null;
57
+ return job;
58
+ }
59
+ export function getOwnerPrefix(userId) {
60
+ return `${OPERATION_ORIGIN}:${userId}:`;
61
+ }
62
+ export function getPollMin(poll = {}) {
63
+ return poll.minSeconds ?? DEFAULT_MIN_POLL_SECONDS;
64
+ }
65
+ export function fillToolName(text, toolName) {
66
+ return text.replaceAll("{tool}", toolName);
67
+ }
68
+ //# sourceMappingURL=operation-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-state.js","sourceRoot":"","sources":["../../src/jobs/operation-state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ import { type CallToolResult, type McpServer } from "@modelcontextprotocol/server";
2
+ import { type JobsContext } from "@softure-ai/jobs/server";
3
+ import type { McpServerIdentity } from "../contract.js";
4
+ import { type OperationPollOptions, type ReadOperationResult } from "./operation-state.js";
5
+ /** The extension's identifier, in the client's per-request capabilities and the server's `capabilities.extensions`. */
6
+ export declare const TASKS_EXTENSION = "io.modelcontextprotocol/tasks";
7
+ export declare const DEFAULT_TASK_TTL_SECONDS = 86400;
8
+ export declare const MIN_TASK_TTL_SECONDS = 60;
9
+ /** Thirty days: a task outlives its operation only so long. */
10
+ export declare const MAX_TASK_TTL_SECONDS = 2592000;
11
+ /** The tool handler's request context (its second argument): only its per-request `_meta` envelope is read. */
12
+ export interface OperationTaskRequest {
13
+ readonly mcpReq: {
14
+ readonly envelope?: object;
15
+ };
16
+ }
17
+ /** A task's status as the extension defines it; operations never ask for input, nor fail at the protocol level. */
18
+ export type OperationTaskStatus = "working" | "completed" | "cancelled";
19
+ /** A task as `tasks/get` answers it. `result` once completed: the `get_operation` answer, `isError` when it failed. */
20
+ export interface OperationTask {
21
+ readonly taskId: string;
22
+ readonly status: OperationTaskStatus;
23
+ readonly statusMessage?: string;
24
+ /** ISO 8601. */
25
+ readonly createdAt: string;
26
+ /** ISO 8601: the job's last change. */
27
+ readonly lastUpdatedAt: string;
28
+ readonly ttlMs: number;
29
+ /** Only while working: the operation's wait (`pollAfterSeconds`) in milliseconds. */
30
+ readonly pollIntervalMs?: number;
31
+ readonly result?: CallToolResult;
32
+ }
33
+ export interface OperationTasksOptions {
34
+ /** `{ db, clock, config }` of the request. */
35
+ readonly ctx: JobsContext;
36
+ /** The request's identity: a task is found only for its owner, and only a writer may cancel it. */
37
+ readonly identity: McpServerIdentity;
38
+ readonly readResult?: ReadOperationResult;
39
+ readonly poll?: OperationPollOptions;
40
+ }
41
+ export interface AnswerOperationTaskInput {
42
+ readonly jobId: string;
43
+ readonly ttlSeconds?: number;
44
+ readonly poll?: OperationPollOptions;
45
+ }
46
+ /** True when the request's client declared the Tasks extension in its per-request capabilities (revision 2026-07-28). */
47
+ export declare function isTasksRequest(request: OperationTaskRequest): boolean;
48
+ export declare function isTaskTtlValid(seconds: number): boolean;
49
+ /**
50
+ * The tool's answer as a task (`resultType: "task"`) for the operation's job: stores the task before answering, as the
51
+ * spec requires, and gives the same account the same task id for the same job.
52
+ */
53
+ export declare function answerOperationTask(ctx: JobsContext, identity: McpServerIdentity, input: AnswerOperationTaskInput): Promise<CallToolResult>;
54
+ /** The caller's task with its operation's state now; `null` when unknown, another account's, or its job is gone. */
55
+ export declare function getOperationTask(ctx: JobsContext, identity: McpServerIdentity, taskId: string, options?: Pick<OperationTasksOptions, "readResult" | "poll">): Promise<OperationTask | "expired" | null>;
56
+ /**
57
+ * Serves the Tasks extension on the app's server: declares the capability and answers `tasks/get`, `tasks/update` and
58
+ * `tasks/cancel` for the request's account. Register it on every server whose tools pass `taskRequest`.
59
+ */
60
+ export declare function registerOperationTasks(server: McpServer, options: OperationTasksOptions): void;
61
+ //# sourceMappingURL=operation-tasks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operation-tasks.d.ts","sourceRoot":"","sources":["../../src/jobs/operation-tasks.ts"],"names":[],"mappings":"AAWA,OAAO,EAKL,KAAK,cAAc,EACnB,KAAK,SAAS,EACf,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAoB,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAG7E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,OAAO,EAKL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACzB,MAAM,sBAAsB,CAAC;AAE9B,uHAAuH;AACvH,eAAO,MAAM,eAAe,kCAAkC,CAAC;AAC/D,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAC/C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,UAAY,CAAC;AAQ9C,+GAA+G;AAC/G,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACjD;AAED,mHAAmH;AACnH,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;AAExE,uHAAuH;AACvH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAC;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,gBAAgB;IAChB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,uCAAuC;IACvC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,qFAAqF;IACrF,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,MAAM,WAAW,qBAAqB;IACpC,8CAA8C;IAC9C,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC;IAC1B,mGAAmG;IACnG,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC;CACtC;AAQD,yHAAyH;AACzH,wBAAgB,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAIrE;AAED,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEvD;AAED;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,iBAAiB,EAAE,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,cAAc,CAAC,CAQjJ;AAED,oHAAoH;AACpH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,WAAW,EAChB,QAAQ,EAAE,iBAAiB,EAC3B,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,YAAY,GAAG,MAAM,CAAM,GAC/D,OAAO,CAAC,aAAa,GAAG,SAAS,GAAG,IAAI,CAAC,CAI3C;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,GAAG,IAAI,CA2B9F"}