@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
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
# Designing MCP Tools for How People Actually Use Them
|
|
2
|
-
|
|
3
|
-
*Lessons from restructuring an MCP server from 7 "super tools" to 20 focused operations*
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## The Starting Point
|
|
8
|
-
|
|
9
|
-
We had built an MCP (Model Context Protocol) server for managing AI Employees on the Ema platform. It worked. Users could create personas, manage workflows, sync across environments. But something felt off.
|
|
10
|
-
|
|
11
|
-
Our server had consolidated ~45 original tools into just 7 "super tools" using a `mode` parameter:
|
|
12
|
-
|
|
13
|
-
```typescript
|
|
14
|
-
// What we had
|
|
15
|
-
persona(mode="list")
|
|
16
|
-
persona(mode="get", id="abc-123")
|
|
17
|
-
persona(mode="create", name="Sales Bot", type="voice", input="...")
|
|
18
|
-
persona(mode="analyze", id="abc-123", fix=true, include=["workflow", "config"])
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Fewer tools seemed better, right? Unix philosophy: do one thing well. Except each tool had 30+ parameters, and the LLM had to figure out which parameters applied to which mode.
|
|
22
|
-
|
|
23
|
-
It was clever engineering. It was also wrong.
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## The Problems We Discovered
|
|
28
|
-
|
|
29
|
-
### Problem 1: Parameter Sprawl
|
|
30
|
-
|
|
31
|
-
Every time an LLM called our `persona` tool, it saw this schema:
|
|
32
|
-
|
|
33
|
-
```json
|
|
34
|
-
{
|
|
35
|
-
"properties": {
|
|
36
|
-
"mode": { "enum": ["list", "get", "create", "update", "clone", "analyze", "sanitize", "templates", ...] },
|
|
37
|
-
"id": { "description": "Persona ID" },
|
|
38
|
-
"name": { "description": "Name for new persona" },
|
|
39
|
-
"type": { "enum": ["voice", "chat", "dashboard"] },
|
|
40
|
-
"from": { "description": "Template or persona to clone from" },
|
|
41
|
-
"input": { "description": "Natural language description" },
|
|
42
|
-
"include_data": { "description": "Include data when cloning" },
|
|
43
|
-
"sanitize": { "description": "Remove PII" },
|
|
44
|
-
"fix": { "description": "Auto-fix issues" },
|
|
45
|
-
"include": { "description": "What to include in analysis" },
|
|
46
|
-
"proto_config": { "description": "Override config" },
|
|
47
|
-
"workflow": { "description": "Direct workflow JSON" },
|
|
48
|
-
// ... 20 more parameters
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
The LLM saw 30 parameters when it only needed 2 for a simple "get me this persona" request. Confusion ensued.
|
|
54
|
-
|
|
55
|
-
### Problem 2: Inconsistent Patterns
|
|
56
|
-
|
|
57
|
-
We had three different patterns across our 7 tools:
|
|
58
|
-
|
|
59
|
-
| Tool | Pattern |
|
|
60
|
-
|------|---------|
|
|
61
|
-
| `persona` | `mode` parameter required |
|
|
62
|
-
| `action` | Flag-based (`all=true`, `suggest="..."`) |
|
|
63
|
-
| `reference` | Hybrid (`type` enum + individual flags) |
|
|
64
|
-
|
|
65
|
-
Which pattern should the LLM use? It depended on which tool. This meant the LLM had to learn 3 different interaction styles.
|
|
66
|
-
|
|
67
|
-
### Problem 3: We Designed for the Wrong User
|
|
68
|
-
|
|
69
|
-
Here's the insight that changed everything:
|
|
70
|
-
|
|
71
|
-
> **We designed tools as if humans would read the schemas. But LLMs read the schemas.**
|
|
72
|
-
|
|
73
|
-
We thought about developer ergonomics: fewer tools, consistent naming, Unix-like. But LLMs don't care about those things. They care about:
|
|
74
|
-
|
|
75
|
-
1. **Does the tool name match the user's intent?**
|
|
76
|
-
2. **Are the parameters relevant to what I'm trying to do?**
|
|
77
|
-
3. **Is the description clear about when to use this?**
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## The Key Insight: Users Speak, LLMs Choose
|
|
82
|
-
|
|
83
|
-
When we observed actual usage, we saw this pattern:
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
User: "Clone the Sales SDR with its data and clean it up for demo"
|
|
87
|
-
│
|
|
88
|
-
▼
|
|
89
|
-
LLM parses intent
|
|
90
|
-
│
|
|
91
|
-
▼
|
|
92
|
-
LLM searches available tools
|
|
93
|
-
│
|
|
94
|
-
▼
|
|
95
|
-
LLM selects: persona(mode="clone", from="...", include_data=true, sanitize=true)
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
The user never typed a tool name. They never selected from a menu. They just described what they wanted in natural language.
|
|
99
|
-
|
|
100
|
-
**This means tool design is really about one thing: making it easy for LLMs to match natural language intent to the right tool with the right parameters.**
|
|
101
|
-
|
|
102
|
-
---
|
|
103
|
-
|
|
104
|
-
## What About Prompts?
|
|
105
|
-
|
|
106
|
-
MCP has two mechanisms: **Tools** and **Prompts**. We initially thought prompts could help—maybe `persona.create` as a prompt that guides the creation flow?
|
|
107
|
-
|
|
108
|
-
But the MCP spec is clear about the distinction:
|
|
109
|
-
|
|
110
|
-
| Mechanism | Who Controls | How Triggered |
|
|
111
|
-
|-----------|--------------|---------------|
|
|
112
|
-
| **Tools** | Model-controlled | LLM invokes automatically |
|
|
113
|
-
| **Prompts** | User-controlled | User explicitly selects (slash commands) |
|
|
114
|
-
|
|
115
|
-
Prompts are like slash commands (`/create_voice_ai`). They're for explicit, user-initiated workflows.
|
|
116
|
-
|
|
117
|
-
**In practice, users rarely use slash commands.** They just talk. Which means tools are what matter for 95% of interactions.
|
|
118
|
-
|
|
119
|
-
> **Design for natural language, not for slash commands. The LLM is the interface. Tools are the API.**
|
|
120
|
-
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
## The Redesign
|
|
124
|
-
|
|
125
|
-
### Principle 1: One Operation, One Tool
|
|
126
|
-
|
|
127
|
-
Instead of modes, each operation gets its own tool:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
// Before: mode-based
|
|
131
|
-
persona(mode="list")
|
|
132
|
-
persona(mode="get", id="abc")
|
|
133
|
-
persona(mode="create", name="Bot", ...)
|
|
134
|
-
|
|
135
|
-
// After: operation-based
|
|
136
|
-
persona() // list (no params = list)
|
|
137
|
-
persona(id="abc") // get (id = get one)
|
|
138
|
-
persona_create(name="Bot", ...)
|
|
139
|
-
persona_clone(from="abc", ...)
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
Each tool has only the parameters relevant to that operation. When the LLM calls `persona_create`, it sees 5 relevant parameters, not 30.
|
|
143
|
-
|
|
144
|
-
### Principle 2: Names Match Natural Language
|
|
145
|
-
|
|
146
|
-
Tool names should match how users describe their intent:
|
|
147
|
-
|
|
148
|
-
| User Says | Tool Name |
|
|
149
|
-
|-----------|-----------|
|
|
150
|
-
| "show me my personas" | `persona` |
|
|
151
|
-
| "create a voice AI" | `persona_create` |
|
|
152
|
-
| "clone it with data" | `persona_clone` |
|
|
153
|
-
| "what's wrong with it" | `persona_analyze` |
|
|
154
|
-
| "push to staging" | `sync_run` |
|
|
155
|
-
|
|
156
|
-
The LLM matches "clone it with data" to `persona_clone(include_data=true)` because the tool name and flag names align with natural language.
|
|
157
|
-
|
|
158
|
-
### Principle 3: Flags for Common Combinations
|
|
159
|
-
|
|
160
|
-
Users often want compound operations: "clone with data AND sanitize." Instead of requiring multiple tool calls, common combinations become flags:
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
persona_clone(
|
|
164
|
-
from: "abc",
|
|
165
|
-
name: "Demo Copy",
|
|
166
|
-
include_data: true, // Clone data files too
|
|
167
|
-
sanitize: true // Remove PII
|
|
168
|
-
)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
This handles 80% of cases in one call. For the other 20%, the LLM can chain tools.
|
|
172
|
-
|
|
173
|
-
### Principle 4: Hierarchy in Names
|
|
174
|
-
|
|
175
|
-
Data and workflows are persona-specific. The naming reflects this:
|
|
176
|
-
|
|
177
|
-
```
|
|
178
|
-
persona # list/get personas
|
|
179
|
-
persona_create # create
|
|
180
|
-
persona_clone # clone
|
|
181
|
-
|
|
182
|
-
persona_data # list data for a persona
|
|
183
|
-
persona_data_upload # upload to a persona
|
|
184
|
-
persona_data_sanitize # sanitize data only
|
|
185
|
-
|
|
186
|
-
persona_workflow # get workflow
|
|
187
|
-
persona_workflow_modify # modify workflow
|
|
188
|
-
persona_workflow_sanitize # sanitize workflow only
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
This makes scope explicit: `persona_sanitize` does everything, `persona_data_sanitize` does just the data.
|
|
192
|
-
|
|
193
|
-
### Principle 5: Cross-Platform Compatibility
|
|
194
|
-
|
|
195
|
-
We almost used dot notation (`persona.data.upload`) because it looks cleaner and the MCP spec allows it. Then we discovered:
|
|
196
|
-
|
|
197
|
-
| Spec | Allows Dots? |
|
|
198
|
-
|------|--------------|
|
|
199
|
-
| MCP | Yes (`admin.tools.list` is valid) |
|
|
200
|
-
| OpenAI API | No (`^[a-zA-Z0-9_-]+$`) |
|
|
201
|
-
|
|
202
|
-
Many MCP clients bridge to OpenAI-compatible APIs. Dot notation would break those integrations. **Snake case (`_`) is the safe choice.**
|
|
203
|
-
|
|
204
|
-
---
|
|
205
|
-
|
|
206
|
-
## The Result
|
|
207
|
-
|
|
208
|
-
### Before: 7 Tools, 30+ Params Each
|
|
209
|
-
|
|
210
|
-
```
|
|
211
|
-
persona(mode, id, name, type, from, input, include_data, sanitize, fix, include, ...)
|
|
212
|
-
data(persona_id, mode, file_id, file, ...)
|
|
213
|
-
action(id, all, query, category, suggest, ...)
|
|
214
|
-
...
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### After: 20 Focused Tools
|
|
218
|
-
|
|
219
|
-
```
|
|
220
|
-
# Core
|
|
221
|
-
persona persona_create persona_clone
|
|
222
|
-
persona_update persona_analyze persona_sanitize
|
|
223
|
-
|
|
224
|
-
# Data (persona-scoped)
|
|
225
|
-
persona_data persona_data_upload persona_data_generate
|
|
226
|
-
persona_data_delete persona_data_sanitize
|
|
227
|
-
|
|
228
|
-
# Workflow (persona-scoped)
|
|
229
|
-
persona_workflow persona_workflow_modify persona_workflow_sanitize
|
|
230
|
-
|
|
231
|
-
# Versions
|
|
232
|
-
persona_version persona_version_create persona_version_restore
|
|
233
|
-
|
|
234
|
-
# Other
|
|
235
|
-
action action_suggest
|
|
236
|
-
sync_run sync_status
|
|
237
|
-
env
|
|
238
|
-
```
|
|
239
|
-
|
|
240
|
-
Each tool has 3-8 parameters. The LLM sees only what's relevant.
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## Key Takeaways
|
|
245
|
-
|
|
246
|
-
### 1. Design for LLM Selection, Not Human Browsing
|
|
247
|
-
|
|
248
|
-
Your tool names and descriptions are an API for LLMs. They need to match natural language patterns so the LLM can find the right tool when the user says "clone this and clean it up."
|
|
249
|
-
|
|
250
|
-
### 2. Users Speak Natural Language, Not Slash Commands
|
|
251
|
-
|
|
252
|
-
Prompts (user-triggered workflows) are a nice-to-have. Tools (model-selected operations) are the core experience. Invest accordingly.
|
|
253
|
-
|
|
254
|
-
### 3. Fewer Parameters Beats Fewer Tools
|
|
255
|
-
|
|
256
|
-
A tool with 30 parameters is harder for an LLM to use correctly than 5 tools with 6 parameters each. The LLM has to filter out irrelevant options with every call.
|
|
257
|
-
|
|
258
|
-
### 4. Flag Names Are Natural Language
|
|
259
|
-
|
|
260
|
-
When you name a flag `include_data`, you're not just documenting—you're making it matchable to "with data" or "include the files." Name flags like users talk.
|
|
261
|
-
|
|
262
|
-
### 5. Interoperability Matters
|
|
263
|
-
|
|
264
|
-
The MCP spec is flexible, but your tools might be bridged to OpenAI, Anthropic, or other APIs. Stick to the common denominator: alphanumeric plus underscore and hyphen.
|
|
265
|
-
|
|
266
|
-
---
|
|
267
|
-
|
|
268
|
-
## The Mental Model
|
|
269
|
-
|
|
270
|
-
```
|
|
271
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
272
|
-
│ USER │
|
|
273
|
-
│ "Clone the sales bot with data and sanitize for demo" │
|
|
274
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
275
|
-
│
|
|
276
|
-
▼
|
|
277
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
278
|
-
│ LLM │
|
|
279
|
-
│ Parses intent → Searches tools → Matches parameters │
|
|
280
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
281
|
-
│
|
|
282
|
-
▼
|
|
283
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
284
|
-
│ TOOL SELECTION │
|
|
285
|
-
│ persona_clone(from="sales-bot", name="Demo", include_data=true,│
|
|
286
|
-
│ sanitize=true) │
|
|
287
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
288
|
-
│
|
|
289
|
-
▼
|
|
290
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
291
|
-
│ MCP SERVER │
|
|
292
|
-
│ Executes operation → Returns result │
|
|
293
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
294
|
-
```
|
|
295
|
-
|
|
296
|
-
The user never sees tool names. The LLM is the interface. **Design your tools for the LLM, and the LLM will serve the user.**
|
|
297
|
-
|
|
298
|
-
---
|
|
299
|
-
|
|
300
|
-
## References
|
|
301
|
-
|
|
302
|
-
- [MCP Specification - Tools](https://modelcontextprotocol.io/specification/2025-11-25/server/tools)
|
|
303
|
-
- [MCP Specification - Prompts](https://modelcontextprotocol.io/specification/2025-11-25/server/prompts)
|
|
304
|
-
- [Awesome MCP Servers](https://mcpservers.org/) - Industry patterns
|
|
305
|
-
- [Playwright MCP](https://github.com/microsoft/playwright-mcp) - Reference implementation
|
|
306
|
-
|
|
307
|
-
---
|
|
308
|
-
|
|
309
|
-
*Have thoughts on MCP tool design? We'd love to hear what patterns work for you.*
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
# Data Architecture & Sourcing Strategy
|
|
2
|
-
|
|
3
|
-
> **Principle**: MCP serves all data. Cursor rules are policy/flow only.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Data Sourcing Hierarchy
|
|
8
|
-
|
|
9
|
-
For any data that MCP exposes, follow this resolution order:
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
1. Ema API (live, authoritative) ← PREFERRED
|
|
13
|
-
2. resources/** (repo files) ← FILE FALLBACK
|
|
14
|
-
3. src/sdk/*.ts (embedded constants) ← CODE FALLBACK
|
|
15
|
-
4. NEVER: .cursor/rules/** ← POLICY ONLY, NO DATA
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
---
|
|
19
|
-
|
|
20
|
-
## Current State Audit
|
|
21
|
-
|
|
22
|
-
### ✅ DYNAMIC (API-First)
|
|
23
|
-
|
|
24
|
-
| Resource | Source | Fallback | Notes |
|
|
25
|
-
|----------|--------|----------|-------|
|
|
26
|
-
| `ema://catalog/agents` | `listActions()` API | `AGENT_CATALOG` | Cached 60s, env-aware |
|
|
27
|
-
| `ema://catalog/agents-summary` | `listActions()` API | `AGENT_CATALOG` | Markdown format |
|
|
28
|
-
| `ema://catalog/templates` | `getPersonaTemplates()` API | Empty (use file-backed) | Cached 60s, env-aware |
|
|
29
|
-
| `ema://catalog/templates-summary` | `getPersonaTemplates()` API | Empty | Markdown format |
|
|
30
|
-
| `action(...)` tool | `listActions()` API | Embedded docs | Full API integration |
|
|
31
|
-
|
|
32
|
-
### ⚠️ HARDCODED (Embedded in Code)
|
|
33
|
-
|
|
34
|
-
| Resource | Source | Can Be Dynamic? | Priority |
|
|
35
|
-
|----------|--------|-----------------|----------|
|
|
36
|
-
| `ema://catalog/patterns` | `WORKFLOW_PATTERNS` | Yes - could query "template personas" | Medium |
|
|
37
|
-
| `ema://catalog/widgets` | `WIDGET_CATALOG` | Yes - could query API | Low |
|
|
38
|
-
| `ema://rules/input-sources` | `INPUT_SOURCE_RULES` | Unlikely - validation logic | Low |
|
|
39
|
-
| `ema://rules/anti-patterns` | `ANTI_PATTERNS` | Unlikely - validation logic | Low |
|
|
40
|
-
| `ema://rules/optimizations` | `OPTIMIZATION_RULES` | Unlikely - validation logic | Low |
|
|
41
|
-
|
|
42
|
-
### 📁 FILE-BACKED (Repo Files - Fallback)
|
|
43
|
-
|
|
44
|
-
| Resource | Path | Notes |
|
|
45
|
-
|----------|------|-------|
|
|
46
|
-
| `ema://templates/voice-ai/*` | `resources/templates/voice-ai/` | Fallback when API unavailable |
|
|
47
|
-
| `ema://templates/chat-ai/*` | `resources/templates/chat-ai/` | Fallback when API unavailable |
|
|
48
|
-
| `ema://templates/dashboard-ai/*` | `resources/templates/dashboard-ai/` | Fallback when API unavailable |
|
|
49
|
-
| `ema://docs/*` | `docs/*.md` | Repo documentation |
|
|
50
|
-
|
|
51
|
-
**Note**: For templates, prefer `ema://catalog/templates` (API-first) over file-backed `ema://templates/*`.
|
|
52
|
-
|
|
53
|
-
---
|
|
54
|
-
|
|
55
|
-
## Making More Things Dynamic
|
|
56
|
-
|
|
57
|
-
### ✅ DONE: Templates
|
|
58
|
-
|
|
59
|
-
Templates are now API-first via `getPersonaTemplates()`:
|
|
60
|
-
|
|
61
|
-
```typescript
|
|
62
|
-
// EmaClient method
|
|
63
|
-
async getPersonaTemplates(): Promise<PersonaTemplateDTO[]>
|
|
64
|
-
|
|
65
|
-
// MCP Resources (API-first with cache)
|
|
66
|
-
ema://catalog/templates // Full template data
|
|
67
|
-
ema://catalog/templates-summary // Markdown summary
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### Medium Priority: Workflow Patterns
|
|
71
|
-
|
|
72
|
-
Patterns could be derived from analyzing existing personas:
|
|
73
|
-
|
|
74
|
-
```typescript
|
|
75
|
-
// Future: Pattern extraction from existing personas
|
|
76
|
-
async function getPatterns() {
|
|
77
|
-
// 1. Query personas tagged as "template" or "pattern"
|
|
78
|
-
const templatePersonas = await client.getPersonasWithTag("template");
|
|
79
|
-
if (templatePersonas.length > 0) {
|
|
80
|
-
return extractPatternsFromPersonas(templatePersonas);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// 2. Fallback to embedded patterns
|
|
84
|
-
return WORKFLOW_PATTERNS;
|
|
85
|
-
}
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Low Priority: Validation Rules
|
|
89
|
-
|
|
90
|
-
These are internal logic, not external data. Keep embedded unless Ema provides a validation API.
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## Where Data Lives
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
ema-mcp-toolkit/
|
|
98
|
-
├── src/
|
|
99
|
-
│ ├── mcp/
|
|
100
|
-
│ │ ├── resources.ts # Resource registry + dynamic fetching
|
|
101
|
-
│ │ ├── server.ts # Tool handlers (API calls)
|
|
102
|
-
│ │ └── prompts.ts # Prompt definitions (structured guidance)
|
|
103
|
-
│ └── sdk/
|
|
104
|
-
│ ├── client.ts # EmaClient (API wrapper)
|
|
105
|
-
│ ├── knowledge.ts # AGENT_CATALOG, WORKFLOW_PATTERNS, WIDGET_CATALOG
|
|
106
|
-
│ └── validation-rules.ts # INPUT_SOURCE_RULES, ANTI_PATTERNS, OPTIMIZATION_RULES
|
|
107
|
-
├── resources/
|
|
108
|
-
│ └── templates/ # File-backed templates (canonical location)
|
|
109
|
-
│ ├── voice-ai/
|
|
110
|
-
│ ├── chat-ai/
|
|
111
|
-
│ └── dashboard-ai/
|
|
112
|
-
└── .cursor/
|
|
113
|
-
└── rules/ # POLICY/FLOW ONLY - NO DATA
|
|
114
|
-
├── base/naming/ # Naming conventions
|
|
115
|
-
├── ema/ # MCP usage guidance
|
|
116
|
-
└── platforms/ema/ # Platform-specific flows
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## Cursor Rules Policy
|
|
122
|
-
|
|
123
|
-
### ✅ ALLOWED in Cursor Rules
|
|
124
|
-
|
|
125
|
-
- **Process flows**: "How to create an AI Employee"
|
|
126
|
-
- **Decision trees**: "When to use HITL"
|
|
127
|
-
- **Tool usage guidance**: "Use `workflow(mode='analyze')` for..."
|
|
128
|
-
- **References to MCP**: "Fetch from `ema://catalog/agents`"
|
|
129
|
-
- **Best practices**: "Always extract email recipients via entity_extraction"
|
|
130
|
-
|
|
131
|
-
### ❌ NOT ALLOWED in Cursor Rules
|
|
132
|
-
|
|
133
|
-
- **Agent definitions**: Use `ema://catalog/agents`
|
|
134
|
-
- **Template content**: Use `ema://templates/*`
|
|
135
|
-
- **Validation rules data**: Use `ema://rules/*`
|
|
136
|
-
- **Hardcoded patterns**: Use `ema://catalog/patterns`
|
|
137
|
-
- **Any data that can change**: Must come from MCP
|
|
138
|
-
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
## Implementation Checklist
|
|
142
|
-
|
|
143
|
-
### Already Done ✅
|
|
144
|
-
|
|
145
|
-
- [x] Agent catalog is API-first (`getDynamicAgentCatalog()`)
|
|
146
|
-
- [x] Templates moved from `.cursor/` to `resources/`
|
|
147
|
-
- [x] `action(...)` tool uses API with docs fallback
|
|
148
|
-
- [x] Resources support `?env=` parameter
|
|
149
|
-
- [x] **Persona templates are API-first** (`getDynamicPersonaTemplates()`)
|
|
150
|
-
- [x] Added `EmaClient.getPersonaTemplates()` method
|
|
151
|
-
- [x] Added `ema://catalog/templates` and `ema://catalog/templates-summary` resources
|
|
152
|
-
|
|
153
|
-
### To Do (Future)
|
|
154
|
-
|
|
155
|
-
- [ ] Extract workflow patterns from template `workflow_definition` fields
|
|
156
|
-
- [ ] Consider caching strategy improvements (longer TTL for stable data)
|
|
157
|
-
- [ ] Add health check for API availability
|
|
158
|
-
|
|
159
|
-
---
|
|
160
|
-
|
|
161
|
-
## Related Documentation
|
|
162
|
-
|
|
163
|
-
- `docs/mcp-tools-guide.md` - Tool usage
|
|
164
|
-
- `docs/naming-conventions.md` - Naming standards
|
|
165
|
-
- `.cursor/rules/base/naming/RULE.md` - Naming enforcement
|
|
166
|
-
- `.cursor/rules/ema/RULE.md` - MCP source-of-truth policy
|