@apify/actors-mcp-server 0.11.7-beta.8 → 0.11.7

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 (220) hide show
  1. package/dist/apify_client.js +4 -1
  2. package/dist/apify_client.js.map +1 -1
  3. package/dist/const.js +4 -1
  4. package/dist/const.js.map +1 -1
  5. package/dist/dev_server.js +4 -1
  6. package/dist/dev_server.js.map +1 -1
  7. package/dist/errors.js +4 -1
  8. package/dist/errors.js.map +1 -1
  9. package/dist/index.js +4 -1
  10. package/dist/index.js.map +1 -1
  11. package/dist/index_internals.d.ts +7 -12
  12. package/dist/index_internals.d.ts.map +1 -1
  13. package/dist/index_internals.js +10 -12
  14. package/dist/index_internals.js.map +1 -1
  15. package/dist/input.js +4 -1
  16. package/dist/input.js.map +1 -1
  17. package/dist/instrument.js +4 -1
  18. package/dist/instrument.js.map +1 -1
  19. package/dist/mcp/actors.d.ts +0 -4
  20. package/dist/mcp/actors.d.ts.map +1 -1
  21. package/dist/mcp/actors.js +4 -14
  22. package/dist/mcp/actors.js.map +1 -1
  23. package/dist/mcp/client.js +4 -1
  24. package/dist/mcp/client.js.map +1 -1
  25. package/dist/mcp/const.js +4 -1
  26. package/dist/mcp/const.js.map +1 -1
  27. package/dist/mcp/proxy.js +4 -1
  28. package/dist/mcp/proxy.js.map +1 -1
  29. package/dist/mcp/server.d.ts +3 -33
  30. package/dist/mcp/server.d.ts.map +1 -1
  31. package/dist/mcp/server.js +42 -390
  32. package/dist/mcp/server.js.map +1 -1
  33. package/dist/mcp/task_execution.d.ts +42 -0
  34. package/dist/mcp/task_execution.d.ts.map +1 -0
  35. package/dist/mcp/task_execution.js +313 -0
  36. package/dist/mcp/task_execution.js.map +1 -0
  37. package/dist/mcp/tool_call_error_mapper.js +4 -1
  38. package/dist/mcp/tool_call_error_mapper.js.map +1 -1
  39. package/dist/mcp/tool_call_telemetry.d.ts +37 -0
  40. package/dist/mcp/tool_call_telemetry.d.ts.map +1 -0
  41. package/dist/mcp/tool_call_telemetry.js +88 -0
  42. package/dist/mcp/tool_call_telemetry.js.map +1 -0
  43. package/dist/mcp/tool_dispatch.js +4 -1
  44. package/dist/mcp/tool_dispatch.js.map +1 -1
  45. package/dist/mcp/utils.js +4 -1
  46. package/dist/mcp/utils.js.map +1 -1
  47. package/dist/payments/const.d.ts +1 -0
  48. package/dist/payments/const.d.ts.map +1 -1
  49. package/dist/payments/const.js +5 -1
  50. package/dist/payments/const.js.map +1 -1
  51. package/dist/payments/helpers.js +4 -1
  52. package/dist/payments/helpers.js.map +1 -1
  53. package/dist/payments/index.js +4 -1
  54. package/dist/payments/index.js.map +1 -1
  55. package/dist/payments/resolve.js +4 -1
  56. package/dist/payments/resolve.js.map +1 -1
  57. package/dist/payments/skyfire.d.ts.map +1 -1
  58. package/dist/payments/skyfire.js +9 -7
  59. package/dist/payments/skyfire.js.map +1 -1
  60. package/dist/payments/types.js +4 -1
  61. package/dist/payments/types.js.map +1 -1
  62. package/dist/payments/x402.js +4 -1
  63. package/dist/payments/x402.js.map +1 -1
  64. package/dist/prompts/index.js +4 -1
  65. package/dist/prompts/index.js.map +1 -1
  66. package/dist/resources/api_resources.js +4 -1
  67. package/dist/resources/api_resources.js.map +1 -1
  68. package/dist/resources/resource_service.js +4 -1
  69. package/dist/resources/resource_service.js.map +1 -1
  70. package/dist/resources/widgets.js +4 -1
  71. package/dist/resources/widgets.js.map +1 -1
  72. package/dist/server_card.js +4 -1
  73. package/dist/server_card.js.map +1 -1
  74. package/dist/state.js +4 -1
  75. package/dist/state.js.map +1 -1
  76. package/dist/stdio.js +4 -1
  77. package/dist/stdio.js.map +1 -1
  78. package/dist/telemetry.js +4 -1
  79. package/dist/telemetry.js.map +1 -1
  80. package/dist/tools/actor_input_schema.js +4 -1
  81. package/dist/tools/actor_input_schema.js.map +1 -1
  82. package/dist/tools/actor_tool_naming.js +4 -1
  83. package/dist/tools/actor_tool_naming.js.map +1 -1
  84. package/dist/tools/actors/actor_definition.js +4 -1
  85. package/dist/tools/actors/actor_definition.js.map +1 -1
  86. package/dist/tools/actors/actor_executor.js +4 -1
  87. package/dist/tools/actors/actor_executor.js.map +1 -1
  88. package/dist/tools/actors/actor_run_response.js +4 -1
  89. package/dist/tools/actors/actor_run_response.js.map +1 -1
  90. package/dist/tools/actors/actor_tools_factory.js +4 -1
  91. package/dist/tools/actors/actor_tools_factory.js.map +1 -1
  92. package/dist/tools/actors/add_actor.js +4 -1
  93. package/dist/tools/actors/add_actor.js.map +1 -1
  94. package/dist/tools/actors/call_actor.js +4 -1
  95. package/dist/tools/actors/call_actor.js.map +1 -1
  96. package/dist/tools/actors/fetch_actor_details.d.ts +1 -7
  97. package/dist/tools/actors/fetch_actor_details.d.ts.map +1 -1
  98. package/dist/tools/actors/fetch_actor_details.js +18 -23
  99. package/dist/tools/actors/fetch_actor_details.js.map +1 -1
  100. package/dist/tools/actors/search_actors.d.ts +1 -6
  101. package/dist/tools/actors/search_actors.d.ts.map +1 -1
  102. package/dist/tools/actors/search_actors.js +18 -22
  103. package/dist/tools/actors/search_actors.js.map +1 -1
  104. package/dist/tools/dev/report_problem.d.ts +13 -0
  105. package/dist/tools/dev/report_problem.d.ts.map +1 -1
  106. package/dist/tools/dev/report_problem.js +18 -1
  107. package/dist/tools/dev/report_problem.js.map +1 -1
  108. package/dist/tools/docs/fetch_apify_docs.js +4 -1
  109. package/dist/tools/docs/fetch_apify_docs.js.map +1 -1
  110. package/dist/tools/docs/search_apify_docs.js +4 -1
  111. package/dist/tools/docs/search_apify_docs.js.map +1 -1
  112. package/dist/tools/index.js +4 -1
  113. package/dist/tools/index.js.map +1 -1
  114. package/dist/tools/registry.js +4 -1
  115. package/dist/tools/registry.js.map +1 -1
  116. package/dist/tools/runs/abort_actor_run.js +4 -1
  117. package/dist/tools/runs/abort_actor_run.js.map +1 -1
  118. package/dist/tools/runs/get_actor_run.d.ts +1 -6
  119. package/dist/tools/runs/get_actor_run.d.ts.map +1 -1
  120. package/dist/tools/runs/get_actor_run.js +21 -25
  121. package/dist/tools/runs/get_actor_run.js.map +1 -1
  122. package/dist/tools/runs/get_actor_run_list.js +4 -1
  123. package/dist/tools/runs/get_actor_run_list.js.map +1 -1
  124. package/dist/tools/runs/get_actor_run_log.js +4 -1
  125. package/dist/tools/runs/get_actor_run_log.js.map +1 -1
  126. package/dist/tools/storage/get_dataset.js +4 -1
  127. package/dist/tools/storage/get_dataset.js.map +1 -1
  128. package/dist/tools/storage/get_dataset_items.js +4 -1
  129. package/dist/tools/storage/get_dataset_items.js.map +1 -1
  130. package/dist/tools/storage/get_dataset_list.js +4 -1
  131. package/dist/tools/storage/get_dataset_list.js.map +1 -1
  132. package/dist/tools/storage/get_dataset_schema.js +4 -1
  133. package/dist/tools/storage/get_dataset_schema.js.map +1 -1
  134. package/dist/tools/storage/get_key_value_store.js +4 -1
  135. package/dist/tools/storage/get_key_value_store.js.map +1 -1
  136. package/dist/tools/storage/get_key_value_store_keys.js +4 -1
  137. package/dist/tools/storage/get_key_value_store_keys.js.map +1 -1
  138. package/dist/tools/storage/get_key_value_store_list.js +4 -1
  139. package/dist/tools/storage/get_key_value_store_list.js.map +1 -1
  140. package/dist/tools/storage/get_key_value_store_record.js +4 -1
  141. package/dist/tools/storage/get_key_value_store_record.js.map +1 -1
  142. package/dist/tools/storage/storage_helpers.js +4 -1
  143. package/dist/tools/storage/storage_helpers.js.map +1 -1
  144. package/dist/tools/structured_output_schemas.js +4 -1
  145. package/dist/tools/structured_output_schemas.js.map +1 -1
  146. package/dist/tools/widgets/call_actor_widget.js +4 -1
  147. package/dist/tools/widgets/call_actor_widget.js.map +1 -1
  148. package/dist/tools/widgets/fetch_actor_details_widget.js +4 -1
  149. package/dist/tools/widgets/fetch_actor_details_widget.js.map +1 -1
  150. package/dist/tools/widgets/get_actor_run_widget.js +4 -1
  151. package/dist/tools/widgets/get_actor_run_widget.js.map +1 -1
  152. package/dist/tools/widgets/search_actors_widget.js +4 -1
  153. package/dist/tools/widgets/search_actors_widget.js.map +1 -1
  154. package/dist/tsconfig.tsbuildinfo +1 -1
  155. package/dist/types.d.ts +0 -11
  156. package/dist/types.d.ts.map +1 -1
  157. package/dist/types.js +4 -1
  158. package/dist/types.js.map +1 -1
  159. package/dist/utils/actor.js +4 -1
  160. package/dist/utils/actor.js.map +1 -1
  161. package/dist/utils/actor_card.js +4 -1
  162. package/dist/utils/actor_card.js.map +1 -1
  163. package/dist/utils/actor_details.js +4 -1
  164. package/dist/utils/actor_details.js.map +1 -1
  165. package/dist/utils/actor_search.js +4 -1
  166. package/dist/utils/actor_search.js.map +1 -1
  167. package/dist/utils/ajv.js +4 -1
  168. package/dist/utils/ajv.js.map +1 -1
  169. package/dist/utils/apify_docs.js +4 -1
  170. package/dist/utils/apify_docs.js.map +1 -1
  171. package/dist/utils/apify_errors.js +4 -1
  172. package/dist/utils/apify_errors.js.map +1 -1
  173. package/dist/utils/apify_properties.js +4 -1
  174. package/dist/utils/apify_properties.js.map +1 -1
  175. package/dist/utils/auth.js +4 -1
  176. package/dist/utils/auth.js.map +1 -1
  177. package/dist/utils/console_link.js +4 -1
  178. package/dist/utils/console_link.js.map +1 -1
  179. package/dist/utils/encode_text.js +4 -1
  180. package/dist/utils/encode_text.js.map +1 -1
  181. package/dist/utils/generic.js +4 -1
  182. package/dist/utils/generic.js.map +1 -1
  183. package/dist/utils/logging.d.ts +2 -0
  184. package/dist/utils/logging.d.ts.map +1 -1
  185. package/dist/utils/logging.js +49 -2
  186. package/dist/utils/logging.js.map +1 -1
  187. package/dist/utils/mcp.js +4 -1
  188. package/dist/utils/mcp.js.map +1 -1
  189. package/dist/utils/mcp_clients.js +4 -1
  190. package/dist/utils/mcp_clients.js.map +1 -1
  191. package/dist/utils/payment_errors.js +4 -1
  192. package/dist/utils/payment_errors.js.map +1 -1
  193. package/dist/utils/pricing_info.js +4 -1
  194. package/dist/utils/pricing_info.js.map +1 -1
  195. package/dist/utils/progress.js +4 -1
  196. package/dist/utils/progress.js.map +1 -1
  197. package/dist/utils/schema_generation.js +4 -1
  198. package/dist/utils/schema_generation.js.map +1 -1
  199. package/dist/utils/server-instructions/index.js +4 -1
  200. package/dist/utils/server-instructions/index.js.map +1 -1
  201. package/dist/utils/server_mode.js +4 -1
  202. package/dist/utils/server_mode.js.map +1 -1
  203. package/dist/utils/tool_categories_helpers.js +4 -1
  204. package/dist/utils/tool_categories_helpers.js.map +1 -1
  205. package/dist/utils/tool_status.js +4 -1
  206. package/dist/utils/tool_status.js.map +1 -1
  207. package/dist/utils/tools.js +4 -1
  208. package/dist/utils/tools.js.map +1 -1
  209. package/dist/utils/tools_loader.js +4 -1
  210. package/dist/utils/tools_loader.js.map +1 -1
  211. package/dist/utils/ttl_lru.js +4 -1
  212. package/dist/utils/ttl_lru.js.map +1 -1
  213. package/dist/utils/userid_cache.js +4 -1
  214. package/dist/utils/userid_cache.js.map +1 -1
  215. package/dist/utils/version.js +4 -1
  216. package/dist/utils/version.js.map +1 -1
  217. package/dist/web/dist/actor-run-widget.js +2 -3
  218. package/dist/web/dist/search-actors-widget.js +2 -3
  219. package/package.json +1 -1
  220. package/dist/web/dist/actor-detail-widget.js +0 -4551
