@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
@@ -28,15 +28,23 @@ Some clients show a **prefixed name** (for example Cursor: `mcp_ema_persona`). A
28
28
  | `reference` | Envs, actions, templates, patterns, concepts, guidance | No (flag-based) |
29
29
  | `sync` | Sync across environments | **YES** |
30
30
 
31
+ ### `workflow` tool (get/deploy only)
32
+
33
+ | Mode | Purpose |
34
+ |------|---------|
35
+ | `get` | Returns workflow_def, schema, examples for LLM |
36
+ | `deploy` | Deploys LLM-generated workflow_def |
37
+
38
+ **LLM does all thinking** (analyze, compare, generate). MCP only provides data and executes.
39
+
31
40
  ### Deprecated tools (still work, show warnings)
32
41
 
33
42
  | Tool | Status | Use Instead |
34
43
  |------|--------|-------------|
35
- | `workflow` | Deprecated | `persona` |
36
44
  | `knowledge` | Deprecated | `data` |
37
45
  | `demo` | Deprecated | `data` + `persona` |
38
46
 
39
- > **Tip**: For new code, use `persona`, `data`, `sync`. Deprecated tools route internally to new ones.
47
+ > **Tip**: For new code, use `persona`, `data`, `workflow`, `sync`.
40
48
 
41
49
  ## ⚠️ THE KEY INSIGHT: ONE CALL
42
50
 
