@ema.co/mcp-toolkit 2026.1.25 → 2026.1.26-4

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.

Potentially problematic release.


This version of @ema.co/mcp-toolkit might be problematic. Click here for more details.

Files changed (87) hide show
  1. package/README.md +10 -2
  2. package/dist/mcp/handlers/action/index.js +3 -18
  3. package/dist/mcp/handlers/data/index.js +385 -41
  4. package/dist/mcp/handlers/data/templates.js +107 -0
  5. package/dist/mcp/handlers/deprecation.js +50 -0
  6. package/dist/mcp/handlers/env/index.js +8 -4
  7. package/dist/mcp/handlers/knowledge/index.js +44 -237
  8. package/dist/mcp/handlers/persona/create.js +47 -18
  9. package/dist/mcp/handlers/persona/index.js +14 -11
  10. package/dist/mcp/handlers/persona/update.js +4 -2
  11. package/dist/mcp/handlers/persona/version.js +234 -0
  12. package/dist/mcp/handlers/sync/index.js +3 -18
  13. package/dist/mcp/handlers/template/index.js +75 -10
  14. package/dist/mcp/handlers/workflow/analyze.js +171 -0
  15. package/dist/mcp/handlers/workflow/compare.js +70 -0
  16. package/dist/mcp/handlers/workflow/deploy.js +73 -0
  17. package/dist/mcp/handlers/workflow/generate.js +350 -0
  18. package/dist/mcp/handlers/workflow/index.js +294 -0
  19. package/dist/mcp/handlers/workflow/modify.js +456 -0
  20. package/dist/mcp/handlers/workflow/optimize.js +136 -0
  21. package/dist/mcp/handlers/workflow/types.js +4 -0
  22. package/dist/mcp/handlers/workflow/utils.js +30 -0
  23. package/dist/mcp/handlers-consolidated.js +73 -2696
  24. package/dist/mcp/prompts.js +83 -43
  25. package/dist/mcp/resources.js +382 -57
  26. package/dist/mcp/server.js +199 -391
  27. package/dist/mcp/{tools-v2.js → tools.js} +20 -54
  28. package/dist/mcp/workflow-operations.js +2 -2
  29. package/dist/sdk/client-adapter.js +267 -32
  30. package/dist/sdk/client.js +45 -16
  31. package/dist/sdk/ema-client.js +183 -0
  32. package/dist/sdk/generated/deprecated-actions.js +171 -0
  33. package/dist/sdk/generated/template-fallbacks.js +123 -0
  34. package/dist/sdk/guidance.js +65 -11
  35. package/dist/sdk/index.js +3 -1
  36. package/dist/sdk/knowledge.js +139 -86
  37. package/dist/sdk/workflow-intent.js +27 -0
  38. package/dist/sdk/workflow-transformer.js +0 -342
  39. package/docs/mcp-tools-guide.md +37 -45
  40. package/package.json +10 -4
  41. package/dist/mcp/handlers/persona/analyze.js +0 -275
  42. package/dist/mcp/handlers/persona/compare.js +0 -32
  43. package/dist/mcp/tools-consolidated.js +0 -875
  44. package/dist/mcp/tools-legacy.js +0 -736
  45. package/docs/CODEBASE-ANALYSIS-2026-01-23.md +0 -936
  46. package/docs/CODEBASE-ANALYSIS-PRIORITIZED.md +0 -774
  47. package/docs/api-contracts.md +0 -216
  48. package/docs/auto-builder-analysis.md +0 -271
  49. package/docs/blog/mcp-tool-design-lessons.md +0 -309
  50. package/docs/data-architecture.md +0 -166
  51. package/docs/demos/ap-invoice-generation.md +0 -347
  52. package/docs/demos/ap-invoice-processing.md +0 -271
  53. package/docs/ema-auto-builder-guide.html +0 -394
  54. package/docs/lessons-learned.md +0 -209
  55. package/docs/llm-native-workflow-design.md +0 -252
  56. package/docs/local-generation.md +0 -508
  57. package/docs/mcp-flow-diagram.md +0 -135
  58. package/docs/migration/action-composition-migration.md +0 -270
  59. package/docs/naming-conventions.md +0 -278
  60. package/docs/proposals/HANDOFF-tool-restructure.md +0 -526
  61. package/docs/proposals/action-composition.md +0 -490
  62. package/docs/proposals/explicit-method-restructure.md +0 -328
  63. package/docs/proposals/mcp-tool-restructure-2026-01.md +0 -366
  64. package/docs/proposals/self-contained-guidance.md +0 -427
  65. package/docs/proto-sdk-generation.md +0 -242
  66. package/docs/release-impact.md +0 -102
  67. package/docs/release-process.md +0 -157
  68. package/docs/staging.RULE.md +0 -142
  69. package/docs/test-persona-creation.md +0 -196
  70. package/docs/tool-consolidation-v2.md +0 -225
  71. package/docs/tool-response-standards.md +0 -256
  72. package/resources/demo-kits/README.md +0 -175
  73. package/resources/demo-kits/finance-ap/manifest.json +0 -150
  74. package/resources/demo-kits/tags.json +0 -91
  75. package/resources/docs/getting-started.md +0 -97
  76. package/resources/templates/auto-builder-rules.md +0 -224
  77. package/resources/templates/chat-ai/README.md +0 -119
  78. package/resources/templates/chat-ai/persona-config.json +0 -111
  79. package/resources/templates/dashboard-ai/README.md +0 -156
  80. package/resources/templates/dashboard-ai/persona-config.json +0 -180
  81. package/resources/templates/demo-scenarios/README.md +0 -63
  82. package/resources/templates/demo-scenarios/test-published-package.md +0 -116
  83. package/resources/templates/document-gen-ai/README.md +0 -132
  84. package/resources/templates/document-gen-ai/persona-config.json +0 -316
  85. package/resources/templates/voice-ai/README.md +0 -123
  86. package/resources/templates/voice-ai/persona-config.json +0 -74
  87. package/resources/templates/voice-ai/workflow-prompt.md +0 -121
@@ -41,22 +41,22 @@ import { createVersionPolicyEngine } from "../sdk/version-policy.js";
41
41
  import { getToolkitRoot } from "../sdk/paths.js";
42
42
  import { SYNC_METADATA_KEY } from "../sdk/models.js";
43
43
  // Auto Builder Knowledge