@@ -1,6 +1,8 @@
1
1
  /**
2
2
  * Model Context Protocol (MCP) server for Apify Actors
3
3
  */
4
+
5
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b73a1497-d81a-5a2a-94ad-aff60a1cb69c")}catch(e){}}();
4
6
  import { randomUUID } from 'node:crypto';
5
7
  // The ext-apps package exposes `./server` via conditional exports only (no `./server/index.js`
6
8
  // wildcard), so we can't satisfy the `import/extensions` rule on this subpath.
@@ -19,28 +21,28 @@ import { prompts } from '../prompts/index.js';
19
21
  import { createResourceService } from '../resources/resource_service.js';
20
22
  import { resolveAvailableWidgets } from '../resources/widgets.js';
21
23
  import { getServerInfo } from '../server_card.js';
22
- import { buildReportedProblemProperties, getTelemetryEnv, trackReportedProblem, trackToolCall } from '../telemetry.js';
24
+ import { getTelemetryEnv } from '../telemetry.js';
23
25
  import { decodeDotPropertyNames } from '../tools/actor_input_schema.js';
24
26
  import { legacyToolNameToNew } from '../tools/actor_tool_naming.js';
25
27
  import { checkPaymentProviderStandbyConflict } from '../tools/actors/call_actor.js';