@@ -102,21 +110,19 @@ persona(
102
110
  persona(mode="get", id="abc-123")
103
111
 
104
112
  // Modify config in ONE call
105
- persona(mode="update", id="abc-123", proto_config={widgets: [{name: "conversationSettings", conversationSettings: {...}}]})
113
+ persona(mode="update", id="abc-123", config={widgets: [{name: "conversationSettings", conversationSettings: {...}}]})
106
114
  ```
107
115
 
108
- ### Analyze/Review an AI Employee
116
+ ### Get workflow data (for LLM to analyze/modify)
109
117
 
110
118
  ```typescript
111
- persona(mode="get", id="abc-123") // Get persona
112
- persona(mode="get", id="abc-123", include_workflow=true) // Include full workflow
119
+ workflow(mode="get", persona_id="abc-123") // Returns workflow_def, schema, examples
113
120
  ```
114
121
 
115
- ### Optimize (auto-fix issues)
122
+ The LLM then analyzes/modifies the workflow and deploys:
116
123
 
117
124
  ```typescript
118
- persona(mode="update", id="abc-123", optimize=true) // Preview fixes
119
- persona(mode="update", id="abc-123", optimize=true, preview=false) // Apply fixes
125
+ workflow(mode="deploy", persona_id="abc-123", workflow_def={...}) // Deploy LLM's result
120
126
  ```
121
127
 
122
128
  ### Upload / manage knowledge base documents
@@ -212,7 +218,7 @@ knowledge(persona_id="target", mode="dashboard_clone", source_persona_id="source
212
218
  persona(mode="version_create", id="My Bot", message="Before adding HITL")
213
219
 
214
220
  // Make changes...
215
- persona(mode="update", id="abc", proto_config={...})
221
+ persona(mode="update", id="abc", config={...})
216
222
 
217
223
  // If something breaks - restore
218
224
  persona(mode="version_list", id="My Bot")
@@ -241,7 +247,7 @@ persona(mode="create", from="Voice AI Starter", name="My Bot", input="...", prev
241
247
 
242
248
  **Update config:**
243
249
  ```typescript
244
- persona(mode="update", id="abc", proto_config={widgets: [{...}]})
250
+ persona(mode="update", id="abc", config={widgets: [{...}]})
245
251
  ```
246
252
 
247
253
  **Clone:**
@@ -249,34 +255,12 @@ persona(mode="update", id="abc", proto_config={widgets: [{...}]})
249
255
  persona(mode="clone", from="source-id", name="My Copy", include_data=true)
250
256
  ```
251
257
 
252
- **Compare:**
253
- ```typescript
254
- persona(mode="compare", id="abc", compare_to="def")
255
- ```
256
-
257
258
  **Sanitize (two-step process):**
258
259
  ```typescript
259
260
  persona(id="abc", sanitize=true) // Step 1: Preview - identify PII
260
261
  persona(id="abc", sanitize=true, sanitize_examples=["Acme"], preview=false) // Step 2: Apply
261
262
  ```
262
263
 
263
- **Analyze (recommended):**
264
- ```typescript
265
- persona(mode="analyze", id="abc") // All aspects
266
- persona(mode="analyze", id="abc", include=["workflow"]) // Workflow only
267
- persona(mode="analyze", id="abc", include=["workflow", "config", "data"])
268
- ```
269
-
270
- **Analyze + auto-fix:**
271
- ```typescript
272
- persona(mode="analyze", id="abc", fix=true)
273
- ```
274
-
275
- **Legacy (deprecated, use mode="analyze" instead):**
276
- ```typescript
277
- persona(id="abc", optimize=true) // Routes to workflow tool internally
278
- ```
279
-
280
264
  **Intent (qualification for complex requests):**
281
265
  ```typescript
282
266
  // GREENFIELD: New persona creation
@@ -299,7 +283,7 @@ Returns:
299
283
  - `status: "needs_qualification"` → `questions` to answer before proceeding
300
284
  - `status: "needs_llm"` → `llm_prompt` to send to LLM for IntentSpec generation
301
285
 
302
- For brownfield, combine with `mode="analyze"` to get current state, then use intent to qualify the change.
286
+ For brownfield, use `workflow(mode="get")` to fetch current state, then use intent to qualify the change.
303
287
 
304
288
  **Templates:**
305
289
  ```typescript
@@ -456,19 +440,27 @@ Start with:
456
440
  - `ema://catalog/templates` (persona templates - dynamic)
457
441
  - `ema://rules/anti-patterns` (what NOT to do)
458
442
 
459
- ## Auto-Fix Capabilities
443
+ ## Workflow Generation (LLM Does the Work)
460
444
 
461
- The `persona(mode="update", id="...", optimize=true)` can automatically fix common issues:
445
+ **MCP provides data and schema. LLM generates workflow_def.**
446
+
447
+ ```typescript
448
+ // 1. Get current workflow + schema
449
+ result = workflow(mode="get", persona_id="abc")
450
+ // Returns: workflow_def, generation_schema, example_workflow, requirements
451
+
452
+ // 2. LLM analyzes and generates new workflow_def
453
+ // (LLM uses schema and examples to build valid workflow)
454
+
455
+ // 3. Deploy LLM's result
456
+ workflow(mode="deploy", persona_id="abc", workflow_def={...})
457
+ ```
462
458
 
463
- | Issue | Severity | Auto-Fix? | Action |
464
- |-------|----------|-----------|--------|
465
- | `orphan` | warning | ✅ | Removes unreachable nodes |
466
- | `dead_end` | critical | | Adds results mapping |
467
- | `missing_workflow_output` | critical | ✅ | Adds results mapping |
468
- | `wrong_input_source` (email_to) | warning | ✅ | Adds entity_extraction |
469
- | `missing_fallback` | critical | ✅ | Adds Fallback category |
470
- | `type_mismatch` | critical | ✅ | Rewires to compatible source |
471
- | `cycle` | critical | ❌ | Requires manual restructuring |
459
+ **Common issues to check when generating:**
460
+ - Missing `WORKFLOW_OUTPUT` in results
461
+ - Missing Fallback category in categorizers
462
+ - Orphan nodes not connected to output
463
+ - Type mismatches between connected nodes
472
464
 
473
465
  ## HITL (Human-in-the-Loop) Policy
474
466
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ema.co/mcp-toolkit",
3
- "version": "2026.1.25",
3
+ "version": "2026.1.26-4",
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",
@@ -52,18 +52,24 @@
52
52
  "lint:unused": "knip",
53
53
  "precommit": "npm run typecheck && npm run test",
54
54
  "prepare": "husky",
55
- "prepublishOnly": "npm run build && npm run test",
55
+ "check:publish": "tsx scripts/check-publish-content.ts",
56
+ "prepublishOnly": "npm run build && npm run test && npm run check:publish",
56
57
  "generate:types": "tsx scripts/generate-types.ts",
57
58
  "generate:api-client": "npx @hey-api/openapi-ts -i src/sdk/generated/openapi.json -o src/sdk/generated/api-client -c @hey-api/client-fetch",
58
59
  "generate:protos": "buf generate ../ema-repos/protos --template buf.gen.yaml",
59
60
  "generate:proto-fields": "tsx scripts/generate-proto-fields.ts",
60
61
  "generate:action-schema": "tsx scripts/generate-action-schema.ts",
61
- "generate:all": "npm run generate:protos && npm run generate:api-client",
62
+ "generate:deprecated-actions": "tsx scripts/generate-deprecated-actions.ts",
63
+ "generate:skill": "tsx scripts/generate-skill.ts",
64
+ "generate:skill:check": "tsx scripts/generate-skill.ts --check",
65
+ "generate:templates": "tsx scripts/generate-templates.ts",
66
+ "generate:templates:check": "tsx scripts/generate-templates.ts --check",
67
+ "generate:all": "npm run generate:protos && npm run generate:api-client && npm run generate:templates && npm run generate:skill",
62
68
  "check:contracts": "tsx scripts/check-api-contracts.ts",
63
69
  "check:schema-sync": "tsx scripts/check-schema-handler-sync.ts",
64
70
  "check:prompt-refs": "tsx scripts/check-prompt-refs.ts",
65
71
  "check:action-aliases": "tsx scripts/check-action-aliases.ts",
66
- "check:all": "npm run check:contracts && npm run check:schema-sync && npm run check:prompt-refs && npm run check:action-aliases",
72
+ "check:all": "npm run check:contracts && npm run check:schema-sync && npm run check:prompt-refs && npm run check:action-aliases && npm run generate:skill:check",
67
73
  "release:check": "tsx scripts/check-release-need.ts"
68
74
  },
