@ema.co/mcp-toolkit 1.4.0 → 1.4.3
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 +23 -1
- package/dist/cli/index.js +0 -0
- package/dist/mcp/handlers-consolidated.js +850 -108
- package/dist/mcp/prompts.js +134 -0
- package/dist/mcp/resources.js +4 -4
- package/dist/mcp/server.js +9 -215
- package/dist/mcp/tools-consolidated.js +75 -52
- package/dist/sdk/client.js +164 -20
- package/dist/sdk/contracts.js +1 -0
- package/docs/mcp-tools-guide.md +134 -17
- package/package.json +5 -3
- package/dist/config.js +0 -136
- package/dist/emaClient.js +0 -398
- package/dist/models.js +0 -8
- package/dist/state.js +0 -88
- package/dist/syncOptions.js +0 -216
package/dist/syncOptions.js
DELETED
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Sync Options Configuration
|
|
3
|
-
*
|
|
4
|
-
* Hierarchical configuration for sync behavior, loaded from:
|
|
5
|
-
* 1. .ema.yaml in repo root (shared team defaults)
|
|
6
|
-
* 2. ~/.ema.yaml in user home (personal overrides)
|
|
7
|
-
* 3. Tool parameters (runtime overrides)
|
|
8
|
-
*
|
|
9
|
-
* Resolution order (lowest → highest priority):
|
|
10
|
-
* Built-in defaults → defaults → targets[env] → personas[name] → tool params
|
|
11
|
-
*/
|
|
12
|
-
import fs from "node:fs";
|
|
13
|
-
import path from "node:path";
|
|
14
|
-
import os from "node:os";
|
|
15
|
-
import yaml from "js-yaml";
|
|
16
|
-
import { z } from "zod";
|
|
17
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
-
// Schema
|
|
19
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
-
const SyncBehaviorSchema = z.object({
|
|
21
|
-
sync_status: z.boolean().optional(),
|
|
22
|
-
dry_run: z.boolean().optional(),
|
|
23
|
-
}).strict();
|
|
24
|
-
const RoutingRuleSchema = z.object({
|
|
25
|
-
match: z.object({
|
|
26
|
-
names: z.array(z.string()).optional().default([]),
|
|
27
|
-
ids: z.array(z.string()).optional().default([]),
|
|
28
|
-
}).strict(),
|
|
29
|
-
targets: z.array(z.string()).min(1),
|
|
30
|
-
}).strict();
|
|
31
|
-
const SyncOptionsConfigSchema = z.object({
|
|
32
|
-
defaults: SyncBehaviorSchema.optional().default({}),
|
|
33
|
-
targets: z.record(SyncBehaviorSchema).optional().default({}),
|
|
34
|
-
personas: z.record(SyncBehaviorSchema).optional().default({}),
|
|
35
|
-
routing: z.array(RoutingRuleSchema).optional().default([]),
|
|
36
|
-
}).strict();
|
|
37
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
38
|
-
// Built-in defaults
|
|
39
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
40
|
-
const BUILTIN_DEFAULTS = {
|
|
41
|
-
sync_status: false,
|
|
42
|
-
dry_run: false,
|
|
43
|
-
};
|
|
44
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
45
|
-
// Config loading
|
|
46
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
47
|
-
let cachedSyncOptions = null;
|
|
48
|
-
function loadYamlFile(filePath) {
|
|
49
|
-
try {
|
|
50
|
-
const content = fs.readFileSync(filePath, "utf8");
|
|
51
|
-
return yaml.load(content);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function findRepoRoot() {
|
|
58
|
-
// Start from current working directory and look for .git or package.json
|
|
59
|
-
let dir = process.cwd();
|
|
60
|
-
while (dir !== path.dirname(dir)) {
|
|
61
|
-
if (fs.existsSync(path.join(dir, ".git")) || fs.existsSync(path.join(dir, "package.json"))) {
|
|
62
|
-
return dir;
|
|
63
|
-
}
|
|
64
|
-
dir = path.dirname(dir);
|
|
65
|
-
}
|
|
66
|
-
return process.cwd();
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Load and merge sync options from all config sources.
|
|
70
|
-
* Caches result for performance.
|
|
71
|
-
*/
|
|
72
|
-
export function loadSyncOptions() {
|
|
73
|
-
if (cachedSyncOptions)
|
|
74
|
-
return cachedSyncOptions;
|
|
75
|
-
const repoRoot = findRepoRoot();
|
|
76
|
-
const homeDir = os.homedir();
|
|
77
|
-
// Load from repo .ema.yaml
|
|
78
|
-
const repoConfigPath = path.join(repoRoot, ".ema.yaml");
|
|
79
|
-
const repoConfig = loadYamlFile(repoConfigPath);
|
|
80
|
-
// Load from ~/.ema.yaml
|
|
81
|
-
const userConfigPath = path.join(homeDir, ".ema.yaml");
|
|
82
|
-
const userConfig = loadYamlFile(userConfigPath);
|
|
83
|
-
// Merge configs (user overrides repo)
|
|
84
|
-
const merged = {
|
|
85
|
-
defaults: {},
|
|
86
|
-
targets: {},
|
|
87
|
-
personas: {},
|
|
88
|
-
routing: [],
|
|
89
|
-
};
|
|
90
|
-
// Apply repo config
|
|
91
|
-
if (repoConfig && typeof repoConfig === "object") {
|
|
92
|
-
const parsed = SyncOptionsConfigSchema.safeParse(repoConfig);
|
|
93
|
-
if (parsed.success) {
|
|
94
|
-
merged.defaults = { ...merged.defaults, ...parsed.data.defaults };
|
|
95
|
-
merged.targets = { ...merged.targets, ...parsed.data.targets };
|
|
96
|
-
merged.personas = { ...merged.personas, ...parsed.data.personas };
|
|
97
|
-
merged.routing = [...(parsed.data.routing ?? [])];
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
// Apply user config (overrides repo)
|
|
101
|
-
if (userConfig && typeof userConfig === "object") {
|
|
102
|
-
const parsed = SyncOptionsConfigSchema.safeParse(userConfig);
|
|
103
|
-
if (parsed.success) {
|
|
104
|
-
merged.defaults = { ...merged.defaults, ...parsed.data.defaults };
|
|
105
|
-
// Deep merge targets
|
|
106
|
-
for (const [env, behavior] of Object.entries(parsed.data.targets ?? {})) {
|
|
107
|
-
merged.targets[env] = { ...merged.targets[env], ...behavior };
|
|
108
|
-
}
|
|
109
|
-
// Deep merge personas
|
|
110
|
-
for (const [name, behavior] of Object.entries(parsed.data.personas ?? {})) {
|
|
111
|
-
merged.personas[name] = { ...merged.personas[name], ...behavior };
|
|
112
|
-
}
|
|
113
|
-
// Prepend user routing rules (higher priority)
|
|
114
|
-
merged.routing = [...(parsed.data.routing ?? []), ...merged.routing];
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
cachedSyncOptions = merged;
|
|
118
|
-
return merged;
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Clear the cached sync options (for testing or config reload).
|
|
122
|
-
*/
|
|
123
|
-
export function clearSyncOptionsCache() {
|
|
124
|
-
cachedSyncOptions = null;
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Resolve sync behavior for a specific persona and target environment.
|
|
128
|
-
*
|
|
129
|
-
* Resolution order (lowest → highest priority):
|
|
130
|
-
* 1. Built-in defaults
|
|
131
|
-
* 2. Config defaults
|
|
132
|
-
* 3. Config targets[targetEnv]
|
|
133
|
-
* 4. Config personas[personaName]
|
|
134
|
-
* 5. Runtime overrides (passed as parameter)
|
|
135
|
-
*/
|
|
136
|
-
export function resolveSyncBehavior(opts) {
|
|
137
|
-
const { personaName, targetEnv, overrides } = opts;
|
|
138
|
-
const config = loadSyncOptions();
|
|
139
|
-
// Start with built-in defaults
|
|
140
|
-
const resolved = { ...BUILTIN_DEFAULTS };
|
|
141
|
-
// Apply config defaults
|
|
142
|
-
if (config.defaults) {
|
|
143
|
-
if (config.defaults.sync_status !== undefined)
|
|
144
|
-
resolved.sync_status = config.defaults.sync_status;
|
|
145
|
-
if (config.defaults.dry_run !== undefined)
|
|
146
|
-
resolved.dry_run = config.defaults.dry_run;
|
|
147
|
-
}
|
|
148
|
-
// Apply target env overrides
|
|
149
|
-
const targetConfig = config.targets?.[targetEnv];
|
|
150
|
-
if (targetConfig) {
|
|
151
|
-
if (targetConfig.sync_status !== undefined)
|
|
152
|
-
resolved.sync_status = targetConfig.sync_status;
|
|
153
|
-
if (targetConfig.dry_run !== undefined)
|
|
154
|
-
resolved.dry_run = targetConfig.dry_run;
|
|
155
|
-
}
|
|
156
|
-
// Apply persona overrides
|
|
157
|
-
if (personaName) {
|
|
158
|
-
const personaConfig = config.personas?.[personaName];
|
|
159
|
-
if (personaConfig) {
|
|
160
|
-
if (personaConfig.sync_status !== undefined)
|
|
161
|
-
resolved.sync_status = personaConfig.sync_status;
|
|
162
|
-
if (personaConfig.dry_run !== undefined)
|
|
163
|
-
resolved.dry_run = personaConfig.dry_run;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// Apply runtime overrides
|
|
167
|
-
if (overrides) {
|
|
168
|
-
if (overrides.sync_status !== undefined)
|
|
169
|
-
resolved.sync_status = overrides.sync_status;
|
|
170
|
-
if (overrides.dry_run !== undefined)
|
|
171
|
-
resolved.dry_run = overrides.dry_run;
|
|
172
|
-
}
|
|
173
|
-
return resolved;
|
|
174
|
-
}
|
|
175
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
176
|
-
// Routing
|
|
177
|
-
// ─────────────────────────────────────────────────────────────────────────────
|
|
178
|
-
/**
|
|
179
|
-
* Check if a string matches a glob pattern (simple implementation).
|
|
180
|
-
* Supports * as wildcard.
|
|
181
|
-
*/
|
|
182
|
-
function matchGlob(pattern, value) {
|
|
183
|
-
const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
|
|
184
|
-
return regex.test(value);
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Get target environments for a persona based on routing rules.
|
|
188
|
-
*/
|
|
189
|
-
export function getRoutingTargets(personaName, personaId) {
|
|
190
|
-
const config = loadSyncOptions();
|
|
191
|
-
const targets = new Set();
|
|
192
|
-
for (const rule of config.routing ?? []) {
|
|
193
|
-
// Check name patterns
|
|
194
|
-
for (const pattern of rule.match.names ?? []) {
|
|
195
|
-
if (matchGlob(pattern, personaName)) {
|
|
196
|
-
rule.targets.forEach((t) => targets.add(t));
|
|
197
|
-
break;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
// Check IDs
|
|
201
|
-
if (rule.match.ids?.includes(personaId)) {
|
|
202
|
-
rule.targets.forEach((t) => targets.add(t));
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
return [...targets];
|
|
206
|
-
}
|
|
207
|
-
/**
|
|
208
|
-
* Validate sync options config.
|
|
209
|
-
*/
|
|
210
|
-
export function validateSyncOptions(input) {
|
|
211
|
-
const result = SyncOptionsConfigSchema.safeParse(input);
|
|
212
|
-
if (!result.success) {
|
|
213
|
-
return { ok: false, errors: result.error.issues.map((i) => `${i.path.join(".")}: ${i.message}`) };
|
|
214
|
-
}
|
|
215
|
-
return { ok: true, config: result.data };
|
|
216
|
-
}
|