26
- import { appendReportProblemNudge } from '../tools/dev/report_problem.js';
28
+ import { withReportProblemNudge } from '../tools/dev/report_problem.js';
27
29
  import { getActorsAsTools } from '../tools/index.js';
28
30
  import { SERVER_MODE, TOOL_TYPE } from '../types.js';
29
31
  import { isMcpClientFaultMessage, logHttpError, sanitizeMezmoMessage } from '../utils/logging.js';
30
- import { computeToolResponseBytes, respondOk } from '../utils/mcp.js';
32
+ import { respondOk } from '../utils/mcp.js';
31
33
  import { isReportProblemBlockedForClient } from '../utils/mcp_clients.js';
32
34
  import { createProgressTracker } from '../utils/progress.js';
33
35
  import { getServerInstructions } from '../utils/server-instructions/index.js';
34
36
  import { parseServerMode, resolveServerMode } from '../utils/server_mode.js';
35
- import { deriveResourceIds, extractAjvErrorDetails } from '../utils/tool_status.js';
37
+ import { extractAjvErrorDetails } from '../utils/tool_status.js';
36
38
  import { buildActorFields, extractActorId, extractActorName, getToolFullName, getToolPublicFieldOnly, } from '../utils/tools.js';
37
39
  import { getActors, getToolsForServerMode, toolNamesToInput } from '../utils/tools_loader.js';
38
- import { getUserInfoCached } from '../utils/userid_cache.js';
39
- import { getPackageVersion } from '../utils/version.js';
40
40
  import { LOG_LEVEL_MAP } from './const.js';
41
+ import { emitTaskStatusNotification, executeToolAndUpdateTask } from './task_execution.js';
41
42
  import { buildToolCallErrorResult, TOOL_CALL_ERROR_KIND } from './tool_call_error_mapper.js';
