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

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.
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ import { randomUUID } from 'node:crypto';
8
8
  import { getUiCapability, RESOURCE_MIME_TYPE } from '@modelcontextprotocol/ext-apps/server';
9
9
  import { InMemoryTaskStore } from '@modelcontextprotocol/sdk/experimental/tasks/stores/in-memory.js';
10
10
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
- import { CallToolRequestSchema, CallToolResultSchema, CancelTaskRequestSchema, ErrorCode, GetPromptRequestSchema, GetTaskPayloadRequestSchema, GetTaskRequestSchema, InitializeRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListTasksRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, RELATED_TASK_META_KEY, ServerNotificationSchema, SetLevelRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
11
+ import { CallToolRequestSchema, CancelTaskRequestSchema, ErrorCode, GetPromptRequestSchema, GetTaskPayloadRequestSchema, GetTaskRequestSchema, InitializeRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ListTasksRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, RELATED_TASK_META_KEY, SetLevelRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
12
12
  import dedent from 'dedent';
13
13
  import log from '@apify/log';
14
14
  import { parseBooleanOrNull } from '@apify/utilities';
@@ -22,26 +22,24 @@ import { getServerInfo } from '../server_card.js';
22
22
  import { buildReportedProblemProperties, getTelemetryEnv, trackReportedProblem, trackToolCall } from '../telemetry.js';
23
23
  import { decodeDotPropertyNames } from '../tools/actor_input_schema.js';
24
24
  import { legacyToolNameToNew } from '../tools/actor_tool_naming.js';
25
- import { actorExecutor } from '../tools/actors/actor_executor.js';
26
25
  import { checkPaymentProviderStandbyConflict } from '../tools/actors/call_actor.js';
27
26
  import { appendReportProblemNudge } from '../tools/dev/report_problem.js';
28
27
  import { getActorsAsTools } from '../tools/index.js';
29
28
  import { SERVER_MODE, TOOL_TYPE } from '../types.js';
30
- import { remoteMcpFailureDetail } from '../utils/apify_errors.js';
31
29
  import { isMcpClientFaultMessage, logHttpError, sanitizeMezmoMessage } from '../utils/logging.js';
32
- import { computeToolResponseBytes, respondErrorNoTelemetry, respondOk } from '../utils/mcp.js';
30
+ import { computeToolResponseBytes, respondOk } from '../utils/mcp.js';
33
31
  import { isReportProblemBlockedForClient } from '../utils/mcp_clients.js';
34
32
  import { createProgressTracker } from '../utils/progress.js';
35
33
  import { getServerInstructions } from '../utils/server-instructions/index.js';
36
34
  import { parseServerMode, resolveServerMode } from '../utils/server_mode.js';
37
- import { applyToolTelemetry, classifyFailureCategory, deriveResourceIds, extractAjvErrorDetails, getToolStatusFromError, } from '../utils/tool_status.js';
35
+ import { deriveResourceIds, extractAjvErrorDetails } from '../utils/tool_status.js';
38
36
  import { buildActorFields, extractActorId, extractActorName, getToolFullName, getToolPublicFieldOnly, } from '../utils/tools.js';
39
37
  import { getActors, getToolsForServerMode, toolNamesToInput } from '../utils/tools_loader.js';
40
38
  import { getUserInfoCached } from '../utils/userid_cache.js';
41
39
  import { getPackageVersion } from '../utils/version.js';
42
- import { connectMCPClient } from './client.js';
43
- import { EXTERNAL_TOOL_CALL_TIMEOUT_MSEC, LOG_LEVEL_MAP } from './const.js';
40
+ import { LOG_LEVEL_MAP } from './const.js';
44
41
  import { buildToolCallErrorResult, TOOL_CALL_ERROR_KIND } from './tool_call_error_mapper.js';
42
+ import { dispatchToolCall } from './tool_dispatch.js';
45
43
  import { createTaskCancellationWatcher, isTaskCancelled, isTaskNotFoundError, parseInputParamsFromUrl, storeTaskResultOrSkipIfExpired, } from './utils.js';
46
44
  /**
47
45
  * Returns true when the initialize request advertises the MCP Apps UI extension
@@ -843,7 +841,7 @@ export class ActorsMcpServer {
843
841
  * @throws {McpError} - based on the McpServer class code from the typescript MCP SDK
844
842
  */
845
843
  this.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
846
- var _a, _b, _c, _d, _e, _f;
844
+ var _a, _b, _c, _d, _e;
847
845
  const params = request.params;
848
846
  // eslint-disable-next-line prefer-const
849
847
  let { name, arguments: args, _meta: meta } = params;
@@ -1090,152 +1088,34 @@ export class ActorsMcpServer {
1090
1088
  callDiagnostics = outcome.callDiagnostics;
1091
1089
  return captureResult(outcome.result);
1092
1090
  }
1093
- // Handle internal tool
1094
- if (tool.type === TOOL_TYPE.INTERNAL) {
1095
- // Tools that may emit notifications/progress during a sync wait must be opted in here.
1096
- // call-actor: emits during start+waitForFinish. get-actor-run: emits when waitSecs > 0.
1097
- const progressTrackerOptIn = tool.name === HELPER_TOOLS.ACTOR_CALL || tool.name === HELPER_TOOLS.ACTOR_RUNS_GET;
1098
- const progressTracker = progressTrackerOptIn
1099
- ? createProgressTracker(progressToken, extra.sendNotification)
1100
- : null;
1101
- try {
1102
- log.info('Calling internal tool', { toolName: tool.name, mcpSessionId, input: logSafeArgs });
1103
- const res = (await tool.call({
1104
- args: toolArgs,
1105
- extra,
1106
- apifyMcpServer: this,
1107
- mcpServer: this.server,
1108
- apifyToken,
1109
- apifyClient: apifyClient,
1110
- progressTracker,
1111
- mcpSessionId,
1112
- }));
1113
- // Extract diagnostics and strip internal fields from res before returning to client.
1114
- ({ toolStatus, callDiagnostics } = applyToolTelemetry(res, actorName, actorId, callDiagnostics));
1115
- return captureResult(res);
1116
- }
1117
- finally {
1118
- progressTracker === null || progressTracker === void 0 ? void 0 : progressTracker.stop();
1119
- }
1120
- }
1121
- if (tool.type === TOOL_TYPE.ACTOR_MCP) {
1122
- let client = null;
1123
- try {
1124
- client = await connectMCPClient(tool.serverUrl, apifyToken, mcpSessionId);
1125
- if (!client) {
1126
- const msg = dedent `
1127
- Failed to connect to MCP server at "${tool.serverUrl}".
1128
- Please verify the server URL is correct and accessible, and ensure you have a valid Apify token with appropriate permissions.
1129
- `;
1130
- log.softFail(msg, { mcpSessionId, failureCategory: FAILURE_CATEGORY.INTERNAL_ERROR });
1131
- await this.server.sendLoggingMessage({ level: 'error', data: msg });
1132
- toolStatus = TOOL_STATUS.SOFT_FAIL;
1133
- callDiagnostics = { ...callDiagnostics, failure_category: FAILURE_CATEGORY.INTERNAL_ERROR };
1134
- return captureResult(respondErrorNoTelemetry(msg));
1135
- }
1136
- // Only set up notification handlers if progressToken is provided by the client
1137
- if (progressToken !== undefined && progressToken !== null) {
1138
- // Set up notification handlers for the client
1139
- for (const schema of ServerNotificationSchema.options) {
1140
- const method = schema.shape.method.value;
1141
- // Forward notifications from the proxy client to the server
1142
- client.setNotificationHandler(schema, async (notification) => {
1143
- log.debug('Sending MCP notification', {
1144
- method,
1145
- mcpSessionId,
1146
- notification,
1147
- });
1148
- await extra.sendNotification(notification);
1149
- });
1150
- }
1151
- }
1152
- log.info('Calling Actor-MCP', {
1153
- toolName: tool.name,
1154
- actorMcpToolName: tool.originToolName,
1155
- actorId: tool.actorId,
1156
- mcpSessionId,
1157
- input: logSafeArgs,
1158
- });
1159
- const res = await client.callTool({
1160
- name: tool.originToolName,
1161
- arguments: toolArgs,
1162
- _meta: { progressToken },
1163
- }, CallToolResultSchema, {
1164
- timeout: EXTERNAL_TOOL_CALL_TIMEOUT_MSEC,
1165
- });
1166
- // TODO: actor-mcp responses are opaque — isError could be a user input problem
1167
- // (e.g. invalid query) or a genuine server failure. We can't distinguish without
1168
- // parsing the error text. Defaulting to INTERNAL_ERROR for now; revisit when
1169
- // actor-mcp gets deeper telemetry treatment.
1170
- if ('isError' in res && res.isError) {
1171
- toolStatus = TOOL_STATUS.SOFT_FAIL;
1172
- callDiagnostics = {
1173
- failure_category: FAILURE_CATEGORY.INTERNAL_ERROR,
1174
- ...buildActorFields(actorName, actorId),
1175
- };
1176
- }
1177
- return captureResult({ ...res });
1178
- }
1179
- catch (error) {
1180
- toolStatus = getToolStatusFromError(error, Boolean((_e = extra.signal) === null || _e === void 0 ? void 0 : _e.aborted));
1181
- const failureDetail = error instanceof Error ? error.message.slice(0, 200) : String(error).slice(0, 200);
1182
- callDiagnostics = {
1183
- failure_category: classifyFailureCategory(error),
1184
- failure_detail: failureDetail,
1185
- ...buildActorFields(actorName, actorId),
1186
- };
1187
- logHttpError(error, `Failed to call MCP tool '${tool.originToolName}' on Actor '${tool.actorId}'`, {
1188
- actorId: tool.actorId,
1189
- toolName: tool.originToolName,
1190
- failureCategory: callDiagnostics.failure_category,
1191
- });
1192
- return captureResult(respondErrorNoTelemetry(`Failed to call MCP tool '${tool.originToolName}' on Actor '${tool.actorId}': ${remoteMcpFailureDetail(error)}`));
1193
- }
1194
- finally {
1195
- if (client)
1196
- await client.close();
1197
- }
1198
- }
1199
- // Handle actor tool
1200
- if (tool.type === TOOL_TYPE.ACTOR) {
1201
- const progressTracker = createProgressTracker(progressToken, extra.sendNotification);
1202
- try {
1203
- log.info('Calling Actor', {
1204
- toolName: tool.name,
1205
- actorName: tool.actorFullName,
1206
- mcpSessionId,
1207
- input: logSafeArgs,
1208
- });
1209
- const executorResult = await actorExecutor.executeActorTool({
1210
- actorFullName: tool.actorFullName,
1211
- input: toolArgs,
1212
- apifyClient: apifyClient,
1213
- callOptions: { memory: tool.memoryMbytes },
1214
- progressTracker,
1215
- abortSignal: extra.signal,
1216
- mcpSessionId,
1217
- datasetItemsSchema: tool.datasetItemsSchema,
1218
- });
1219
- if (!executorResult) {
1220
- toolStatus = TOOL_STATUS.ABORTED;
1221
- // Receivers of cancellation notifications SHOULD NOT send a response for the cancelled request
1222
- // https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/cancellation#behavior-requirements
1223
- return captureResult({});
1224
- }
1225
- // Mirror the INTERNAL branch: read the telemetry the executor embedded on error
1226
- // results (e.g. respondUserError → SOFT_FAIL/INVALID_INPUT), strip it from the wire,
1227
- // and set failure_category so the report-problem nudge picks the softer variant.
1228
- ({ toolStatus, callDiagnostics } = applyToolTelemetry(executorResult, actorName, actorId, callDiagnostics));
1229
- return captureResult(executorResult);
1230
- }
1231
- finally {
1232
- if (progressTracker) {
1233
- progressTracker.stop();
1234
- }
1235
- }
1236
- }
1237
- // If we reached here without returning, it means the tool type was not recognized (user error)
1238
- toolStatus = TOOL_STATUS.SOFT_FAIL;
1091
+ // Progress tracker: opt in for the two INTERNAL tools that emit during a sync wait
1092
+ // (call-actor start+waitForFinish, get-actor-run when waitSecs > 0), and unconditionally
1093
+ // for ACTOR tools. ACTOR_MCP forwards notifications directly, not via a tracker.
1094
+ const progressTrackerOptIn = tool.type === TOOL_TYPE.ACTOR ||
1095
+ (tool.type === TOOL_TYPE.INTERNAL &&
1096
+ (tool.name === HELPER_TOOLS.ACTOR_CALL || tool.name === HELPER_TOOLS.ACTOR_RUNS_GET));
1097
+ const progressTracker = progressTrackerOptIn
1098
+ ? createProgressTracker(progressToken, extra.sendNotification)
1099
+ : null;
1100
+ const dispatchResult = await dispatchToolCall({
1101
+ tool,
1102
+ toolArgs: toolArgs,
1103
+ logSafeArgs,
1104
+ apifyToken,
1105
+ apifyClient: apifyClient,
1106
+ apifyMcpServer: this,
1107
+ mcpSessionId,
1108
+ progressToken,
1109
+ progressTracker,
1110
+ shouldForwardNotifications: true,
1111
+ extra,
1112
+ actorName,
1113
+ actorId,
1114
+ taskMode: false,
1115
+ });
1116
+ toolStatus = dispatchResult.toolStatus;
1117
+ callDiagnostics = dispatchResult.callDiagnostics;
1118
+ return captureResult(dispatchResult.result);
1239
1119
  }
1240
1120
  catch (error) {
1241
1121
  // Re-throw MCP protocol errors (e.g. from failInvalidParams) so the SDK
@@ -1244,8 +1124,8 @@ export class ActorsMcpServer {
1244
1124
  // Re-throwing first is order-equivalent only because no McpError with an HTTP-range
1245
1125
  // code reaches this catch: an McpError(402) WOULD satisfy the x402 predicate
1246
1126
  // (getHttpStatusCode falls through to `.code`), but every remote-McpError route is
1247
- // sealed by its own inner catch before reaching here, and all in-repo McpErrors use
1248
- // negative ErrorCode.* values.
1127
+ // sealed by an inner catch (ACTOR_MCP branch, call-actor MCP passthrough) and all
1128
+ // in-repo McpErrors use negative ErrorCode.* values.
1249
1129
  if (error instanceof McpError) {
1250
1130
  throw error;
1251
1131
  }
@@ -1253,7 +1133,7 @@ export class ActorsMcpServer {
1253
1133
  toolName: name,
1254
1134
  actorName,
1255
1135
  actorId,
1256
- isAborted: Boolean((_f = extra.signal) === null || _f === void 0 ? void 0 : _f.aborted),
1136
+ isAborted: Boolean((_e = extra.signal) === null || _e === void 0 ? void 0 : _e.aborted),
1257
1137
  });
1258
1138
  toolStatus = errorResult.toolStatus;
1259
1139
  // Propagate 402 Payment Required as a tool result per x402 MCP transport spec:
@@ -1316,18 +1196,6 @@ export class ActorsMcpServer {
1316
1196
  });
1317
1197
  }
