@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/dist/mcp/resources.js
CHANGED
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
* Provides static and file-backed resources for the Ema MCP Server.
|
|
5
5
|
*
|
|
6
6
|
* Resources are the canonical source of truth for:
|
|
7
|
-
* -
|
|
8
|
-
* - Agent Catalog: Dynamic list of available workflow agents
|
|
7
|
+
* - Agent Catalog: Dynamic list of available workflow agents + API templates
|
|
9
8
|
* - Validation Rules: Input/output compatibility rules
|
|
10
9
|
* - Documentation: User guides and references
|
|
10
|
+
* - Schemas: Action schemas and type definitions
|
|
11
|
+
*
|
|
12
|
+
* Note: File-backed templates (ema://templates/*) were removed.
|
|
13
|
+
* Use API templates via ema://catalog/persona-templates or template() tool.
|
|
11
14
|
*
|
|
12
15
|
* Why resources vs tools:
|
|
13
16
|
* - Resources: Static/reference content the AI assistant reads to understand context
|
|
@@ -27,11 +30,12 @@ import { dirname } from "node:path";
|
|
|
27
30
|
const __filename = fileURLToPath(import.meta.url);
|
|
28
31
|
const __dirname = dirname(__filename);
|
|
29
32
|
// Import knowledge catalogs for dynamic resources
|
|
30
|
-
import { AGENT_CATALOG, WORKFLOW_PATTERNS, WIDGET_CATALOG } from "../sdk/knowledge.js";
|
|
33
|
+
import { AGENT_CATALOG, WORKFLOW_PATTERNS, WIDGET_CATALOG, ALL_DEPRECATED_ACTIONS, DEPRECATED_ACTIONS_WITH_REPLACEMENT, DEPRECATED_ACTIONS_NO_REPLACEMENT, WORKFLOW_ENABLING_CONSTRAINTS, MINIMUM_VIABLE_WORKFLOWS, } from "../sdk/knowledge.js";
|
|
31
34
|
import { INPUT_SOURCE_RULES, ANTI_PATTERNS, OPTIMIZATION_RULES } from "../sdk/validation-rules.js";
|
|
32
35
|
import { EmaClient } from "../sdk/client.js";
|
|
33
36
|
import { APISchemaRegistry } from "../sdk/workflow-validator.js";
|
|
34
37
|
import { loadConfigFromJsonEnv, loadConfigOptional, resolveBearerToken, getEnvByName, getMasterEnv, } from "../sdk/config.js";
|
|
38
|
+
import { VOICE_TEMPLATE_FALLBACK, VOICE_TEMPLATE_FIELD_DOCS, } from "../sdk/generated/template-fallbacks.js";
|
|
35
39
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
36
40
|
// Security Utilities
|
|
37
41
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
@@ -97,7 +101,7 @@ function hasPathTraversal(uriPath) {
|
|
|
97
101
|
const RESOURCE_MAP = {
|
|
98
102
|
// Core Documentation (files that exist in this repo)
|
|
99
103
|
"ema://docs/getting-started": {
|
|
100
|
-
path: "
|
|
104
|
+
path: "docs/mcp-tools-guide.md",
|
|
101
105
|
description: "Quick start guide: first steps, key concepts, essential rules, common operations",
|
|
102
106
|
mimeType: "text/markdown",
|
|
103
107
|
},
|
|
@@ -116,42 +120,10 @@ const RESOURCE_MAP = {
|
|
|
116
120
|
description: "MCP tools usage guide: tool categories, best practices, example call sequences, workflow review patterns",
|
|
117
121
|
mimeType: "text/markdown",
|
|
118
122
|
},
|
|
119
|
-
// Templates -
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
mimeType: "application/json",
|
|
124
|
-
},
|
|
125
|
-
"ema://templates/voice-ai/workflow-prompt": {
|
|
126
|
-
path: "resources/templates/voice-ai/workflow-prompt.md",
|
|
127
|
-
description: "Voice AI Auto Builder prompt template with node definitions, connections, and validation assertions",
|
|
128
|
-
mimeType: "text/markdown",
|
|
129
|
-
},
|
|
130
|
-
"ema://templates/voice-ai/readme": {
|
|
131
|
-
path: "resources/templates/voice-ai/README.md",
|
|
132
|
-
description: "Voice AI deployment guide: setup steps, testing checklist, maintenance procedures",
|
|
133
|
-
mimeType: "text/markdown",
|
|
134
|
-
},
|
|
135
|
-
"ema://templates/chat-ai/config": {
|
|
136
|
-
path: "resources/templates/chat-ai/persona-config.json",
|
|
137
|
-
description: "Chat AI persona configuration template: chatbotSdkConfig, feedbackMessage, fileUpload settings",
|
|
138
|
-
mimeType: "application/json",
|
|
139
|
-
},
|
|
140
|
-
"ema://templates/chat-ai/readme": {
|
|
141
|
-
path: "resources/templates/chat-ai/README.md",
|
|
142
|
-
description: "Chat AI deployment guide: workflow generation, widget configuration, knowledge base setup",
|
|
143
|
-
mimeType: "text/markdown",
|
|
144
|
-
},
|
|
145
|
-
"ema://templates/dashboard-ai/config": {
|
|
146
|
-
path: "resources/templates/dashboard-ai/persona-config.json",
|
|
147
|
-
description: "Dashboard AI persona configuration template: inputSchema, batchSettings, timeout configuration",
|
|
148
|
-
mimeType: "application/json",
|
|
149
|
-
},
|
|
150
|
-
"ema://templates/dashboard-ai/readme": {
|
|
151
|
-
path: "resources/templates/dashboard-ai/README.md",
|
|
152
|
-
description: "Dashboard AI deployment guide: batch processing setup, input configuration",
|
|
153
|
-
mimeType: "text/markdown",
|
|
154
|
-
},
|
|
123
|
+
// Templates - REMOVED (file-backed templates removed in favor of API + generated fallbacks)
|
|
124
|
+
// Use: client.getPersonaTemplates() for live API templates
|
|
125
|
+
// Use: getTemplateFallback("voice") from sdk/generated/template-fallbacks.ts for offline fallbacks
|
|
126
|
+
// See: ema://catalog/persona-templates for dynamic API-backed template listing
|
|
155
127
|
// DEPRECATED: Use ema://docs/usage-guide (dynamic) instead
|
|
156
128
|
// This static resource is kept for backwards compatibility but now generates from guidance module
|
|
157
129
|
};
|
|
@@ -236,7 +208,330 @@ const DYNAMIC_RESOURCES = [
|
|
|
236
208
|
mimeType: "application/json",
|
|
237
209
|
generate: async () => JSON.stringify(OPTIMIZATION_RULES, null, 2),
|
|
238
210
|
},
|
|
239
|
-
//
|
|
211
|
+
// Deprecated Actions - API-first with fallback
|
|
212
|
+
{
|
|
213
|
+
uri: "ema://rules/deprecated-actions",
|
|
214
|
+
name: "rules/deprecated-actions",
|
|
215
|
+
description: "Deprecated actions list: actions to avoid in new workflows, with their replacements and migration notes",
|
|
216
|
+
mimeType: "application/json",
|
|
217
|
+
generate: async (ctx) => {
|
|
218
|
+
// Try API first using existing client infrastructure
|
|
219
|
+
let apiDeprecated = [];
|
|
220
|
+
let source = "fallback";
|
|
221
|
+
try {
|
|
222
|
+
const client = getClientForEnvName(ctx.env);
|
|
223
|
+
if (client) {
|
|
224
|
+
const actions = await client.listActions();
|
|
225
|
+
apiDeprecated = actions.filter(a => a.deprecated).map(a => a.id);
|
|
226
|
+
source = "api";
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
// API unavailable, use fallback
|
|
231
|
+
}
|
|
232
|
+
// Merge API deprecated with fallback replacement info
|
|
233
|
+
const result = {
|
|
234
|
+
_note: "Actions marked deprecated should not be used in new workflows. Use replacements where available.",
|
|
235
|
+
_source: source,
|
|
236
|
+
_api_deprecated_count: apiDeprecated.length,
|
|
237
|
+
// From API (current deprecated status)
|
|
238
|
+
api_deprecated: apiDeprecated.length > 0 ? apiDeprecated : undefined,
|
|
239
|
+
// From fallback (includes replacement info)
|
|
240
|
+
with_replacement: DEPRECATED_ACTIONS_WITH_REPLACEMENT.map(d => ({
|
|
241
|
+
action: d.action,
|
|
242
|
+
version: d.version,
|
|
243
|
+
replacement: d.replacement,
|
|
244
|
+
replacement_version: d.replacementVersion,
|
|
245
|
+
migration_notes: d.migrationNotes,
|
|
246
|
+
})),
|
|
247
|
+
no_replacement: DEPRECATED_ACTIONS_NO_REPLACEMENT.map(d => ({
|
|
248
|
+
action: d.action,
|
|
249
|
+
version: d.version,
|
|
250
|
+
environment: d.environment,
|
|
251
|
+
notes: d.migrationNotes,
|
|
252
|
+
})),
|
|
253
|
+
_tip: "Check workflow(mode='get') for deprecation_warnings on specific workflows",
|
|
254
|
+
};
|
|
255
|
+
return JSON.stringify(result, null, 2);
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
uri: "ema://rules/deprecated-actions-summary",
|
|
260
|
+
name: "rules/deprecated-actions-summary",
|
|
261
|
+
description: "Deprecated actions summary: quick reference table of deprecated actions and replacements",
|
|
262
|
+
mimeType: "text/markdown",
|
|
263
|
+
generate: async (ctx) => {
|
|
264
|
+
// Try API first using existing client infrastructure
|
|
265
|
+
let apiDeprecated = [];
|
|
266
|
+
let source = "fallback";
|
|
267
|
+
try {
|
|
268
|
+
const client = getClientForEnvName(ctx.env);
|
|
269
|
+
if (client) {
|
|
270
|
+
const actions = await client.listActions();
|
|
271
|
+
apiDeprecated = actions.filter(a => a.deprecated).map(a => a.id);
|
|
272
|
+
source = "api";
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch {
|
|
276
|
+
// API unavailable, use fallback
|
|
277
|
+
}
|
|
278
|
+
let md = "# Deprecated Actions\n\n";
|
|
279
|
+
md += "> Do NOT use these actions in new workflows. Use replacements where available.\n\n";
|
|
280
|
+
md += `> Source: ${source} (${source === "api" ? "live" : "synced 2026-01-26"})\n\n`;
|
|
281
|
+
if (apiDeprecated.length > 0) {
|
|
282
|
+
md += "## From API (Current)\n\n";
|
|
283
|
+
md += "| Action ID | Status |\n";
|
|
284
|
+
md += "|-----------|--------|\n";
|
|
285
|
+
for (const id of apiDeprecated) {
|
|
286
|
+
md += `| \`${id}\` | DEPRECATED |\n`;
|
|
287
|
+
}
|
|
288
|
+
md += "\n";
|
|
289
|
+
}
|
|
290
|
+
md += "## Actions with Known Replacements\n\n";
|
|
291
|
+
md += "| Deprecated Action | Version | Replacement | Notes |\n";
|
|
292
|
+
md += "|-------------------|---------|-------------|-------|\n";
|
|
293
|
+
for (const d of DEPRECATED_ACTIONS_WITH_REPLACEMENT) {
|
|
294
|
+
const repl = Array.isArray(d.replacement) ? d.replacement.join(" or ") : d.replacement;
|
|
295
|
+
const replVer = d.replacementVersion ? ` ${d.replacementVersion}` : "";
|
|
296
|
+
md += `| \`${d.action}\` | ${d.version} | \`${repl}\`${replVer} | ${d.migrationNotes || "-"} |\n`;
|
|
297
|
+
}
|
|
298
|
+
md += "\n## Actions with No Known Replacement\n\n";
|
|
299
|
+
md += "| Action | Environment | Notes |\n";
|
|
300
|
+
md += "|--------|-------------|-------|\n";
|
|
301
|
+
for (const d of DEPRECATED_ACTIONS_NO_REPLACEMENT) {
|
|
302
|
+
md += `| \`${d.action}\` | ${d.environment || "all"} | ${d.migrationNotes || "-"} |\n`;
|
|
303
|
+
}
|
|
304
|
+
md += `\n**Total Known Deprecated**: ${ALL_DEPRECATED_ACTIONS.length} actions\n`;
|
|
305
|
+
md += `\n> **Best Practice**: Use \`workflow(mode="get")\` to check for deprecation warnings in specific workflows.\n`;
|
|
306
|
+
return md;
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
// Workflow Enabling Constraints - Requirements for persona activation
|
|
310
|
+
{
|
|
311
|
+
uri: "ema://rules/workflow-constraints",
|
|
312
|
+
name: "rules/workflow-constraints",
|
|
313
|
+
description: "Workflow enabling constraints: requirements that must be met before a persona can be activated",
|
|
314
|
+
mimeType: "application/json",
|
|
315
|
+
generate: async () => JSON.stringify({
|
|
316
|
+
_note: "These constraints are checked by the Ema backend when enabling a persona.",
|
|
317
|
+
_source: "ema/ema_backend/db/models/personas_model.py:672-756",
|
|
318
|
+
_last_synced: "2026-01-26",
|
|
319
|
+
enabling_constraints: WORKFLOW_ENABLING_CONSTRAINTS,
|
|
320
|
+
minimum_viable_workflows: MINIMUM_VIABLE_WORKFLOWS,
|
|
321
|
+
}, null, 2),
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
uri: "ema://rules/workflow-constraints-summary",
|
|
325
|
+
name: "rules/workflow-constraints-summary",
|
|
326
|
+
description: "Workflow constraints summary: checklist of requirements for enabling a persona",
|
|
327
|
+
mimeType: "text/markdown",
|
|
328
|
+
generate: async () => {
|
|
329
|
+
let md = "# Workflow Enabling Constraints\n\n";
|
|
330
|
+
md += "> These constraints must be satisfied for a persona to be activated.\n\n";
|
|
331
|
+
md += "> Source: ema_backend/db/models/personas_model.py (synced 2026-01-26)\n\n";
|
|
332
|
+
md += "## Required Checks\n\n";
|
|
333
|
+
md += "| # | Constraint | Error State | Fix |\n";
|
|
334
|
+
md += "|---|------------|-------------|-----|\n";
|
|
335
|
+
for (const c of WORKFLOW_ENABLING_CONSTRAINTS) {
|
|
336
|
+
const critical = c.critical ? "**" : "";
|
|
337
|
+
md += `| ${c.id} | ${critical}${c.name}${critical} | \`${c.errorState}\` | ${c.fix} |\n`;
|
|
338
|
+
}
|
|
339
|
+
md += "\n## Minimum Viable Workflows by Type\n\n";
|
|
340
|
+
for (const [type, mvw] of Object.entries(MINIMUM_VIABLE_WORKFLOWS)) {
|
|
341
|
+
md += `### ${type}\n\n`;
|
|
342
|
+
md += `**Structure**: \`${mvw.exampleStructure}\`\n\n`;
|
|
343
|
+
md += `- Required nodes: ${mvw.requiredNodes.map(n => `\`${n}\``).join(", ")}\n`;
|
|
344
|
+
md += `- Required outputs: ${mvw.requiredOutputs.map(o => `\`${o}\``).join(", ")}\n`;
|
|
345
|
+
if (mvw.requiredWidgets) {
|
|
346
|
+
md += `- Required widgets: ${mvw.requiredWidgets.map(w => `\`${w}\``).join(", ")}\n`;
|
|
347
|
+
}
|
|
348
|
+
if (mvw.notes) {
|
|
349
|
+
md += `- Notes: ${mvw.notes}\n`;
|
|
350
|
+
}
|
|
351
|
+
md += "\n";
|
|
352
|
+
}
|
|
353
|
+
md += "## Critical Rule: WORKFLOW_OUTPUT\n\n";
|
|
354
|
+
md += "**Every workflow must have a `results.WORKFLOW_OUTPUT` that maps to an action output.**\n\n";
|
|
355
|
+
md += "```json\n";
|
|
356
|
+
md += '{\n "results": {\n "WORKFLOW_OUTPUT": {\n "actionName": "respond_node",\n "outputName": "response_with_sources"\n }\n }\n}\n';
|
|
357
|
+
md += "```\n";
|
|
358
|
+
return md;
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
362
|
+
// Workflow Requirements & Guidance
|
|
363
|
+
// NOT hardcoded templates - provide requirements and let LLM generate
|
|
364
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
365
|
+
{
|
|
366
|
+
uri: "ema://templates/voice-ai/requirements",
|
|
367
|
+
name: "templates/voice-ai/requirements",
|
|
368
|
+
description: "Voice AI workflow requirements and guidance. Use workflow(mode='get') for schema, then generate workflow_def.",
|
|
369
|
+
mimeType: "application/json",
|
|
370
|
+
generate: async () => {
|
|
371
|
+
return JSON.stringify({
|
|
372
|
+
_note: "Requirements and guidance for Voice AI workflows. LLM generates workflow_def based on these.",
|
|
373
|
+
_usage: "1) workflow(mode='get', persona_id='...') for schema, 2) Generate workflow_def, 3) workflow(mode='deploy', ...)",
|
|
374
|
+
hard_requirements: {
|
|
375
|
+
workflow_output: {
|
|
376
|
+
rule: "MUST have results.WORKFLOW_OUTPUT mapped to final action output",
|
|
377
|
+
example: '{ "results": { "WORKFLOW_OUTPUT": { "actionName": "respond", "outputName": "response" } } }',
|
|
378
|
+
},
|
|
379
|
+
workflow_name: {
|
|
380
|
+
rule: "workflowName MUST be ['ema', 'personas', '<actual_persona_id>']",
|
|
381
|
+
},
|
|
382
|
+
trigger: {
|
|
383
|
+
rule: "Voice AI uses chat_trigger (type CHAT)",
|
|
384
|
+
namespace: ["triggers", "emainternal"],
|
|
385
|
+
},
|
|
386
|
+
response: {
|
|
387
|
+
rule: "Must produce a response output that wires to WORKFLOW_OUTPUT",
|
|
388
|
+
},
|
|
389
|
+
},
|
|
390
|
+
required_widgets: [
|
|
391
|
+
{ name: "conversationSettings", type: 39, purpose: "Voice identity, welcome message, instructions" },
|
|
392
|
+
{ name: "voiceSettings", type: 40, purpose: "Language, voice model" },
|
|
393
|
+
{ name: "callSettings", type: 41, purpose: "Call forwarding, spam prevention" },
|
|
394
|
+
{ name: "vadSettings", type: 42, purpose: "Voice activity detection, timeouts" },
|
|
395
|
+
],
|
|
396
|
+
common_patterns: {
|
|
397
|
+
simple_qa: "chat_trigger → search → respond_for_external_actions → WORKFLOW_OUTPUT",
|
|
398
|
+
with_routing: "chat_trigger → chat_categorizer → [branch per intent] → respond → WORKFLOW_OUTPUT",
|
|
399
|
+
with_tools: "chat_trigger → categorizer → external_action_caller → respond_for_external_actions → WORKFLOW_OUTPUT",
|
|
400
|
+
},
|
|
401
|
+
best_practices: [
|
|
402
|
+
"Use search/v2 (NOT v0) with datastore_configs",
|
|
403
|
+
"Include Fallback category in every categorizer",
|
|
404
|
+
"Use respond_for_external_actions (NOT deprecated respond_with_sources)",
|
|
405
|
+
"Consider general_hitl before actions with side effects",
|
|
406
|
+
],
|
|
407
|
+
_next_step: "Call workflow(mode='get', persona_id='...') to get full schema, then generate workflow_def",
|
|
408
|
+
}, null, 2);
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
uri: "ema://templates/voice-ai/config",
|
|
413
|
+
name: "templates/voice-ai/config",
|
|
414
|
+
description: "Voice AI configuration template (proto_config widgets). Customize values for your use case.",
|
|
415
|
+
mimeType: "application/json",
|
|
416
|
+
generate: async () => {
|
|
417
|
+
const config = {
|
|
418
|
+
_note: "Voice AI configuration template. Customize values for your use case.",
|
|
419
|
+
_usage: "persona(method='update', id='<ID>', config={widgets: [<these widgets with your values>]})",
|
|
420
|
+
widgets: [
|
|
421
|
+
{
|
|
422
|
+
name: "conversationSettings",
|
|
423
|
+
type: 39,
|
|
424
|
+
conversationSettings: {
|
|
425
|
+
...VOICE_TEMPLATE_FALLBACK.conversationSettings,
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: "voiceSettings",
|
|
430
|
+
type: 40,
|
|
431
|
+
voiceSettings: {
|
|
432
|
+
...VOICE_TEMPLATE_FALLBACK.voiceSettings,
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
name: "callSettings",
|
|
437
|
+
type: 41,
|
|
438
|
+
callSettings: {
|
|
439
|
+
...VOICE_TEMPLATE_FALLBACK.callSettings,
|
|
440
|
+
},
|
|
441
|
+
},
|
|
442
|
+
{
|
|
443
|
+
name: "vadSettings",
|
|
444
|
+
type: 42,
|
|
445
|
+
vadSettings: {
|
|
446
|
+
...VOICE_TEMPLATE_FALLBACK.vadSettings,
|
|
447
|
+
},
|
|
448
|
+
},
|
|
449
|
+
],
|
|
450
|
+
field_docs: VOICE_TEMPLATE_FIELD_DOCS,
|
|
451
|
+
};
|
|
452
|
+
return JSON.stringify(config, null, 2);
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
uri: "ema://templates/voice-ai/guide",
|
|
457
|
+
name: "templates/voice-ai/guide",
|
|
458
|
+
description: "Voice AI creation guide with requirements and step-by-step process",
|
|
459
|
+
mimeType: "text/markdown",
|
|
460
|
+
generate: async () => {
|
|
461
|
+
return `# Voice AI Creation Guide
|
|
462
|
+
|
|
463
|
+
## Process (Follow This Order)
|
|
464
|
+
|
|
465
|
+
### 1. Create Persona
|
|
466
|
+
\`\`\`
|
|
467
|
+
persona(method="create", name="Your Voice AI", type="voice")
|
|
468
|
+
\`\`\`
|
|
469
|
+
|
|
470
|
+
### 2. Get Workflow Schema
|
|
471
|
+
\`\`\`
|
|
472
|
+
workflow(mode="get", persona_id="<ID>")
|
|
473
|
+
\`\`\`
|
|
474
|
+
This returns:
|
|
475
|
+
- Current workflow (if any)
|
|
476
|
+
- Deprecation warnings (fix these first!)
|
|
477
|
+
- Generation schema (agents, constraints)
|
|
478
|
+
- Requirements and guidance
|
|
479
|
+
|
|
480
|
+
### 3. Generate Workflow
|
|
481
|
+
Using the schema, generate a workflow_def that:
|
|
482
|
+
- Has WORKFLOW_OUTPUT in results
|
|
483
|
+
- Uses non-deprecated actions
|
|
484
|
+
- Follows the flow pattern: trigger → processing → response → OUTPUT
|
|
485
|
+
|
|
486
|
+
### 4. Deploy Workflow
|
|
487
|
+
\`\`\`
|
|
488
|
+
workflow(mode="deploy", persona_id="<ID>", workflow_def={...}, preview=true)
|
|
489
|
+
\`\`\`
|
|
490
|
+
Always preview first!
|
|
491
|
+
|
|
492
|
+
### 5. Configure Settings
|
|
493
|
+
\`\`\`
|
|
494
|
+
persona(method="update", id="<ID>", config={widgets: [...]})
|
|
495
|
+
\`\`\`
|
|
496
|
+
|
|
497
|
+
### 6. Upload Knowledge
|
|
498
|
+
\`\`\`
|
|
499
|
+
persona(id="<ID>", data={method:"upload", path:"your-data.txt"})
|
|
500
|
+
\`\`\`
|
|
501
|
+
|
|
502
|
+
## Hard Requirements
|
|
503
|
+
|
|
504
|
+
| Requirement | Why |
|
|
505
|
+
|-------------|-----|
|
|
506
|
+
| WORKFLOW_OUTPUT | Persona cannot be activated without it |
|
|
507
|
+
| workflowName format | API rejects invalid namespaces |
|
|
508
|
+
| Non-deprecated actions | Deprecated actions may fail |
|
|
509
|
+
|
|
510
|
+
## Check for Deprecated Actions
|
|
511
|
+
|
|
512
|
+
\`workflow(mode="get")\` returns \`deprecation_warnings\` if any actions are deprecated.
|
|
513
|
+
**Fix these BEFORE deploying.**
|
|
514
|
+
|
|
515
|
+
## Common Deprecated Actions
|
|
516
|
+
|
|
517
|
+
| Deprecated | Use Instead |
|
|
518
|
+
|------------|-------------|
|
|
519
|
+
| search/v0 | search/v2 (requires datastore_configs) |
|
|
520
|
+
| respond_with_sources | respond_for_external_actions |
|
|
521
|
+
| call_llm/v0 | call_llm/v2 |
|
|
522
|
+
|
|
523
|
+
## Anti-Patterns
|
|
524
|
+
|
|
525
|
+
❌ Cloning random existing persona
|
|
526
|
+
❌ Skipping workflow_def
|
|
527
|
+
❌ Using deprecated actions
|
|
528
|
+
❌ Deploying without preview
|
|
529
|
+
|
|
530
|
+
${VOICE_TEMPLATE_FIELD_DOCS}
|
|
531
|
+
`;
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
// Persona Templates - Dynamic from API with fallback
|
|
240
535
|
{
|
|
241
536
|
uri: "ema://catalog/templates",
|
|
242
537
|
name: "catalog/templates",
|
|
@@ -244,7 +539,15 @@ const DYNAMIC_RESOURCES = [
|
|
|
244
539
|
mimeType: "application/json",
|
|
245
540
|
generate: async (ctx) => {
|
|
246
541
|
const templates = await getDynamicPersonaTemplates({ env: ctx.env });
|
|
247
|
-
|
|
542
|
+
if (templates.length > 0) {
|
|
543
|
+
return JSON.stringify(templates.map(templateDtoToResource), null, 2);
|
|
544
|
+
}
|
|
545
|
+
// Fallback when API unavailable - provide guidance
|
|
546
|
+
return JSON.stringify({
|
|
547
|
+
_note: "API templates unavailable. Use catalog(method='list', type='templates') tool which connects to API directly, or use template(config='voice|chat|dashboard') for config fallbacks.",
|
|
548
|
+
fallback_types: ["voice", "chat", "dashboard"],
|
|
549
|
+
how_to_get: "catalog(method='list', type='templates') or template(config='voice')",
|
|
550
|
+
}, null, 2);
|
|
248
551
|
},
|
|
249
552
|
},
|
|
250
553
|
{
|
|
@@ -255,7 +558,28 @@ const DYNAMIC_RESOURCES = [
|
|
|
255
558
|
generate: async (ctx) => {
|
|
256
559
|
const templates = await getDynamicPersonaTemplates({ env: ctx.env });
|
|
257
560
|
if (templates.length === 0) {
|
|
258
|
-
return
|
|
561
|
+
return `# Persona Templates
|
|
562
|
+
|
|
563
|
+
> API templates not available. Use one of these alternatives:
|
|
564
|
+
|
|
565
|
+
## Option 1: Use the catalog tool directly
|
|
566
|
+
\`\`\`
|
|
567
|
+
catalog(method="list", type="templates")
|
|
568
|
+
\`\`\`
|
|
569
|
+
This connects to the API and may have different credentials.
|
|
570
|
+
|
|
571
|
+
## Option 2: Use config fallbacks
|
|
572
|
+
\`\`\`
|
|
573
|
+
template(config="voice") // Voice AI config template
|
|
574
|
+
template(config="chat") // Chat AI config template
|
|
575
|
+
template(config="dashboard") // Dashboard AI config template
|
|
576
|
+
\`\`\`
|
|
577
|
+
|
|
578
|
+
## Option 3: Create from scratch
|
|
579
|
+
\`\`\`
|
|
580
|
+
persona(method="create", name="My AI", type="voice|chat|dashboard")
|
|
581
|
+
\`\`\`
|
|
582
|
+
`;
|
|
259
583
|
}
|
|
260
584
|
const byCategory = new Map();
|
|
261
585
|
for (const t of templates) {
|
|
@@ -727,10 +1051,11 @@ export class ResourceRegistry {
|
|
|
727
1051
|
buildResourceIndex() {
|
|
728
1052
|
const resources = this.list().filter((r) => r.uri !== "ema://index/all-resources");
|
|
729
1053
|
// Group resources by category
|
|
1054
|
+
// Note: ema://templates/* file-backed resources removed - use API templates or generated fallbacks
|
|
730
1055
|
const docs = resources.filter((r) => r.uri.startsWith("ema://docs/"));
|
|
731
|
-
const templates = resources.filter((r) => r.uri.startsWith("ema://templates/"));
|
|
732
1056
|
const catalog = resources.filter((r) => r.uri.startsWith("ema://catalog/"));
|
|
733
1057
|
const rules = resources.filter((r) => r.uri.startsWith("ema://rules/"));
|
|
1058
|
+
const schemas = resources.filter((r) => r.uri.startsWith("ema://schema/"));
|
|
734
1059
|
const markdown = `# Ema MCP Resources Index
|
|
735
1060
|
|
|
736
1061
|
> Available resources exposed by the Ema MCP Server
|
|
@@ -742,9 +1067,9 @@ export class ResourceRegistry {
|
|
|
742
1067
|
| Category | Count | Description |
|
|
743
1068
|
|----------|-------|-------------|
|
|
744
1069
|
| Documentation | ${docs.length} | User guides, README, tool references |
|
|
745
|
-
|
|
|
746
|
-
| Catalog | ${catalog.length} | Agent catalog, workflow patterns, widgets |
|
|
1070
|
+
| Catalog | ${catalog.length} | Agent catalog, workflow patterns, templates |
|
|
747
1071
|
| Rules | ${rules.length} | Validation rules, anti-patterns, optimizations |
|
|
1072
|
+
| Schemas | ${schemas.length} | Action schemas, type definitions |
|
|
748
1073
|
|
|
749
1074
|
## Documentation (${docs.length})
|
|
750
1075
|
|
|
@@ -752,14 +1077,6 @@ export class ResourceRegistry {
|
|
|
752
1077
|
|-----|-------------|
|
|
753
1078
|
${docs.map((r) => `| \`${r.uri}\` | ${r.description} |`).join("\n")}
|
|
754
1079
|
|
|
755
|
-
## Templates (${templates.length})
|
|
756
|
-
|
|
757
|
-
> Use templates as starting points for new AI Employees
|
|
758
|
-
|
|
759
|
-
| URI | Description |
|
|
760
|
-
|-----|-------------|
|
|
761
|
-
${templates.map((r) => `| \`${r.uri}\` | ${r.description} |`).join("\n")}
|
|
762
|
-
|
|
763
1080
|
## Catalog (${catalog.length})
|
|
764
1081
|
|
|
765
1082
|
> Dynamic catalogs generated from SDK knowledge
|
|
@@ -776,6 +1093,14 @@ ${catalog.map((r) => `| \`${r.uri}\` | ${r.description} |`).join("\n")}
|
|
|
776
1093
|
|-----|-------------|
|
|
777
1094
|
${rules.map((r) => `| \`${r.uri}\` | ${r.description} |`).join("\n")}
|
|
778
1095
|
|
|
1096
|
+
## Schemas (${schemas.length})
|
|
1097
|
+
|
|
1098
|
+
> Action schemas and type definitions
|
|
1099
|
+
|
|
1100
|
+
| URI | Description |
|
|
1101
|
+
|-----|-------------|
|
|
1102
|
+
${schemas.map((r) => `| \`${r.uri}\` | ${r.description} |`).join("\n")}
|
|
1103
|
+
|
|
779
1104
|
## Usage
|
|
780
1105
|
|
|
781
1106
|
To read a resource, use the \`resources/read\` endpoint:
|
|
@@ -795,10 +1120,10 @@ To read a resource, use the \`resources/read\` endpoint:
|
|
|
795
1120
|
|------|-----|
|
|
796
1121
|
| Get agent definitions | Resource: \`ema://catalog/agents\` |
|
|
797
1122
|
| Get input/output compatibility rules | Resource: \`ema://rules/input-sources\` |
|
|
798
|
-
| Get persona
|
|
1123
|
+
| Get persona templates | Resource: \`ema://catalog/persona-templates\` (API) or Tool: \`template(config="voice")\` |
|
|
799
1124
|
| Query live persona data | Tool: \`persona\` |
|
|
800
|
-
|
|
|
801
|
-
|
|
|
1125
|
+
| Get workflow data | Tool: \`workflow(mode="get")\` |
|
|
1126
|
+
| Deploy workflow | Tool: \`workflow(mode="deploy")\` |
|
|
802
1127
|
`;
|
|
803
1128
|
return {
|
|
804
1129
|
uri: "ema://index/all-resources",
|