@taskforcehq/taskforce 0.3.329 → 0.3.330

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 (321) hide show
  1. package/dist/Taskforce.module.css +290 -45
  2. package/dist/components/features/AiProfilesModule.js +3 -5
  3. package/dist/components/features/TaskSettings.js +70 -14
  4. package/dist/components/features/TaskforceAgentsModule.d.ts +1 -2
  5. package/dist/components/features/TaskforceAgentsModule.js +586 -116
  6. package/dist/components/features/agentConnections/AgentConnectionControl.d.ts +15 -0
  7. package/dist/components/features/agentConnections/AgentConnectionControl.js +125 -0
  8. package/dist/components/features/agentConnections/ModelConnectionsPanel.d.ts +18 -0
  9. package/dist/components/features/agentConnections/ModelConnectionsPanel.js +393 -0
  10. package/dist/components/features/agentConnections/modelConnectionsApi.d.ts +65 -0
  11. package/dist/components/features/agentConnections/modelConnectionsApi.js +129 -0
  12. package/dist/components/features/taskforceAgentAssignments/AgentBehaviorAssignments.js +15 -24
  13. package/dist/components/features/taskforceAgentEditorModel.d.ts +2 -1
  14. package/dist/components/features/taskforceAgentEditorModel.js +3 -1
  15. package/dist/components/features/workflowManager/workflowManagerApi.d.ts +1 -1
  16. package/dist/components/features/workflowManager/workflowManagerApi.js +3 -0
  17. package/dist/components/task/TaskWorkflowAssignmentField.js +68 -10
  18. package/dist/components/views/StandaloneLayout.js +27 -26
  19. package/dist/components/views/standalone/modals/SyncStatusModal.d.ts +4 -3
  20. package/dist/components/views/standalone/modals/SyncStatusModal.js +33 -38
  21. package/dist/config/envSchema.js +48 -1
  22. package/dist/core/McpTokenService.d.ts +23 -1
  23. package/dist/core/McpTokenService.js +93 -10
  24. package/dist/core/TaskChecklistCommandService.d.ts +27 -0
  25. package/dist/core/TaskChecklistCommandService.js +83 -5
  26. package/dist/core/TaskLifecycleCommandService.d.ts +3 -1
  27. package/dist/core/TaskLifecycleCommandService.js +6 -2
  28. package/dist/core/Taskforce.d.ts +32 -0
  29. package/dist/core/Taskforce.js +125 -4
  30. package/dist/core/types.d.ts +8 -0
  31. package/dist/documentReviews/commandService.d.ts +2 -1
  32. package/dist/documentReviews/commandService.js +6 -3
  33. package/dist/hooks/sync/orchestratorShared.d.ts +1 -0
  34. package/dist/hooks/sync/orchestratorShared.js +2 -0
  35. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.d.ts +3 -0
  36. package/dist/hooks/sync/useLocalSyncCoordinatorSnapshot.js +85 -9
  37. package/dist/hooks/sync/useSyncStatusControls.d.ts +4 -1
  38. package/dist/hooks/sync/useSyncStatusControls.js +47 -11
  39. package/dist/hooks/useSyncOrchestrator.d.ts +3 -0
  40. package/dist/hooks/useSyncOrchestrator.js +111 -2
  41. package/dist/hooks/useTaskData.d.ts +31 -1
  42. package/dist/hooks/useTaskData.js +29 -7
  43. package/dist/hooks/useTaskMutations.d.ts +3 -1
  44. package/dist/hooks/useTaskMutations.js +46 -12
  45. package/dist/hooks/useTaskforce.d.ts +2 -0
  46. package/dist/hooks/useTaskforce.js +11 -2
  47. package/dist/mcp/clientRegistry.d.ts +2 -2
  48. package/dist/mcp/clientRegistry.js +1 -1
  49. package/dist/mcp/documentAssetRegistrar.js +9 -6
  50. package/dist/mcp/durableTaskMutationRouter.d.ts +4 -1
  51. package/dist/mcp/durableTaskMutationRouter.js +10 -0
  52. package/dist/mcp/durableTaskRelationshipMutationRouter.js +4 -0
  53. package/dist/mcp/httpProtocolRouting.d.ts +10 -0
  54. package/dist/mcp/httpProtocolRouting.js +19 -0
  55. package/dist/mcp/localCliHealth.d.ts +2 -2
  56. package/dist/mcp/localCliHealth.js +2 -2
  57. package/dist/mcp/localServiceProxy.d.ts +1 -0
  58. package/dist/mcp/localServiceProxy.js +530 -68
  59. package/dist/mcp/planningAttachmentCommandAdapter.d.ts +3 -1
  60. package/dist/mcp/planningAttachmentCommandAdapter.js +20 -2
  61. package/dist/mcp/runtime.d.ts +54 -79
  62. package/dist/mcp/runtime.js +384 -97
  63. package/dist/mcp/taskPlanningRegistrar.js +23 -4
  64. package/dist/mcp/toolProfiles.d.ts +2 -0
  65. package/dist/mcp/toolProfiles.js +10 -0
  66. package/dist/mcp/toolRegistry.d.ts +1 -0
  67. package/dist/mcp/toolRegistry.js +1 -0
  68. package/dist/mcp/workflowExecutionRegistrar.js +4 -4
  69. package/dist/migrations/taskSchemaMigrations.d.ts +5 -0
  70. package/dist/migrations/taskSchemaMigrations.js +415 -0
  71. package/dist/runtime/appGates.d.ts +2 -1
  72. package/dist/runtime/appGates.js +7 -0
  73. package/dist/server/index.d.ts +3 -0
  74. package/dist/server/index.js +108 -11
  75. package/dist/server/localDatabaseIdentity.js +4 -1
  76. package/dist/server/localServiceLease.js +2 -1
  77. package/dist/server/localServiceSessions.d.ts +14 -17
  78. package/dist/server/localServiceSessions.js +308 -94
  79. package/dist/server/localWorkspaceSyncServerRuntime.js +12 -14
  80. package/dist/server/routes/admin.d.ts +4 -0
  81. package/dist/server/routes/admin.js +112 -3
  82. package/dist/server/routes/agents.d.ts +7 -0
  83. package/dist/server/routes/agents.js +277 -24
  84. package/dist/server/routes/billing.js +5 -1
  85. package/dist/server/routes/durableTaskHttpRouters.d.ts +2 -0
  86. package/dist/server/routes/executorPhaseAApprovals.d.ts +19 -0
  87. package/dist/server/routes/executorPhaseAApprovals.js +140 -0
  88. package/dist/server/routes/executorPhaseAIssuerRedemptions.d.ts +11 -0
  89. package/dist/server/routes/executorPhaseAIssuerRedemptions.js +24 -0
  90. package/dist/server/routes/githubReviewEvidence.d.ts +19 -0
  91. package/dist/server/routes/githubReviewEvidence.js +116 -0
  92. package/dist/server/routes/localService.d.ts +15 -4
  93. package/dist/server/routes/localService.js +136 -40
  94. package/dist/server/routes/modelConnections.d.ts +24 -0
  95. package/dist/server/routes/modelConnections.js +205 -0
  96. package/dist/server/routes/shared.d.ts +19 -0
  97. package/dist/server/routes/shared.js +95 -19
  98. package/dist/server/routes/sync.js +1 -0
  99. package/dist/server/routes/syncAuxRoutes.js +5 -1
  100. package/dist/server/routes/syncPushRoutes.d.ts +1 -0
  101. package/dist/server/routes/syncPushRoutes.js +1 -0
  102. package/dist/server/routes/syncV3FeedRoutes.js +10 -1
  103. package/dist/server/routes/syncV3OperationRoutes.js +35 -9
  104. package/dist/server/routes/tasks.js +21 -2
  105. package/dist/server/routes/workflows.js +9 -1
  106. package/dist/server/routes.js +59 -0
  107. package/dist/services/codexAppServerModelGateway.d.ts +54 -5
  108. package/dist/services/codexAppServerModelGateway.js +246 -21
  109. package/dist/services/codexDeviceCodeLoginManager.d.ts +39 -0
  110. package/dist/services/codexDeviceCodeLoginManager.js +265 -0
  111. package/dist/services/codexModelProviderConnectionLifecycle.d.ts +8 -0
  112. package/dist/services/codexModelProviderConnectionLifecycle.js +73 -0
  113. package/dist/services/executorPhaseAApprovalRuntime.d.ts +14 -0
  114. package/dist/services/executorPhaseAApprovalRuntime.js +24 -0
  115. package/dist/services/executorPhaseAApprovalService.d.ts +40 -0
  116. package/dist/services/executorPhaseAApprovalService.js +609 -0
  117. package/dist/services/executorPhaseADriftEvaluator.d.ts +78 -0
  118. package/dist/services/executorPhaseADriftEvaluator.js +93 -0
  119. package/dist/services/executorPhaseAIssuerCore.d.ts +126 -0
  120. package/dist/services/executorPhaseAIssuerCore.js +295 -0
  121. package/dist/services/executorPhaseAIssuerRedemptionService.d.ts +34 -0
  122. package/dist/services/executorPhaseAIssuerRedemptionService.js +158 -0
  123. package/dist/services/githubReviewEvidenceRuntime.d.ts +14 -0
  124. package/dist/services/githubReviewEvidenceRuntime.js +30 -0
  125. package/dist/services/githubReviewEvidenceService.d.ts +93 -0
  126. package/dist/services/githubReviewEvidenceService.js +336 -0
  127. package/dist/services/modelGateway.d.ts +7 -0
  128. package/dist/services/modelProviderConnectionService.d.ts +71 -0
  129. package/dist/services/modelProviderConnectionService.js +279 -0
  130. package/dist/services/modelProviderCredentialHome.d.ts +32 -0
  131. package/dist/services/modelProviderCredentialHome.js +271 -0
  132. package/dist/services/ownerScopedModelConnectionGateway.d.ts +12 -0
  133. package/dist/services/ownerScopedModelConnectionGateway.js +30 -0
  134. package/dist/services/taskforceAgentConnectionBindingService.d.ts +66 -0
  135. package/dist/services/taskforceAgentConnectionBindingService.js +185 -0
  136. package/dist/services/taskforceAgentMcpBridge.d.ts +1 -1
  137. package/dist/services/taskforceAgentMcpBridge.js +7 -24
  138. package/dist/shared/adminEdgeProxy.d.ts +5 -0
  139. package/dist/shared/adminEdgeProxy.js +94 -0
  140. package/dist/shared/adminProxySessionCookies.d.ts +16 -0
  141. package/dist/shared/adminProxySessionCookies.js +86 -0
  142. package/dist/shared/aiProfileColors.d.ts +31 -1
  143. package/dist/shared/aiProfileColors.js +14 -6
  144. package/dist/shared/executorPhaseAApprovalGoldenVector.json +269 -0
  145. package/dist/shared/executorPhaseAApprovalReceipt.d.ts +112 -0
  146. package/dist/shared/executorPhaseAApprovalReceipt.js +58 -0
  147. package/dist/shared/executorPhaseAApprovalTrustPolicy.json +10 -0
  148. package/dist/shared/executorPhaseADriftContracts.d.ts +37 -0
  149. package/dist/shared/executorPhaseADriftContracts.js +63 -0
  150. package/dist/shared/executorPhaseAIssuerContracts.d.ts +75 -0
  151. package/dist/shared/executorPhaseAIssuerContracts.js +90 -0
  152. package/dist/shared/executorPhaseARunAuthorization.d.ts +120 -0
  153. package/dist/shared/executorPhaseARunAuthorization.js +232 -0
  154. package/dist/shared/executorPhaseASchemaValidation.d.ts +7 -0
  155. package/dist/shared/executorPhaseASchemaValidation.js +53 -0
  156. package/dist/shared/executorPhaseASchemas/approval-receipt.schema.json +106 -0
  157. package/dist/shared/executorPhaseASchemas/drift-attestation.schema.json +54 -0
  158. package/dist/shared/executorPhaseASchemas/drift-request.schema.json +47 -0
  159. package/dist/shared/executorPhaseASchemas/foundation-manifest.schema.json +29 -0
  160. package/dist/shared/executorPhaseASchemas/issuer-audit-record.schema.json +24 -0
  161. package/dist/shared/executorPhaseASchemas/issuer-proof.schema.json +43 -0
  162. package/dist/shared/executorPhaseASchemas/issuer-redemption-request.schema.json +18 -0
  163. package/dist/shared/executorPhaseASchemas/issuer-redemption-response.schema.json +39 -0
  164. package/dist/shared/executorPhaseASchemas/logical-envelope.schema.json +149 -0
  165. package/dist/shared/executorPhaseASchemas/preflight-report.schema.json +216 -0
  166. package/dist/shared/executorPhaseASchemas/run-capability.schema.json +111 -0
  167. package/dist/shared/executorPhaseASchemas/sender-proof.schema.json +37 -0
  168. package/dist/shared/executorPhaseASchemas/workload-grant.schema.json +68 -0
  169. package/dist/shared/executorPhaseASchemas/workload-jwt-claims.schema.json +67 -0
  170. package/dist/shared/executorPhaseATiming.d.ts +1 -0
  171. package/dist/shared/executorPhaseATiming.js +1 -0
  172. package/dist/shared/planningIdentity.js +1 -1
  173. package/dist/shared/productLogoKeys.d.ts +2 -0
  174. package/dist/shared/productLogoKeys.js +18 -0
  175. package/dist/shared/taskforceAgentDefinition.d.ts +0 -1
  176. package/dist/shared/taskforceAgentDefinition.js +6 -9
  177. package/dist/shared/taskforceAgentModels.js +7 -3
  178. package/dist/shared/userFeatureGrants.d.ts +4 -0
  179. package/dist/shared/userFeatureGrants.js +7 -0
  180. package/dist/storage/executorPhaseAApprovalReceiptStore.d.ts +37 -0
  181. package/dist/storage/executorPhaseAApprovalReceiptStore.js +81 -0
  182. package/dist/storage/executorPhaseARunAuthorizationStore.d.ts +103 -0
  183. package/dist/storage/executorPhaseARunAuthorizationStore.js +492 -0
  184. package/dist/storage/githubReviewEvidenceInstallationStore.d.ts +26 -0
  185. package/dist/storage/githubReviewEvidenceInstallationStore.js +89 -0
  186. package/dist/storage/modelProviderConnectionStore.d.ts +99 -0
  187. package/dist/storage/modelProviderConnectionStore.js +446 -0
  188. package/dist/storage/postgresAdapter.d.ts +4 -0
  189. package/dist/storage/postgresAdapter.js +11 -0
  190. package/dist/storage/postgresWorker.js +9 -1
  191. package/dist/storage/postgresWorkerProtocol.d.ts +1 -0
  192. package/dist/storage/taskforceAgentConnectionBindingStore.d.ts +31 -0
  193. package/dist/storage/taskforceAgentConnectionBindingStore.js +84 -0
  194. package/dist/sync/coordinator/localSyncExecutionPermitStore.js +60 -29
  195. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.d.ts +10 -0
  196. package/dist/sync/coordinator/localWorkspaceSyncPendingV2PushProgress.js +29 -0
  197. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.d.ts +15 -1
  198. package/dist/sync/coordinator/localWorkspaceSyncRunnerState.js +99 -2
  199. package/dist/sync/coordinator/workspaceSyncCredentialBroker.d.ts +1 -0
  200. package/dist/sync/coordinator/workspaceSyncCredentialBroker.js +33 -4
  201. package/dist/sync/engine/workspaceSyncContentLifecycleAdapter.d.ts +2 -1
  202. package/dist/sync/engine/workspaceSyncContentVersionStore.d.ts +38 -0
  203. package/dist/sync/engine/workspaceSyncContentVersionStore.js +50 -1
  204. package/dist/sync/engine/workspaceSyncEngineLifecyclePolicy.js +6 -6
  205. package/dist/sync/engine/workspaceSyncEnginePushCompletion.d.ts +14 -0
  206. package/dist/sync/engine/workspaceSyncEnginePushCompletion.js +84 -0
  207. package/dist/sync/engine/workspaceSyncEngineRecovery.js +1 -0
  208. package/dist/sync/engine/workspaceSyncEngineRuntime.d.ts +1 -0
  209. package/dist/sync/engine/workspaceSyncEngineRuntime.js +1 -0
  210. package/dist/sync/engine/workspaceSyncEngineServerRunnerOperations.js +112 -38
  211. package/dist/sync/engine/workspaceSyncEngineServerSnapshotReader.js +6 -0
  212. package/dist/sync/engine/workspaceSyncEngineTransfers.js +3 -1
  213. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.d.ts +1 -0
  214. package/dist/sync/engine/workspaceSyncV2ChangeDispatcher.js +29 -0
  215. package/dist/sync/syncApplyHandlers.d.ts +2 -0
  216. package/dist/sync/syncApplyHandlers.js +10 -1
  217. package/dist/sync/syncService.d.ts +15 -0
  218. package/dist/sync/syncService.js +83 -18
  219. package/dist/sync/taskforceAgentSyncAuthorization.d.ts +16 -0
  220. package/dist/sync/taskforceAgentSyncAuthorization.js +20 -0
  221. package/dist/sync/v3/combinedFeedCapability.js +4 -0
  222. package/dist/sync/v3/durableInitiativeMutationRouter.js +18 -10
  223. package/dist/sync/v3/durableOperationReplay.d.ts +14 -0
  224. package/dist/sync/v3/durableOperationReplay.js +18 -0
  225. package/dist/sync/v3/durableTaskAttachmentLinksMutationRouter.js +3 -0
  226. package/dist/sync/v3/durableTaskChecklistMutationRouter.d.ts +2 -1
  227. package/dist/sync/v3/durableTaskChecklistMutationRouter.js +58 -15
  228. package/dist/sync/v3/durableTaskCommentMutationRouter.js +3 -0
  229. package/dist/sync/v3/durableTaskHttpRootMutationRouter.d.ts +1 -1
  230. package/dist/sync/v3/durableTaskHttpRootMutationRouter.js +10 -0
  231. package/dist/sync/v3/durableTaxonomyMutationRouter.js +5 -0
  232. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.d.ts +11 -0
  233. package/dist/sync/v3/durableWorkflowRuntimeMutationRouter.js +39 -10
  234. package/dist/sync/v3/durableWorkstreamMutationRouter.js +18 -10
  235. package/dist/sync/v3/durableWorkstreamTaskOrderMutationRouter.js +16 -5
  236. package/dist/sync/v3/localOutboxDispatchRuntime.js +2 -2
  237. package/dist/sync/v3/localTaskChecklistOutboxHandler.js +16 -2
  238. package/dist/sync/v3/localTaskChecklistOutboxService.d.ts +4 -0
  239. package/dist/sync/v3/localTaskChecklistOutboxService.js +14 -1
  240. package/dist/sync/v3/localTaskStatusOutboxService.d.ts +8 -0
  241. package/dist/sync/v3/localTaskStatusOutboxService.js +219 -12
  242. package/dist/sync/v3/syncDurabilityStore.d.ts +34 -0
  243. package/dist/sync/v3/syncDurabilityStore.js +168 -2
  244. package/dist/sync/v3/taskChecklistMutationService.d.ts +11 -0
  245. package/dist/sync/v3/taskChecklistMutationService.js +44 -1
  246. package/dist/sync/v3/taskStatusMutationService.d.ts +29 -1
  247. package/dist/sync/v3/taskStatusMutationService.js +119 -3
  248. package/dist/sync/v3/workflowAssignmentSync.d.ts +5 -0
  249. package/dist/sync/v3/workflowAssignmentSync.js +27 -0
  250. package/dist/sync/v3/workspaceSyncJournalReader.js +1 -1
  251. package/dist/sync/v3/workspaceSyncOperationRetentionService.d.ts +16 -0
  252. package/dist/sync/v3/workspaceSyncOperationRetentionService.js +83 -0
  253. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.d.ts +1 -0
  254. package/dist/sync/v3/workspaceSyncV3CloudOperationHandler.js +9 -2
  255. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.d.ts +7 -0
  256. package/dist/sync/v3/workspaceSyncV3CombinedRepairBaseline.js +44 -32
  257. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.d.ts +9 -5
  258. package/dist/sync/v3/workspaceSyncV3CombinedRepairMaterialization.js +54 -38
  259. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.d.ts +10 -0
  260. package/dist/sync/v3/workspaceSyncV3CombinedRepairSnapshot.js +70 -31
  261. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.d.ts +2 -1
  262. package/dist/sync/v3/workspaceSyncV3CombinedWireContract.js +16 -0
  263. package/dist/sync/v3/workspaceSyncV3CoverageRegistry.js +6 -0
  264. package/dist/sync/v3/workspaceSyncV3OperationProtocol.d.ts +3 -0
  265. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.d.ts +5 -0
  266. package/dist/sync/v3/workspaceSyncV3OperatorDiagnostics.js +36 -2
  267. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.d.ts +17 -0
  268. package/dist/sync/v3/workspaceSyncV3RepairSnapshotRetentionService.js +64 -0
  269. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.d.ts +7 -0
  270. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverCoverage.js +33 -0
  271. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.d.ts +7 -0
  272. package/dist/sync/v3/workspaceSyncV3WorkflowTaskCoverWireContract.js +8 -0
  273. package/dist/sync/workspaceRepair.d.ts +5 -2
  274. package/dist/sync/workspaceRepair.js +161 -6
  275. package/dist/sync/workspaceSyncModel.d.ts +21 -0
  276. package/dist/sync/workspaceSyncModel.js +35 -7
  277. package/dist/sync/workspaceSyncState.d.ts +1 -0
  278. package/dist/sync/workspaceSyncV2SnapshotBuilder.d.ts +6 -0
  279. package/dist/sync/workspaceSyncV2SnapshotBuilder.js +5 -0
  280. package/dist/ui/assets/AiIdentityRosterCard-OcSz1PkK.js +1 -0
  281. package/dist/ui/assets/AiProfilesModule-ByhYW5Xi.js +1 -0
  282. package/dist/ui/assets/{AnnotatedAttachmentWorkspace-B68Wg-RV.js → AnnotatedAttachmentWorkspace-BTM6nIg_.js} +1 -1
  283. package/dist/ui/assets/{AssetTraySortControl-C8Rztyal.js → AssetTraySortControl-DabEG8L4.js} +1 -1
  284. package/dist/ui/assets/{ContextAttachmentManager-Cj3c7X9y.js → ContextAttachmentManager-Coa8yVGM.js} +1 -1
  285. package/dist/ui/assets/{DocumentWorkspace-B5uvzems.js → DocumentWorkspace-BB0qhdix.js} +1 -1
  286. package/dist/ui/assets/{EntityActivityTimeline-BVFvCB5R.js → EntityActivityTimeline-CZ8x4UJE.js} +1 -1
  287. package/dist/ui/assets/{PlanningModule-B5DWQOGz.js → PlanningModule-pRPjR7v5.js} +1 -1
  288. package/dist/ui/assets/{PlansPage-AY4cGWco.js → PlansPage-D86pZSSl.js} +1 -1
  289. package/dist/ui/assets/{TaskContextUpload-DZxTVesW.js → TaskContextUpload-BVIkU9yT.js} +1 -1
  290. package/dist/ui/assets/TaskSettings-Cv1mNhv_.js +12 -0
  291. package/dist/ui/assets/TaskforceAgentsModule-b-8R25cJ.css +1 -0
  292. package/dist/ui/assets/TaskforceAgentsModule-gmH-PD2q.js +24 -0
  293. package/dist/ui/assets/{WorkflowManagerModule-DEr5di_r.js → WorkflowManagerModule-DbfnHJ-f.js} +1 -1
  294. package/dist/ui/assets/index-BZ-hdZSk.css +1 -0
  295. package/dist/ui/assets/index-CTsDBaef.js +7 -0
  296. package/dist/ui/assets/{vendor-icons-D9Lpw-j4.js → vendor-icons-Bsq-mcEn.js} +1 -1
  297. package/dist/ui/branding/logos/letterhead_dark.png +0 -0
  298. package/dist/ui/branding/logos/letterhead_light.png +0 -0
  299. package/dist/ui/branding/logos/signature_dark.png +0 -0
  300. package/dist/ui/branding/logos/signature_light.png +0 -0
  301. package/dist/ui/index.html +3 -3
  302. package/dist/utils/aiProfileDefaultLogo.js +16 -48
  303. package/dist/utils/httpSetCookie.d.ts +1 -0
  304. package/dist/utils/httpSetCookie.js +4 -1
  305. package/dist/utils/localRuntimeUrl.d.ts +1 -0
  306. package/dist/utils/localRuntimeUrl.js +14 -0
  307. package/dist/utils/productLogoRegistry.d.ts +2 -0
  308. package/dist/utils/productLogoRegistry.js +36 -0
  309. package/dist/utils/syncStatusPresentation.d.ts +4 -0
  310. package/dist/utils/syncStatusPresentation.js +17 -0
  311. package/dist/utils/taskEvents.d.ts +2 -0
  312. package/dist/utils/workspaceSyncPresentation.d.ts +1 -1
  313. package/dist/utils/workspaceSyncPresentation.js +23 -17
  314. package/package.json +22 -4
  315. package/dist/ui/assets/AiIdentityRosterCard-BZM4aQnM.js +0 -1
  316. package/dist/ui/assets/AiProfilesModule-BbAEWtHH.js +0 -1
  317. package/dist/ui/assets/TaskSettings-BeWAuyZj.js +0 -12
  318. package/dist/ui/assets/TaskforceAgentsModule-BifCYtjR.js +0 -21
  319. package/dist/ui/assets/TaskforceAgentsModule-D6IC0S7Q.css +0 -1
  320. package/dist/ui/assets/index-I5zhdtgt.js +0 -7
  321. package/dist/ui/assets/index-VRFsx3wz.css +0 -1