43
+ import { logToolCallAndTelemetry, prepareTelemetryData } from './tool_call_telemetry.js';
42
44
  import { dispatchToolCall } from './tool_dispatch.js';
43
- import { createTaskCancellationWatcher, isTaskCancelled, isTaskNotFoundError, parseInputParamsFromUrl, storeTaskResultOrSkipIfExpired, } from './utils.js';
45
+ import { parseInputParamsFromUrl, storeTaskResultOrSkipIfExpired } from './utils.js';
44
46
  /**
45
47
  * Returns true when the initialize request advertises the MCP Apps UI extension
46
48
  * with the widget MIME type. Used to resolve `'auto'` server mode.
@@ -54,33 +56,6 @@ function isUiSupportedByClient(request) {
54
56
  const uiCap = getUiCapability((_a = request === null || request === void 0 ? void 0 : request.params) === null || _a === void 0 ? void 0 : _a.capabilities);
55
57
  return (_c = (_b = uiCap === null || uiCap === void 0 ? void 0 : uiCap.mimeTypes) === null || _b === void 0 ? void 0 : _b.includes(RESOURCE_MIME_TYPE)) !== null && _c !== void 0 ? _c : false;
56
58
  }
57
- /** Send notifications/tasks/status for taskId. Routes via session transport (no relatedRequestId).
58
- * Swallows errors — notifications are advisory. */
59
- export async function emitTaskStatusNotification(taskId, mcpSessionId, taskStore, server) {
60
- try {
61
- const task = await taskStore.getTask(taskId, mcpSessionId);
62
- if (!task)
63
- return;
64
- // Per spec: notifications/tasks/status MUST NOT carry _meta.related-task (task ID is in params).
65
- // Called without options so the notification routes through the session transport,
66
- // not the request-scoped stream (which closes once the initial { task } response is flushed).
67
- await server.notification({
68
- method: 'notifications/tasks/status',
69
- params: {
70
- taskId: task.taskId,
71
- status: task.status,
72
- createdAt: task.createdAt,
73
- lastUpdatedAt: task.lastUpdatedAt,
74
- ttl: task.ttl,
75
- ...(task.statusMessage != null && { statusMessage: task.statusMessage }),
76
- ...(task.pollInterval != null && { pollInterval: task.pollInterval }),
77
- },
78
- });
79
- }
80
- catch {
81
- // Silent fail — notifications are advisory
82
- }
83
- }
84
59
  /**
85
60
  * Shared diagnostics for a pre-flight failure (standby-provider conflict or missing/invalid payment
86
61
  * signature) — a call outcome already known before any Actor runs. Standby rejection wins over the
@@ -197,18 +172,18 @@ export class ActorsMcpServer {
197
172
  writable: true,
198
173
  value: []
199
174
  });
200
- // Telemetry configuration (resolved from options and env vars in setupTelemetry)
175
+ // Telemetry configuration (resolved from options and env vars, see setupTelemetry)
201
176
  Object.defineProperty(this, "telemetryEnabled", {
202
177
  enumerable: true,
203
178
  configurable: true,
204
179
  writable: true,
205
- value: null
180
+ value: void 0
206
181
  });
207
182
  Object.defineProperty(this, "telemetryEnv", {
208
183
  enumerable: true,
209
184
  configurable: true,
210
185
  writable: true,
211
- value: DEFAULT_TELEMETRY_ENV
186
+ value: void 0
212
187
  });
213
188
  // List of widgets that are ready to be served
214
189
  Object.defineProperty(this, "availableWidgets", {
@@ -275,7 +250,9 @@ export class ActorsMcpServer {
275
250
  },
276
251
  instructions: getServerInstructions(),
277
252
  });
278
- this.setupTelemetry();
253
+ const { telemetryEnabled, telemetryEnv } = this.setupTelemetry();
254
+ this.telemetryEnabled = telemetryEnabled;
255
+ this.telemetryEnv = telemetryEnv;
279
256
  this.setupInitializeHandler();
280
257
  this.setupLoggingProxy();
281
258
  this.tools = new Map();
@@ -294,18 +271,21 @@ export class ActorsMcpServer {
294
271
  */
