@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.
- package/README.md +10 -2
- package/dist/mcp/handlers/action/index.js +3 -18
- package/dist/mcp/handlers/data/index.js +385 -41
- package/dist/mcp/handlers/data/templates.js +107 -0
- package/dist/mcp/handlers/deprecation.js +50 -0
- package/dist/mcp/handlers/env/index.js +8 -4
- package/dist/mcp/handlers/knowledge/index.js +44 -237
- package/dist/mcp/handlers/persona/create.js +47 -18
- package/dist/mcp/handlers/persona/index.js +14 -11
- package/dist/mcp/handlers/persona/update.js +4 -2
- package/dist/mcp/handlers/persona/version.js +234 -0
- package/dist/mcp/handlers/sync/index.js +3 -18
- package/dist/mcp/handlers/template/index.js +75 -10
- package/dist/mcp/handlers/workflow/analyze.js +171 -0
- package/dist/mcp/handlers/workflow/compare.js +70 -0
- package/dist/mcp/handlers/workflow/deploy.js +73 -0
- package/dist/mcp/handlers/workflow/generate.js +350 -0
- package/dist/mcp/handlers/workflow/index.js +294 -0
- package/dist/mcp/handlers/workflow/modify.js +456 -0
- package/dist/mcp/handlers/workflow/optimize.js +136 -0
- package/dist/mcp/handlers/workflow/types.js +4 -0
- package/dist/mcp/handlers/workflow/utils.js +30 -0
- package/dist/mcp/handlers-consolidated.js +73 -2696
- package/dist/mcp/prompts.js +83 -43
- package/dist/mcp/resources.js +382 -57
- package/dist/mcp/server.js +199 -391
- package/dist/mcp/{tools-v2.js → tools.js} +20 -54
- package/dist/mcp/workflow-operations.js +2 -2
- package/dist/sdk/client-adapter.js +267 -32
- package/dist/sdk/client.js +45 -16
- package/dist/sdk/ema-client.js +183 -0
- package/dist/sdk/generated/deprecated-actions.js +171 -0
- package/dist/sdk/generated/template-fallbacks.js +123 -0
- package/dist/sdk/guidance.js +65 -11
- package/dist/sdk/index.js +3 -1
- package/dist/sdk/knowledge.js +139 -86
- package/dist/sdk/workflow-intent.js +27 -0
- package/dist/sdk/workflow-transformer.js +0 -342
- package/docs/mcp-tools-guide.md +37 -45
- package/package.json +10 -4
- package/dist/mcp/handlers/persona/analyze.js +0 -275
- package/dist/mcp/handlers/persona/compare.js +0 -32
- package/dist/mcp/tools-consolidated.js +0 -875
- package/dist/mcp/tools-legacy.js +0 -736
- package/docs/CODEBASE-ANALYSIS-2026-01-23.md +0 -936
- package/docs/CODEBASE-ANALYSIS-PRIORITIZED.md +0 -774
- package/docs/api-contracts.md +0 -216
- package/docs/auto-builder-analysis.md +0 -271
- package/docs/blog/mcp-tool-design-lessons.md +0 -309
- package/docs/data-architecture.md +0 -166
- package/docs/demos/ap-invoice-generation.md +0 -347
- package/docs/demos/ap-invoice-processing.md +0 -271
- package/docs/ema-auto-builder-guide.html +0 -394
- package/docs/lessons-learned.md +0 -209
- package/docs/llm-native-workflow-design.md +0 -252
- package/docs/local-generation.md +0 -508
- package/docs/mcp-flow-diagram.md +0 -135
- package/docs/migration/action-composition-migration.md +0 -270
- package/docs/naming-conventions.md +0 -278
- package/docs/proposals/HANDOFF-tool-restructure.md +0 -526
- package/docs/proposals/action-composition.md +0 -490
- package/docs/proposals/explicit-method-restructure.md +0 -328
- package/docs/proposals/mcp-tool-restructure-2026-01.md +0 -366
- package/docs/proposals/self-contained-guidance.md +0 -427
- package/docs/proto-sdk-generation.md +0 -242
- package/docs/release-impact.md +0 -102
- package/docs/release-process.md +0 -157
- package/docs/staging.RULE.md +0 -142
- package/docs/test-persona-creation.md +0 -196
- package/docs/tool-consolidation-v2.md +0 -225
- package/docs/tool-response-standards.md +0 -256
- package/resources/demo-kits/README.md +0 -175
- package/resources/demo-kits/finance-ap/manifest.json +0 -150
- package/resources/demo-kits/tags.json +0 -91
- package/resources/docs/getting-started.md +0 -97
- package/resources/templates/auto-builder-rules.md +0 -224
- package/resources/templates/chat-ai/README.md +0 -119
- package/resources/templates/chat-ai/persona-config.json +0 -111
- package/resources/templates/dashboard-ai/README.md +0 -156
- package/resources/templates/dashboard-ai/persona-config.json +0 -180
- package/resources/templates/demo-scenarios/README.md +0 -63
- package/resources/templates/demo-scenarios/test-published-package.md +0 -116
- package/resources/templates/document-gen-ai/README.md +0 -132
- package/resources/templates/document-gen-ai/persona-config.json +0 -316
- package/resources/templates/voice-ai/README.md +0 -123
- package/resources/templates/voice-ai/persona-config.json +0 -74
- package/resources/templates/voice-ai/workflow-prompt.md +0 -121
package/docs/mcp-tools-guide.md
CHANGED
|
@@ -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`.
|
|
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",
|
|
113
|
+
persona(mode="update", id="abc-123", config={widgets: [{name: "conversationSettings", conversationSettings: {...}}]})
|
|
106
114
|
```
|
|
107
115
|
|
|
108
|
-
###
|
|
116
|
+
### Get workflow data (for LLM to analyze/modify)
|
|
109
117
|
|
|
110
118
|
```typescript
|
|
111
|
-
|
|
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
|
-
|
|
122
|
+
The LLM then analyzes/modifies the workflow and deploys:
|
|
116
123
|
|
|
117
124
|
```typescript
|
|
118
|
-
|
|
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",
|
|
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",
|
|
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,
|
|
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
|
-
##
|
|
443
|
+
## Workflow Generation (LLM Does the Work)
|
|
460
444
|
|
|
461
|
-
|
|
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
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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.
|
|
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
|
-
"
|
|
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:
|
|
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
|
-
}
|