44
- import { AGENT_CATALOG, WIDGET_CATALOG, WORKFLOW_PATTERNS, QUALIFYING_QUESTIONS, PLATFORM_CONCEPTS, WORKFLOW_EXECUTION_MODEL, COMMON_MISTAKES, DEBUG_CHECKLIST, GUIDANCE_TOPICS, VOICE_PERSONA_TEMPLATE, PROJECT_TYPES, getAgentsByCategory, getAgentByName, getWidgetsForPersonaType, checkTypeCompatibility, getQualifyingQuestionsByCategory, getConceptByTerm, suggestAgentsForUseCase, validateWorkflowPrompt,
44
+ import { AGENT_CATALOG, WIDGET_CATALOG, WORKFLOW_PATTERNS, QUALIFYING_QUESTIONS, PLATFORM_CONCEPTS, WORKFLOW_EXECUTION_MODEL, COMMON_MISTAKES, DEBUG_CHECKLIST, GUIDANCE_TOPICS, PROJECT_TYPES, getAgentsByCategory, getAgentByName, getWidgetsForPersonaType, checkTypeCompatibility, getQualifyingQuestionsByCategory, getConceptByTerm, suggestAgentsForUseCase, validateWorkflowPrompt,
45
45
  // Workflow Analysis
46
46
  analyzeWorkflow, detectWorkflowIssues, validateWorkflowConnections, suggestWorkflowFixes, } from "../sdk/knowledge.js";
47
+ // Template fallbacks (generated from protos, used when API unavailable)
48
+ import { getTemplateFallback, getTemplateFieldDocs, VOICE_TEMPLATE_FALLBACK } from "../sdk/generated/template-fallbacks.js";
47
49
  // Workflow Compiler (Template-driven)
48
50
  import { compileWorkflow, } from "../sdk/workflow-generator.js";
49
51
  // V2 Tools (4 tools: persona, catalog, sync, env) - NEW DEFAULT
50
- import { generateToolsV2, } from "./tools-v2.js";
51
- // V1 Consolidated Tools (7 mode-based tools) - BACKWARDS COMPAT
52
- import { generateConsolidatedTools, } from "./tools-consolidated.js";
53
- // Legacy Tools (get_persona, find_personas, etc.) - DEPRECATED
54
- import { generateLegacyTools, } from "./tools-legacy.js";
55
- // Feature flags for tool versions
56
- // V2 is default (4 tools), set EMA_ENABLE_V1_TOOLS=true for 7-tool mode-based interface
57
- const ENABLE_V1_TOOLS = process.env.EMA_ENABLE_V1_TOOLS === "true";
58
- const ENABLE_LEGACY_TOOLS = process.env.EMA_ENABLE_LEGACY_TOOLS === "true";
59
- import { handleEnv, handlePersona, handleWorkflow, handleAction, handleData, handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
52
+ import { generateTools, } from "./tools.js";
53
+ import { handleEnv, handlePersona,
54
+ // handleWorkflow - removed, now using extracted handler from ./handlers/workflow/index.js
55
+ handleAction,
56
+ // handleData - removed, now using extracted handler from ./handlers/data/index.js
57
+ handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
58
+ // Import extracted handlers
59
+ import { handleWorkflow } from "./handlers/workflow/index.js";
60
60
  // Import from handler utilities (normalizeTriggerType uses generated enum labels)
61
61
  import { normalizeTriggerType } from "./handlers/utils.js";
62
62
  // Import from SDK proto-config (CANONICAL widget validation and merging)
@@ -92,6 +92,9 @@ function summarizeWorkflow(workflowDef) {
92
92
  if (nodeNames.length > 0) {
93
93
  lines.push(`\nNodes: ${nodeNames.slice(0, 20).join(", ")}${nodeNames.length > 20 ? "..." : ""}`);
94
94
  }
95
+ // TODO: This uses keyword matching to detect workflow features.
96
+ // Consider using ActionRegistry metadata instead for consistency with LLM-driven architecture.
97
+ // Current approach is acceptable for Auto Builder descriptions but could be improved.
95
98
  // Check for categorizer (indicates intent routing)
96
99
  const hasCategorizer = Array.from(actionTypes.keys()).some(t => t.includes("categorizer"));
97
100
  if (hasCategorizer) {
@@ -111,8 +114,19 @@ function summarizeWorkflow(workflowDef) {
111
114
  * Apply automatic fixes to a workflow based on detected issues.
112
115
  * This function attempts to fix common issues like missing WORKFLOW_OUTPUT,
113
116
  * wrong input sources, and other structural problems.
117
+ *
118
+ * @deprecated This function violates the LLM-driven architecture principle.
119
+ * MCP should not auto-fix workflows - it should return suggestions for the Agent to apply.
120
+ * Per CLAUDE.md: "Auto-fix issues | ❌ FORBIDDEN | ✅ Proposes fixes"
121
+ *
122
+ * This function will be removed in a future version. Instead:
123
+ * 1. Use analyzeWorkflow() to detect issues
124
+ * 2. Return issues as suggestions to the Agent
125
+ * 3. Let Agent apply fixes via persona(id="...", operations=[...])
114
126
  */
115
127
  function applyWorkflowFixes(workflowDef, issues, persona) {
128
+ // Log deprecation warning
129
+ console.warn("[DEPRECATED] applyWorkflowFixes() called - this function violates LLM-driven architecture and will be removed");
116
130
  // Deep clone the workflow to avoid mutating the original
117
131
  const fixedWorkflow = JSON.parse(JSON.stringify(workflowDef));
118
132
  const appliedFixes = [];
@@ -1093,102 +1107,46 @@ function withEnvParam(props, required = []) {
1093
1107
  // Tool Definitions
1094
1108
  // ─────────────────────────────────────────────────────────────────────────────
1095
1109
  //
1096
- // TOOL STRUCTURE:
1097
- // 1. CONSOLIDATED TOOLS (9 tools) - Unix CLI pattern with flags
1098
- // - env, persona, workflow, action, template, knowledge, reference, sync, demo
1099
- // - Defined in: ./tools-consolidated.ts
1100
- //
1101
- // 2. LEGACY TOOLS (40+ tools) - Old separate tools for backwards compatibility
1102
- // - Defined in: ./tools-legacy.ts
1103
- // - Enable with EMA_ENABLE_LEGACY_TOOLS=true
1110
+ // V2 TOOLS (5 tools) - LLM-optimized minimal interface
1111
+ // - env, persona, catalog, workflow, sync
1112
+ // - Defined in: ./tools.ts
1104
1113
  //
1105
1114
  // NAMING CONVENTION:
1106
- // - Tool names are defined as BASE NAMES (e.g., "persona", "list_ai_employees")
1115
+ // - Tool names are defined as BASE NAMES (e.g., "persona")
1107
1116
  // - MCP clients prefix with "mcp_{server}_" (e.g., "mcp_ema_persona")
1108
1117
  //
1109
1118
  // ─────────────────────────────────────────────────────────────────────────────
1110
1119
  /**
1111
- * Generate all available tools based on configuration
1120
+ * Generate all available tools
1112
1121
  *
1113
- * Tool versions:
1114
- * - V2 (default): 4 tools (persona, catalog, sync, env) - LLM-optimized
1115
- * - V1: 7 mode-based tools - set EMA_ENABLE_V1_TOOLS=true
1116
- * - Legacy: Individual tools - set EMA_ENABLE_LEGACY_TOOLS=true
1122
+ * V2: 5 tools (persona, catalog, workflow, sync, env) - LLM-optimized
1117
1123
  *
1118
- * Why V2 by default:
1124
+ * Why V2:
1119
1125
  * - Minimal tool count optimizes LLM tool selection
1120
1126
  * - Data operations under persona (always persona-scoped)
1121
1127
  * - Catalog consolidates all reference data (actions, templates, etc.)
1122
- * - Clear separation: entity (persona), reference (catalog), operation (sync)
1128
+ * - Clear separation: entity (persona), reference (catalog), operation (sync, workflow)
1123
1129
  */
1124
1130
  function generateAllTools() {
1125
1131
  const envNames = getAvailableEnvironments().map(e => e.name);
1126
1132
  const defaultEnv = getDefaultEnvName();
1127
- // V1 mode-based tools (for backwards compat)
1128
- if (ENABLE_V1_TOOLS) {
1129
- console.error("[MCP] V1 mode-based tools enabled via EMA_ENABLE_V1_TOOLS=true");
1130
- const consolidatedTools = generateConsolidatedTools(envNames, defaultEnv);
1131
- if (ENABLE_LEGACY_TOOLS) {
1132
- console.error("[MCP] WARNING: Legacy tools also enabled");
1133
- const legacyTools = generateLegacyTools(envNames, defaultEnv);
1134
- return [...consolidatedTools, ...legacyTools];
1135
- }
1136
- return consolidatedTools;
1137
- }
1138
- // V2 minimal tools (default) - 4 tools: persona, catalog, sync, env
1139
- const v2Tools = generateToolsV2(envNames, defaultEnv);
1140
- if (ENABLE_LEGACY_TOOLS) {
1141
- console.error("[MCP] WARNING: Legacy tools enabled alongside V2");
1142
- const legacyTools = generateLegacyTools(envNames, defaultEnv);
1143
- return [...v2Tools, ...legacyTools];
1144
- }
1145
- return v2Tools;
1133
+ return generateTools(envNames, defaultEnv);
1146
1134
  }
1147
1135
  // Generate tools (called once at module load)
1148
1136
  const TOOLS = generateAllTools();
1149
1137
  // ─────────────────────────────────────────────────────────────────────────────
1150
- // ADDITIONAL TOOLS (not in consolidated or legacy)
1151
- // These are special-purpose tools that don't fit the standard patterns
1138
+ // ADDITIONAL TOOLS (special-purpose inline tools)
1139
+ // These handle specific operations that don't fit the V2 pattern
1152
1140
  // ─────────────────────────────────────────────────────────────────────────────
1153
1141
  const ADDITIONAL_TOOLS = [
1154
- // ─────────────────────────────────────────────────────────────────────────
1155
- // NOTE: Legacy tools (get_persona, find_personas, create_ai_employee, etc.)
1156
- // have been moved to ./tools-legacy.ts for backwards compatibility.
1157
- //
1158
- // Consolidated tools (persona, workflow, action, etc.) are generated from
1159
- // ./tools-consolidated.ts following Unix CLI patterns.
1142
+ // NOTE: Tools (persona, catalog, workflow, sync, env) are in ./tools.ts
1160
1143
  //
1161
- // Only special-purpose tools remain here:
1162
- // - "workflow" (unified tool) - experimental, bridges old and new patterns
1163
- // - Demo data tools - special-purpose data generation
1164
- // ─────────────────────────────────────────────────────────────────────────
1165
- // INLINE LEGACY TOOLS REMOVED
1166
- // All legacy tools (get_workflow_action, find_workflow_actions, compare_ai_employees,
1167
- // list_ai_employee_templates, sync, sync_info, list_auto_builder_agents, etc.)
1168
- // have been moved to ./tools-legacy.ts
1169
- // ─────────────────────────────────────────────────────────────────────────
1170
- // ─────────────────────────────────────────────────────────────────────────────
1171
- // LEGACY INLINE TOOLS REMOVED - See ./tools-legacy.ts
1172
- // ─────────────────────────────────────────────────────────────────────────────
1173
- // The following tools have been removed from this file and are now generated
1174
- // from tools-legacy.ts: list_auto_builder_agents, get_auto_builder_agent,
1175
- // suggest_agents_for_use_case, get_workflow_pattern, list_workflow_patterns,
1176
- // check_type_compatibility, get_widget_reference, get_qualifying_questions,
1177
- // get_voice_persona_template, validate_workflow_prompt, get_auto_builder_guidance,
1178
- // get_platform_concept, list_platform_concepts, get_common_mistakes,
1179
- // get_debug_checklist, get_workflow_execution_model, analyze_workflow,
1180
- // detect_workflow_issues, validate_workflow_connections, suggest_workflow_fixes,
1181
- // compare_workflow_versions, get_workflow_metrics, compile_workflow,
1182
- // upload_data_source, delete_data_source, list_data_sources, get_embedding_status,
1144
+ // Special-purpose tools here:
1145
+ // - compile_workflow - Direct workflow compilation
1146
+ // - Demo data tools - RAG document generation/validation
1147
+ // - Data source tools - Upload/delete/manage knowledge sources
1183
1148
  // toggle_embedding
1184
1149
  // ─────────────────────────────────────────────────────────────────────────────
1185
- // The remaining legacy tools are handled by the LEGACY_TOOL_MAPPING in
1186
- // tools-consolidated.ts for routing to consolidated handlers.
1187
- //
1188
- // INLINE DEFINITIONS REMOVED - They are now in tools-legacy.ts
1189
- // (analyze_workflow, detect_workflow_issues, validate_workflow_connections, suggest_workflow_fixes)
1190
- // (compare_workflow_versions, get_workflow_metrics) - moved to tools-legacy.ts
1191
- // ─────────────────────────────────────────────────────────────────────────────
1192
1150
  // Workflow Compilation - Template-driven, no biased patterns
1193
1151
  // Read ema://catalog/patterns for pattern references, then construct nodes
1194
1152
  // ─────────────────────────────────────────────────────────────────────────────
@@ -1606,11 +1564,6 @@ Returns:
1606
1564
  required: ["entity_type"],
1607
1565
  },
1608
1566
  },
1609
- // ═══════════════════════════════════════════════════════════════════════════
1610
- // CONSOLIDATED TOOLS (Unix CLI pattern)
1611
- // These 9 tools follow Unix conventions: single command with flags
1612
- // ═══════════════════════════════════════════════════════════════════════════
1613
- ...generateConsolidatedTools(getAvailableEnvironments().map(e => e.name), getDefaultEnvName()),
1614
1567
  ];
1615
1568
  const toolHandlers = {
1616
1569
  // Environment Management
@@ -1980,19 +1933,29 @@ const toolHandlers = {
1980
1933
  if (!analysis.validation_passed) {
1981
1934
  validationResults.valid = false;
1982
1935
  validationResults.issues = analysis.issues ?? [];
1983
- // Auto-fix if enabled
1936
+ // Auto-fix handling (DEPRECATED - returns suggestions instead of auto-applying)
1984
1937
  if (autoFix && validationResults.issues.length > 0) {
1985
- fixAttempted = true;
1986
- const fixResult = applyWorkflowFixes(workflowDef, validationResults.issues, persona);
1987
- workflowDef = fixResult.fixedWorkflow;
1988
- appliedFixes.push(...fixResult.appliedFixes);
1989
- // Re-validate after fixes
1990
- const reAnalysis = analyzeWorkflow(workflowDef, {
1938
+ // DEPRECATED: autoFix no longer auto-applies fixes.
1939
+ // Per LLM-driven architecture, MCP returns suggestions for Agent to apply.
1940
+ return {
1941
+ environment: client["env"].name,
1942
+ success: false,
1991
1943
  persona_id: personaId,
1992
- persona_name: persona.name ?? "Unknown"
1993
- });
1994
- validationResults.valid = reAnalysis.validation_passed;
1995
- validationResults.issues = reAnalysis.issues ?? [];
1944
+ persona_name: persona.name,
1945
+ validation_failed: true,
1946
+ issues: validationResults.issues,
1947
+ // Return suggestions instead of applying fixes
1948
+ suggestions: validationResults.issues.map(issue => ({
1949
+ issue_type: issue.type,
1950
+ severity: issue.severity,
1951
+ node: issue.node,
1952
+ reason: issue.reason,
1953
+ suggested_action: `Fix "${issue.type}" on node "${issue.node ?? 'workflow'}": ${issue.reason}`,
1954
+ })),
1955
+ applied_fixes: [], // Empty - no longer auto-applying
1956
+ _deprecated: "autoFix is deprecated. Fixes are no longer auto-applied. Use the suggestions to build explicit workflow modifications.",
1957
+ _tip: "Apply fixes using: persona(id=\"...\", operations=[{type:\"rewire\", ...}]) or persona(id=\"...\", workflow_spec={...})",
1958
+ };
1996
1959
  }
1997
1960
  }
1998
1961
  }
@@ -2207,130 +2170,62 @@ const toolHandlers = {
2207
2170
  }
2208
2171
  return result;
2209
2172
  }
2210
- // Step 3: Apply fixes
2211
- let fixedWorkflow = workflowDef;
2173
+ // Step 3: Return suggestions instead of auto-applying (DEPRECATED behavior)
2174
+ // Per LLM-driven architecture, MCP returns suggestions for Agent to apply.
2175
+ const suggestions = issues.map(issue => ({
2176
+ issue_type: issue.type,
2177
+ severity: issue.severity,
2178
+ node: issue.node,
2179
+ reason: issue.reason,
2180
+ suggested_action: `Fix "${issue.type}" on node "${issue.node ?? 'workflow'}": ${issue.reason}`,
2181
+ }));
2182
+ // DEPRECATED: No longer auto-apply fixes
2183
+ // The appliedFixes array is now always empty
2212
2184
  const appliedFixes = [];
2213
- if (issues.length > 0) {
2214
- const fixResult = applyWorkflowFixes(workflowDef, issues, persona);
2215
- fixedWorkflow = fixResult.fixedWorkflow;
2216
- appliedFixes.push(...fixResult.appliedFixes);
2217
- }
2218
- // Re-analyze after fixes
2219
- const postFixAnalysis = analyzeWorkflow(fixedWorkflow, {
2220
- persona_id: personaId,
2221
- persona_name: persona.name ?? "Unknown",
2222
- });
2223
- const remainingIssues = postFixAnalysis.issues ?? [];
2185
+ const fixedWorkflow = workflowDef; // Workflow unchanged
2186
+ // No re-analysis needed since we don't auto-fix
2187
+ const remainingIssues = issues;
2224
2188
  const remainingCritical = remainingIssues.filter(i => i.severity === "critical");
2225
- // If preview mode, show what would happen without deploying
2189
+ // If preview mode, show suggestions (DEPRECATED: no longer auto-applies)
2226
2190
  if (preview) {
2227
- const fixedCount = appliedFixes.filter(f => f.applied).length;
2228
- const failedCount = appliedFixes.filter(f => !f.applied).length;
2229
2191
  const previewResult = {
2230
2192
  success: true,
2231
2193
  persona: persona.name,
2232
- status: "📋 Preview - Fixes Available",
2194
+ status: "📋 Preview - Suggestions Available",
2233
2195
  mode: "optimize",
2234
2196
  nodes: fixedWorkflow.actions?.length ?? 0,
2235
2197
  found_issues: issues.length,
2236
- can_fix: fixedCount,
2237
- cannot_fix: failedCount,
2238
- ready_to_deploy: remainingCritical.length === 0,
2198
+ // Return suggestions instead of applied fixes
2199
+ suggestions: suggestions,
2239
2200
  issues: issues.length > 0 ? issues.map(i => `${i.severity === "critical" ? "❌" : "⚠️"} ${i.type}: ${i.reason}`) : ["No issues found"],
2240
- fixes: appliedFixes.length > 0 ? appliedFixes.map(f => `${f.applied ? "✅" : "❌"} ${f.description}`) : [],
2241
- next_step: remainingCritical.length === 0
2242
- ? `Run workflow(persona_id="${personaId}", mode="optimize") without preview to deploy fixes.`
2243
- : `${remainingCritical.length} critical issue(s) need manual fix in Ema UI.`,
2201
+ applied_fixes: [], // Empty - no longer auto-applying
2202
+ _deprecated: "Auto-fix is deprecated. Review suggestions and apply fixes explicitly.",
2203
+ _tip: "Apply fixes using: persona(id=\"...\", operations=[...]) or use Ema UI Auto Builder",
2244
2204
  };
2245
2205
  if (enhancementPrompt) {
2246
- previewResult.enhancement_note = `Enhancement "${enhancementPrompt}" noted. Auto-fixes will be applied first; use Ema UI Auto Builder for the enhancement.`;
2206
+ previewResult.enhancement_note = `Enhancement "${enhancementPrompt}" noted. Use Ema UI Auto Builder to make this change.`;
2247
2207
  }
2248
2208
  return previewResult;
2249
2209
  }
2250
- // Step 4: Deploy if no critical issues remain
2251
- if (remainingCritical.length > 0) {
2252
- return {
2253
- success: false,
2254
- persona: persona.name,
2255
- status: "❌ Cannot auto-fix",
2256
- fixed: appliedFixes.filter(f => f.applied).length,
2257
- remaining_critical: remainingCritical.length,
2258
- manual_fixes_needed: remainingCritical.map(i => ({
2259
- problem: i.type,
2260
- details: i.reason,
2261
- fix: i.recommendation,
2262
- })),
2263
- message: `${remainingCritical.length} issue(s) need manual fix in the Ema UI Auto Builder.`,
2264
- };
2265
- }
2266
- // Sanitize workflow before deployment
2267
- // Fix enumTypes - check nested structure
2268
- const enumTypes = fixedWorkflow.enumTypes;
2269
- if (Array.isArray(enumTypes)) {
2270
- const validEnumTypes = enumTypes.filter(e => {
2271
- const outerName = e.name;
2272
- const innerName = outerName?.name;
2273
- const actualName = innerName?.name;
2274
- return typeof actualName === "string" && actualName.trim().length > 0;
2275
- });
2276
- if (validEnumTypes.length > 0) {
2277
- fixedWorkflow.enumTypes = validEnumTypes;
2278
- }
2279
- else {
2280
- delete fixedWorkflow.enumTypes;
2281
- }
2282
- }
2283
- // Copy workflowName from existing
2284
- const existingWfName = workflowDef.workflowName;
2285
- if (existingWfName) {
2286
- fixedWorkflow.workflowName = JSON.parse(JSON.stringify(existingWfName));
2287
- }
2288
- // Sanitize existing proto_config widgets
2289
- const mergedProtoConfig = mergeProtoConfig(persona.proto_config, undefined);
2290
- // Build and send request
2291
- const req = {
2292
- persona_id: personaId,
2293
- proto_config: mergedProtoConfig,
2294
- workflow: fixedWorkflow,
2210
+ // Step 4: Return suggestions for issues (DEPRECATED: no longer auto-deploys)
2211
+ // Per LLM-driven architecture, return suggestions for Agent to review and apply
2212
+ // The Agent should use explicit operations to apply fixes, then deploy separately.
2213
+ return {
2214
+ success: true,
2215
+ persona: persona.name,
2216
+ status: remainingCritical.length > 0
2217
+ ? "⚠️ Issues Found - Review Suggestions"
2218
+ : "📋 Minor Issues - Review Suggestions",
2219
+ found_issues: issues.length,
2220
+ critical_issues: remainingCritical.length,
2221
+ suggestions: suggestions,
2222
+ applied_fixes: [], // Empty - no longer auto-applying
2223
+ _deprecated: "Auto-fix and auto-deploy are deprecated. Review suggestions and apply fixes explicitly.",
2224
+ _tip: remainingCritical.length > 0
2225
+ ? "Critical issues found. Review suggestions and fix in Ema UI Auto Builder or use explicit operations."
2226
+ : "Apply fixes using: persona(id=\"...\", operations=[...]) or use Ema UI Auto Builder",
2295
2227
  };
2296
- const actionsArr = fixedWorkflow.actions ?? [];
2297
- try {
2298
- await client.updateAiEmployee(req);
2299
- const fixedCount = appliedFixes.filter(f => f.applied).length;
2300
- const deployResult = {
2301
- success: true,
2302
- persona: persona.name,
2303
- status: "✅ Optimized & Deployed",
2304
- mode: "optimized",
2305
- issues_found: issues.length,
2306
- issues_fixed: fixedCount,
2307
- nodes: postFixAnalysis.summary?.total_nodes ?? actionsArr.length,
2308
- message: fixedCount > 0
2309
- ? `Fixed ${fixedCount} issue(s) and deployed!`
2310
- : "Deployed successfully!",
2311
- next_step: "Test in the Ema simulator to verify behavior.",
2312
- };
2313
- if (enhancementPrompt) {
2314
- deployResult.enhancement_note = `Fixes applied. Enhancement "${enhancementPrompt}" requires manual implementation via Ema UI Auto Builder.`;
2315
- }
2316
- return deployResult;
2317
- }
2318
- catch (err) {
2319
- const errorMessage = err instanceof Error ? err.message : String(err);
2320
- // Extract EmaApiError body if available
2321
- const apiBody = err?.body;
2322
- const statusCode = err?.statusCode;
2323
- return {
2324
- success: false,
2325
- persona: persona.name,
2326
- status: "❌ Deploy Failed",
2327
- error: errorMessage,
2328
- status_code: statusCode,
2329
- api_response: apiBody ? JSON.parse(apiBody) : undefined,
2330
- fixes_attempted: appliedFixes.filter(f => f.applied).length,
2331
- suggestion: "Check the api_response field for the actual backend error.",
2332
- };
2333
- }
2228
+ // Note: Auto-deploy code removed (was dead code after deprecation)
2334
2229
  },
2335
2230
  // ─────────────────────────────────────────────────────────────────────────
2336
2231
  // Action Handlers (Consolidated)
@@ -2826,10 +2721,14 @@ const toolHandlers = {
2826
2721
  };
2827
2722
  },
2828
2723
  get_voice_persona_template: async () => {
2724
+ // Use generated fallback from proto definitions
2725
+ // In production, prefer API templates via client.getPersonaTemplates()
2726
+ const template = getTemplateFallback("voice");
2829
2727
  return {
2830
- template: VOICE_PERSONA_TEMPLATE,
2831
- required_fields: ["welcomeMessage", "identityAndPurpose", "takeActionInstructions", "hangupInstructions"],
2832
- optional_fields: ["transferCallInstructions", "speechCharacteristics", "systemPrompt", "formFillingInstructions", "waitMessage"],
2728
+ template: template || VOICE_TEMPLATE_FALLBACK,
2729
+ field_docs: getTemplateFieldDocs("voice"),
2730
+ required_fields: ["conversationSettings.welcomeMessage", "conversationSettings.identityAndPurpose", "conversationSettings.takeActionInstructions", "conversationSettings.hangupInstructions"],
2731
+ optional_fields: ["conversationSettings.transferCallInstructions", "conversationSettings.speechCharacteristics", "conversationSettings.systemPrompt", "conversationSettings.formFillingInstructions", "conversationSettings.waitMessage"],
2833
2732
  project_type: PROJECT_TYPES.voice,
2834
2733
  widget_ids: {
2835
2734
  voiceSettings: 38,
@@ -2837,12 +2736,8 @@ const toolHandlers = {
2837
2736
  vadSettings: 43,
2838
2737
  dataStorageSettings: 42,
2839
2738
  },
2840
- instructions: [
2841
- "Replace all {placeholder} values with actual content",
2842
- "takeActionInstructions uses </Case N> format for each action",
2843
- "speechCharacteristics should include TTS pronunciation rules",
2844
- "systemPrompt defines tool calling behavior",
2845
- ],
2739
+ _source: "generated_fallback",
2740
+ _note: "This template is auto-generated from proto definitions. For live templates, use client.getPersonaTemplates().",
2846
2741
  };
2847
2742
  },
2848
2743
  validate_workflow_prompt: async (args) => {
@@ -4049,28 +3944,32 @@ const toolHandlers = {
4049
3944
  const { handleData: handleDataNew } = await import("./handlers/data/index.js");
4050
3945
  return handleDataNew({ persona_id: personaId, env: args.env, data }, client);
4051
3946
  }
4052
- // LEGACY FLAG FORMAT (backwards compatibility)
3947
+ // LEGACY FLAG FORMAT (backwards compatibility) - use extracted handler
3948
+ const { handleData: handleDataExtracted } = await import("./handlers/data/index.js");
3949
+ const readFileFn = (path) => fs.readFile(path);
4053
3950
  if (data.list === true) {
4054
- return handleData({ mode: "list", persona_id: personaId, env: args.env }, client, (path) => fs.readFile(path));
3951
+ return handleDataExtracted({ method: "list", persona_id: personaId, env: args.env }, client, readFileFn);
4055
3952
  }
4056
3953
  if (typeof data.upload === "string") {
4057
- return handleData({ mode: "upload", persona_id: personaId, file: data.upload, env: args.env }, client, (path) => fs.readFile(path));
3954
+ return handleDataExtracted({ method: "upload", persona_id: personaId, data: { path: data.upload }, env: args.env }, client, readFileFn);
4058
3955
  }
4059
3956
  if (typeof data.delete === "string") {
4060
- return handleData({ mode: "delete", persona_id: personaId, file_id: data.delete, env: args.env }, client, (path) => fs.readFile(path));
3957
+ return handleDataExtracted({ method: "delete", persona_id: personaId, data: { file_id: data.delete }, env: args.env }, client, readFileFn);
4061
3958
  }
4062
3959
  if (typeof data.generate === "string" || data.template) {
4063
- return handleData({
4064
- mode: "generate",
3960
+ return handleDataExtracted({
3961
+ method: "generate",
4065
3962
  persona_id: personaId,
4066
- input: data.generate,
4067
- from: data.template,
4068
- count: data.count,
3963
+ data: {
3964
+ input: data.generate,
3965
+ from: data.template,
3966
+ count: data.count,
3967
+ },
4069
3968
  env: args.env
4070
- }, client, (path) => fs.readFile(path));
3969
+ }, client, readFileFn);
4071
3970
  }
4072
3971
  if (typeof data.embed === "boolean") {
4073
- return handleData({ mode: "embedding", persona_id: personaId, enabled: data.embed, env: args.env }, client, (path) => fs.readFile(path));
3972
+ return handleDataExtracted({ method: "embedding", persona_id: personaId, data: { enabled: data.embed }, env: args.env }, client, readFileFn);
4074
3973
  }
4075
3974
  if (typeof data.search === "string") {
4076
3975
  return handleKnowledge({ mode: "search", persona_id: personaId, query: data.search, env: args.env }, client, (path) => fs.readFile(path));
@@ -4149,7 +4048,9 @@ const toolHandlers = {
4149
4048
  data: async (args) => {
4150
4049
  const client = createClient(args.env);
4151
4050
  const fs = await import("fs/promises");
4152
- return handleData(args, client, (path) => fs.readFile(path));
4051
+ // Use extracted handler
4052
+ const { handleData: handleDataExtracted } = await import("./handlers/data/index.js");
4053
+ return handleDataExtracted(args, client, (path) => fs.readFile(path));
4153
4054
  },
4154
4055
  reference: async (args) => {
4155
4056
  // v2: expanded reference handler with envs, actions, templates, patterns support
@@ -4169,9 +4070,11 @@ const toolHandlers = {
4169
4070
  // catalog: Consolidated reference data (actions, templates, widgets, voices, patterns, concepts)
4170
4071
  catalog: async (args) => {
4171
4072
  const catalogType = args.type;
4073
+ const method = args.method;
4172
4074
  const id = args.id;
4173
4075
  const query = args.query;
4174
- const recommend = args.recommend;
4076
+ // Note: schema uses 'for' parameter for recommend (not 'recommend')
4077
+ const forUseCase = args.for;
4175
4078
  const category = args.category;
4176
4079
  const client = createClient(args.env);
4177
4080
  if (!catalogType) {
@@ -4183,9 +4086,16 @@ const toolHandlers = {
4183
4086
  switch (catalogType) {
4184
4087
  case "actions": {
4185
4088
  // Route to action handler
4186
- if (recommend) {
4187
- const suggestions = suggestAgentsForUseCase(recommend);
4188
- return { type: "actions", use_case: recommend, recommendations: suggestions };
4089
+ if (method === "recommend" && forUseCase) {
4090
+ const suggestions = suggestAgentsForUseCase(forUseCase);
4091
+ return {
4092
+ type: "actions",
4093
+ use_case: forUseCase,
4094
+ recommendations: suggestions,
4095
+ _tip: suggestions.length > 0
4096
+ ? `Found ${suggestions.length} relevant agents. Use catalog(method="get", type="actions", id="<name>") for details.`
4097
+ : "No specific recommendations. Try browsing with catalog(method=\"list\", type=\"actions\").",
4098
+ };
4189
4099
  }
4190
4100
  if (id) {
4191
4101
  const action = getAgentByName(id);
@@ -4209,7 +4119,9 @@ const toolHandlers = {
4209
4119
  return {
4210
4120
  type: "actions",
4211
4121
  count: actions.length,
4212
- actions: actions.map(a => ({ name: a.actionName, displayName: a.displayName, category: a.category, description: a.description }))
4122
+ actions: actions.map(a => ({ name: a.actionName, displayName: a.displayName, category: a.category, description: a.description })),
4123
+ _tip: "Get details: catalog(method=\"get\", type=\"actions\", id=\"<name>\")",
4124
+ _next_step: actions.length > 0 ? `catalog(method="get", type="actions", id="${actions[0].actionName}")` : undefined,
4213
4125
  };
4214
4126
  }
4215
4127
  case "templates": {
@@ -4231,7 +4143,13 @@ const toolHandlers = {
4231
4143
  return {
4232
4144
  type: "templates",
4233
4145
  count: filtered.length,
4234
- templates: filtered.map(t => ({ id: t.id, name: t.name, description: t.description }))
4146
+ templates: filtered.map(t => ({ id: t.id, name: t.name, description: t.description })),
4147
+ _tip: filtered.length > 0
4148
+ ? "Create from template: persona(method=\"create\", name=\"My AI\", from=\"<template_id>\")"
4149
+ : "No templates found. Create from scratch: persona(method=\"create\", name=\"My AI\", type=\"voice|chat|dashboard\")",
4150
+ _next_step: filtered.length > 0
4151
+ ? `catalog(method="get", type="templates", id="${filtered[0].id}")`
4152
+ : undefined,
4235
4153
  };
4236
4154
  }
4237
4155
  case "widgets": {
@@ -4266,13 +4184,20 @@ const toolHandlers = {
4266
4184
  };
4267
4185
  }
4268
4186
  case "patterns": {
4269
- if (recommend) {
4187
+ if (method === "recommend" && forUseCase) {
4270
4188
  // Find patterns matching use case
4271
- const q = recommend.toLowerCase();
4189
+ const q = forUseCase.toLowerCase();
4272
4190
  const matches = WORKFLOW_PATTERNS.filter(p => p.name.toLowerCase().includes(q) ||
4273
4191
  p.description.toLowerCase().includes(q) ||
4274
4192
  p.useCase.toLowerCase().includes(q));
4275
- return { type: "patterns", use_case: recommend, recommendations: matches };
4193
+ return {
4194
+ type: "patterns",
4195
+ use_case: forUseCase,
4196
+ recommendations: matches,
4197
+ _tip: matches.length > 0
4198
+ ? `Found ${matches.length} matching patterns. Use catalog(method="get", type="patterns", id="<name>") for full details.`
4199
+ : "No matching patterns. Try catalog(method=\"list\", type=\"patterns\") to see all available.",
4200
+ };
4276
4201
  }
4277
4202
  if (id) {
4278
4203
  const pattern = WORKFLOW_PATTERNS.find(p => p.name === id);
@@ -4324,14 +4249,14 @@ const toolHandlers = {
4324
4249
  // Note: demo is handled via a consolidated adapter below
4325
4250
  };
4326
4251
  // ─────────────────────────────────────────────────────────────────────────────
4327
- // Consolidated Tool Adapters (contract ↔ implementation)
4252
+ // V2 Tool Adapters (contract ↔ implementation)
4328
4253
  // ─────────────────────────────────────────────────────────────────────────────
4329
4254
  //
4330
- // The tool schemas in tools-consolidated.ts are the public MCP contract.
4331
- // This file still contains a number of proven "legacy" handlers that we reuse
4255
+ // The tool schemas in tools.ts are the public MCP contract.
4256
+ // This file still contains proven handlers that we reuse
4332
4257
  // (e.g. deploy_workflow, optimize_workflow, compile_workflow, etc.).
4333
4258
  //
4334
- // These adapters ensure the consolidated tool surface behaves as documented,
4259
+ // These adapters ensure the V2 tool surface behaves as documented,
4335
4260
  // while preserving the existing internal implementations.
4336
4261
  const legacyWorkflowTool = toolHandlers.workflow;
4337
4262
  const legacyDeployWorkflow = toolHandlers.deploy_workflow;
@@ -4347,110 +4272,27 @@ const legacyConsolidateDemoData = toolHandlers.consolidate_demo_data;
4347
4272
  const legacyGenerateDemoDocument = toolHandlers.generate_demo_document;
4348
4273
  const legacyValidateDemoDocument = toolHandlers.validate_demo_document;
4349
4274
  const legacyGetDemoDataTemplate = toolHandlers.get_demo_data_template;
4350
- // Unify workflow modes: generate | analyze | deploy | optimize | compare | compile
4275
+ // Workflow tool: MCP provides data (get) and executes (deploy). LLM does all thinking.
4351
4276
  toolHandlers.workflow = async (args) => {
4352
- // Normalize persona type alias: tool schema uses "type", internal uses "persona_type"
4353
4277
  const normalizedArgs = { ...(args ?? {}) };
4354
- if (normalizedArgs.persona_type === undefined && normalizedArgs.type !== undefined) {
4355
- normalizedArgs.persona_type = normalizedArgs.type;
4356
- }
4357
4278
  const personaId = normalizedArgs.persona_id ? String(normalizedArgs.persona_id) : undefined;
4358
4279
  const workflowDef = normalizedArgs.workflow_def;
4359
- const inputProvided = normalizedArgs.input !== undefined;
4360
- // Normalize mode aliases
4361
- const rawMode = normalizedArgs.mode ? String(normalizedArgs.mode) : undefined;
4362
- const mode = rawMode === "improve" ? "optimize" : rawMode;
4363
- // Default mode selection:
4364
- // - persona_id + workflow_def deploy (direct deployment, no input needed)
4365
- // - persona_id + input → modify (BROWNFIELD: generate new workflow from input)
4366
- // - persona_id only or workflow_def → analyze (inspect)
4367
- // - input only → generate (GREENFIELD: create from scratch)
4368
- // - Otherwise → generate (and prompt for missing info)
4369
- const effectiveMode = mode ??
4370
- (personaId && workflowDef ? "deploy" : // Direct deployment (no input required)
4371
- personaId && inputProvided ? "modify" : // BROWNFIELD: existing persona + new requirements
4372
- workflowDef || personaId ? "analyze" : // Inspect existing
4373
- "generate"); // GREENFIELD: new workflow
4374
- switch (effectiveMode) {
4375
- case "generate": {
4376
- const result = await legacyWorkflowTool({ ...normalizedArgs, mode: "generate" });
4377
- // Ensure next_steps point at consolidated tools by default
4378
- if (result && typeof result === "object") {
4379
- const obj = result;
4380
- const persona_id = obj.persona_id ? String(obj.persona_id) : personaId;
4381
- const deployed = obj.deployed === true;
4382
- obj.next_steps = deployed
4383
- ? persona_id
4384
- ? [`Verify: persona(id="${persona_id}", include_workflow=true)`]
4385
- : ["Verify the deployed AI Employee in the Ema UI"]
4386
- : persona_id
4387
- ? [
4388
- `Deploy: workflow(mode="deploy", persona_id="${persona_id}", workflow_def=<workflow_def>, proto_config=<proto_config>)`,
4389
- `Verify: persona(id="${persona_id}", include_workflow=true)`,
4390
- ]
4391
- : [
4392
- "Create an AI Employee in Ema, then deploy:",
4393
- `workflow(mode="deploy", persona_id="<persona_id>", workflow_def=<workflow_def>, proto_config=<proto_config>)`,
4394
- ];
4395
- }
4396
- return result;
4397
- }
4398
- case "analyze": {
4399
- const include = Array.isArray(normalizedArgs.include)
4400
- ? normalizedArgs.include.map(String)
4401
- : ["issues", "connections", "fixes", "metrics"];
4402
- let wf = workflowDef;
4403
- let meta;
4404
- if (!wf && personaId) {
4405
- const client = createClient(normalizedArgs.env);
4406
- const persona = await client.getPersonaById(personaId);
4407
- if (!persona)
4408
- throw new Error(`AI Employee not found: ${personaId}`);
4409
- wf = persona.workflow_def;
4410
- meta = {
4411
- persona_id: personaId,
4412
- persona_name: persona.name,
4413
- environment: client["env"].name,
4414
- };
4415
- }
4416
- if (!wf) {
4417
- return {
4418
- error: "Missing workflow to analyze. Provide persona_id or workflow_def.",
4419
- hint: 'Examples: workflow(mode="analyze", persona_id="...") or workflow(mode="analyze", workflow_def={...})',
4420
- };
4421
- }
4422
- const out = { mode: "analyze", ...(meta ?? {}) };
4423
- // Issues + summary (source of truth)
4424
- const issuesResult = await legacyDetectWorkflowIssues({ workflow_def: wf });
4425
- const issues = issuesResult.issues;
4426
- if (include.includes("issues")) {
4427
- out.issues = issuesResult.issues;
4428
- out.issue_summary = issuesResult.summary;
4429
- out.validation_passed = issuesResult.validation_passed;
4430
- }
4431
- if (include.includes("connections")) {
4432
- out.connections = await legacyValidateWorkflowConnections({ workflow_def: wf });
4433
- }
4434
- if (include.includes("fixes")) {
4435
- out.fixes = Array.isArray(issues) ? await legacySuggestWorkflowFixes({ issues }) : { error: "No issues array available to generate fixes" };
4436
- }
4437
- if (include.includes("metrics")) {
4438
- const actions = wf.actions ?? [];
4439
- const edges = wf.edges ?? [];
4440
- out.metrics = {
4441
- node_count: Array.isArray(actions) ? actions.length : 0,
4442
- edge_count: Array.isArray(edges) ? edges.length : 0,
4443
- };
4444
- }
4445
- return out;
4280
+ const mode = normalizedArgs.mode ? String(normalizedArgs.mode) : undefined;
4281
+ // Route to handleWorkflow for get/deploy (the only public modes)
4282
+ const client = createClient(normalizedArgs.env);
4283
+ switch (mode) {
4284
+ case "get": {
4285
+ // Return workflow data for LLM to analyze/modify
4286
+ return handleWorkflow({
4287
+ mode: "get",
4288
+ persona_id: personaId,
4289
+ env: normalizedArgs.env,
4290
+ }, client, () => undefined);
4446
4291
  }
4447
4292
  case "deploy": {
4448
4293
  if (!personaId) {
4449
- throw new Error('persona_id is required for workflow(mode="deploy")');
4294
+ return { error: 'persona_id is required for workflow(mode="deploy")' };
4450
4295
  }
4451
- // Use clean deploy path via handleWorkflow (no brownfield merge, no excessive validation)
4452
- // User can still request validation via validate=true, but default is now direct deploy
4453
- const client = createClient(normalizedArgs.env);
4454
4296
  // Optional: pre-deploy version snapshot
4455
4297
  const targetEnv = normalizedArgs.env ?? getDefaultEnvName();
4456
4298
  let versionCreated;
@@ -4476,8 +4318,7 @@ toolHandlers.workflow = async (args) => {
4476
4318
  catch {
4477
4319
  // Version tracking is best-effort
4478
4320
  }
4479
- // Route to clean handleWorkflow deploy (handlers-consolidated.ts)
4480
- // This path: sanitizes workflow → calls client.updateAiEmployee → done
4321
+ // Route to handleWorkflow deploy
4481
4322
  const deployResult = await handleWorkflow({
4482
4323
  mode: "deploy",
4483
4324
  persona_id: personaId,
@@ -4491,58 +4332,25 @@ toolHandlers.workflow = async (args) => {
4491
4332
  }
4492
4333
  return deployResult;
4493
4334
  }
4494
- case "optimize": {
4495
- // optimize_workflow supports both:
4496
- // - fix mode: id (name/id) OR persona_id
4497
- // - generate mode: persona_id + prompt
4498
- const preview = normalizedArgs.preview === true;
4499
- const id = normalizedArgs.id ? String(normalizedArgs.id) : undefined;
4500
- const identifier = normalizedArgs.identifier ? String(normalizedArgs.identifier) : undefined; // deprecated alias
4501
- const idOrIdentifier = id ?? identifier;
4502
- // If a natural-language workflow "input" is provided, treat it as a prompt to optimize_workflow.
4503
- const input = normalizedArgs.input;
4504
- const prompt = typeof input === "string" ? input : undefined;
4505
- return legacyOptimizeWorkflow({
4506
- identifier: idOrIdentifier ?? personaId,
4507
- persona_id: personaId,
4508
- prompt,
4509
- type: normalizedArgs.persona_type,
4510
- preview,
4511
- env: normalizedArgs.env,
4512
- });
4513
- }
4514
- case "compare": {
4515
- if (!personaId) {
4516
- throw new Error('persona_id is required for workflow(mode="compare")');
4517
- }
4518
- const compareTo = normalizedArgs.compare_to ? String(normalizedArgs.compare_to) : undefined;
4519
- if (!compareTo) {
4520
- throw new Error('compare_to is required for workflow(mode="compare")');
4521
- }
4522
- return legacyCompareWorkflowVersions({
4523
- persona_id_before: personaId,
4524
- persona_id_after: compareTo,
4525
- env: normalizedArgs.env,
4526
- });
4527
- }
4528
- case "compile": {
4529
- // Compile requires node specs + result mappings.
4530
- if (!normalizedArgs.name || !normalizedArgs.description) {
4531
- throw new Error('workflow(mode="compile") requires name and description');
4532
- }
4533
- if (!normalizedArgs.persona_type) {
4534
- throw new Error('workflow(mode="compile") requires persona type via type="voice|chat|dashboard"');
4535
- }
4536
- return legacyCompileWorkflow({
4537
- name: normalizedArgs.name,
4538
- description: normalizedArgs.description,
4539
- persona_type: normalizedArgs.persona_type,
4540
- nodes: normalizedArgs.nodes,
4541
- result_mappings: normalizedArgs.result_mappings,
4542
- });
4335
+ // REMOVED modes - LLM does these
4336
+ case "analyze":
4337
+ case "compare":
4338
+ case "compile":
4339
+ case "optimize":
4340
+ case "generate": {
4341
+ return {
4342
+ error: `Mode "${mode}" removed - LLM does this thinking`,
4343
+ hint: "Use workflow(mode='get') to fetch data, then analyze/generate in your reasoning. Deploy with workflow(mode='deploy').",
4344
+ valid_modes: ["get", "deploy"],
4345
+ };
4543
4346
  }
4544
4347
  default: {
4545
- return legacyWorkflowTool({ ...normalizedArgs, mode: effectiveMode });
4348
+ // No mode or unknown mode - require explicit mode
4349
+ return {
4350
+ error: `Mode required. Valid modes: get, deploy`,
4351
+ hint: "workflow(mode='get') returns data for LLM. workflow(mode='deploy') executes LLM's workflow_def.",
4352
+ example: `workflow(mode="get", persona_id="...")`,
4353
+ };
4546
4354
  }
4547
4355
  }
4548
4356
  };
@@ -4904,8 +4712,8 @@ function determineOperation(toolName, args) {
4904
4712
  if (toolName === "catalog") {
4905
4713
  if (args.id)
4906
4714
  return "get";
4907
- if (args.recommend)
4908
- return "recommend";
4715
+ if (args.for)
4716
+ return "recommend"; // V2 schema uses 'for' parameter
4909
4717
  if (args.query)
4910
4718
  return "search";
4911
4719
  return "list";