@yugabytedb/meko-mcp 2.0.0 → 2.1.0
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.
- package/README.md +31 -6
- package/assets/hooks-handlers/codex-session-end.sh +78 -0
- package/assets/hooks-handlers/lib/capture.js +163 -14
- package/assets/hooks-handlers/lib/checkpoint-timer.js +44 -2
- package/assets/hooks-handlers/session-end.sh +10 -0
- package/assets/hooks-handlers/session-start.sh +8 -1
- package/assets/hooks-handlers/test_checkpoint_timer.sh +162 -0
- package/assets/scripts/package-desktop-skill.sh +32 -1
- package/assets/skills/meko-mcp-tools/SKILL.md +47 -41
- package/assets/skills/meko-mcp-tools/references/_sections.md +2 -4
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +29 -25
- package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +5 -7
- package/assets/skills/meko-mcp-tools/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +63 -46
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +6 -6
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +4 -4
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +17 -22
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +40 -39
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +4 -18
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +9 -8
- package/assets/skills/meko-mcp-tools-desktop/SKILL.md +49 -42
- package/assets/skills/meko-mcp-tools-desktop/desktop/README.md +6 -6
- package/assets/skills/meko-mcp-tools-desktop/references/_sections.md +2 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-agent-id-conventions.md +28 -24
- package/assets/skills/meko-mcp-tools-desktop/references/tools-conversation-reasoning.md +50 -0
- package/assets/skills/meko-mcp-tools-desktop/references/tools-cookbook.md +61 -36
- package/assets/skills/meko-mcp-tools-desktop/references/tools-known-limitations.md +4 -4
- package/assets/skills/meko-mcp-tools-desktop/references/tools-memory-vs-conversation.md +16 -19
- package/assets/skills/meko-mcp-tools-desktop/references/tools-overview.md +40 -39
- package/assets/skills/meko-mcp-tools-desktop/references/tools-rag-workflow.md +1 -2
- package/assets/skills/meko-mcp-tools-desktop/references/tools-troubleshooting.md +3 -17
- package/assets/skills/meko-select-datapack-desktop/SKILL.md +31 -21
- package/assets/skills/meko-select-datapack-desktop/references/cookbook.md +8 -8
- package/assets/skills/meko-select-datapack-desktop/references/role-display-future.md +41 -0
- package/assets/skills/meko-select-datapack-desktop/references/troubleshooting.md +1 -1
- package/bin/create-meko-setup.mjs +45 -6
- package/lib/clients/claude-code.mjs +8 -4
- package/lib/clients/claude-desktop.mjs +14 -0
- package/lib/clients/codex.mjs +23 -8
- package/lib/clients/common.mjs +2 -0
- package/lib/clients/cursor.mjs +7 -2
- package/lib/detect.mjs +7 -2
- package/lib/prompt.mjs +1 -1
- package/lib/url-selection.mjs +55 -0
- package/package.json +1 -1
- package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +0 -71
- package/assets/skills/meko-mcp-tools-desktop/references/tools-scope-permissions.md +0 -71
package/lib/clients/codex.mjs
CHANGED
|
@@ -77,14 +77,19 @@ const RC_FENCE_END = "# <<< meko mcp <<<";
|
|
|
77
77
|
const SKILLS = [{ name: "meko-mcp-tools" }];
|
|
78
78
|
// Codex hook timeouts are in SECONDS (Duration::from_secs in
|
|
79
79
|
// codex-rs/hooks/src/engine/command_runner.rs), not milliseconds like Claude
|
|
80
|
-
// Code / Cursor.
|
|
81
|
-
//
|
|
80
|
+
// Code / Cursor. Codex hard-caps SessionEnd at three seconds, so its dedicated
|
|
81
|
+
// handler only spools input and launches the actual capture in the background.
|
|
82
82
|
const MEKO_HOOKS = [
|
|
83
83
|
{ event: "SessionStart", script: "session-start.sh", timeout: 15 },
|
|
84
84
|
{ event: "PreCompact", script: "pre-compact.sh" },
|
|
85
|
-
{ event: "SessionEnd", script: "session-end.sh", timeout:
|
|
85
|
+
{ event: "SessionEnd", script: "codex-session-end.sh", timeout: 3 },
|
|
86
|
+
];
|
|
87
|
+
// Include the former synchronous Codex SessionEnd handler so reinstall prunes
|
|
88
|
+
// it instead of leaving both old and new handlers active.
|
|
89
|
+
const MEKO_HOOK_SCRIPTS = [
|
|
90
|
+
...MEKO_HOOKS.map((hook) => hook.script),
|
|
91
|
+
"session-end.sh",
|
|
86
92
|
];
|
|
87
|
-
const MEKO_HOOK_SCRIPTS = MEKO_HOOKS.map((hook) => hook.script);
|
|
88
93
|
|
|
89
94
|
/**
|
|
90
95
|
* @param {{
|
|
@@ -196,10 +201,11 @@ export function createCodexAdapter(options = {}) {
|
|
|
196
201
|
surfaces.app = app?.found ? app : null;
|
|
197
202
|
}
|
|
198
203
|
|
|
204
|
+
let cliFound = false;
|
|
199
205
|
if (surfaces.cli) {
|
|
200
206
|
try {
|
|
201
207
|
runCommand(`codex mcp get ${shellQuote(name)}`);
|
|
202
|
-
|
|
208
|
+
cliFound = true;
|
|
203
209
|
} catch {
|
|
204
210
|
// fall through to TOML grep — `codex mcp get` exits non-zero when
|
|
205
211
|
// the entry isn't present, but might also fail for unrelated
|
|
@@ -209,8 +215,17 @@ export function createCodexAdapter(options = {}) {
|
|
|
209
215
|
}
|
|
210
216
|
const path = settingsPathFor(scope, null);
|
|
211
217
|
const raw = safeReadFile(path);
|
|
212
|
-
if (raw
|
|
213
|
-
|
|
218
|
+
if (raw !== null) {
|
|
219
|
+
const parsed = parseCodexConfigForServer(raw, name);
|
|
220
|
+
if (parsed.found) {
|
|
221
|
+
return {
|
|
222
|
+
found: true,
|
|
223
|
+
status: "Configured",
|
|
224
|
+
...(parsed.url ? { url: parsed.url } : {}),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return cliFound
|
|
214
229
|
? { found: true, status: "Configured" }
|
|
215
230
|
: { found: false, status: "" };
|
|
216
231
|
},
|
|
@@ -640,7 +655,7 @@ function upsertCodexMekoHooks(hooksPath, hooksRoot, { envFilePath } = {}) {
|
|
|
640
655
|
function buildCodexHookCommand(scriptPath, { envFilePath } = {}) {
|
|
641
656
|
const parts = [];
|
|
642
657
|
if (envFilePath) parts.push(`. ${shellQuote(envFilePath)}`);
|
|
643
|
-
parts.push(`bash ${shellQuote(scriptPath)}`);
|
|
658
|
+
parts.push(`MEKO_HOOK_CLIENT=codex bash ${shellQuote(scriptPath)}`);
|
|
644
659
|
return parts.join(" && ");
|
|
645
660
|
}
|
|
646
661
|
|
package/lib/clients/common.mjs
CHANGED
|
@@ -16,6 +16,8 @@ import { dirname, join, resolve } from "node:path";
|
|
|
16
16
|
import { fileURLToPath } from "node:url";
|
|
17
17
|
|
|
18
18
|
export const MEKO_MCP_USER_AGENT = "meko-mcp-installer/1.0";
|
|
19
|
+
export const MEKO_PRODUCTION_MCP_URL = "https://mcp.mekodata.ai/mcp";
|
|
20
|
+
export const MEKO_PRODUCTION_CONSOLE_URL = "https://cloud.mekodata.ai";
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* @returns {string} Absolute repository root path.
|
package/lib/clients/cursor.mjs
CHANGED
|
@@ -75,8 +75,13 @@ export function createCursorAdapter(customPaths = {}) {
|
|
|
75
75
|
detectExisting(name, { scope, projectRoot }) {
|
|
76
76
|
const path = paths.getMcpPath(scope, projectRoot);
|
|
77
77
|
const cfg = readJsonFile(path);
|
|
78
|
-
const
|
|
79
|
-
|
|
78
|
+
const entry = cfg?.mcpServers?.[name];
|
|
79
|
+
const found = Boolean(entry);
|
|
80
|
+
return {
|
|
81
|
+
found,
|
|
82
|
+
status: found ? "Configured" : "",
|
|
83
|
+
...(typeof entry?.url === "string" ? { url: entry.url } : {}),
|
|
84
|
+
};
|
|
80
85
|
},
|
|
81
86
|
removeRegistration(name, { scope, projectRoot }) {
|
|
82
87
|
const mcpPath = paths.getMcpPath(scope, projectRoot);
|
package/lib/detect.mjs
CHANGED
|
@@ -110,7 +110,7 @@ export function getClaudeCodeConfigPath() {
|
|
|
110
110
|
* `scope` — "user" (default) or "project". Project scope looks under `projects[projectRoot].mcpServers`.
|
|
111
111
|
* `projectRoot` — absolute path used as the key into `projects[...]` when `scope === "project"`.
|
|
112
112
|
* Ignored for user scope. Must be supplied by the caller for project scope.
|
|
113
|
-
* @returns {{ found: boolean, status: string }}
|
|
113
|
+
* @returns {{ found: boolean, status: string, url?: string }}
|
|
114
114
|
* `found` - true if a matching MCP entry exists at the scope-appropriate location.
|
|
115
115
|
* `status` - "Configured" when found, "" otherwise. (Kept as a string for
|
|
116
116
|
* API compatibility with the prior implementation; callers use
|
|
@@ -129,5 +129,10 @@ export function detectExistingMeko(serverName = "meko", options = {}) {
|
|
|
129
129
|
if (!entry) {
|
|
130
130
|
return { found: false, status: "" };
|
|
131
131
|
}
|
|
132
|
-
|
|
132
|
+
const url = typeof entry.url === "string" ? entry.url : undefined;
|
|
133
|
+
return {
|
|
134
|
+
found: true,
|
|
135
|
+
status: "Configured",
|
|
136
|
+
...(url ? { url } : {}),
|
|
137
|
+
};
|
|
133
138
|
}
|
package/lib/prompt.mjs
CHANGED
|
@@ -50,7 +50,7 @@ function question(query) {
|
|
|
50
50
|
*
|
|
51
51
|
* @example
|
|
52
52
|
* const choice = await askChoice('Connection type:', [
|
|
53
|
-
* { label: 'Cloud Meko', description: 'Hosted at
|
|
53
|
+
* { label: 'Cloud Meko', description: 'Hosted at mekodata.ai' },
|
|
54
54
|
* { label: 'Local Meko', description: 'docker-compose stack' },
|
|
55
55
|
* ]);
|
|
56
56
|
*/
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { MEKO_PRODUCTION_MCP_URL } from "./clients/common.mjs";
|
|
2
|
+
|
|
3
|
+
function validHttpUrl(value) {
|
|
4
|
+
if (typeof value !== "string" || !value.trim()) return null;
|
|
5
|
+
const candidate = value.trim();
|
|
6
|
+
try {
|
|
7
|
+
const parsed = new URL(candidate);
|
|
8
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return null;
|
|
9
|
+
parsed.pathname = parsed.pathname.replace(/\/+$/, "") || "/";
|
|
10
|
+
return { value: candidate, comparisonKey: parsed.toString() };
|
|
11
|
+
} catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Select the URL offered by interactive/non-interactive setup.
|
|
18
|
+
* Explicit CLI URLs are resolved before this helper is called.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveSuggestedMcpUrl({
|
|
21
|
+
adapters,
|
|
22
|
+
clients,
|
|
23
|
+
name = "meko",
|
|
24
|
+
scope = "user",
|
|
25
|
+
projectRoot = process.cwd(),
|
|
26
|
+
}) {
|
|
27
|
+
const existingUrlsByKey = new Map();
|
|
28
|
+
for (const client of clients) {
|
|
29
|
+
const adapter = adapters[client];
|
|
30
|
+
if (!adapter?.detectExisting) continue;
|
|
31
|
+
try {
|
|
32
|
+
const existing = adapter.detectExisting(name, { scope, projectRoot });
|
|
33
|
+
const url = existing?.found ? validHttpUrl(existing.url) : null;
|
|
34
|
+
if (url && !existingUrlsByKey.has(url.comparisonKey)) {
|
|
35
|
+
existingUrlsByKey.set(url.comparisonKey, url.value);
|
|
36
|
+
}
|
|
37
|
+
} catch {
|
|
38
|
+
// Existing-config discovery is advisory. Installation performs its own
|
|
39
|
+
// prerequisite and config checks later with actionable errors.
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const uniqueUrls = [...existingUrlsByKey.values()];
|
|
44
|
+
if (uniqueUrls.length === 1) {
|
|
45
|
+
return { url: uniqueUrls[0], source: "existing", existingUrls: uniqueUrls };
|
|
46
|
+
}
|
|
47
|
+
if (uniqueUrls.length > 1) {
|
|
48
|
+
return { url: null, source: "conflict", existingUrls: uniqueUrls };
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
url: MEKO_PRODUCTION_MCP_URL,
|
|
52
|
+
source: "production-default",
|
|
53
|
+
existingUrls: [],
|
|
54
|
+
};
|
|
55
|
+
}
|
package/package.json
CHANGED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# Scope Permission Hierarchy and Per-Tool Requirements
|
|
2
|
-
|
|
3
|
-
**WRONG:** `memory_add(scope="read", ...)` → PermissionError: requires 'write' or higher.
|
|
4
|
-
**WRONG:** `memory_delete_all(scope="write", ...)` → PermissionError: requires 'admin'.
|
|
5
|
-
|
|
6
|
-
## Scope Hierarchy
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
admin (level 2) -- can do everything
|
|
10
|
-
↓
|
|
11
|
-
write (level 1) -- can read + write, not admin-only
|
|
12
|
-
↓
|
|
13
|
-
read (level 0) -- can only read
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Higher scopes include lower scopes. An unrecognized scope string always fails.
|
|
17
|
-
|
|
18
|
-
## Per-Tool Requirements
|
|
19
|
-
|
|
20
|
-
### read scope (9 tools)
|
|
21
|
-
|
|
22
|
-
| Tool | Group |
|
|
23
|
-
|------|-------|
|
|
24
|
-
| `knowledgebase_search` | RAG |
|
|
25
|
-
| `memory_search` | Memory |
|
|
26
|
-
| `memory_get_by_id` | Memory |
|
|
27
|
-
| `memory_get_all` | Memory |
|
|
28
|
-
| `flush_pending_memory_candidates` | Memory |
|
|
29
|
-
| `conversation_get` | Conversation |
|
|
30
|
-
| `conversation_list` | Conversation |
|
|
31
|
-
| `datapack_list` | Datapack |
|
|
32
|
-
| `datapack_describe` | Datapack |
|
|
33
|
-
|
|
34
|
-
### write scope (9 tools)
|
|
35
|
-
|
|
36
|
-
| Tool | Group |
|
|
37
|
-
|------|-------|
|
|
38
|
-
| `memory_add` | Memory |
|
|
39
|
-
| `memory_update` | Memory |
|
|
40
|
-
| `memory_delete_by_id` | Memory |
|
|
41
|
-
| `conversation_create` | Conversation |
|
|
42
|
-
| `conversation_add_message` | Conversation |
|
|
43
|
-
| `conversation_update` | Conversation |
|
|
44
|
-
| `datapack_create` | Datapack |
|
|
45
|
-
| `datapack_update` | Datapack |
|
|
46
|
-
| `track_token_usage` | Observability |
|
|
47
|
-
|
|
48
|
-
### admin scope (3 tools — destructive, irreversible)
|
|
49
|
-
|
|
50
|
-
| Tool | Group |
|
|
51
|
-
|------|-------|
|
|
52
|
-
| `memory_delete_all` | Memory |
|
|
53
|
-
| `conversation_delete` | Conversation |
|
|
54
|
-
| `datapack_delete` | Datapack |
|
|
55
|
-
|
|
56
|
-
Agent and knowledge-base lifecycle tools are not MCP-exposed — see "Platform capabilities NOT exposed via MCP" in `tools-overview.md`.
|
|
57
|
-
|
|
58
|
-
## Best Practices
|
|
59
|
-
|
|
60
|
-
1. **Use the minimum scope needed.** `scope="read"` for reads documents intent and prevents accidental writes.
|
|
61
|
-
2. **The scope is a parameter, not an auth token.** When OAuth is enabled, the actual permission check happens against the OAuth token's claims. Both `scope` parameter and OAuth permissions must be satisfied.
|
|
62
|
-
|
|
63
|
-
## Common Mistakes
|
|
64
|
-
|
|
65
|
-
**WRONG:** `scope="all"` — there is no "all" scope. Valid values are exactly: `"read"`, `"write"`, `"admin"`. Nothing else.
|
|
66
|
-
|
|
67
|
-
Other invalid values that will fail: `"readwrite"`, `"rw"`, `"full"`, `"any"`.
|
|
68
|
-
|
|
69
|
-
The error `Insufficient scope: 'all'. This tool requires 'read' or higher.` means the scope string was not recognized as a valid value. Always use one of the three valid strings.
|
|
70
|
-
|
|
71
|
-
**Default choice:** Start with `scope="read"` unless you specifically need to write or delete.
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
# Scope Permission Hierarchy and Per-Tool Requirements
|
|
2
|
-
|
|
3
|
-
**WRONG:** `memory_add(scope="read", ...)` → PermissionError: requires 'write' or higher.
|
|
4
|
-
**WRONG:** `memory_delete_all(scope="write", ...)` → PermissionError: requires 'admin'.
|
|
5
|
-
|
|
6
|
-
## Scope Hierarchy
|
|
7
|
-
|
|
8
|
-
```
|
|
9
|
-
admin (level 2) -- can do everything
|
|
10
|
-
↓
|
|
11
|
-
write (level 1) -- can read + write, not admin-only
|
|
12
|
-
↓
|
|
13
|
-
read (level 0) -- can only read
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
Higher scopes include lower scopes. An unrecognized scope string always fails.
|
|
17
|
-
|
|
18
|
-
## Per-Tool Requirements
|
|
19
|
-
|
|
20
|
-
### read scope (9 tools)
|
|
21
|
-
|
|
22
|
-
| Tool | Group |
|
|
23
|
-
|------|-------|
|
|
24
|
-
| `knowledgebase_search` | RAG |
|
|
25
|
-
| `memory_search` | Memory |
|
|
26
|
-
| `memory_get_by_id` | Memory |
|
|
27
|
-
| `memory_get_all` | Memory |
|
|
28
|
-
| `flush_pending_memory_candidates` | Memory |
|
|
29
|
-
| `conversation_get` | Conversation |
|
|
30
|
-
| `conversation_list` | Conversation |
|
|
31
|
-
| `datapack_list` | Datapack |
|
|
32
|
-
| `datapack_describe` | Datapack |
|
|
33
|
-
|
|
34
|
-
### write scope (9 tools)
|
|
35
|
-
|
|
36
|
-
| Tool | Group |
|
|
37
|
-
|------|-------|
|
|
38
|
-
| `memory_add` | Memory |
|
|
39
|
-
| `memory_update` | Memory |
|
|
40
|
-
| `memory_delete_by_id` | Memory |
|
|
41
|
-
| `conversation_create` | Conversation |
|
|
42
|
-
| `conversation_add_message` | Conversation |
|
|
43
|
-
| `conversation_update` | Conversation |
|
|
44
|
-
| `datapack_create` | Datapack |
|
|
45
|
-
| `datapack_update` | Datapack |
|
|
46
|
-
| `track_token_usage` | Observability |
|
|
47
|
-
|
|
48
|
-
### admin scope (3 tools — destructive, irreversible)
|
|
49
|
-
|
|
50
|
-
| Tool | Group |
|
|
51
|
-
|------|-------|
|
|
52
|
-
| `memory_delete_all` | Memory |
|
|
53
|
-
| `conversation_delete` | Conversation |
|
|
54
|
-
| `datapack_delete` | Datapack |
|
|
55
|
-
|
|
56
|
-
Agent and knowledge-base lifecycle tools are not MCP-exposed — see "Platform capabilities NOT exposed via MCP" in `tools-overview.md`.
|
|
57
|
-
|
|
58
|
-
## Best Practices
|
|
59
|
-
|
|
60
|
-
1. **Use the minimum scope needed.** `scope="read"` for reads documents intent and prevents accidental writes.
|
|
61
|
-
2. **The scope is a parameter, not an auth token.** When OAuth is enabled, the actual permission check happens against the OAuth token's claims. Both `scope` parameter and OAuth permissions must be satisfied.
|
|
62
|
-
|
|
63
|
-
## Common Mistakes
|
|
64
|
-
|
|
65
|
-
**WRONG:** `scope="all"` — there is no "all" scope. Valid values are exactly: `"read"`, `"write"`, `"admin"`. Nothing else.
|
|
66
|
-
|
|
67
|
-
Other invalid values that will fail: `"readwrite"`, `"rw"`, `"full"`, `"any"`.
|
|
68
|
-
|
|
69
|
-
The error `Insufficient scope: 'all'. This tool requires 'read' or higher.` means the scope string was not recognized as a valid value. Always use one of the three valid strings.
|
|
70
|
-
|
|
71
|
-
**Default choice:** Start with `scope="read"` unless you specifically need to write or delete.
|