@@ -1,6 +1,5 @@
1
- import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { CallToolRequestSchema, ListResourceTemplatesRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
1
+ import { Server } from '@modelcontextprotocol/server';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/server/stdio';
4
3
  import * as fs from 'fs';
5
4
  import * as path from 'path';
6
5
  import { createHash, randomUUID } from 'node:crypto';
@@ -80,7 +79,7 @@ import { createDurableTaskChecklistMutationRouter, DurableTaskChecklistRouterInP
80
79
  import { DurableTaskChecklistMutationError } from '../sync/v3/taskChecklistMutationService.js';
81
80
  import { createDurableTaskAttachmentLinksMutationRouter, DurableTaskAttachmentLinksRouterInProgressError, } from '../sync/v3/durableTaskAttachmentLinksMutationRouter.js';
82
81
  import { DurableTaskAttachmentLinksMutationError } from '../sync/v3/taskAttachmentLinksMutationService.js';
83
- import { createDurableWorkflowRuntimeMutationRouter, resolveWorkflowRuntimeMutationCapability, } from '../sync/v3/durableWorkflowRuntimeMutationRouter.js';
82
+ import { areWorkflowRuntimeMutationsFenced, createDurableWorkflowRuntimeMutationRouter, resolveWorkflowRuntimeMutationCapability, } from '../sync/v3/durableWorkflowRuntimeMutationRouter.js';
84
83
  import { serializeCanonicalPlanningAttachmentLinks } from '../sync/planningCanonicalFields.js';
85
84
  import { buildCanonicalTaxonomyStateMutation, } from '../sync/v3/taxonomyStateMutation.js';
86
85
  import { buildTaskDeepLink, buildTaskforceDeepLink, normalizeTaskforceApplicationBaseUrl, } from '../shared/taskDeepLinks.js';
@@ -747,6 +746,9 @@ function createOwnedTaskforceMcpCore(projectRoot, tenantId, localDataOwnerPermit
747
746
  },
748
747
  });
