@ema.co/mcp-toolkit 2026.2.5 → 2026.2.19
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/.context/public/guides/ema-user-guide.md +12 -16
- package/.context/public/guides/mcp-tools-guide.md +203 -334
- package/LICENSE +29 -21
- package/README.md +58 -35
- package/dist/mcp/domain/loop-detection.js +97 -0
- package/dist/mcp/domain/proto-constraints.js +284 -0
- package/dist/mcp/domain/structural-rules.js +12 -5
- package/dist/mcp/domain/validation-rules.js +107 -20
- package/dist/mcp/domain/workflow-graph-optimizer.js +235 -0
- package/dist/mcp/domain/workflow-graph-transforms.js +808 -0
- package/dist/mcp/domain/workflow-graph.js +374 -0
- package/dist/mcp/domain/workflow-optimizer.js +10 -4
- package/dist/mcp/guidance.js +54 -31
- package/dist/mcp/handlers/feedback/index.js +139 -0
- package/dist/mcp/handlers/feedback/store.js +262 -0
- package/dist/mcp/handlers/persona/index.js +237 -8
- package/dist/mcp/handlers/persona/schema.js +27 -0
- package/dist/mcp/handlers/reference/index.js +6 -4
- package/dist/mcp/handlers/workflow/index.js +25 -28
- package/dist/mcp/handlers/workflow/optimize.js +73 -33
- package/dist/mcp/handlers/workflow/validation.js +1 -1
- package/dist/mcp/knowledge-types.js +7 -0
- package/dist/mcp/knowledge.js +146 -834
- package/dist/mcp/resources.js +610 -18
- package/dist/mcp/server.js +233 -2156
- package/dist/mcp/tools.js +91 -5
- package/dist/sdk/generated/agent-catalog.js +615 -0
- package/dist/sdk/generated/deprecated-actions.js +182 -96
- package/dist/sdk/generated/proto-fields.js +2 -1
- package/dist/sdk/generated/protos/service/agent_qa/v1/agent_qa_pb.js +460 -21
- package/dist/sdk/generated/protos/service/auth/v1/auth_pb.js +11 -1
- package/dist/sdk/generated/protos/service/dataingest/v1/dataingest_pb.js +173 -66
- package/dist/sdk/generated/protos/service/feedback/v1/feedback_pb.js +43 -1
- package/dist/sdk/generated/protos/service/llmservice/v1/llmservice_pb.js +26 -21
- package/dist/sdk/generated/protos/service/persona/v1/persona_config_pb.js +100 -89
- package/dist/sdk/generated/protos/service/persona/v1/persona_pb.js +126 -116
- package/dist/sdk/generated/protos/service/persona/v1/shared_widgets/widget_types_pb.js +33 -1
- package/dist/sdk/generated/protos/service/persona/v1/voicebot_widgets/widget_types_pb.js +60 -11
- package/dist/sdk/generated/protos/service/tenant/v1/tenant_pb.js +1 -1
- package/dist/sdk/generated/protos/service/user/v1/user_pb.js +1 -1
- package/dist/sdk/generated/protos/service/utils/v1/agent_qa_pb.js +35 -0
- package/dist/sdk/generated/protos/service/workflows/v1/action_registry_pb.js +1 -1
- package/dist/sdk/generated/protos/service/workflows/v1/action_type_pb.js +6 -1
- package/dist/sdk/generated/protos/service/workflows/v1/chatbot_pb.js +106 -11
- package/dist/sdk/generated/protos/service/workflows/v1/common_forms_pb.js +1 -1
- package/dist/sdk/generated/protos/service/workflows/v1/coordinator_pb.js +1 -1
- package/dist/sdk/generated/protos/service/workflows/v1/external_actions_pb.js +31 -1
- package/dist/sdk/generated/protos/service/workflows/v1/well_known_pb.js +5 -1
- package/dist/sdk/generated/protos/service/workflows/v1/workflow_pb.js +1 -1
- package/dist/sdk/generated/protos/util/tracking_metadata_pb.js +1 -1
- package/dist/sdk/generated/widget-catalog.js +60 -0
- package/docs/README.md +17 -9
- package/package.json +2 -2
- package/.context/public/guides/dashboard-operations.md +0 -286
- package/.context/public/guides/email-patterns.md +0 -125
- package/dist/mcp/domain/intent-architect.js +0 -914
- package/dist/mcp/domain/quality-gates.js +0 -110
- package/dist/mcp/domain/workflow-execution-analyzer.js +0 -412
- package/dist/mcp/domain/workflow-intent.js +0 -1806
- package/dist/mcp/domain/workflow-merge.js +0 -449
- package/dist/mcp/domain/workflow-tracer.js +0 -648
- package/dist/mcp/domain/workflow-transformer.js +0 -742
- package/dist/mcp/handlers/persona/intent.js +0 -141
- package/dist/mcp/handlers/workflow/analyze.js +0 -119
- package/dist/mcp/handlers/workflow/compare.js +0 -70
- package/dist/mcp/handlers/workflow/generate.js +0 -384
- package/dist/mcp/handlers-consolidated.js +0 -333
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* - get: Return workflow data + schema for LLM to generate/modify
|
|
6
6
|
* - deploy: Deploy LLM-generated workflow_def
|
|
7
7
|
* - validate: Validate a workflow_def before deploying
|
|
8
|
+
* - optimize: Structural graph optimization
|
|
8
9
|
*
|
|
9
10
|
* THE LLM DOES ALL THE THINKING. MCP provides data and executes.
|
|
10
11
|
*
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
* - generate: Had MCP generating workflow - LLM should generate full workflow_def
|
|
14
15
|
*
|
|
15
16
|
* DEPRECATED (kept for backwards compat, but not exposed):
|
|
16
|
-
* - analyze,
|
|
17
|
+
* - analyze, compare: LLM can do this by fetching rules and comparing
|
|
17
18
|
*/
|
|
18
19
|
import { generateSchema } from "../../domain/generation-schema.js";
|
|
19
20
|
import { fingerprintPersona } from "../../../sync.js";
|
|
@@ -21,18 +22,13 @@ import { fingerprintPersona } from "../../../sync.js";
|
|
|
21
22
|
export * from "./types.js";
|
|
22
23
|
// Re-export utilities
|
|
23
24
|
export * from "./utils.js";
|
|
24
|
-
// Import internal handlers
|
|
25
|
-
import { handleWorkflowAnalyze } from "./analyze.js";
|
|
26
|
-
import { handleWorkflowCompare } from "./compare.js";
|
|
25
|
+
// Import internal handlers
|
|
27
26
|
import { handleWorkflowOptimize } from "./optimize.js";
|
|
28
27
|
import { handleWorkflowDeploy } from "./deploy.js";
|
|
29
28
|
import { handleWorkflowValidate } from "./validate.js";
|
|
30
29
|
// Re-export for internal use (persona handler routes to these)
|
|
31
|
-
export { handleWorkflowAnalyze } from "./analyze.js";
|
|
32
|
-
export { handleWorkflowCompare } from "./compare.js";
|
|
33
30
|
export { handleWorkflowOptimize } from "./optimize.js";
|
|
34
31
|
export { handleWorkflowDeploy } from "./deploy.js";
|
|
35
|
-
export { handleWorkflowGenerate } from "./generate.js";
|
|
36
32
|
// NOTE: modify.ts REMOVED - violated LLM-driven architecture
|
|
37
33
|
// The correct flow is: workflow(mode="get") → LLM modifies → workflow(mode="deploy")
|
|
38
34
|
// Fallback deprecated actions - ONLY used when API unavailable
|
|
@@ -228,8 +224,8 @@ async function handleWorkflowGet(args, client) {
|
|
|
228
224
|
/**
|
|
229
225
|
* Main workflow handler with mode-based dispatch
|
|
230
226
|
*
|
|
231
|
-
* PUBLIC modes: get, deploy
|
|
232
|
-
* INTERNAL modes: modify, generate, analyze,
|
|
227
|
+
* PUBLIC modes: get, deploy, validate, optimize
|
|
228
|
+
* INTERNAL modes: modify, generate, analyze, compare (called from persona tool)
|
|
233
229
|
*/
|
|
234
230
|
export async function handleWorkflow(args, client, _getTemplateId) {
|
|
235
231
|
const personaId = args.persona_id;
|
|
@@ -246,6 +242,9 @@ export async function handleWorkflow(args, client, _getTemplateId) {
|
|
|
246
242
|
if (mode === "validate") {
|
|
247
243
|
return handleWorkflowValidate(args, client);
|
|
248
244
|
}
|
|
245
|
+
if (mode === "optimize") {
|
|
246
|
+
return handleWorkflowOptimize(args, client);
|
|
247
|
+
}
|
|
249
248
|
// REMOVED: modify, generate modes violated LLM-driven architecture
|
|
250
249
|
// MCP was doing LLM work (parsing operations, generating workflows)
|
|
251
250
|
// Correct flow: LLM generates full workflow_def → workflow(mode="deploy")
|
|
@@ -261,16 +260,17 @@ export async function handleWorkflow(args, client, _getTemplateId) {
|
|
|
261
260
|
_tip: "The LLM generates the full workflow_def. MCP just deploys it.",
|
|
262
261
|
};
|
|
263
262
|
}
|
|
264
|
-
//
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
263
|
+
// REMOVED: analyze, compare - LLM does this by fetching rules and comparing
|
|
264
|
+
if (mode === "analyze" || mode === "compare") {
|
|
265
|
+
return {
|
|
266
|
+
error: `Mode "${mode}" has been removed.`,
|
|
267
|
+
reason: "LLM can do analysis/comparison by fetching ema://rules/* and reasoning about workflow_def.",
|
|
268
|
+
correct_flow: [
|
|
269
|
+
"1. workflow(mode='get', persona_id='...') - get current workflow_def",
|
|
270
|
+
"2. Fetch ema://rules/anti-patterns and ema://rules/structural-invariants",
|
|
271
|
+
"3. LLM analyzes/compares the data",
|
|
272
|
+
],
|
|
273
|
+
};
|
|
274
274
|
}
|
|
275
275
|
// Auto-detect: only deploy if workflow_def provided
|
|
276
276
|
if (personaId && workflowDef) {
|
|
@@ -283,18 +283,17 @@ export async function handleWorkflow(args, client, _getTemplateId) {
|
|
|
283
283
|
// Invalid mode
|
|
284
284
|
return {
|
|
285
285
|
error: `Invalid or missing mode: ${mode}`,
|
|
286
|
-
public_modes: ["get", "deploy", "validate"],
|
|
287
|
-
hint: "MCP provides data (get), validates (validate), and executes (deploy). LLM does all thinking.",
|
|
286
|
+
public_modes: ["get", "deploy", "validate", "optimize"],
|
|
287
|
+
hint: "MCP provides data (get), validates (validate), optimizes (optimize), and executes (deploy). LLM does all thinking.",
|
|
288
288
|
};
|
|
289
289
|
}
|
|
290
290
|
/**
|
|
291
291
|
* Check if a workflow mode has been extracted
|
|
292
292
|
*/
|
|
293
293
|
export function hasExtractedWorkflowHandler(mode) {
|
|
294
|
-
// PUBLIC: get, deploy, validate
|
|
295
|
-
//
|
|
296
|
-
|
|
297
|
-
const extractedModes = ["get", "deploy", "validate", "analyze", "optimize", "compare"];
|
|
294
|
+
// PUBLIC: get, deploy, validate, optimize
|
|
295
|
+
// REMOVED: modify, extend, generate, analyze, compare
|
|
296
|
+
const extractedModes = ["get", "deploy", "validate", "optimize"];
|
|
298
297
|
return extractedModes.includes(mode);
|
|
299
298
|
}
|
|
300
299
|
/**
|
|
@@ -305,11 +304,9 @@ export function getWorkflowModeHandler(mode) {
|
|
|
305
304
|
case "get":
|
|
306
305
|
case "deploy":
|
|
307
306
|
case "validate":
|
|
308
|
-
case "analyze":
|
|
309
307
|
case "optimize":
|
|
310
|
-
case "compare":
|
|
311
308
|
return handleWorkflow;
|
|
312
|
-
// REMOVED: modify, extend, generate
|
|
309
|
+
// REMOVED: modify, extend, generate, analyze, compare
|
|
313
310
|
default:
|
|
314
311
|
return undefined;
|
|
315
312
|
}
|
|
@@ -1,50 +1,90 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Workflow Optimize Handler
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* The LLM should:
|
|
8
|
-
* 1. Get workflow with workflow(mode="get")
|
|
9
|
-
* 2. Fetch rules from ema://rules/anti-patterns
|
|
10
|
-
* 3. Apply rules and propose fixes
|
|
11
|
-
* 4. Deploy via workflow(mode="deploy")
|
|
4
|
+
* Structural graph optimization using the workflow-graph-optimizer.
|
|
5
|
+
* Accepts persona_id (fetches workflow) OR workflow_def (direct optimization).
|
|
6
|
+
* Returns optimized workflow_def + report. Does NOT auto-deploy.
|
|
12
7
|
*/
|
|
8
|
+
import { optimizeWorkflow } from "../../domain/workflow-graph-optimizer.js";
|
|
13
9
|
/**
|
|
14
|
-
* Handle workflow
|
|
10
|
+
* Handle workflow(mode="optimize") - structural graph optimization
|
|
15
11
|
*
|
|
16
|
-
*
|
|
12
|
+
* Follows the same parameter extraction pattern as handleWorkflowValidate:
|
|
13
|
+
* - persona_id → fetch workflow from persona
|
|
14
|
+
* - workflow_def → optimize directly
|
|
15
|
+
* - auto_apply (default true) → apply safe auto-transforms
|
|
16
|
+
* - max_passes (default 5) → convergence limit
|
|
17
17
|
*/
|
|
18
18
|
export async function handleWorkflowOptimize(args, client) {
|
|
19
19
|
const personaId = args.persona_id;
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
const workflowDef = args.workflow_def;
|
|
21
|
+
const autoApply = args.auto_apply ?? true;
|
|
22
|
+
const maxPasses = args.max_passes ?? 5;
|
|
23
|
+
// Get workflow to optimize
|
|
24
|
+
let workflowToOptimize = null;
|
|
25
|
+
let personaName;
|
|
26
|
+
if (workflowDef) {
|
|
27
|
+
// Use provided workflow_def directly
|
|
28
|
+
workflowToOptimize = workflowDef;
|
|
22
29
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
30
|
+
else if (personaId) {
|
|
31
|
+
// Get workflow from persona
|
|
32
|
+
const persona = await client.getPersonaById(personaId);
|
|
33
|
+
if (!persona) {
|
|
34
|
+
return { error: `Persona not found: ${personaId}` };
|
|
35
|
+
}
|
|
36
|
+
personaName = persona.name;
|
|
37
|
+
const personaWorkflowDef = persona.workflow_def;
|
|
38
|
+
if (!personaWorkflowDef) {
|
|
39
|
+
return {
|
|
40
|
+
error: `Persona "${persona.name}" has no workflow to optimize`,
|
|
41
|
+
_tip: "Deploy a workflow first, then optimize it",
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
workflowToOptimize = personaWorkflowDef;
|
|
26
45
|
}
|
|
27
|
-
|
|
28
|
-
if (!existingWorkflow) {
|
|
46
|
+
else {
|
|
29
47
|
return {
|
|
30
|
-
error:
|
|
31
|
-
hint: "Use mode='generate' to create a workflow first",
|
|
48
|
+
error: "Either persona_id or workflow_def required for optimize mode",
|
|
32
49
|
};
|
|
33
50
|
}
|
|
34
|
-
|
|
35
|
-
|
|
51
|
+
if (!workflowToOptimize) {
|
|
52
|
+
return { error: "Could not extract workflow for optimization" };
|
|
53
|
+
}
|
|
54
|
+
// Run the graph optimizer
|
|
55
|
+
const result = optimizeWorkflow(workflowToOptimize, {
|
|
56
|
+
autoApply,
|
|
57
|
+
maxPasses,
|
|
58
|
+
});
|
|
59
|
+
// Format response
|
|
60
|
+
const response = {
|
|
36
61
|
mode: "optimize",
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
workflow_def:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
62
|
+
...(personaId && { persona_id: personaId }),
|
|
63
|
+
...(personaName && { persona_name: personaName }),
|
|
64
|
+
// Core result
|
|
65
|
+
modified: result.modified,
|
|
66
|
+
workflow_def: result.workflowDef,
|
|
67
|
+
// What was done
|
|
68
|
+
applied_transforms: result.appliedTransforms.length > 0
|
|
69
|
+
? result.appliedTransforms
|
|
70
|
+
: undefined,
|
|
71
|
+
// What the LLM should review
|
|
72
|
+
advisories: result.advisories.length > 0
|
|
73
|
+
? result.advisories
|
|
74
|
+
: undefined,
|
|
75
|
+
// Before/after metrics
|
|
76
|
+
metrics: result.metrics,
|
|
77
|
+
// Post-optimization validation
|
|
78
|
+
validation: result.validation,
|
|
79
|
+
// Guidance
|
|
80
|
+
_tip: result.modified
|
|
81
|
+
? "Optimization applied transforms. Review the changes, then deploy with: workflow(mode='deploy', persona_id='...', base_fingerprint='<fingerprint>', workflow_def={...})"
|
|
82
|
+
: result.advisories.length > 0
|
|
83
|
+
? "No auto-transforms applied, but advisories found. Review them and modify the workflow_def manually if needed."
|
|
84
|
+
: "Workflow is already optimal. No changes needed.",
|
|
85
|
+
_next_step: result.modified
|
|
86
|
+
? "workflow(mode='get', persona_id='...') to get fresh fingerprint, then workflow(mode='deploy', persona_id='...', base_fingerprint='<fingerprint>', workflow_def={optimized_workflow_def})"
|
|
87
|
+
: undefined,
|
|
49
88
|
};
|
|
89
|
+
return response;
|
|
50
90
|
}
|
|
@@ -706,7 +706,7 @@ export function validateExternalActionCallerTools(workflowDef) {
|
|
|
706
706
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
707
707
|
// LOOP DETECTION VALIDATION
|
|
708
708
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
709
|
-
import { detectLoops } from "../../domain/
|
|
709
|
+
import { detectLoops } from "../../domain/loop-detection.js";
|
|
710
710
|
/**
|
|
711
711
|
* Validate that workflow has no circular dependencies.
|
|
712
712
|
* Circular references cause infinite execution loops.
|