295
272
  setupTelemetry() {
296
273
  var _a, _b, _c;
274
+ let telemetryEnabled;
297
275
  const explicitEnabled = parseBooleanOrNull((_a = this.options.telemetry) === null || _a === void 0 ? void 0 : _a.enabled);
298
276
  if (explicitEnabled !== null) {
299
- this.telemetryEnabled = explicitEnabled;
277
+ telemetryEnabled = explicitEnabled;
300
278
  }
301
279
  else {
302
280
  const envEnabled = parseBooleanOrNull(process.env.TELEMETRY_ENABLED);
303
- this.telemetryEnabled = envEnabled !== null && envEnabled !== void 0 ? envEnabled : DEFAULT_TELEMETRY_ENABLED;
281
+ telemetryEnabled = envEnabled !== null && envEnabled !== void 0 ? envEnabled : DEFAULT_TELEMETRY_ENABLED;
304
282
  }
305
283
  // Configure telemetryEnv: explicit option > env var > default ('PROD')
306
- if (this.telemetryEnabled) {
307
- this.telemetryEnv = getTelemetryEnv((_c = (_b = this.options.telemetry) === null || _b === void 0 ? void 0 : _b.env) !== null && _c !== void 0 ? _c : process.env.TELEMETRY_ENV);
284
+ let telemetryEnv = DEFAULT_TELEMETRY_ENV;
285
+ if (telemetryEnabled) {
286
+ telemetryEnv = getTelemetryEnv((_c = (_b = this.options.telemetry) === null || _b === void 0 ? void 0 : _b.env) !== null && _c !== void 0 ? _c : process.env.TELEMETRY_ENV);
308
287
  }
288
+ return { telemetryEnabled, telemetryEnv };
309
289
  }
310
290
  /**
311
291
  * Override the SDK's `initialize` request handler to run mode resolution and
@@ -387,23 +367,10 @@ export class ActorsMcpServer {
387
367
  * survive a load that never sees an initialize.
388
368
  */
389
369
  isReportProblemServable() {
390
- return (!!this.telemetryEnabled &&
370
+ return (this.telemetryEnabled &&
391
371
  this.clientKnown &&
392
372
  !isReportProblemBlockedForClient(this.options.initializeRequestData));
393
373
  }
394
- /**
395
- * Append the report-problem nudge to a failed tool result. Thin wrapper over
396
- * {@link appendReportProblemNudge} that fills in whether report-problem is served on this
397
- * connection; suppression by category/402 is handled inside the helper.
398
- */
399
- withReportProblemNudge(result, failingToolName, failureCategory, failureHttpStatus) {
400
- return appendReportProblemNudge(result, {
401
- failingToolName,
402
- available: this.tools.has(HELPER_TOOLS.PROBLEM_REPORT),
403
- failureCategory,
404
- failureHttpStatus,
405
- });
406
- }
407
374
  composePendingToolsForClient() {
408
375
  if (this.pendingToolsUntilClientKnown.length === 0)
409
376
  return;
@@ -868,7 +835,13 @@ export class ActorsMcpServer {
868
835
  // On a failed result, nudge the agent to report the blocker via report-problem at the
869
836
  // moment it decides what to do next. Gated on the tool actually being served (see
870
837
  // isReportProblemServable), so clients where it is blocklisted or telemetry is off never see it.
871
- const augmented = this.withReportProblemNudge(r, resolvedToolName, callDiagnostics.failure_category, callDiagnostics.failure_http_status);
838
+ const augmented = withReportProblemNudge({
839
+ result: r,
840
+ tools: this.tools,
841
+ failingToolName: resolvedToolName,
842
+ failureCategory: callDiagnostics.failure_category,
843
+ failureHttpStatus: callDiagnostics.failure_http_status,
844
+ });
872
845
  toolResult = augmented;
873
846
  return augmented;
874
847
  };
@@ -890,7 +863,12 @@ export class ActorsMcpServer {
890
863
  };
891
864
  // Initialize telemetry with raw tool name — updated below once the tool is resolved.
892
865
  // This ensures telemetry is available even for early failures (missing token, tool not found).
893
- const { telemetryData, userId } = await this.prepareTelemetryData(name, mcpSessionId, apifyToken);
866
+ const { telemetryData, userId } = await prepareTelemetryData({
867
+ toolName: name,
868
+ mcpSessionId,
869
+ apifyToken,
870
+ apifyMcpServer: this,
871
+ });
894
872
  // actorName/actorId are declared here so they're available in the catch block for telemetry.
895
873
  // Set after tool resolution (inside the try block).
896
874
  let actorName;
@@ -1058,7 +1036,7 @@ export class ActorsMcpServer {
1058
1036
  }
1059
1037
  // Execute the tool asynchronously and update task status
1060
1038
  setImmediate(() => {
1061
- this.executeToolAndUpdateTask({
1039
+ executeToolAndUpdateTask({
1062
1040
  taskId: task.taskId,
1063
1041
  tool,
1064
1042
  toolArgs: toolArgs,
@@ -1070,6 +1048,7 @@ export class ActorsMcpServer {
1070
1048
  mcpSessionId,
1071
1049
  actorName,
1072
1050
  actorId,
1051
+ apifyMcpServer: this,
1073
1052
  }).catch((error) =>
1074
1053
  // Benign task-expiry is handled in-method (see the catch block and
1075
1054
  // storeTaskResultOrSkipIfExpired); anything reaching here is genuinely unexpected.
@@ -1182,7 +1161,7 @@ export class ActorsMcpServer {
1182
1161
  }
1183
1162
  finally {
1184
1163
  if (shouldTrackTelemetry) {
1185
- this.logToolCallAndTelemetry({
1164
+ logToolCallAndTelemetry({
1186
1165
  toolName: resolvedToolName,
1187
1166
  mcpSessionId,
1188
1167
  toolStatus,
@@ -1193,340 +1172,12 @@ export class ActorsMcpServer {
1193
1172
  args,
1194
1173
  result: toolResult,
1195
1174
  taskId: preflightTaskId,
1175
+ apifyMcpServer: this,
1196
1176
  });
1197
1177
  }
1198
1178
  }
1199
1179
  });
1200
1180
  }
1201
- /**
1202
- * Logs tool call completion at INFO level and tracks telemetry.
1203
- * Computes duration once so both the log line and telemetry event use the same value.
1204
- * Response bytes and resource ids are derived here from the raw `result` (+ `args`) so every
1205
- * call site stays a plain hand-off — no path can forget to compute or strip them.
1206
- */
1207
- logToolCallAndTelemetry(params) {
1208
- const durationMs = Date.now() - params.startTime;
1209
- // `result` is undefined only on short-circuit paths that never produced a payload (e.g. a
1210
- // cancelled task); skip byte accounting there. `null`/`{}` still measure as zero bytes.
1211
- const responseBytes = params.result === undefined ? undefined : computeToolResponseBytes(params.result);
1212
- log.info('Tool call completed', {
1213
- toolName: params.toolName,
1214
- mcpSessionId: params.mcpSessionId,
1215
- toolStatus: params.toolStatus,
1216
- durationMs,
1217
- ...(responseBytes !== undefined && {
1218
- responseContentBytes: responseBytes.contentBytes,
1219
- responseStructuredContentBytes: responseBytes.structuredContentBytes,
1220
- responseFileBytes: responseBytes.fileBytes,
1221
- }),
1222
- ...(params.taskId !== undefined && { taskId: params.taskId }),
1223
- });
1224
- if (params.telemetryData) {
1225
- const finalizedTelemetryData = {
1226
- ...params.telemetryData,
1227
- tool_status: params.toolStatus,
1228
- tool_exec_time_ms: durationMs,
1229
- ...(responseBytes && {
1230
- tool_response_content_bytes: responseBytes.contentBytes,
1231
- tool_response_structured_content_bytes: responseBytes.structuredContentBytes,
1232
- tool_response_file_bytes: responseBytes.fileBytes,
1233
- }),
1234
- // Always include actor_name/actor_id; failure-specific fields are only present when callDiagnostics has them.
1235
- ...params.callDiagnostics,
1236
- // Resource ids are read once here from the args + the tool's public output; no tool
1237
- // threads them back. Applied uniformly, last. See deriveResourceIds.
1238
- ...deriveResourceIds(params.args, params.result),
1239
- };
1240
- trackToolCall(params.userId, this.telemetryEnv, finalizedTelemetryData);
1241
- // A successful report-problem call also emits a dedicated feedback event carrying the
1242
- // submission. A downstream Segment destination fans it out to Slack/GitHub.
1243
- if (params.toolName === HELPER_TOOLS.PROBLEM_REPORT &&
1244
- params.toolStatus === TOOL_STATUS.SUCCEEDED &&
1245
- params.args) {
1246
- trackReportedProblem(params.userId, this.telemetryEnv, buildReportedProblemProperties(finalizedTelemetryData, params.args));
1247
- }
1248
- }
1249
- }
1250
- // TODO: outer orchestration here (pre-flight, telemetry bookkeeping, task-store handling) still duplicates the CallToolRequestSchema handler's logic; the dispatch ladder is now shared. Refactor.
1251
- /**
1252
- * Executes a tool asynchronously for a long-running task and updates task status.
1253
- *
1254
- * @param params - Tool execution parameters
1255
- * @param params.taskId - The task identifier
1256
- * @param params.tool - The tool to execute
1257
- * @param params.args - Tool arguments
1258
- * @param params.apifyToken - Apify API token
1259
- * @param params.progressToken - Progress token for notifications
1260
- * @param params.extra - Extra request handler context
1261
- * @param params.mcpSessionId - MCP session ID for telemetry
1262
- */
1263
- async executeToolAndUpdateTask(params) {
1264
- const { taskId, tool, toolArgs, logSafeArgs, apifyClient, apifyToken, progressToken, extra, mcpSessionId, actorName, actorId, } = params;
1265
- let toolStatus = TOOL_STATUS.SUCCEEDED;
1266
- // Always populate actor fields so they're tracked on both success and failure paths.
1267
- let callDiagnostics = { ...buildActorFields(actorName, actorId) };
1268
- const startTime = Date.now();
1269
- log.debug('[executeToolAndUpdateTask] Starting task execution', {
1270
- taskId,
1271
- toolName: tool.name,
1272
- mcpSessionId,
1273
- });
1274
- // Prepare telemetry before try-catch so it's accessible to both paths.
1275
- // This avoids re-fetching user data in the error handler.
1276
- const { telemetryData, userId } = await this.prepareTelemetryData(getToolFullName(tool), mcpSessionId, apifyToken);
1277
- const finishTaskTracking = (status, diagnostics, result) => {
1278
- this.logToolCallAndTelemetry({
1279
- toolName: tool.name,
1280
- mcpSessionId,
1281
- toolStatus: status,
1282
- startTime,
1283
- taskId,
1284
- telemetryData,
1285
- userId,
1286
- callDiagnostics: diagnostics,
1287
- args: toolArgs,
1288
- result,
1289
- });
1290
- };
1291
- // Terminal step shared by every task outcome: store the result (expiry-tolerant),
1292
- // emit the status notification, record telemetry.
1293
- const completeTask = async (storeStatus, taskResult, status, diagnostics) => {
1294
- await storeTaskResultOrSkipIfExpired(this.taskStore, tool.name, taskId, storeStatus, taskResult, mcpSessionId);
1295
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1296
- finishTaskTracking(status, diagnostics, taskResult);
1297
- };
1298
- // Once a task is cancelled the spec forbids writing a result; every storage path
1299
- // must short-circuit here. `logSuffix` is concatenated after "Task was cancelled"
1300
- // so we keep the existing log format and the existing telemetry status per path.
1301
- const skipIfTaskCancelled = async (logSuffix, status, diagnostics) => {
1302
- if (!(await isTaskCancelled(taskId, mcpSessionId, this.taskStore)))
1303
- return false;
1304
- log.debug(`[executeToolAndUpdateTask] Task was cancelled${logSuffix}`, { taskId, mcpSessionId });
1305
- finishTaskTracking(status, diagnostics);
1306
- return true;
1307
- };
1308
- // Bridges MCP `tasks/cancel` to the running handler: when the client
1309
- // explicitly cancels the task, this signal aborts so the underlying
1310
- // Actor run stops instead of consuming compute until natural completion.
1311
- // Per MCP tasks spec, request-level aborts (client disconnect,
1312
- // notifications/cancelled for the original request ID) MUST NOT cancel
1313
- // the task — `extra.signal` is intentionally not chained here.
1314
- const cancelWatcher = createTaskCancellationWatcher({
1315
- taskId,
1316
- mcpSessionId,
1317
- taskStore: this.taskStore,
1318
- });
1319
- const taskExtra = { ...extra, signal: cancelWatcher.signal };
1320
- try {
1321
- log.debug('[executeToolAndUpdateTask] Updating task status to working', {
1322
- taskId,
1323
- mcpSessionId,
1324
- });
1325
- // The store rejects terminal → 'working' transitions. If `tasks/cancel` raced
1326
- // with us (between handler dispatch and the first watcher tick at ~500 ms),
1327
- // updateTaskStatus throws — re-check the store to tell a clean cancel-race
1328
- // apart from a genuine store error.
1329
- // noinspection ExceptionCaughtLocallyJS
1330
- try {
1331
- await this.taskStore.updateTaskStatus(taskId, 'working', undefined, mcpSessionId);
1332
- }
1333
- catch (err) {
1334
- if (await skipIfTaskCancelled(' before execution started, skipping', TOOL_STATUS.ABORTED, {
1335
- ...buildActorFields(actorName, actorId),
1336
- }))
1337
- return;
1338
- throw err;
1339
- }
1340
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1341
- // Execute the tool and get the result
1342
- let result = {};
1343
- // Callback to propagate Actor run statusMessage into the task store and emit a push notification.
1344
- // TODO(TC-3): cancel arriving while this is scheduled throws cancelled → working;
1345
- // currently swallowed by progress.ts's tick catch — guard or catch explicitly.
1346
- const onStatusMessage = async (message) => {
1347
- await this.taskStore.updateTaskStatus(taskId, 'working', message, mcpSessionId);
1348
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1349
- };
1350
- // ACTOR_MCP never reads the tracker (matching the sync path, which passes null for it);
1351
- // INTERNAL/ACTOR get one built from taskId + onStatusMessage, which dispatch consumes
1352
- // and stops.
1353
- const progressTracker = tool.type === TOOL_TYPE.ACTOR_MCP
1354
- ? null
1355
- : createProgressTracker(progressToken, extra.sendNotification, taskId, onStatusMessage);
1356
- const dispatchResult = await dispatchToolCall({
1357
- tool,
1358
- toolArgs,
1359
- logSafeArgs,
1360
- apifyToken,
1361
- apifyClient,
1362
- apifyMcpServer: this,
1363
- mcpSessionId,
1364
- progressToken,
1365
- progressTracker,
1366
- shouldForwardNotifications: false,
1367
- extra: taskExtra,
1368
- actorName,
1369
- actorId,
1370
- taskMode: true,
1371
- logContext: { messageSuffix: ' for task', fields: { taskId } },
1372
- });
1373
- result = dispatchResult.result;
1374
- toolStatus = dispatchResult.toolStatus;
1375
- callDiagnostics = dispatchResult.callDiagnostics;
1376
- // Check if task was cancelled before storing result
1377
- if (await skipIfTaskCancelled(', skipping result storage', toolStatus))
1378
- return;
1379
- // On a failed result, nudge the agent to report the blocker via report-problem (mirrors the
1380
- // synchronous CallTool path, which task-mode calls like call-actor bypass).
1381
- result = this.withReportProblemNudge(result, tool.name, callDiagnostics.failure_category, callDiagnostics.failure_http_status);
1382
- // Store the result in the task store
1383
- log.debug('[executeToolAndUpdateTask] Storing completed result', {
1384
- taskId,
1385
- mcpSessionId,
1386
- });
1387
- await completeTask('completed', result, toolStatus, callDiagnostics);
1388
- log.debug('Task completed successfully', { taskId, toolName: tool.name, mcpSessionId });
1389
- }
1390
- catch (error) {
1391
- // Reached only when the task expired before the `working` transition (updateTaskStatus
1392
- // above rethrows the store's unknown-taskId error). The tool never ran and the task is
1393
- // gone, so soft-fail, record telemetry, and stop. Every result store (success and error
1394
- // paths) tolerates expiry via storeTaskResultOrSkipIfExpired, so they don't reach here.
1395
- if (isTaskNotFoundError(error)) {
1396
- log.softFail('Task expired before execution started', {
1397
- taskId,
1398
- toolName: tool.name,
1399
- mcpSessionId,
1400
- });
1401
- finishTaskTracking(TOOL_STATUS.SOFT_FAIL, {
1402
- failure_category: FAILURE_CATEGORY.INTERNAL_ERROR,
1403
- ...buildActorFields(actorName, actorId),
1404
- });
1405
- return;
1406
- }
1407
- const errorResult = buildToolCallErrorResult(error, {
1408
- toolName: tool.name,
1409
- actorName,
1410
- actorId,
1411
- isAborted: Boolean(cancelWatcher.signal.aborted),
1412
- });
1413
- // Handle 402 Payment Required — return structured x402 result so clients can auto-pay
1414
- if (errorResult.kind === TOOL_CALL_ERROR_KIND.PAYMENT) {
1415
- logHttpError(error, 'Payment required while calling tool (task mode)', { toolName: tool.name });
1416
- // Per MCP tasks spec: once a task is cancelled it MUST remain cancelled,
1417
- // so guard storeTaskResult against a cancel that raced with this 402.
1418
- if (await skipIfTaskCancelled(', skipping 402 result storage', TOOL_STATUS.ABORTED, {
1419
- ...buildActorFields(actorName, actorId),
1420
- }))
1421
- return;
1422
- await completeTask('completed', errorResult.response, errorResult.toolStatus, errorResult.callDiagnostics);
1423
- return;
1424
- }
1425
- if (errorResult.kind === TOOL_CALL_ERROR_KIND.APPROVAL) {
1426
- logHttpError(error, 'Permission approval required while calling tool (task mode)', {
1427
- toolName: tool.name,
1428
- });
1429
- // Per MCP tasks spec: once a task is cancelled it MUST remain cancelled,
1430
- // so guard storeTaskResult against a cancel that raced with this approval error.
1431
- if (await skipIfTaskCancelled(', skipping permission-approval result storage', TOOL_STATUS.ABORTED, {
1432
- ...buildActorFields(actorName, actorId),
1433
- }))
1434
- return;
1435
- await completeTask('completed', errorResult.response, errorResult.toolStatus, errorResult.callDiagnostics);
1436
- return;
1437
- }
1438
- toolStatus = errorResult.toolStatus;
1439
- callDiagnostics = errorResult.callDiagnostics;
1440
- // Log level follows the already-classified toolStatus:
1441
- // SOFT_FAIL (e.g. 402/403 user quota, client-side issues) → softFail
1442
- // FAILED/ABORTED/other → error
1443
- if (toolStatus === TOOL_STATUS.SOFT_FAIL) {
1444
- // Mezmo promotes on "error" in message/keys — use errMessage key, sanitized.
1445
- const errMessage = sanitizeMezmoMessage(error instanceof Error ? error.message : String(error));
1446
- log.softFail('Tool execution soft-failed for task', {
1447
- taskId,
1448
- toolName: tool.name,
1449
- toolStatus,
1450
- mcpSessionId,
1451
- failureCategory: callDiagnostics.failure_category,
1452
- failureHttpStatus: callDiagnostics.failure_http_status,
1453
- actorName: callDiagnostics.actor_name,
1454
- errMessage,
1455
- });
1456
- }
1457
- else {
1458
- log.error('Error executing tool for task', {
1459
- taskId,
1460
- toolName: tool.name,
1461
- toolStatus,
1462
- mcpSessionId,
1463
- failureCategory: callDiagnostics.failure_category,
1464
- failureHttpStatus: callDiagnostics.failure_http_status,
1465
- actorName: callDiagnostics.actor_name,
1466
- error,
1467
- });
1468
- }
1469
- const { userText } = errorResult;
1470
- // Check if task was cancelled before storing result
1471
- if (await skipIfTaskCancelled(', skipping result storage', toolStatus, callDiagnostics))
1472
- return;
1473
- log.debug('[executeToolAndUpdateTask] Storing failed result', {
1474
- taskId,
1475
- mcpSessionId,
1476
- });
1477
- // Nudge on a genuinely-failed task result (mirrors the completed path and the sync
1478
- // captureResult). INTERNAL_ERROR and an unknown category get the full nudge; a genuine
1479
- // INVALID_INPUT gets the softer nudge; payment (402) is suppressed via the HTTP status and
1480
- // AUTH / PERMISSION_APPROVAL_REQUIRED via NON_NUDGE_FAILURE_CATEGORIES. The 402 branch above
1481
- // returns before reaching here, so this only sees non-payment failures.
1482
- const failedResult = this.withReportProblemNudge({
1483
- content: [
1484
- {
1485
- type: 'text',
1486
- text: userText,
1487
- },
1488
- ],
1489
- isError: true,
1490
- internalToolStatus: toolStatus,
1491
- }, tool.name, callDiagnostics.failure_category, callDiagnostics.failure_http_status);
1492
- await completeTask('failed', failedResult, toolStatus, callDiagnostics);
1493
- }
1494
- finally {
1495
- cancelWatcher.dispose();
1496
- }
1497
- }
1498
- /*
1499
- * Creates telemetry data for a tool call.
1500
- */
1501
- async prepareTelemetryData(toolName, mcpSessionId, apifyToken) {
1502
- var _a, _b, _c, _d, _e;
1503
- if (!this.telemetryEnabled) {
1504
- return { telemetryData: null, userId: null };
1505
- }
1506
- // Get userId from cache or fetch from API
1507
- let userId = null;
1508
- if (apifyToken) {
1509
- const apifyClient = new ApifyClient({ token: apifyToken });
1510
- ({ userId } = await getUserInfoCached(apifyToken, apifyClient));
1511
- log.debug('Telemetry: fetched userId', { userId, mcpSessionId });
1512
- }
1513
- const capabilities = (_b = (_a = this.options.initializeRequestData) === null || _a === void 0 ? void 0 : _a.params) === null || _b === void 0 ? void 0 : _b.capabilities;
1514
- const params = (_c = this.options.initializeRequestData) === null || _c === void 0 ? void 0 : _c.params;
1515
- const telemetryData = {
1516
- app: 'mcp',
1517
- app_version: getPackageVersion() || '',
1518
- mcp_client_name: ((_d = params === null || params === void 0 ? void 0 : params.clientInfo) === null || _d === void 0 ? void 0 : _d.name) || '',
1519
- mcp_client_version: ((_e = params === null || params === void 0 ? void 0 : params.clientInfo) === null || _e === void 0 ? void 0 : _e.version) || '',
1520
- mcp_protocol_version: (params === null || params === void 0 ? void 0 : params.protocolVersion) || '',
1521
- mcp_client_capabilities: capabilities || null,
1522
- mcp_session_id: mcpSessionId || '',
1523
- transport_type: this.options.transportType || '',
1524
- tool_name: toolName,
1525
- tool_status: TOOL_STATUS.SUCCEEDED, // Will be updated in finally
1526
- tool_exec_time_ms: 0, // Will be calculated in finally
1527
- };
1528
- return { telemetryData, userId };
1529
- }
1530
1181
  /**
1531
1182
  * Resolves widgets and determines which ones are ready to be served.
1532
1183
  */
@@ -1593,4 +1244,5 @@ export class ActorsMcpServer {
1593
1244
  await this.server.close();
1594
1245
  }
1595
1246
  }
1596
- //# sourceMappingURL=server.js.map
1247
+ //# sourceMappingURL=server.js.map
1248
+ //# debugId=b73a1497-d81a-5a2a-94ad-aff60a1cb69c