@ema.co/mcp-toolkit 1.7.1 → 2026.1.17

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.

@@ -2288,25 +2288,223 @@ export async function handleKnowledge(args, client, readFile) {
2288
2288
  }
2289
2289
  }
2290
2290
  // ═══════════════════════════════════════════════════════════════════════════
2291
- // REFERENCE Handler
2291
+ // REFERENCE Handler (v2 unified: envs, actions, templates, patterns, concepts, guidance)
2292
2292
  // ═══════════════════════════════════════════════════════════════════════════
2293
- export function handleReference(args) {
2294
- // Get concept
2295
- if (args.concept) {
2296
- const concept = getConceptByTerm(args.concept);
2297
- if (!concept) {
2298
- return { error: `Concept not found: ${args.concept}` };
2293
+ export async function handleReference(args, context) {
2294
+ const type = args.type;
2295
+ // ─────────────────────────────────────────────────────────────────────────
2296
+ // type="envs" - List available environments
2297
+ // ─────────────────────────────────────────────────────────────────────────
2298
+ if (type === "envs") {
2299
+ const getEnvs = context?.getEnvironments;
2300
+ if (!getEnvs) {
2301
+ return { error: "Environment context not available" };
2299
2302
  }
2300
- return concept;
2303
+ const envs = getEnvs();
2304
+ return {
2305
+ environments: envs.map(e => ({
2306
+ name: e.name,
2307
+ default: e.isDefault,
2308
+ })),
2309
+ count: envs.length,
2310
+ toolkit: context?.toolkit ?? { name: "unknown", version: "unknown" },
2311
+ };
2312
+ }
2313
+ // ─────────────────────────────────────────────────────────────────────────
2314
+ // type="actions" - Action/agent lookup (replaces handleAction)
2315
+ // ─────────────────────────────────────────────────────────────────────────
2316
+ if (type === "actions") {
2317
+ const client = context?.client;
2318
+ const id = args.id;
2319
+ // Categories list
2320
+ if (args.categories) {
2321
+ const categories = [...new Set(Object.values(AGENT_CATALOG).map(a => a.category))];
2322
+ return { categories, count: categories.length };
2323
+ }
2324
+ // Suggest for use case
2325
+ if (args.suggest) {
2326
+ const suggestions = suggestAgentsForUseCase(args.suggest);
2327
+ return { suggestions, use_case: args.suggest };
2328
+ }
2329
+ // Get single action
2330
+ if (id) {
2331
+ // Try API first if client available
2332
+ if (client) {
2333
+ try {
2334
+ const actions = await client.listActions();
2335
+ const action = actions.find(a => a.id === id ||
2336
+ a.name === id ||
2337
+ a.name?.toLowerCase() === id.toLowerCase());
2338
+ const result = action ? {
2339
+ id: action.id,
2340
+ name: action.name,
2341
+ category: action.category,
2342
+ enabled: action.enabled,
2343
+ inputs: action.inputs,
2344
+ outputs: action.outputs,
2345
+ source: "api",
2346
+ } : {};
2347
+ // Include docs if requested or if not found in API
2348
+ if (args.include_docs || !action) {
2349
+ const doc = getAgentByName(id);
2350
+ if (doc) {
2351
+ result.documentation = doc;
2352
+ result.source = action ? "api+docs" : "docs";
2353
+ }
2354
+ }
2355
+ if (Object.keys(result).length === 0) {
2356
+ return { error: `Action not found: ${id}` };
2357
+ }
2358
+ return result;
2359
+ }
2360
+ catch {
2361
+ // Fallback to docs only
2362
+ const doc = getAgentByName(id);
2363
+ if (doc) {
2364
+ return { ...doc, source: "docs" };
2365
+ }
2366
+ return { error: `Action not found: ${id}` };
2367
+ }
2368
+ }
2369
+ // No client - use docs only
2370
+ const doc = getAgentByName(id);
2371
+ if (doc) {
2372
+ return { ...doc, source: "docs" };
2373
+ }
2374
+ return { error: `Action not found: ${id}` };
2375
+ }
2376
+ // List actions
2377
+ if (client) {
2378
+ try {
2379
+ let actions = await client.listActions();
2380
+ // Apply filters
2381
+ if (args.query) {
2382
+ const q = args.query.toLowerCase();
2383
+ actions = actions.filter(a => a.name?.toLowerCase().includes(q));
2384
+ }
2385
+ if (args.category) {
2386
+ actions = actions.filter(a => a.category === args.category);
2387
+ }
2388
+ // Apply limit
2389
+ const limit = args.limit || 100;
2390
+ actions = actions.slice(0, limit);
2391
+ return {
2392
+ count: actions.length,
2393
+ actions: actions.map(a => ({
2394
+ id: a.id,
2395
+ name: a.name,
2396
+ category: a.category,
2397
+ enabled: a.enabled,
2398
+ })),
2399
+ };
2400
+ }
2401
+ catch {
2402
+ // Fallback to catalog
2403
+ }
2404
+ }
2405
+ // Fallback to catalog
2406
+ let agents = Object.entries(AGENT_CATALOG);
2407
+ if (args.category) {
2408
+ agents = agents.filter(([_, a]) => a.category === args.category);
2409
+ }
2410
+ if (args.query) {
2411
+ const q = args.query.toLowerCase();
2412
+ agents = agents.filter(([name]) => name.toLowerCase().includes(q));
2413
+ }
2414
+ return {
2415
+ count: agents.length,
2416
+ actions: agents.map(([name, agent]) => ({
2417
+ name,
2418
+ category: agent.category,
2419
+ description: agent.description,
2420
+ source: "catalog",
2421
+ })),
2422
+ };
2423
+ }
2424
+ // ─────────────────────────────────────────────────────────────────────────
2425
+ // type="templates" - List persona templates
2426
+ // ─────────────────────────────────────────────────────────────────────────
2427
+ if (type === "templates") {
2428
+ return {
2429
+ templates: [
2430
+ { id: "00000000-0000-0000-0000-00000000001e", name: "Voice AI", type: "voice" },
2431
+ { id: "00000000-0000-0000-0000-000000000004", name: "Chat AI", type: "chat" },
2432
+ { id: "00000000-0000-0000-0000-000000000002", name: "Dashboard AI", type: "dashboard" },
2433
+ ],
2434
+ note: "Use type='voice'|'chat'|'dashboard' when creating personas - template is auto-selected",
2435
+ };
2436
+ }
2437
+ // ─────────────────────────────────────────────────────────────────────────
2438
+ // type="patterns" - Workflow patterns
2439
+ // ─────────────────────────────────────────────────────────────────────────
2440
+ if (type === "patterns") {
2441
+ // Get specific pattern
2442
+ if (args.pattern) {
2443
+ const patternName = args.pattern;
2444
+ const pattern = WORKFLOW_PATTERNS[patternName];
2445
+ if (!pattern) {
2446
+ return { error: `Pattern not found: ${args.pattern}` };
2447
+ }
2448
+ return pattern;
2449
+ }
2450
+ // List patterns
2451
+ let patterns = Object.entries(WORKFLOW_PATTERNS);
2452
+ if (args.persona_type) {
2453
+ patterns = patterns.filter(([_, p]) => !p.personaType || p.personaType === args.persona_type);
2454
+ }
2455
+ return {
2456
+ count: patterns.length,
2457
+ patterns: patterns.map(([name, p]) => ({
2458
+ name,
2459
+ description: p.description,
2460
+ use_case: p.useCase,
2461
+ persona_type: p.personaType,
2462
+ })),
2463
+ };
2301
2464
  }
2302
- // List concepts
2303
- if (args.concepts) {
2465
+ // ─────────────────────────────────────────────────────────────────────────
2466
+ // type="widgets" - Widget reference
2467
+ // ─────────────────────────────────────────────────────────────────────────
2468
+ if (type === "widgets") {
2469
+ const personaType = args.persona_type ?? "voice";
2470
+ const widgets = getWidgetsForPersonaType(personaType);
2471
+ return { type: personaType, widgets };
2472
+ }
2473
+ // ─────────────────────────────────────────────────────────────────────────
2474
+ // type="concepts" - List all concepts
2475
+ // ─────────────────────────────────────────────────────────────────────────
2476
+ if (type === "concepts" || args.concepts) {
2304
2477
  return {
2305
2478
  concepts: PLATFORM_CONCEPTS,
2306
2479
  count: PLATFORM_CONCEPTS.length,
2307
2480
  };
2308
2481
  }
2482
+ // ─────────────────────────────────────────────────────────────────────────
2483
+ // questions=true - Qualifying questions
2484
+ // ─────────────────────────────────────────────────────────────────────────
2485
+ if (args.questions) {
2486
+ let questions = QUALIFYING_QUESTIONS;
2487
+ if (args.category) {
2488
+ questions = getQualifyingQuestionsByCategory(args.category);
2489
+ }
2490
+ if (args.required_only) {
2491
+ questions = getRequiredQualifyingQuestions();
2492
+ }
2493
+ return { questions, count: questions.length };
2494
+ }
2495
+ // ─────────────────────────────────────────────────────────────────────────
2496
+ // Get specific concept
2497
+ // ─────────────────────────────────────────────────────────────────────────
2498
+ if (args.concept) {
2499
+ const concept = getConceptByTerm(args.concept);
2500
+ if (!concept) {
2501
+ return { error: `Concept not found: ${args.concept}` };
2502
+ }
2503
+ return concept;
2504
+ }
2505
+ // ─────────────────────────────────────────────────────────────────────────
2309
2506
  // Get guidance
2507
+ // ─────────────────────────────────────────────────────────────────────────
2310
2508
  if (args.guidance) {
2311
2509
  const topic = GUIDANCE_TOPICS[args.guidance];
2312
2510
  if (!topic) {
@@ -2342,7 +2540,128 @@ export function handleReference(args) {
2342
2540
  const result = validateWorkflowPrompt(args.validate_prompt);
2343
2541
  return result;
2344
2542
  }
2345
- return { error: "Specify concept, concepts=true, guidance, mistakes=true, checklist=true, execution=true, check_types, or validate_prompt" };
2543
+ return {
2544
+ error: "Specify type (envs|actions|templates|patterns|widgets|concepts), or use concept, guidance, questions, mistakes, checklist, execution, check_types, validate_prompt",
2545
+ examples: [
2546
+ 'reference(type="envs")',
2547
+ 'reference(type="actions")',
2548
+ 'reference(type="actions", id="send_email")',
2549
+ 'reference(type="patterns")',
2550
+ 'reference(concept="HITL")',
2551
+ 'reference(guidance="categorizer-routing")',
2552
+ 'reference(questions=true)',
2553
+ ],
2554
+ };
2555
+ }
2556
+ // ═══════════════════════════════════════════════════════════════════════════
2557
+ // DATA Handler (v2 alias for knowledge)
2558
+ // ═══════════════════════════════════════════════════════════════════════════
2559
+ export async function handleData(args, client, readFile) {
2560
+ // Map v2 modes to knowledge modes
2561
+ const mode = args.mode;
2562
+ const knowledgeArgs = { ...args };
2563
+ // Mode mapping
2564
+ if (mode === "get" && args.file_id) {
2565
+ knowledgeArgs.mode = "list"; // List with specific file context
2566
+ }
2567
+ else if (mode === "embedding") {
2568
+ // Embedding operations
2569
+ if (args.enabled !== undefined) {
2570
+ knowledgeArgs.mode = "toggle";
2571
+ }
2572
+ else {
2573
+ knowledgeArgs.mode = "status";
2574
+ }
2575
+ }
2576
+ else if (mode === "sanitize") {
2577
+ // Data sanitization - needs special handling
2578
+ const personaId = args.persona_id;
2579
+ const includeWorkflow = args.include_workflow;
2580
+ const sanitizeExamples = args.sanitize_examples;
2581
+ const persona = await client.getPersonaById(personaId);
2582
+ if (!persona) {
2583
+ return { error: `Persona not found: ${personaId}` };
2584
+ }
2585
+ // Create sanitization session
2586
+ const session = new SanitizationSession();
2587
+ // Detect and sanitize in proto_config
2588
+ const protoConfig = persona.proto_config;
2589
+ let sanitizedConfig = protoConfig;
2590
+ if (protoConfig) {
2591
+ // Apply pattern-based detection and sanitization
2592
+ const clonedConfig = JSON.parse(JSON.stringify(protoConfig)); // Deep clone
2593
+ // Recursively find and sanitize string values
2594
+ const sanitizeObject = (obj) => {
2595
+ for (const key of Object.keys(obj)) {
2596
+ const val = obj[key];
2597
+ if (typeof val === "string" && val.length > 0) {
2598
+ const detected = detectWithPatterns(val);
2599
+ for (const entity of detected) {
2600
+ const replacement = session.getOrCreateReplacement(entity.value, entity.type);
2601
+ obj[key] = obj[key].split(entity.value).join(replacement);
2602
+ }
2603
+ // Also apply user examples
2604
+ if (sanitizeExamples) {
2605
+ for (const example of sanitizeExamples) {
2606
+ if (obj[key].includes(example)) {
2607
+ const replacement = session.getOrCreateReplacement(example, "unknown");
2608
+ obj[key] = obj[key].split(example).join(replacement);
2609
+ }
2610
+ }
2611
+ }
2612
+ }
2613
+ else if (typeof val === "object" && val !== null) {
2614
+ sanitizeObject(val);
2615
+ }
2616
+ }
2617
+ };
2618
+ sanitizeObject(clonedConfig);
2619
+ sanitizedConfig = clonedConfig;
2620
+ }
2621
+ // Optionally sanitize workflow
2622
+ let sanitizedWorkflow = persona.workflow_def;
2623
+ if (includeWorkflow && sanitizedWorkflow) {
2624
+ const clonedWorkflow = JSON.parse(JSON.stringify(sanitizedWorkflow));
2625
+ const sanitizeWfObj = (obj) => {
2626
+ for (const key of Object.keys(obj)) {
2627
+ const val = obj[key];
2628
+ if (typeof val === "string" && val.length > 0) {
2629
+ const detected = detectWithPatterns(val);
2630
+ for (const entity of detected) {
2631
+ const replacement = session.getOrCreateReplacement(entity.value, entity.type);
2632
+ obj[key] = obj[key].split(entity.value).join(replacement);
2633
+ }
2634
+ }
2635
+ else if (typeof val === "object" && val !== null) {
2636
+ sanitizeWfObj(val);
2637
+ }
2638
+ }
2639
+ };
2640
+ sanitizeWfObj(clonedWorkflow);
2641
+ sanitizedWorkflow = clonedWorkflow;
2642
+ }
2643
+ // Apply updates
2644
+ await client.updateAiEmployee({
2645
+ persona_id: personaId,
2646
+ proto_config: sanitizedConfig ?? {},
2647
+ workflow: includeWorkflow ? sanitizedWorkflow : undefined,
2648
+ });
2649
+ // Convert Map to array for JSON response
2650
+ const mappingsMap = session.getMappings();
2651
+ const mappingsArray = Array.from(mappingsMap.entries()).map(([original, replacement]) => ({
2652
+ original,
2653
+ replacement,
2654
+ }));
2655
+ return {
2656
+ success: true,
2657
+ persona_id: personaId,
2658
+ entities_sanitized: mappingsMap.size,
2659
+ mappings: mappingsArray,
2660
+ workflow_sanitized: !!includeWorkflow,
2661
+ };
2662
+ }
2663
+ // Default: delegate to knowledge handler
2664
+ return handleKnowledge(knowledgeArgs, client, readFile);
2346
2665
  }
2347
2666
  // ═══════════════════════════════════════════════════════════════════════════
2348
2667
  // SYNC Handler
@@ -51,7 +51,7 @@ import { generateLegacyTools, } from "./tools-legacy.js";
51
51
  // Feature flag: Legacy tools are DISABLED by default to prevent LLM confusion
52
52
  // Set EMA_ENABLE_LEGACY_TOOLS=true only if you need backwards compatibility
53
53
  const ENABLE_LEGACY_TOOLS = process.env.EMA_ENABLE_LEGACY_TOOLS === "true";
54
- import { handleEnv, handlePersona, handleWorkflow, handleAction, handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
54
+ import { handleEnv, handlePersona, handleWorkflow, handleAction, handleData, handleTemplate, handleKnowledge, handleReference, } from "./handlers-consolidated.js";
55
55
  // ─────────────────────────────────────────────────────────────────────────────
56
56
  // Autobuilder Prompt Generation
57
57
  // ─────────────────────────────────────────────────────────────────────────────
@@ -4742,8 +4742,23 @@ const toolHandlers = {
4742
4742
  const fs = await import("fs/promises");
4743
4743
  return handleKnowledge(args, client, (path) => fs.readFile(path));
4744
4744
  },
4745
+ // v2: data is an alias for knowledge with simplified interface
4746
+ data: async (args) => {
4747
+ const client = createClient(args.env);
4748
+ const fs = await import("fs/promises");
4749
+ return handleData(args, client, (path) => fs.readFile(path));
4750
+ },
4745
4751
  reference: async (args) => {
4746
- return handleReference(args);
4752
+ // v2: expanded reference handler with envs, actions, templates, patterns support
4753
+ const client = createClient(args.env);
4754
+ return handleReference(args, {
4755
+ getEnvironments: () => getAvailableEnvironments().map(e => ({
4756
+ name: e.name,
4757
+ isDefault: e.name === getDefaultEnvName(),
4758
+ })),
4759
+ toolkit: { name: TOOLKIT_NAME, version: TOOLKIT_VERSION },
4760
+ client,
4761
+ });
4747
4762
  },
4748
4763
  // Note: 'sync' handler already exists above - keeping it for full functionality
4749
4764
  // Note: demo is handled via a consolidated adapter below
@@ -465,75 +465,142 @@ Ask the user these questions, then put answers into ONE workflow() call.
465
465
  }, ["persona_id"]),
466
466
  },
467
467
  // ═══════════════════════════════════════════════════════════════════════
468
- // 7. REFERENCE - Platform concepts, guidance, validation
468
+ // 7. REFERENCE - All reference info (envs, actions, templates, patterns, concepts, guidance)
469
469
  // ═══════════════════════════════════════════════════════════════════════
470
470
  {
471
471
  name: "reference",
472
- description: `Get platform documentation and validation tools.
472
+ description: `All reference information: environments, actions, templates, patterns, concepts, guidance.
473
473
 
474
- **Concepts**:
475
- reference(concept="HITL")
476
- reference(concepts=true) # List all
474
+ **Environments**:
475
+ reference(type="envs")
476
+
477
+ **Actions** (workflow building blocks):
478
+ reference(type="actions") # List all
479
+ reference(type="actions", query="email") # Search
480
+ reference(type="actions", id="send_email") # Get specific
481
+ reference(type="actions", suggest="IT helpdesk") # Suggest for use case
482
+ reference(type="actions", categories=true) # List categories
483
+
484
+ **Templates & Patterns**:
485
+ reference(type="templates") # List persona templates
486
+ reference(type="patterns") # List workflow patterns
487
+ reference(type="patterns", pattern="intent-routing") # Get specific
477
488
 
478
- **Guidance**:
489
+ **Widgets**:
490
+ reference(type="widgets", persona_type="voice")
491
+
492
+ **Concepts & Guidance**:
493
+ reference(concept="HITL")
479
494
  reference(guidance="categorizer-routing")
480
- reference(guidance="type-compatibility")
481
- reference(guidance="workflow-structure") # Summarizer → Extractor → JSON mapper pattern
482
- reference(guidance="search-node-timing") # When to use search nodes, early vs late
483
- reference(guidance="node-execution-conditions") # When nodes execute or are skipped
484
- reference(guidance="array-preservation") # How to preserve arrays through extraction → mapping → downstream
485
- reference(guidance="search-filtering") # Semantic query + structured filters best practices
486
- reference(guidance="fallback-response-inputs") # Fallback should use full conversation + context
487
- reference(guidance="separate-vs-merged-inputs") # Keep separate named_inputs for multi-source data
488
- reference(guidance="folder-path-filtering") # Folder path filtering with semantic query
489
- reference(guidance="automated-extraction-json") # Automating extraction → JSON mapper pattern
490
- reference(guidance="when-filters-necessary") # When filters are required vs optional
491
- reference(guidance="filter-query-guidance") # When to use filters vs queries vs both
492
- reference(guidance="workflow-structure")
493
- reference(guidance="search-node-timing")
494
- reference(guidance="node-execution-conditions")
495
+ reference(questions=true) # Qualifying questions
495
496
 
496
497
  **Debugging**:
497
498
  reference(mistakes=true)
498
499
  reference(checklist=true)
499
- reference(execution=true) # Workflow execution model
500
+ reference(execution=true)
500
501
 
501
502
  **Validation**:
502
- reference(check_types={source: "CHAT_CONVERSATION", target: "TEXT_WITH_SOURCES"})
503
- reference(validate_prompt="Create a bot...")`,
504
- inputSchema: {
505
- type: "object",
506
- properties: {
507
- // Concepts
508
- concept: { type: "string", description: "Get definition of platform term" },
509
- concepts: { type: "boolean", description: "List all platform concepts" },
510
- // Guidance
511
- guidance: {
512
- type: "string",
513
- enum: [
514
- "categorizer-routing", "type-compatibility", "named-inputs",
515
- "hitl-patterns", "multi-source-search", "voice-tool-calling",
516
- "guardrails", "output-mapping", "workflow-execution", "conversation-vs-query"
517
- ],
518
- description: "Get guidance on topic"
519
- },
520
- // Debugging
521
- mistakes: { type: "boolean", description: "Get common mistakes list" },
522
- checklist: { type: "boolean", description: "Get debug checklist" },
523
- execution: { type: "boolean", description: "Get workflow execution model" },
524
- // Validation
525
- check_types: {
526
- type: "object",
527
- properties: {
528
- source: { type: "string", description: "Source output type" },
529
- target: { type: "string", description: "Target input type" },
530
- },
531
- description: "Check type compatibility"
503
+ reference(check_types={source: "CHAT_CONVERSATION", target: "TEXT"})`,
504
+ inputSchema: withEnv({
505
+ // Type selector (v2)
506
+ type: {
507
+ type: "string",
508
+ enum: ["envs", "actions", "templates", "patterns", "widgets", "concepts"],
509
+ description: "What type of reference information"
510
+ },
511
+ // Actions
512
+ id: { type: "string", description: "Action ID for details" },
513
+ query: { type: "string", description: "Search actions by name" },
514
+ suggest: { type: "string", description: "Suggest actions for use case" },
515
+ categories: { type: "boolean", description: "List action categories" },
516
+ category: { type: "string", description: "Filter by category" },
517
+ include_docs: { type: "boolean", description: "Include full documentation" },
518
+ limit: { type: "number", description: "Max results" },
519
+ // Patterns
520
+ pattern: {
521
+ type: "string",
522
+ enum: ["simple-kb-search", "intent-routing", "multi-source-search", "tool-calling", "hitl-approval", "document-processing", "guardrails-pattern"],
523
+ description: "Get specific pattern"
524
+ },
525
+ // Widgets
526
+ persona_type: { type: "string", enum: ["voice", "chat", "dashboard"], description: "Persona type for widgets" },
527
+ // Concepts
528
+ concept: { type: "string", description: "Get definition of platform term" },
529
+ concepts: { type: "boolean", description: "List all platform concepts" },
530
+ // Questions
531
+ questions: { type: "boolean", description: "Get qualifying questions" },
532
+ required_only: { type: "boolean", description: "Only required questions" },
533
+ // Guidance
534
+ guidance: {
535
+ type: "string",
536
+ enum: [
537
+ "categorizer-routing", "type-compatibility", "named-inputs",
538
+ "hitl-patterns", "multi-source-search", "voice-tool-calling",
539
+ "guardrails", "output-mapping", "workflow-execution", "conversation-vs-query"
540
+ ],
541
+ description: "Get guidance on topic"
542
+ },
543
+ // Debugging
544
+ mistakes: { type: "boolean", description: "Get common mistakes list" },
545
+ checklist: { type: "boolean", description: "Get debug checklist" },
546
+ execution: { type: "boolean", description: "Get workflow execution model" },
547
+ // Validation
548
+ check_types: {
549
+ type: "object",
550
+ properties: {
551
+ source: { type: "string", description: "Source output type" },
552
+ target: { type: "string", description: "Target input type" },
532
553
  },
533
- validate_prompt: { type: "string", description: "Validate workflow prompt" },
554
+ description: "Check type compatibility"
534
555
  },
535
- required: [],
536
- },
556
+ validate_prompt: { type: "string", description: "Validate workflow prompt" },
557
+ }),
558
+ },
559
+ // ═══════════════════════════════════════════════════════════════════════
560
+ // 7b. DATA - Manage persona data (v2 simplified interface for knowledge)
561
+ // ═══════════════════════════════════════════════════════════════════════
562
+ {
563
+ name: "data",
564
+ description: `Manage AI Employee data (files).
565
+
566
+ **List files**:
567
+ data(persona_id="abc")
568
+ data(persona_id="abc", limit=50)
569
+
570
+ **Upload file** (file provided via conversation context):
571
+ data(persona_id="abc", mode="upload")
572
+
573
+ **Delete file**:
574
+ data(persona_id="abc", mode="delete", file_id="file-123")
575
+
576
+ **Sanitize data**:
577
+ data(persona_id="abc", mode="sanitize")
578
+ data(persona_id="abc", mode="sanitize", include_workflow=true)
579
+
580
+ **Embedding**:
581
+ data(persona_id="abc", mode="embedding") # Get status
582
+ data(persona_id="abc", mode="embedding", enabled=true) # Toggle`,
583
+ inputSchema: withEnv({
584
+ persona_id: { type: "string", description: "AI Employee ID (required)" },
585
+ mode: {
586
+ type: "string",
587
+ enum: ["list", "upload", "delete", "sanitize", "embedding"],
588
+ description: "Operation (default: list)"
589
+ },
590
+ // Get/Delete specific file
591
+ file_id: { type: "string", description: "File ID for delete" },
592
+ // List options
593
+ limit: { type: "number", description: "Max results (default: 50)" },
594
+ page: { type: "number", description: "Page number (default: 1)" },
595
+ // Upload
596
+ file: { type: "string", description: "File path for upload" },
597
+ tags: { type: "string", description: "Tags for uploaded file" },
598
+ // Sanitize options
599
+ include_workflow: { type: "boolean", description: "Also sanitize workflow config" },
600
+ sanitize_examples: { type: "array", items: { type: "string" }, description: "Additional sensitive items" },
601
+ // Embedding toggle
602
+ enabled: { type: "boolean", description: "Enable/disable embedding" },
603
+ }, ["persona_id"]),
537
604
  },
538
605
  // ═══════════════════════════════════════════════════════════════════════
539
606
  // 8. SYNC - Environment synchronization
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ema.co/mcp-toolkit",
3
- "version": "1.7.1",
3
+ "version": "2026.1.17",
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",