69
75
  "repository": {
@@ -1,275 +0,0 @@
1
- /**
2
- * Persona ANALYZE mode handler
3
- *
4
- * Analyzes a persona for issues in workflow, config, and data.
5
- * Returns decompiled WorkflowSpec + schema for LLM-native modifications.
6
- *
7
- * ARCHITECTURE NOTE: MCP provides context, Agent proposes fixes.
8
- * The `fix` parameter is DEPRECATED - agent should build workflow_spec fixes.
9
- */
10
- import { resolvePersona } from "../utils.js";
11
- import { detectWorkflowIssues, suggestWorkflowFixes } from "../../../sdk/knowledge.js";
12
- import { autoFixWorkflow } from "../../../sdk/workflow-fixer.js";
13
- import { decompileWorkflow, summarizeSpec, WORKFLOW_SCHEMA_FOR_LLM } from "../../../sdk/workflow-transformer.js";
14
- import { hasFallback, GUIDANCE_RULES } from "../../../sdk/guidance.js";
15
- /**
16
- * Handle persona(mode="analyze") - analyze persona for issues
17
- *
18
- * @param args.id - Persona ID or name (required)
19
- * @param args.fix - DEPRECATED: Returns preview instead of deploying. Agent should build workflow_spec.
20
- * @param args.include - Aspects to analyze (workflow, config, data)
21
- */
22
- export async function handleAnalyze(args, client) {
23
- const idOrName = (args.id ?? args.identifier);
24
- if (!idOrName) {
25
- return { status: "error", error: "id required for analyze mode" };
26
- }
27
- const persona = await resolvePersona(client, idOrName);
28
- if (!persona) {
29
- return { status: "error", error: `Persona not found: ${idOrName}` };
30
- }
31
- const fix = args.fix;
32
- const includeAspects = args.include ?? ["workflow", "config", "data"];
33
- // Collect issues across all aspects
34
- const issues = [];
35
- const fixesApplied = [];
36
- // ── Analyze Workflow ──
37
- if (includeAspects.includes("workflow") && persona.workflow_def) {
38
- const workflowDef = persona.workflow_def;
39
- // Use the sophisticated workflow issue detection
40
- const workflowIssues = detectWorkflowIssues(workflowDef);
41
- const suggestedFixes = suggestWorkflowFixes(workflowIssues);
42
- // Map workflow issues to our uniform format
43
- for (const issue of workflowIssues) {
44
- const wfIssue = issue;
45
- const severityMap = {
46
- "critical": "critical",
47
- "warning": "warning",
48
- "info": "info",
49
- };
50
- const matchingFix = suggestedFixes.find(f => f.issue_type === wfIssue.type);
51
- issues.push({
52
- id: `wf-${wfIssue.type}-${wfIssue.node || "global"}`,
53
- severity: severityMap[wfIssue.severity] || "warning",
54
- category: "workflow",
55
- title: `${wfIssue.type}${wfIssue.node ? `: ${wfIssue.node}` : ""}`,
56
- description: wfIssue.reason,
57
- auto_fixable: !!matchingFix,
58
- fix_description: matchingFix?.description,
59
- });
60
- }
61
- }
62
- // ── Analyze Config ──
63
- if (includeAspects.includes("config") && persona.proto_config) {
64
- const protoConfig = persona.proto_config;
65
- const widgets = (protoConfig.widgets || []);
66
- // Check for malformed widgets
67
- for (const widget of widgets) {
68
- const widgetName = widget.name;
69
- if (!widgetName || widgetName.trim() === "") {
70
- issues.push({
71
- id: `widget-empty-name`,
72
- severity: "warning",
73
- category: "config",
74
- title: "Widget with empty name",
75
- description: "A widget has an empty or missing name field",
76
- auto_fixable: false,
77
- });
78
- }
79
- }
80
- // Check for generic description
81
- const description = persona.description;
82
- if (!description || description.length < 20 || description.includes("template")) {
83
- issues.push({
84
- id: `generic-description`,
85
- severity: "info",
86
- category: "metadata",
87
- title: "Generic or missing description",
88
- description: "Persona description appears to be a template default or too short",
89
- auto_fixable: false,
90
- });
91
- }
92
- }
93
- // ── Analyze Data Sources ──
94
- if (includeAspects.includes("data")) {
95
- try {
96
- const dataSources = await client.listDataSourceFiles(persona.id);
97
- const files = dataSources.files || [];
98
- // Check data source health
99
- if (files.length === 0) {
100
- issues.push({
101
- id: `no-data-sources`,
102
- severity: "info",
103
- category: "data",
104
- title: "No data sources uploaded",
105
- description: "Persona has no knowledge files - Knowledge Agent won't have context to search",
106
- auto_fixable: false,
107
- });
108
- }
109
- // Check for failed uploads
110
- for (const file of files) {
111
- if (file.status === "failed" || file.status === "error") {
112
- issues.push({
113
- id: `failed-upload-${file.id}`,
114
- severity: "warning",
115
- category: "data",
116
- title: `Failed upload: ${file.filename}`,
117
- description: `File upload failed with status: ${file.status}`,
118
- auto_fixable: false,
119
- });
120
- }
121
- }
122
- }
123
- catch {
124
- // Data source listing may fail for some persona types
125
- }
126
- }
127
- // ── Handle fix parameter (DEPRECATED) ──
128
- // DEPRECATED: fix=true no longer auto-deploys. Returns preview for agent to review.
129
- // Architecture: MCP provides context, Agent proposes and builds fixes.
130
- let fixPreview;
131
- if (fix && persona.workflow_def) {
132
- // Log deprecation warning
133
- console.warn("[DEPRECATED] fix=true is deprecated. MCP should not auto-fix - agent builds workflow_spec.\n" +
134
- "See CLAUDE.md 'MCP vs Agent: Separation of Duties'.\n" +
135
- "Returning preview instead of deploying.");
136
- const workflowDef = persona.workflow_def;
137
- const fixResult = autoFixWorkflow(workflowDef);
138
- // Record what would be fixed
139
- for (const applied of fixResult.fixesApplied) {
140
- fixesApplied.push({
141
- issue_id: applied.issueType,
142
- action: applied.description,
143
- result: "preview", // Changed from success/failed to preview
144
- });
145
- }
146
- // Return preview instead of deploying
147
- if (fixResult.fixesApplied.length > 0 && fixResult.success) {
148
- // Determine persona type for decompile
149
- const protoConfig = persona.proto_config;
150
- const projectSettings = protoConfig?.projectSettings;
151
- const personaType = projectSettings?.projectType === 5 ? "voice" : "chat";
152
- try {
153
- fixPreview = {
154
- proposed_spec: decompileWorkflow(fixResult.workflowDef, personaType),
155
- changes: fixResult.fixesApplied.map(f => f.description),
156
- };
157
- }
158
- catch {
159
- // Decompile failed, just note the changes
160
- fixPreview = {
161
- changes: fixResult.fixesApplied.map(f => f.description),
162
- };
163
- }
164
- }
165
- }
166
- // ── Build Response ──
167
- const analysisSummary = {
168
- total_issues: issues.length,
169
- by_severity: {
170
- critical: issues.filter(i => i.severity === "critical").length,
171
- warning: issues.filter(i => i.severity === "warning").length,
172
- info: issues.filter(i => i.severity === "info").length,
173
- },
174
- by_category: {
175
- workflow: issues.filter(i => i.category === "workflow").length,
176
- config: issues.filter(i => i.category === "config").length,
177
- data: issues.filter(i => i.category === "data").length,
178
- metadata: issues.filter(i => i.category === "metadata").length,
179
- },
180
- };
181
- const status = analysisSummary.by_severity.critical > 0
182
- ? "critical"
183
- : analysisSummary.total_issues > 0
184
- ? "issues_found"
185
- : "healthy";
186
- // ── Decompile Workflow for LLM-native modifications ──
187
- let workflowSpec;
188
- let workflowSummary;
189
- if (persona.workflow_def) {
190
- const workflowDef = persona.workflow_def;
191
- // Determine persona type
192
- const protoConfig = persona.proto_config;
193
- const projectSettings = protoConfig?.projectSettings;
194
- const personaType = projectSettings?.projectType === 5 ? "voice" : "chat";
195
- try {
196
- workflowSpec = decompileWorkflow(workflowDef, personaType);
197
- workflowSummary = summarizeSpec(workflowSpec);
198
- }
199
- catch (e) {
200
- // Decompile failed - include error in response
201
- workflowSummary = `Decompile failed: ${e instanceof Error ? e.message : String(e)}`;
202
- }
203
- }
204
- const result = {
205
- status,
206
- persona: { id: persona.id, name: persona.name },
207
- summary: analysisSummary,
208
- issues,
209
- };
210
- // Include workflow_spec for LLM-native modifications (unless include_spec=false)
211
- const includeSpec = args.include_spec !== false;
212
- if (includeSpec && workflowSpec) {
213
- result.workflow_spec = workflowSpec;
214
- result.workflow_summary = workflowSummary;
215
- result.schema = WORKFLOW_SCHEMA_FOR_LLM;
216
- result.modification_hint =
217
- "To modify this workflow:\n" +
218
- "1. Analyze the workflow_spec above\n" +
219
- "2. Modify the spec (add/remove/update nodes, change inputs/outputs)\n" +
220
- "3. Call persona(id=\"" + persona.id + "\", update={workflow_spec: <modified_spec>})\n" +
221
- "\n" +
222
- "The SDK will compile your WorkflowSpec to workflow_def and deploy it.";
223
- // Add workflow-specific guidance based on state
224
- const workflowGuidance = [];
225
- // Check for Fallback in categorizers
226
- if (!hasFallback(workflowSpec)) {
227
- const fallbackRule = GUIDANCE_RULES.find(r => r.id === "categorizer-fallback");
228
- if (fallbackRule) {
229
- workflowGuidance.push(`⚠️ ${fallbackRule.title}: ${fallbackRule.do}`);
230
- }
231
- }
232
- // Add general workflow tips
233
- const previewRule = GUIDANCE_RULES.find(r => r.id === "preview-before-deploy");
234
- if (previewRule) {
235
- workflowGuidance.push(`💡 ${previewRule.title}: ${previewRule.do}`);
236
- }
237
- if (workflowGuidance.length > 0) {
238
- result.workflow_guidance = workflowGuidance;
239
- }
240
- }
241
- if (fix) {
242
- // DEPRECATED: Return preview, not deployment result
243
- result.deprecation_warning =
244
- "fix=true is DEPRECATED. MCP should not auto-fix workflows.\n" +
245
- "The agent should review issues, ask the user which to fix, " +
246
- "build the workflow_spec, and call persona(update={workflow_spec: ...})";
247
- if (fixPreview) {
248
- result.fix_preview = {
249
- status: "preview_only",
250
- proposed_changes: fixPreview.changes,
251
- proposed_spec: fixPreview.proposed_spec,
252
- deploy_command: `persona(id="${persona.id}", update={workflow_spec: <proposed_spec above>})`,
253
- };
254
- }
255
- else {
256
- result.fix_preview = {
257
- status: "no_fixes_available",
258
- message: "No auto-fixable issues found. Review issues above and build fixes manually.",
259
- };
260
- }
261
- }
262
- else {
263
- // Guide agent to the correct flow (no mention of fix=true)
264
- result.next_steps = {
265
- has_issues: issues.length > 0,
266
- agent_action: issues.length > 0
267
- ? "Review issues above. Ask user which to fix. Build workflow_spec with fixes. Deploy via update."
268
- : "No issues found. Persona is healthy.",
269
- manual_actions: issues
270
- .filter(i => !i.auto_fixable)
271
- .map(i => `${i.title}: ${i.description}`),
272
- };
273
- }
274
- return result;
275
- }
@@ -1,32 +0,0 @@
1
- /**
2
- * Persona COMPARE mode handler
3
- *
4
- * Compares two personas, optionally across environments.
5
- */
6
- import { resolvePersona, comparePersonas } from "../utils.js";
7
- /**
8
- * Handle persona(mode="compare") - compare two personas
9
- *
10
- * @param args.id - First persona ID or name (required)
11
- * @param args.compare_to - Second persona ID or name (required)
12
- * @param args.compare_env - Optional environment for second persona
13
- * @param createClientForEnv - Factory to create client for different env
14
- */
15
- export async function handleCompare(args, client, createClientForEnv) {
16
- const idOrName = (args.id ?? args.identifier);
17
- if (!idOrName || !args.compare_to) {
18
- return { error: "id and compare_to required for compare mode" };
19
- }
20
- const persona1 = await resolvePersona(client, idOrName);
21
- const compareEnv = args.compare_env;
22
- const client2 = compareEnv && createClientForEnv ? createClientForEnv(compareEnv) : client;
23
- const persona2 = await resolvePersona(client2, args.compare_to);
24
- if (!persona1 || !persona2) {
25
- return { error: "One or both personas not found" };
26
- }
27
- return {
28
- persona_1: { id: persona1.id, name: persona1.name },
29
- persona_2: { id: persona2.id, name: persona2.name, env: compareEnv },
30
- differences: comparePersonas(persona1, persona2),
31
- };
32
- }