@ema.co/mcp-toolkit 2026.2.24 → 2026.2.27

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.
@@ -412,15 +412,41 @@ export async function handleUpdate(args, client) {
412
412
  hint: "Set preview=false to deploy these changes",
413
413
  };
414
414
  }
415
+ // Determine the state to set:
416
+ // - "ready" when deploying a workflow OR when explicitly enabling the persona
417
+ // - "inactive" when explicitly disabling the persona
418
+ // This matches the behavior of the Ema frontend
419
+ let stateToSet;
420
+ if (args.enabled === true) {
421
+ stateToSet = "ready";
422
+ }
423
+ else if (args.enabled === false) {
424
+ stateToSet = "inactive";
425
+ }
426
+ else if (workflowToSet) {
427
+ // Deploying a workflow implies activating the persona
428
+ stateToSet = "ready";
429
+ }
430
+ const updateRequest = {
431
+ persona_id: persona.id,
432
+ name: args.name,
433
+ description: args.description,
434
+ proto_config: mergedProtoConfig,
435
+ workflow: workflowToSet,
436
+ enabled_by_user: typeof args.enabled === "boolean" ? args.enabled : undefined,
437
+ ...(stateToSet ? { state: stateToSet } : {}),
438
+ };
439
+ // Debug: log what we're sending
440
+ console.error("[persona/update] Sending to API:", JSON.stringify({
441
+ persona_id: updateRequest.persona_id,
442
+ enabled_by_user: updateRequest.enabled_by_user,
443
+ state: updateRequest.state,
444
+ has_workflow: !!updateRequest.workflow,
445
+ has_proto_config: !!updateRequest.proto_config,
446
+ }));
415
447
  try {
416
- await client.updateAiEmployee({
417
- persona_id: persona.id,
418
- name: args.name,
419
- description: args.description,
420
- proto_config: mergedProtoConfig,
421
- workflow: workflowToSet,
422
- enabled_by_user: typeof args.enabled === "boolean" ? args.enabled : undefined,
423
- });
448
+ const apiResponse = await client.updateAiEmployee(updateRequest);
449
+ console.error("[persona/update] API response:", JSON.stringify(apiResponse));
424
450
  }
425
451
  catch (apiErr) {
426
452
  // Return structured error consistent with other handlers
@@ -233,6 +233,9 @@ export async function handleWorkflowDeploy(args, client) {
233
233
  persona_id: personaId,
234
234
  workflow: sanitizedWorkflow,
235
235
  proto_config: protoConfigToUse,
236
+ // Set state to "ready" to activate the persona after deployment
237
+ // This matches the behavior of the Ema frontend
238
+ state: "ready",
236
239
  });
237
240
  // ═══════════════════════════════════════════════════════════════════════════
238
241
  // CRITICAL: Check for silent deployment failure
@@ -14,6 +14,7 @@
14
14
  * 2. Semantic validation (logic) - catches wiring/reference errors
15
15
  * 3. Best practices (warnings) - non-blocking suggestions
16
16
  */
17
+ import { ConnectError, Code } from "@connectrpc/connect";
17
18
  import { validateWorkflowDefSchema } from "../../domain/workflow-def-schema.js";
18
19
  // Re-export schema validation for use by other handlers
19
20
  export { validateWorkflowDefSchema };
@@ -248,6 +249,7 @@ export async function validateSearchDataSourceConsistency(workflowDef, personaId
248
249
  // Try to get data source stats for each widget used by search nodes (at least one must have indexed data)
249
250
  let dataSourceStats = null;
250
251
  let lastError;
252
+ let isPermissionError = false;
251
253
  for (const widgetName of widgetNames) {
252
254
  try {
253
255
  const stats = await client.getDataSourceAggregates(personaId, widgetName);
@@ -261,13 +263,27 @@ export async function validateSearchDataSourceConsistency(workflowDef, personaId
261
263
  }
262
264
  catch (err) {
263
265
  lastError = err;
266
+ // Check for permission/auth errors - these should block, not warn
267
+ if (err instanceof ConnectError) {
268
+ if (err.code === Code.PermissionDenied || err.code === Code.Unauthenticated) {
269
+ isPermissionError = true;
270
+ }
271
+ }
264
272
  }
265
273
  }
266
- if (!dataSourceStats && lastError) {
267
- console.error(`[validation] Could not verify data sources for ${personaId}`, lastError);
268
- }
269
- // If we couldn't get stats, allow through but warn (don't block on API errors)
274
+ // If we couldn't get stats, skip validation with appropriate warning
270
275
  if (!dataSourceStats) {
276
+ if (isPermissionError) {
277
+ const errorMsg = lastError instanceof ConnectError ? lastError.rawMessage : String(lastError);
278
+ // Permission to getDataSourceAggregates != permission to updateAiEmployee
279
+ // Skip validation but warn - don't block activation
280
+ return {
281
+ valid: true,
282
+ _warning: `Could not verify data source consistency - permission denied for data source API (${errorMsg}). Skipping this validation.`,
283
+ validation_skipped: "search_data_source_consistency_permission",
284
+ };
285
+ }
286
+ // Other errors (network, etc.) - also skip with warning
271
287
  return {
272
288
  valid: true,
273
289
  _warning: "Could not verify data source consistency - API error. Proceed with caution.",
package/dist/mcp/tools.js CHANGED
@@ -45,6 +45,8 @@ export function generateTools(envNames, defaultEnv) {
45
45
 
46
46
  ## Update
47
47
  - \`persona(method="update", id="abc", config={...})\` - update config (name, description, widgets)
48
+ - \`persona(method="update", id="abc", enabled=true)\` - activate persona
49
+ - \`persona(method="update", id="abc", enabled=false)\` - deactivate persona
48
50
 
49
51
  **IMPORTANT (strict)**:
50
52
  - Always fetch latest state immediately before changing: \`persona(method="get", id="abc", include_fingerprint=true)\`
@@ -183,6 +185,10 @@ persona(
183
185
  type: "object",
184
186
  description: "Proto config to update - name, description, widgets (for method=update)"
185
187
  },
188
+ enabled: {
189
+ type: "boolean",
190
+ description: "Enable/disable persona (for method=update). Set to true to activate, false to deactivate.",
191
+ },
186
192
  base_fingerprint: {
187
193
  type: "string",
188
194
  description: "Fingerprint from persona(method='get', include_fingerprint=true). REQUIRED for method=update unless force=true (stale-state protection).",
@@ -177,6 +177,8 @@ export class EmaClientAdapter {
177
177
  proto_config: req.proto_config,
178
178
  name: req.name,
179
179
  description: req.description,
180
+ state: req.state,
181
+ enabled_by_user: req.enabled_by_user,
180
182
  });
181
183
  return result;
182
184
  }
@@ -278,6 +278,8 @@ export class EmaClientV2 {
278
278
  proto_config: data.proto_config,
279
279
  name: data.name,
280
280
  description: data.description,
281
+ state: data.state,
282
+ enabled_by_user: data.enabled_by_user,
281
283
  },
282
284
  });
283
285
  return result.data;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ema.co/mcp-toolkit",
3
- "version": "2026.2.24",
3
+ "version": "2026.2.27",
4
4
  "description": "Ema AI Employee toolkit - MCP server, CLI, and SDK for managing AI Employees across environments",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",