1318
1198
  }
1319
- const availableTools = this.listToolNames();
1320
- const msg = dedent `
1321
- Unknown tool type for "${name}".
1322
- Available tools: ${availableTools.length > 0 ? availableTools.join(', ') : 'none'}.
1323
- Please verify the tool name and ensure the tool is properly registered.
1324
- `;
1325
- log.softFail(msg, { mcpSessionId, statusCode: 404 });
1326
- await this.server.sendLoggingMessage({
1327
- level: 'error',
1328
- data: msg,
1329
- });
1330
- throw new McpError(ErrorCode.InvalidParams, msg);
1331
1199
  });
1332
1200
  }
1333
1201
  /**
@@ -1379,7 +1247,7 @@ export class ActorsMcpServer {
1379
1247
  }
1380
1248
  }
1381
1249
  }
1382
- // TODO: this function quite duplicates the main tool call login the CallToolRequestSchema handler, we should refactor
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.
1383
1251
  /**
1384
1252
  * Executes a tool asynchronously for a long-running task and updates task status.
1385
1253
  *
@@ -1420,6 +1288,13 @@ export class ActorsMcpServer {
1420
1288
  result,
1421
1289
  });
1422
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
+ };
1423
1298
  // Once a task is cancelled the spec forbids writing a result; every storage path
1424
1299
  // must short-circuit here. `logSuffix` is concatenated after "Task was cancelled"
1425
1300
  // so we keep the existing log format and the existing telemetry status per path.
@@ -1472,77 +1347,32 @@ export class ActorsMcpServer {
1472
1347
  await this.taskStore.updateTaskStatus(taskId, 'working', message, mcpSessionId);
1473
1348
  await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1474
1349
  };
1475
- // Handle internal tool execution in task mode
1476
- if (toolStatus === TOOL_STATUS.SUCCEEDED && tool.type === TOOL_TYPE.INTERNAL) {
1477
- const progressTracker = createProgressTracker(progressToken, extra.sendNotification, taskId, onStatusMessage);
1478
- try {
1479
- log.info('Calling internal tool for task', {
1480
- taskId,
1481
- toolName: tool.name,
1482
- mcpSessionId,
1483
- input: logSafeArgs,
1484
- });
1485
- const res = (await tool.call({
1486
- args: toolArgs,
1487
- extra: taskExtra,
1488
- apifyMcpServer: this,
1489
- mcpServer: this.server,
1490
- apifyToken,
1491
- apifyClient,
1492
- progressTracker,
1493
- mcpSessionId,
1494
- taskMode: true,
1495
- }));
1496
- ({ toolStatus, callDiagnostics } = applyToolTelemetry(res, actorName, actorId, callDiagnostics));
1497
- result = res;
1498
- }
1499
- finally {
1500
- if (progressTracker) {
1501
- progressTracker.stop();
1502
- }
1503
- }
1504
- }
1505
- // Handle actor tool execution in task mode
1506
- if (toolStatus === TOOL_STATUS.SUCCEEDED && tool.type === TOOL_TYPE.ACTOR) {
1507
- const progressTracker = createProgressTracker(progressToken, extra.sendNotification, taskId, onStatusMessage);
1508
- try {
1509
- log.info('Calling Actor for task', {
1510
- taskId,
1511
- toolName: tool.name,
1512
- actorName: tool.actorFullName,
1513
- mcpSessionId,
1514
- input: logSafeArgs,
1515
- });
1516
- const executorResult = await actorExecutor.executeActorTool({
1517
- actorFullName: tool.actorFullName,
1518
- input: toolArgs,
1519
- apifyClient,
1520
- callOptions: { memory: tool.memoryMbytes },
1521
- progressTracker,
1522
- abortSignal: cancelWatcher.signal,
1523
- mcpSessionId,
1524
- datasetItemsSchema: tool.datasetItemsSchema,
1525
- taskMode: true,
1526
- });
1527
- if (!executorResult) {
1528
- toolStatus = TOOL_STATUS.ABORTED;
1529
- // Receivers of cancellation notifications SHOULD NOT send a response for the cancelled request
1530
- // https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/cancellation#behavior-requirements
1531
- result = {};
1532
- }
1533
- else {
1534
- // Mirror the INTERNAL task branch: extract embedded telemetry so failure_category
1535
- // drives the success-path nudge below and toolTelemetry is stripped from the wire.
1536
- ({ toolStatus, callDiagnostics } = applyToolTelemetry(executorResult, actorName, actorId, callDiagnostics));
1537
- result = executorResult;
1538
- }
1539
- }
1540
- finally {
1541
- if (progressTracker) {
1542
- progressTracker.stop();
1543
- }
1544
- }
1545
- }
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;
1546
1376
  // Check if task was cancelled before storing result
1547
1377
  if (await skipIfTaskCancelled(', skipping result storage', toolStatus))
1548
1378
  return;
@@ -1554,10 +1384,8 @@ export class ActorsMcpServer {
1554
1384
  taskId,
1555
1385
  mcpSessionId,
1556
1386
  });
1557
- await storeTaskResultOrSkipIfExpired(this.taskStore, tool.name, taskId, 'completed', result, mcpSessionId);
1387
+ await completeTask('completed', result, toolStatus, callDiagnostics);
1558
1388
  log.debug('Task completed successfully', { taskId, toolName: tool.name, mcpSessionId });
1559
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1560
- finishTaskTracking(toolStatus, callDiagnostics, result);
1561
1389
  }
1562
1390
  catch (error) {
1563
1391
  // Reached only when the task expired before the `working` transition (updateTaskStatus
@@ -1591,9 +1419,7 @@ export class ActorsMcpServer {
1591
1419
  ...buildActorFields(actorName, actorId),
1592
1420
  }))
1593
1421
  return;
1594
- await storeTaskResultOrSkipIfExpired(this.taskStore, tool.name, taskId, 'completed', errorResult.response, mcpSessionId);
1595
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1596
- finishTaskTracking(errorResult.toolStatus, errorResult.callDiagnostics, errorResult.response);
1422
+ await completeTask('completed', errorResult.response, errorResult.toolStatus, errorResult.callDiagnostics);
1597
1423
  return;
1598
1424
  }
1599
1425
  if (errorResult.kind === TOOL_CALL_ERROR_KIND.APPROVAL) {
@@ -1606,9 +1432,7 @@ export class ActorsMcpServer {
1606
1432
  ...buildActorFields(actorName, actorId),
1607
1433
  }))
1608
1434
  return;
1609
- await storeTaskResultOrSkipIfExpired(this.taskStore, tool.name, taskId, 'completed', errorResult.response, mcpSessionId);
1610
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1611
- finishTaskTracking(errorResult.toolStatus, errorResult.callDiagnostics, errorResult.response);
1435
+ await completeTask('completed', errorResult.response, errorResult.toolStatus, errorResult.callDiagnostics);
1612
1436
  return;
1613
1437
  }
1614
1438
  toolStatus = errorResult.toolStatus;
@@ -1650,10 +1474,11 @@ export class ActorsMcpServer {
1650
1474
  taskId,
1651
1475
  mcpSessionId,
1652
1476
  });
1653
- // Nudge on a genuinely-failed task result. INTERNAL_ERROR and an unknown category get the
1654
- // full nudge; a genuine INVALID_INPUT gets the softer nudge; payment (402) is suppressed via
1655
- // the HTTP status and AUTH / PERMISSION_APPROVAL_REQUIRED via NON_NUDGE_FAILURE_CATEGORIES.
1656
- // The 402 branch above returns before reaching here, so this only sees non-payment failures.
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.
1657
1482
  const failedResult = this.withReportProblemNudge({
1658
1483
  content: [
1659
1484
  {
@@ -1664,9 +1489,7 @@ export class ActorsMcpServer {
1664
1489
  isError: true,
1665
1490
  internalToolStatus: toolStatus,
1666
1491
  }, tool.name, callDiagnostics.failure_category, callDiagnostics.failure_http_status);
1667
- await storeTaskResultOrSkipIfExpired(this.taskStore, tool.name, taskId, 'failed', failedResult, mcpSessionId);
1668
- await emitTaskStatusNotification(taskId, mcpSessionId, this.taskStore, this.server);
1669
- finishTaskTracking(toolStatus, callDiagnostics, failedResult);
1492
+ await completeTask('failed', failedResult, toolStatus, callDiagnostics);
1670
1493
  }
1671
1494
  finally {
1672
1495
  cancelWatcher.dispose();