749
748
  }
749
+ export function createStatelessTaskforceMcpServer(options = {}, factory = createTaskforceMcpServer) {
750
+ return factory({ ...options, resourceSubscriptionMode: 'disabled' });
751
+ }
750
752
  export function createTaskforceMcpServer(options = {}) {
751
753
  // In dev (tsx), this module lives in src/mcp/.
752
754
  // In prod, it lives in dist/mcp/.
@@ -754,6 +756,9 @@ export function createTaskforceMcpServer(options = {}) {
754
756
  const PROJECT_NAME = path.basename(PROJECT_ROOT);
755
757
  const logStartup = options.logStartup !== false;
756
758
  const runtimeMode = options.runtimeMode === 'cloud' ? 'cloud' : 'local';
759
+ const modernProtocol = options.protocolEra === 'modern';
760
+ const supportsLegacyResourceSubscriptions = !modernProtocol
761
+ && options.resourceSubscriptionMode === 'legacy-long-lived';
757
762
  const applicationBaseUrl = normalizeTaskforceApplicationBaseUrl(options.applicationBaseUrl)
758
763
  || (runtimeMode === 'cloud'
759
764
  ? resolveCloudApplicationBaseUrl()
@@ -836,8 +841,6 @@ export function createTaskforceMcpServer(options = {}) {
836
841
  };
837
842
  const operationIdentityScope = options.operationIdentityScope
838
843
  ? {
839
- generation: String(options.operationIdentityScope.generation || '').trim(),
840
- sessionId: String(options.operationIdentityScope.sessionId || '').trim(),
841
844
  connectionInstance: String(options.operationIdentityScope.connectionInstance || '').trim(),
842
845
  }
843
846
  : null;
@@ -845,7 +848,7 @@ export function createTaskforceMcpServer(options = {}) {
845
848
  throw new Error('Shared MCP operation identity scope is incomplete.');
846
849
  }
847
850
  const runtimeRequestNamespace = operationIdentityScope
848
- ? fingerprintWorkspaceSyncPayload({ kind: 'shared-mcp-session', ...operationIdentityScope })
851
+ ? fingerprintWorkspaceSyncPayload({ kind: 'shared-mcp-process', ...operationIdentityScope })
849
852
  : runtimeMode === 'cloud'
850
853
  ? String(options.auth?.requestId || '').trim() || randomUUID()
851
854
  : randomUUID();
@@ -1204,8 +1207,8 @@ export function createTaskforceMcpServer(options = {}) {
1204
1207
  }, {
1205
1208
  capabilities: {
1206
1209
  resources: {
1207
- subscribe: true,
1208
- listChanged: true,
1210
+ ...(supportsLegacyResourceSubscriptions ? { subscribe: true } : {}),
1211
+ ...(!modernProtocol ? { listChanged: true } : {}),
1209
1212
  },
1210
1213
  tools: {},
1211
1214
  },
@@ -2225,42 +2228,38 @@ export function createTaskforceMcpServer(options = {}) {
2225
2228
  return null;
2226
2229
  return resolved;
2227
2230
  }
2228
- function resolveFinishTaskReviewer(task) {
2231
+ function resolveFinishTaskReviewer(task, reviewer) {
2232
+ if (reviewer !== undefined) {
2233
+ const resolvedReviewer = resolveRuntimeTaskAssigneeInput(reviewer);
2234
+ const actor = resolvedReviewer
2235
+ ? core.resolveWorkspaceActor(ACTIVE_WORKSPACE_ID, resolvedReviewer)
2236
+ : null;
2237
+ const eligible = actor?.kind === 'ai'
2238
+ ? core.listAiProfiles(ACTIVE_WORKSPACE_ID).some((profile) => profile.id === actor.id)
2239
+ : core.listWorkspaceUsers(ACTIVE_WORKSPACE_ID).some((user) => (user.userId === actor?.id
2240
+ && String(user.status || '').trim().toLowerCase() === 'active'
2241
+ && user.disabled !== true));
2242
+ if (!actor || actor.meta?.unresolved === true || !eligible) {
2243
+ throw new McpPublicError('reviewer must identify an active human or AI assignee in the current workspace. Call list_assignees and retry with an assignee ID.', 'MCP_REVIEWER_INVALID');
2244
+ }
2245
+ return { assignee: actor.id, source: 'explicit' };
2246
+ }
2229
2247
  const existingAssignee = String(task?.assignee || '').trim();
2230
2248
  if (existingAssignee) {
2231
2249
  const existingActor = core.resolveWorkspaceActor(ACTIVE_WORKSPACE_ID, existingAssignee);
2232
- if (existingActor?.kind === 'human' && existingActor.meta?.unresolved !== true) {
2250
+ const eligibleExistingHuman = existingActor?.kind === 'human'
2251
+ && existingActor.meta?.unresolved !== true
2252
+ && core.listWorkspaceUsers(ACTIVE_WORKSPACE_ID).some((user) => (user.userId === existingActor.id
2253
+ && String(user.status || '').trim().toLowerCase() === 'active'
2254
+ && user.disabled !== true));
2255
+ if (eligibleExistingHuman) {
2233
2256
  return {
2234
2257
  assignee: existingActor.id,
2235
2258
  source: 'existing_human_owner',
2236
2259
  };
2237
2260
  }
2238
2261
  }
2239
- if (runtimeMode === 'cloud' && auditActorUserId !== 'anonymous') {
2240
- const currentUser = core.listWorkspaceUsers(ACTIVE_WORKSPACE_ID)
2241
- .find((user) => user.userId === auditActorUserId
2242
- && String(user.status || '').trim().toLowerCase() === 'active'
2243
- && user.disabled !== true);
2244
- if (currentUser) {
2245
- return { assignee: currentUser.userId, source: 'current_user' };
2246
- }
2247
- }
2248
- const workspaceOwner = core.listWorkspaceUsers(ACTIVE_WORKSPACE_ID)
2249
- .filter((user) => String(user.status || '').trim().toLowerCase() === 'active' && user.disabled !== true)
2250
- .sort((left, right) => {
2251
- const leftRank = left.role === 'owner' ? 0 : left.role === 'admin' ? 1 : 2;
2252
- const rightRank = right.role === 'owner' ? 0 : right.role === 'admin' ? 1 : 2;
2253
- if (leftRank !== rightRank)
2254
- return leftRank - rightRank;
2255
- return String(left.displayName || left.email || left.userId).localeCompare(String(right.displayName || right.email || right.userId), undefined, { sensitivity: 'base' });
2256
- })[0];
2257
- if (workspaceOwner && (workspaceOwner.role === 'owner' || workspaceOwner.role === 'admin')) {
2258
- return {
2259
- assignee: workspaceOwner.userId,
2260
- source: 'workspace_owner',
2261
- };
2262
- }
2263
- throw new McpPublicError('Could not resolve a human reviewer for review handoff. Resolve a current human user, set a human owner on the task, or ensure the workspace has an active owner/admin.', 'MCP_REVIEWER_REQUIRED');
2262
+ throw new McpPublicError('Review handoff requires an explicit reviewer when the task has no eligible existing human reviewer. Call list_assignees and retry finish_task with reviewer set to a human or AI assignee ID.', 'MCP_REVIEWER_REQUIRED');
2264
2263
  }
2265
2264
  function getActiveMcpActorRef() {
2266
2265
  if (activeAiProfileId)
@@ -2301,13 +2300,19 @@ export function createTaskforceMcpServer(options = {}) {
2301
2300
  }).task;
2302
2301
  }
2303
2302
  if (!useStatusBoundary) {
2304
- return core.updateTask(input.task.id, input.updates, ACTIVE_WORKSPACE_ID, { actorRef: getActiveMcpActorRef() });
2303
+ return core.updateTask(input.task.id, input.updates, ACTIVE_WORKSPACE_ID, {
2304
+ actorRef: getActiveMcpActorRef(),
2305
+ ...(input.deferNotifications ? { persistBackup: false, emitRealtime: false } : {}),
2306
+ });
2305
2307
  }
2306
2308
  const unsupported = Object.keys(input.updates).filter((field) => (!durableStatusControlFields.has(field) && !durableTaskMetadataFieldNames.has(field)));
2307
2309
  if (unsupported.length > 0) {
2308
2310
  throw new TaskforceRuleError(`Combined durable task status update contains unsupported fields: ${unsupported.sort().join(', ')}.`, 400, 'TASK_STATUS_INVALID_PAYLOAD');
2309
2311
  }
2310
2312
  const status = String(hasStatus ? input.updates.status : input.task.status || 'task').trim();
2313
+ if (status === 'review' && String(input.task.status || '').trim() !== 'review' && !input.reviewHandoff) {
2314
+ throw new McpPublicError('Moving a task to review requires finish_task with a nonblank evidence comment.', 'TASK_REVIEW_HANDOFF_REQUIRED', 400);
2315
+ }
2311
2316
  const metadataPatch = selectDurableTaskMetadataPatch(input.updates);
2312
2317
  delete metadataPatch.assignee;
2313
2318
  const assigneeIntent = input.assigneeIntent || (Object.prototype.hasOwnProperty.call(input.updates, 'assignee')
@@ -2322,10 +2327,73 @@ export function createTaskforceMcpServer(options = {}) {
2322
2327
  : null;
2323
2328
  return durableTaskMutationRouter.setStatus({
2324
2329
  taskId: input.task.id,
2325
- payload: { status, assigneeIntent, canceledReason, metadataPatch },
2330
+ payload: {
2331
+ status,
2332
+ assigneeIntent,
2333
+ canceledReason,
2334
+ metadataPatch,
2335
+ ...(input.reviewHandoff ? { reviewHandoff: input.reviewHandoff } : {}),
2336
+ },
2326
2337
  actorRef: getActiveMcpActorRef(),
2327
2338
  }).task;
2328
2339
  }
2340
+ function mutateTaskReviewHandoffThroughBoundary(input) {
2341
+ const validation = validateStructuredCommentForAdd(input.handoffComment);
2342
+ if (!validation.ok)
2343
+ throw new McpPublicError(validation.message);
2344
+ const actorRef = getActiveMcpActorRef();
2345
+ const operationId = requireStableMcpRequestId('operation', `review-handoff-comment:${input.task.id}`);
2346
+ const commentId = requireStableMcpRequestId('comment', `review-handoff:${input.task.id}`);
2347
+ const comment = {
2348
+ id: commentId,
2349
+ author: actorRef,
2350
+ submittedAuthor: actorRef,
2351
+ text: input.handoffComment,
2352
+ };
2353
+ if (durableTaskMutationRouter.enabled) {
2354
+ return mutateTaskThroughStatusBoundary({
2355
+ task: input.task,
2356
+ updates: input.updates,
2357
+ assigneeIntent: input.assigneeIntent,
2358
+ reviewHandoff: { comment },
2359
+ });
2360
+ }
2361
+ let updated;
2362
+ try {
2363
+ updated = core.getDatabaseAdapter().transaction(() => {
2364
+ mutateTaskThroughStatusBoundary({
2365
+ task: input.task,
2366
+ updates: input.updates,
2367
+ assigneeIntent: input.assigneeIntent,
2368
+ deferNotifications: true,
2369
+ });
2370
+ const durableRouter = getDurableTaskCommentMutationRouter(actorRef, operationId);
2371
+ const task = durableRouter.enabled
2372
+ ? durableRouter.append({
2373
+ taskId: input.task.id,
2374
+ comment: { ...comment, timestamp: new Date().toISOString() },
2375
+ }).task
2376
+ : core.addComment(input.task.id, input.handoffComment, actorRef, ACTIVE_WORKSPACE_ID, {
2377
+ actorRef,
2378
+ persistBackup: false,
2379
+ emitRealtime: false,
2380
+ commentId,
2381
+ });
2382
+ if (!task)
2383
+ throw new Error(`Task ${input.task.id} not found`);
2384
+ return task;
2385
+ })();
2386
+ }
2387
+ catch (error) {
2388
+ try {
2389
+ core.notifyDurableTaskMetadataCommitted(ACTIVE_WORKSPACE_ID, input.task.id);
2390
+ }
2391
+ catch { /* Preserve the original handoff failure. */ }
2392
+ throw error;
2393
+ }
2394
+ core.notifyDurableTaskMetadataCommitted(ACTIVE_WORKSPACE_ID, input.task.id);
2395
+ return updated;
2396
+ }
2329
2397
  function mutateTaskLifecycleThroughBoundary(input) {
2330
2398
  if (!durableTaskMutationRouter.enabled)
2331
2399
  return input.legacy();
@@ -3706,7 +3774,7 @@ export function createTaskforceMcpServer(options = {}) {
3706
3774
  const hydratedWorkstream = core.getWorkstream(workstream.id, ACTIVE_WORKSPACE_ID) || workstream;
3707
3775
  return { id: hydratedWorkstream.id, workstream: hydratedWorkstream };
3708
3776
  }
3709
- server.setRequestHandler(ListResourcesRequestSchema, async () => {
3777
+ server.setRequestHandler('resources/list', async () => {
3710
3778
  const resources = [
3711
3779
  {
3712
3780
  uri: RESOURCE_CONFIG_URI,
@@ -3753,7 +3821,7 @@ export function createTaskforceMcpServer(options = {}) {
3753
3821
  resources,
3754
3822
  };
3755
3823
  });
3756
- server.setRequestHandler(ListResourceTemplatesRequestSchema, async () => {
3824
+ server.setRequestHandler('resources/templates/list', async () => {
3757
3825
  if (!hasPermission(RESOURCE_PERMISSIONS.task)) {
3758
3826
  return { resourceTemplates: [] };
3759
3827
  }
@@ -3785,7 +3853,7 @@ export function createTaskforceMcpServer(options = {}) {
3785
3853
  ],
3786
3854
  };
3787
3855
  });
3788
- server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
3856
+ server.setRequestHandler('resources/read', async (request) => {
3789
3857
  const uri = request.params.uri;
3790
3858
  assertResourcePermission(uri);
3791
3859
  if (uri === RESOURCE_CONFIG_URI) {
@@ -3891,24 +3959,26 @@ export function createTaskforceMcpServer(options = {}) {
3891
3959
  }
3892
3960
  throw new Error(`Unknown resource URI: ${uri}`);
3893
3961
  });
3894
- server.setRequestHandler(SubscribeRequestSchema, async (request) => {
3895
- const uri = request.params.uri;
3896
- if (!isSupportedResourceUri(uri)) {
3897
- throw new Error(`Unsupported resource URI for subscribe: ${uri}`);
3898
- }
3899
- assertResourcePermission(uri);
3900
- resourceSubscriptions.add(uri);
3901
- return {};
3902
- });
3903
- server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
3904
- const uri = request.params.uri;
3905
- if (!isSupportedResourceUri(uri)) {
3906
- throw new Error(`Unsupported resource URI for unsubscribe: ${uri}`);
3907
- }
3908
- assertResourcePermission(uri);
3909
- resourceSubscriptions.delete(uri);
3910
- return {};
3911
- });
3962
+ if (supportsLegacyResourceSubscriptions) {
3963
+ server.setRequestHandler('resources/subscribe', async (request) => {
3964
+ const uri = request.params.uri;
3965
+ if (!isSupportedResourceUri(uri)) {
3966
+ throw new Error(`Unsupported resource URI for subscribe: ${uri}`);
3967
+ }
3968
+ assertResourcePermission(uri);
3969
+ resourceSubscriptions.add(uri);
3970
+ return {};
3971
+ });
3972
+ server.setRequestHandler('resources/unsubscribe', async (request) => {
3973
+ const uri = request.params.uri;
3974
+ if (!isSupportedResourceUri(uri)) {
3975
+ throw new Error(`Unsupported resource URI for unsubscribe: ${uri}`);
3976
+ }
3977
+ assertResourcePermission(uri);
3978
+ resourceSubscriptions.delete(uri);
3979
+ return {};
3980
+ });
3981
+ }
3912
3982
  /**
3913
3983
  * Tool Definitions
3914
3984
  */
@@ -4024,16 +4094,19 @@ export function createTaskforceMcpServer(options = {}) {
4024
4094
  const tool = registeredTools.find((candidate) => candidate.name === name);
4025
4095
  return tool ? materializeToolDescriptor(tool, buildToolDescriptorContext()) : null;
4026
4096
  };
4027
- server.setRequestHandler(ListToolsRequestSchema, async () => {
4097
+ const listTools = async () => {
4028
4098
  const context = buildToolDescriptorContext();
4029
4099
  const tools = registeredTools
4030
4100
  .map((tool) => materializeToolDescriptor(tool, context))
4031
4101
  .filter((tool) => (isMcpToolVisibleInProfile(tool.name, activeToolProfile)
4032
4102
  && hasPermission(TOOL_PERMISSIONS[tool.name])));
4033
4103
  return {
4034
- tools,
4104
+ // Descriptors are validated by Taskforce's JSON Schema contract before
4105
+ // registration; v2 narrows the equivalent recursive JSON value type.
4106
+ tools: tools,
4035
4107
  };
4036
- });
4108
+ };
4109
+ server.setRequestHandler('tools/list', listTools);
4037
4110
  const resolvePlanningAttachmentTarget = (targetType, inputId) => {
4038
4111
  if (targetType === 'initiative') {
4039
4112
  const { id, initiative } = resolveInitiativeByIdentifierOrThrow(inputId);
@@ -4953,7 +5026,9 @@ export function createTaskforceMcpServer(options = {}) {
4953
5026
  const taskLifecycleCommandService = createTaskLifecycleCommandService({
4954
5027
  formatTaskIdentifier,
4955
5028
  resolveAssigneeLabel: (assignee) => core.resolveWorkspaceActor(ACTIVE_WORKSPACE_ID, assignee)?.label || assignee,
4956
- setStatus: (input) => mutateTaskThroughStatusBoundary(input),
5029
+ setStatus: (input) => input.handoffComment
5030
+ ? mutateTaskReviewHandoffThroughBoundary(input)
5031
+ : mutateTaskThroughStatusBoundary(input),
4957
5032
  mutateLifecycle: (input) => mutateTaskLifecycleThroughBoundary({
4958
5033
  taskId: input.taskId,
4959
5034
  mutationKind: input.mutationKind,
@@ -4973,7 +5048,7 @@ export function createTaskforceMcpServer(options = {}) {
4973
5048
  });
4974
5049
  },
4975
5050
  }),
4976
- resolveReviewer: (task) => resolveFinishTaskReviewer(task),
5051
+ resolveReviewer: (task, reviewer) => resolveFinishTaskReviewer(task, reviewer),
4977
5052
  });
4978
5053
  const planningCommandPreparationService = new PlanningCommandPreparationService({
4979
5054
  resolveOwner: resolvePlanningOwnerInput,
@@ -4986,12 +5061,17 @@ export function createTaskforceMcpServer(options = {}) {
4986
5061
  listItems: (taskId) => core.listChecklistItems(taskId, ACTIVE_WORKSPACE_ID),
4987
5062
  createId: (scope, key) => requireStableMcpRequestId(scope, key),
4988
5063
  now: () => new Date().toISOString(),
4989
- replace: ({ taskId, items, operationId }) => {
5064
+ replace: ({ taskId, items, operationId, expectedDetailRevision, requireDurableIdempotency, itemUpdateIntent, }) => {
4990
5065
  const actorRef = getActiveMcpActorRef();
4991
5066
  const durableRouter = getDurableTaskChecklistMutationRouter(actorRef, operationId);
5067
+ if (requireDurableIdempotency) {
5068
+ requireDurableExplicitIdempotency(durableRouter.enabled, 'task checklist');
5069
+ }
4992
5070
  return durableRouter.enabled
4993
- ? durableRouter.replace({ taskId, items }).task
4994
- : core.updateTask(taskId, { checklistItems: items }, ACTIVE_WORKSPACE_ID, { actorRef });
5071
+ ? durableRouter.replace({ taskId, items, expectedDetailRevision, itemUpdateIntent }).task
5072
+ : expectedDetailRevision
5073
+ ? core.updateTaskIfDetailRevisionMatches(taskId, expectedDetailRevision, { checklistItems: items }, ACTIVE_WORKSPACE_ID, { actorRef })
5074
+ : core.updateTask(taskId, { checklistItems: items }, ACTIVE_WORKSPACE_ID, { actorRef });
4995
5075
  },
4996
5076
  });
4997
5077
  const annotatedAttachmentCommandService = createAnnotatedAttachmentCommandService({
@@ -5014,7 +5094,7 @@ export function createTaskforceMcpServer(options = {}) {
5014
5094
  }
5015
5095
  function rethrowChecklistCommandError(error) {
5016
5096
  if (error instanceof TaskChecklistCommandError) {
5017
- if (error.code === 'TASK_NOT_FOUND') {
5097
+ if (error.code === 'TASK_NOT_FOUND' || error.code === 'TASK_CHECKLIST_ITEM_NOT_FOUND') {
5018
5098
  throw new McpPublicError(error.message, 'MCP_NOT_FOUND', error.statusCode);
5019
5099
  }
5020
5100
  throw new McpPublicError(error.message);
@@ -5455,6 +5535,9 @@ export function createTaskforceMcpServer(options = {}) {
5455
5535
  requiresCommentEvidence: step.requiresCommentEvidence,
5456
5536
  } : {}),
5457
5537
  }));
5538
+ const currentStep = assignment.execution.status === 'running'
5539
+ ? assignment.steps.find((step) => step.id === assignment.execution.currentStepId)
5540
+ : undefined;
5458
5541
  return {
5459
5542
  content: [{ type: 'text', text: JSON.stringify({
5460
5543
  task: withTaskUrl({ id: task.id, referenceLabel: formatTaskIdentifier(task), title: task.title }),
@@ -5466,11 +5549,23 @@ export function createTaskforceMcpServer(options = {}) {
5466
5549
  currentStepId: assignment.execution.currentStepId || null,
5467
5550
  steps,
5468
5551
  },
5552
+ completionCall: currentStep ? {
5553
+ tool: 'complete_workflow_step',
5554
+ arguments: {
5555
+ taskId,
5556
+ executionId: assignment.execution.id,
5557
+ stepId: currentStep.id,
5558
+ },
5559
+ } : null,
5469
5560
  }, null, 2) }],
5470
5561
  };
5471
5562
  }
5472
5563
  case "complete_workflow_step": {
5473
5564
  const { taskId, executionId, stepId, evidenceCommentId } = args;
5565
+ const normalizedEvidenceCommentId = evidenceCommentId == null ? undefined : evidenceCommentId;
5566
+ if (areWorkflowRuntimeMutationsFenced()) {
5567
+ throw new McpPublicError('Workflow execution changes are temporarily paused.', 'WORKFLOW_RUNTIME_MUTATIONS_FENCED', 503);
5568
+ }
5474
5569
  const { task } = resolveTaskByIdentifierOrThrow(taskId);
5475
5570
  ensureResolvedProfileForSessionBootstrap();
5476
5571
  const agentProfileId = String(activeAiProfileId || '').trim();
@@ -5483,7 +5578,7 @@ export function createTaskforceMcpServer(options = {}) {
5483
5578
  throw new McpPublicError('The workflow execution does not belong to this task.', 'WORKFLOW_TASK_MISMATCH', 409);
5484
5579
  }
5485
5580
  const idempotencyKey = `agent-step-${createHash('sha256')
5486
- .update(`${executionId}:${stepId}:${agentProfileId}:${String(evidenceCommentId || '')}`)
5581
+ .update(`${executionId}:${stepId}:${agentProfileId}:${String(normalizedEvidenceCommentId || '')}`)
5487
5582
  .digest('hex')
5488
5583
  .slice(0, 32)}`;
5489
5584
  let result;
@@ -5505,7 +5600,7 @@ export function createTaskforceMcpServer(options = {}) {
5505
5600
  }).completeStep({
5506
5601
  executionId,
5507
5602
  expectedStepId: stepId,
5508
- evidenceCommentId,
5603
+ evidenceCommentId: normalizedEvidenceCommentId,
5509
5604
  })
5510
5605
  : executionService.completeCurrentStep({
5511
5606
  workspaceId: ACTIVE_WORKSPACE_ID,
@@ -5513,7 +5608,7 @@ export function createTaskforceMcpServer(options = {}) {
5513
5608
  actorId: agentProfileId,
5514
5609
  actorType: 'agent',
5515
5610
  expectedStepId: stepId,
5516
- evidenceCommentId,
5611
+ evidenceCommentId: normalizedEvidenceCommentId,
5517
5612
  idempotencyKey,
5518
5613
  });
5519
5614
  }
@@ -6170,12 +6265,14 @@ export function createTaskforceMcpServer(options = {}) {
6170
6265
  const { taskId } = args;
6171
6266
  const { id: resolvedTaskId } = resolveTaskByIdentifierOrThrow(taskId);
6172
6267
  const checklist = core.listChecklistItems(resolvedTaskId, ACTIVE_WORKSPACE_ID);
6268
+ const detailRevision = core.getTaskDetailRevision(resolvedTaskId, ACTIVE_WORKSPACE_ID);
6173
6269
  return {
6174
6270
  content: [{
6175
6271
  type: "text",
6176
6272
  text: JSON.stringify({
6177
6273
  taskId: resolvedTaskId,
6178
6274
  ...(buildTaskUrl({ id: resolvedTaskId }) ? { url: buildTaskUrl({ id: resolvedTaskId }) } : {}),
6275
+ detailRevision,
6179
6276
  items: checklist,
6180
6277
  }, null, 2),
6181
6278
  }],
@@ -6245,6 +6342,49 @@ export function createTaskforceMcpServer(options = {}) {
6245
6342
  }],
6246
6343
  };
6247
6344
  }
6345
+ case "update_task_checklist_item": {
6346
+ const { taskId, itemId, text, done, order, expectedDetailRevision, idempotencyKey: rawIdempotencyKey, } = args;
6347
+ const idempotencyKey = normalizeExplicitIdempotencyKey(rawIdempotencyKey);
6348
+ const operationId = idempotencyKey
6349
+ ? stableExplicitMutationId('operation', 'update_task_checklist_item', idempotencyKey)
6350
+ : requireStableMcpRequestId('operation', 'task-checklist-update');
6351
+ let result;
6352
+ try {
6353
+ result = taskChecklistCommandService.update({
6354
+ taskId,
6355
+ itemId,
6356
+ text,
6357
+ done,
6358
+ order,
6359
+ expectedDetailRevision,
6360
+ operationId,
6361
+ requireDurableIdempotency: Boolean(idempotencyKey),
6362
+ });
6363
+ }
6364
+ catch (error) {
6365
+ rethrowChecklistCommandError(error);
6366
+ }
6367
+ const detailRevision = core.getTaskDetailRevision(result.taskId, ACTIVE_WORKSPACE_ID);
6368
+ recordMcpWriteAudit('update_task_checklist_item', {
6369
+ taskId: result.taskId,
6370
+ itemId: result.item.id,
6371
+ });
6372
+ await notifyResourceMutation({
6373
+ includeTasks: true,
6374
+ taskIds: [result.taskId],
6375
+ });
6376
+ return {
6377
+ content: [{
6378
+ type: "text",
6379
+ text: JSON.stringify({
6380
+ taskId: result.taskId,
6381
+ ...(buildTaskUrl({ id: result.taskId }) ? { url: buildTaskUrl({ id: result.taskId }) } : {}),
6382
+ detailRevision,
6383
+ item: result.item,
6384
+ }, null, 2),
6385
+ }],
6386
+ };
6387
+ }
6248
6388
  case "get_task_attachments": {
6249
6389
  const { id, taskId, attachmentId } = args;
6250
6390
  const taskIdentifier = taskId ?? id;
@@ -6978,14 +7118,40 @@ export function createTaskforceMcpServer(options = {}) {
6978
7118
  };
6979
7119
  }
6980
7120
  case "review_document": {
6981
- const { id, documentId, sessionId, title, comments, prompt } = args;
7121
+ const { id, documentId, sessionId, title, comments, prompt, parentCommentId, threadCommentId, threadStatus, } = args;
6982
7122
  const asset = resolveDocumentAssetByIdentifierOrThrow(documentId ?? id);
6983
7123
  const normalizedComments = Array.isArray(comments)
6984
7124
  ? comments
6985
7125
  : (typeof prompt === 'string' && prompt.trim()
6986
7126
  ? [{ body: prompt.trim() }]
6987
7127
  : []);
6988
- if (normalizedComments.length === 0) {
7128
+ const normalizedSessionId = typeof sessionId === 'string' ? sessionId.trim() : '';
7129
+ const normalizedParentCommentId = typeof parentCommentId === 'string' ? parentCommentId.trim() : '';
7130
+ const normalizedThreadCommentId = typeof threadCommentId === 'string' ? threadCommentId.trim() : '';
7131
+ const hasThreadStatus = threadStatus !== undefined;
7132
+ const hasThreadUpdate = Boolean(normalizedThreadCommentId) || hasThreadStatus;
7133
+ const hasCommentsArgument = Object.prototype.hasOwnProperty.call(args, 'comments');
7134
+ const hasPromptArgument = Object.prototype.hasOwnProperty.call(args, 'prompt');
7135
+ const hasTitleArgument = Object.prototype.hasOwnProperty.call(args, 'title');
7136
+ if (hasThreadUpdate && (!normalizedThreadCommentId || (threadStatus !== 'open' && threadStatus !== 'resolved'))) {
7137
+ throw new McpPublicError('threadCommentId and threadStatus are required together');
7138
+ }
7139
+ if ((normalizedParentCommentId || hasThreadUpdate) && !normalizedSessionId) {
7140
+ throw new McpPublicError('sessionId is required for reply and thread-status updates');
7141
+ }
7142
+ if (hasThreadUpdate && (normalizedParentCommentId || hasCommentsArgument || hasPromptArgument || hasTitleArgument)) {
7143
+ throw new McpPublicError('Thread-status updates cannot be combined with comments, replies, or a session title');
7144
+ }
7145
+ if (normalizedParentCommentId && hasTitleArgument) {
7146
+ throw new McpPublicError('Replies cannot set a session title');
7147
+ }
7148
+ if (hasCommentsArgument && hasPromptArgument) {
7149
+ throw new McpPublicError('comments and prompt cannot be combined');
7150
+ }
7151
+ if (normalizedParentCommentId && normalizedComments.length !== 1) {
7152
+ throw new McpPublicError('Replies require exactly one comment or prompt');
7153
+ }
7154
+ if (!hasThreadUpdate && normalizedComments.length === 0) {
6989
7155
  throw new McpPublicError('comments array is required');
6990
7156
  }
6991
7157
  for (const comment of normalizedComments) {
@@ -6997,13 +7163,115 @@ export function createTaskforceMcpServer(options = {}) {
6997
7163
  throw new McpPublicError(anchorError);
6998
7164
  }
6999
7165
  }
7166
+ if (normalizedParentCommentId && normalizedComments[0]?.anchor !== undefined && normalizedComments[0]?.anchor !== null) {
7167
+ throw new McpPublicError('Replies cannot have anchors');
7168
+ }
7169
+ if (hasThreadUpdate) {
7170
+ const existingSession = core.getDocumentReviewSession({
7171
+ workspaceId: ACTIVE_WORKSPACE_ID,
7172
+ sessionId: normalizedSessionId,
7173
+ });
7174
+ if (!existingSession) {
7175
+ throw new McpPublicError(`Document review session ${normalizedSessionId} not found.`, 'MCP_NOT_FOUND', 404);
7176
+ }
7177
+ if (existingSession.assetId !== asset.assetId) {
7178
+ throw new McpPublicError(`Document review session ${normalizedSessionId} is not linked to document ${getDocumentReferenceLabel(asset) || asset.assetId}.`, 'MCP_ATTACHMENT_CONFLICT', 409);
7179
+ }
7180
+ const updatedSession = core.updateDocumentReviewThreadStatus({
7181
+ workspaceId: ACTIVE_WORKSPACE_ID,
7182
+ sessionId: normalizedSessionId,
7183
+ commentId: normalizedThreadCommentId,
7184
+ status: threadStatus,
7185
+ actorId: getActiveMcpActorRef(),
7186
+ });
7187
+ const updatedThread = updatedSession.comments.find((entry) => entry.id === normalizedThreadCommentId) || null;
7188
+ const sessionSummary = buildDocumentReviewSessionSummary(updatedSession);
7189
+ recordMcpWriteAudit('review_document', {
7190
+ documentAssetId: asset.assetId,
7191
+ sessionId: updatedSession.id,
7192
+ sessionAction: 'reused',
7193
+ threadCommentId: normalizedThreadCommentId,
7194
+ threadStatus,
7195
+ });
7196
+ return {
7197
+ content: [{
7198
+ type: 'text',
7199
+ text: JSON.stringify({
7200
+ document: {
7201
+ assetId: asset.assetId,
7202
+ referenceLabel: getDocumentReferenceLabel(asset),
7203
+ },
7204
+ sessionId: updatedSession.id,
7205
+ sessionAction: 'reused',
7206
+ postedCommentIds: [],
7207
+ commentCount: 0,
7208
+ thread: buildCompactDocumentReviewComment(updatedThread),
7209
+ unresolvedThreadCount: sessionSummary.unresolvedThreadCount,
7210
+ nextTool: 'get_document_reviews',
7211
+ suggestedArgs: {
7212
+ documentId: getDocumentReferenceLabel(asset) || asset.assetId,
7213
+ sessionId: updatedSession.id,
7214
+ },
7215
+ }, null, 2),
7216
+ }],
7217
+ };
7218
+ }
7219
+ if (normalizedParentCommentId) {
7220
+ const existingSession = core.getDocumentReviewSession({
7221
+ workspaceId: ACTIVE_WORKSPACE_ID,
7222
+ sessionId: normalizedSessionId,
7223
+ });
7224
+ if (!existingSession) {
7225
+ throw new McpPublicError(`Document review session ${normalizedSessionId} not found.`, 'MCP_NOT_FOUND', 404);
7226
+ }
7227
+ if (existingSession.assetId !== asset.assetId) {
7228
+ throw new McpPublicError(`Document review session ${normalizedSessionId} is not linked to document ${getDocumentReferenceLabel(asset) || asset.assetId}.`, 'MCP_ATTACHMENT_CONFLICT', 409);
7229
+ }
7230
+ const repliedSession = core.addDocumentReviewReply({
7231
+ workspaceId: ACTIVE_WORKSPACE_ID,
7232
+ sessionId: normalizedSessionId,
7233
+ parentCommentId: normalizedParentCommentId,
7234
+ body: normalizedComments[0].body,
7235
+ actorId: getActiveMcpActorRef(),
7236
+ });
7237
+ const postedReply = repliedSession.comments.at(-1) || null;
7238
+ recordMcpWriteAudit('review_document', {
7239
+ documentAssetId: asset.assetId,
7240
+ sessionId: repliedSession.id,
7241
+ sessionAction: 'reused',
7242
+ parentCommentId: normalizedParentCommentId,
7243
+ commentCount: 1,
7244
+ });
7245
+ return {
7246
+ content: [{
7247
+ type: 'text',
7248
+ text: JSON.stringify({
7249
+ document: {
7250
+ assetId: asset.assetId,
7251
+ referenceLabel: getDocumentReferenceLabel(asset),
7252
+ },
7253
+ sessionId: repliedSession.id,
7254
+ sessionAction: 'reused',
7255
+ postedCommentIds: postedReply ? [postedReply.id] : [],
7256
+ commentCount: postedReply ? 1 : 0,
7257
+ reply: buildCompactDocumentReviewComment(postedReply),
7258
+ nextTool: 'get_document_reviews',
7259
+ suggestedArgs: {
7260
+ documentId: getDocumentReferenceLabel(asset) || asset.assetId,
7261
+ sessionId: repliedSession.id,
7262
+ },
7263
+ }, null, 2),
7264
+ }],
7265
+ };
7266
+ }
7000
7267
  let commandResult;
7001
7268
  try {
7002
7269
  commandResult = documentReviewCommandService.review({
7003
7270
  workspaceId: ACTIVE_WORKSPACE_ID,
7004
7271
  assetId: asset.assetId,
7272
+ documentVersion: asset.version,
7005
7273
  documentLabel: getDocumentReferenceLabel(asset) || asset.assetId,
7006
- sessionId: sessionId && typeof sessionId === 'string' ? sessionId : null,
7274
+ sessionId: normalizedSessionId || null,
7007
7275
  title: typeof title === 'string' ? title : null,
7008
7276
  comments: normalizedComments,
7009
7277
  actorId: getActiveMcpActorRef(),
@@ -7029,6 +7297,7 @@ export function createTaskforceMcpServer(options = {}) {
7029
7297
  },
7030
7298
  sessionId: currentSession.id,
7031
7299
  sessionAction,
7300
+ documentVersion: currentSession.documentVersion,
7032
7301
  postedCommentIds,
7033
7302
  commentCount: postedCommentIds.length,
7034
7303
  nextTool: 'get_document_reviews',
@@ -7353,13 +7622,6 @@ export function createTaskforceMcpServer(options = {}) {
7353
7622
  actorRef: getActiveMcpActorRef(),
7354
7623
  provisionalLocalReference: shouldUseProvisionalTaskReferences(runtimeMode)
7355
7624
  }), replayed: false };
7356
- if ('operationId' in task) {
7357
- options.onOperationAccepted?.({
7358
- operationId: task.operationId,
7359
- mutationKind: 'create',
7360
- payloadFingerprint: fingerprintWorkspaceSyncPayload(prepared.durableTask || {}),
7361
- });
7362
- }
7363
7625
  recordMcpWriteAudit('create_task', {
7364
7626
  taskId: task.task?.id || null,
7365
7627
  title: task.task?.title || null,
@@ -7478,6 +7740,9 @@ export function createTaskforceMcpServer(options = {}) {
7478
7740
  const inputId = args.id;
7479
7741
  const { id, task: existingTask } = resolveTaskByIdentifierOrThrow(inputId);
7480
7742
  const prepared = taskRootCommandPreparationService.prepareUpdate(args);
7743
+ if (prepared.updates.status === 'review' && existingTask.status !== 'review') {
7744
+ throw new McpPublicError('update_task cannot move a task to review. Use finish_task with outcome=\'review\' and a nonblank evidence comment so the handoff commits atomically.', 'TASK_REVIEW_HANDOFF_REQUIRED', 400);
7745
+ }
7481
7746
  const updated = mutateTaskThroughStatusBoundary({ task: existingTask, updates: prepared.updates });
7482
7747
  if (!updated) {
7483
7748
  throw new Error(`Task ${id} not found`);
@@ -7516,13 +7781,13 @@ export function createTaskforceMcpServer(options = {}) {
7516
7781
  }
7517
7782
  case "finish_task": {
7518
7783
  try {
7519
- const { id: inputId, outcome, comment } = args;
7784
+ const { id: inputId, outcome, comment, reviewer } = args;
7520
7785
  const normalizedOutcome = String(outcome || '').trim().toLowerCase();
7521
7786
  if (normalizedOutcome !== 'done' && normalizedOutcome !== 'review') {
7522
7787
  throw new McpPublicError("outcome must be 'done' or 'review'");
7523
7788
  }
7524
7789
  const { id, task: existingTask } = resolveTaskByIdentifierOrThrow(inputId);
7525
- const result = taskLifecycleCommandService.finish(existingTask, { outcome: normalizedOutcome, comment });
7790
+ const result = taskLifecycleCommandService.finish(existingTask, { outcome: normalizedOutcome, comment, reviewer });
7526
7791
  recordMcpWriteAudit('finish_task', {
7527
7792
  taskId: id,
7528
7793
  outcome: normalizedOutcome,
@@ -7906,6 +8171,14 @@ export function createTaskforceMcpServer(options = {}) {
7906
8171
  update.complexity = resolveNumberOption('complexity', update.complexity, COMPLEXITY_OPTIONS);
7907
8172
  }
7908
8173
  const preview = core.bulkUpdateFieldsPreview(resolvedList, ACTIVE_WORKSPACE_ID);
8174
+ for (const item of preview.toApply) {
8175
+ if (item.fields.status !== 'review')
8176
+ continue;
8177
+ const existingTask = core.getTask(item.id, ACTIVE_WORKSPACE_ID);
8178
+ if (existingTask?.status !== 'review') {
8179
+ throw new McpPublicError('bulk_update_fields cannot move a task to review. Use finish_task with outcome=\'review\' and a nonblank evidence comment.', 'TASK_REVIEW_HANDOFF_REQUIRED', 400);
8180
+ }
8181
+ }
7909
8182
  const forceStatusBoundary = (durableTaskMutationRouter.enabled
7910
8183
  && preview.toApply.some((item) => Object.prototype.hasOwnProperty.call(item.fields, 'status')));
7911
8184
  const durableBatch = forceStatusBoundary || durableTaskRootMutationRouter.metadataEnabled;
@@ -8029,8 +8302,8 @@ export function createTaskforceMcpServer(options = {}) {
8029
8302
  };
8030
8303
  const toolHandlers = new Map(registeredTools.map((tool) => [tool.name, tool.handler]));
8031
8304
  const mcpInputValidator = createMcpInputValidator();
8032
- server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
8033
- const { name, arguments: args } = resolveMcpToolCallCompatibility(request.params.name, request.params.arguments);
8305
+ const callTool = async (params, context = {}) => {
8306
+ const { name, arguments: args } = resolveMcpToolCallCompatibility(params.name, params.arguments);
8034
8307
  const toolStartedAtMs = Date.now();
8035
8308
  let preparationMs = 0;
8036
8309
  let validationMs = 0;
@@ -8073,11 +8346,11 @@ export function createTaskforceMcpServer(options = {}) {
8073
8346
  }
8074
8347
  });
8075
8348
  let result;
8076
- if (extra.requestId === undefined || extra.requestId === null) {
8349
+ if (context.requestId === undefined || context.requestId === null) {
8077
8350
  result = await execute();
8078
8351
  }
8079
8352
  else {
8080
- const transportSessionId = String(extra.sessionId || '').trim();
8353
+ const transportSessionId = String(context.sessionId || '').trim();
8081
8354
  const requestIdentity = operationIdentityScope
8082
8355
  ? fingerprintWorkspaceSyncPayload({
8083
8356
  kind: 'shared-mcp-request',
@@ -8086,18 +8359,18 @@ export function createTaskforceMcpServer(options = {}) {
8086
8359
  || options.auth?.mcpConnectionId
8087
8360
  || options.auth?.mcpClientId
8088
8361
  || 'mcp',
8089
- requestId: { type: typeof extra.requestId, value: extra.requestId },
8362
+ requestId: { type: typeof context.requestId, value: context.requestId },
8090
8363
  tool: name,
8091
8364
  })
8092
8365
  : [
8093
8366
  ...(runtimeMode === 'local' || !transportSessionId ? [runtimeRequestNamespace] : []),
8094
8367
  String(transportSessionId || options.auth?.mcpConnectionId || options.auth?.mcpClientId || 'mcp'),
8095
- String(extra.requestId),
8368
+ String(context.requestId),
8096
8369
  name,
8097
8370
  ].join(':');
8098
8371
  const logicalCloudCreateIdentity = [
8099
8372
  String(transportSessionId || options.auth?.mcpConnectionId || options.auth?.mcpClientId || 'mcp'),
8100
- String(extra.requestId),
8373
+ String(context.requestId),
8101
8374
  name,
8102
8375
  ].join(':');
8103
8376
  result = await cloudCreateRequestIdentity.run(logicalCloudCreateIdentity, () => mcpRequestIdentity.run(requestIdentity, execute));
@@ -8116,14 +8389,14 @@ export function createTaskforceMcpServer(options = {}) {
8116
8389
  responseBytes = measureToolResultBytes(result);
8117
8390
  return result;
8118
8391
  }
8119
- const result = buildUnexpectedToolErrorResult(auditRequestId || extra.requestId);
8392
+ const result = buildUnexpectedToolErrorResult(auditRequestId || context.requestId);
8120
8393
  responseBytes = measureToolResultBytes(result);
8121
8394
  return result;
8122
8395
  }
8123
8396
  finally {
8124
8397
  try {
8125
8398
  options.onToolCallTiming?.({
8126
- requestId: String(auditRequestId || extra.requestId || '').trim() || null,
8399
+ requestId: String(auditRequestId || context.requestId || '').trim() || null,
8127
8400
  toolName: name,
8128
8401
  isWrite: isMcpWriteToolName(name),
8129
8402
  outcome: timingOutcome,
@@ -8139,7 +8412,11 @@ export function createTaskforceMcpServer(options = {}) {
8139
8412
  // Observability must never change tool behavior.
8140
8413
  }
8141
8414
  }
8142
- });
8415
+ };
8416
+ server.setRequestHandler('tools/call', (request, ctx) => callTool(request.params, {
8417
+ requestId: ctx.mcpReq.id,
8418
+ sessionId: ctx.sessionId,
8419
+ }));
8143
8420
  return {
8144
8421
  server,
8145
8422
  core,
@@ -8149,6 +8426,16 @@ export function createTaskforceMcpServer(options = {}) {
8149
8426
  tenantId,
8150
8427
  version: MCP_SERVER_VERSION,
8151
8428
  toolProfile: activeToolProfile,
8429
+ listTools,
8430
+ callTool,
8431
+ };
8432
+ }
8433
+ export async function connectMcpRuntimeToStdio(runtime, transport = new StdioServerTransport()) {
8434
+ await runtime.server.connect(transport);
8435
+ return {
8436
+ ...runtime,
8437
+ transport,
8438
+ close: () => runtime.server.close(),
8152
8439
  };
8153
8440
  }
8154
8441
  export async function startTaskforceMcpStdioServer(options = {}) {
@@ -8164,18 +8451,18 @@ export async function startTaskforceMcpStdioServer(options = {}) {
8164
8451
  projectRoot,
8165
8452
  tenantId,
8166
8453
  core,
8454
+ resourceSubscriptionMode: options.resourceSubscriptionMode ?? 'legacy-long-lived',
8167
8455
  auth: {
8168
8456
  ...envAuth,
8169
8457
  ...(options.auth || {}),
8170
8458
  },
8171
8459
  });
8172
- const transport = new StdioServerTransport();
8173
- await runtime.server.connect(transport);
8460
+ const connected = await connectMcpRuntimeToStdio(runtime);
8174
8461
  const close = createTaskforceMcpStdioClose({
8175
- closeServer: () => runtime.server.close(),
8462
+ closeServer: connected.close,
8176
8463
  ...(ownsCore ? { closeOwnedCore: () => core.close() } : {}),
8177
8464
  });
8178
- return { ...runtime, transport, close };
8465
+ return { ...runtime, transport: connected.transport, close };
8179
8466
  }
8180
8467
  catch (error) {
8181
8468
  try {