@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
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# Complete Tool Catalog and Decision Tree
|
|
2
2
|
|
|
3
|
-
**
|
|
3
|
+
**23 tools on Cloud Meko** (verified against `https://mcp.mekodata.ai/mcp`). Grouped: Memory (8), Conversation (6), Knowledge Base (1), Datapack (5), Artifacts (2), Observability (1).
|
|
4
4
|
|
|
5
5
|
## Quick health check before using tools
|
|
6
6
|
|
|
7
7
|
Before starting a session, verify that the Meko MCP tools are working:
|
|
8
8
|
|
|
9
|
-
1. `memory_search(
|
|
10
|
-
2. `datapack_list(
|
|
9
|
+
1. `memory_search(query="test", agent_id="<your-session-agent-id>", conversation_id="<session-conversation-id>")` — Confirms memory subsystem is up. Use the `agent_id` and `conversation_id` from the SessionStart `additionalContext`. May fail with "connection already closed" — see `tools-troubleshooting.md`.
|
|
10
|
+
2. `datapack_list()` — Confirms Meko API connectivity. Returns the datapacks your token has access to.
|
|
11
11
|
|
|
12
12
|
## Decision tree: which tool do I need?
|
|
13
13
|
|
|
@@ -20,6 +20,7 @@ User wants to...
|
|
|
20
20
|
│ ├── Store a fact/preference/entity? -----------> memory_add (write)
|
|
21
21
|
│ ├── Store a full conversation (multi-turn)? ---> conversation_create + conversation_add_message (write)
|
|
22
22
|
│ ├── Search past knowledge? --------------------> memory_search (read)
|
|
23
|
+
│ ├── Share private memories with the team? -----> memory_promote (write; owner/maintainer only)
|
|
23
24
|
│ └── Retrieve a past conversation? -------------> conversation_get (read)
|
|
24
25
|
├── Persist or retrieve a file?
|
|
25
26
|
│ ├── Upload a generated file (report, CSV, PDF)? -> artifact_put (write)
|
|
@@ -32,58 +33,58 @@ Agent / knowledge-base lifecycle is managed **outside** the MCP surface — typi
|
|
|
32
33
|
|
|
33
34
|
## Knowledge Base Tools (1)
|
|
34
35
|
|
|
35
|
-
| Tool |
|
|
36
|
-
|
|
37
|
-
| `knowledgebase_search(
|
|
36
|
+
| Tool | Purpose |
|
|
37
|
+
|------|---------|
|
|
38
|
+
| `knowledgebase_search(query, agent_id, conversation_id, datapack_id, limit=10)` | Semantic search across KB chunks. `datapack_id` is REQUIRED (no default). |
|
|
38
39
|
|
|
39
40
|
## Memory Tools (8)
|
|
40
41
|
|
|
41
|
-
| Tool |
|
|
42
|
-
|
|
43
|
-
| `memory_add(
|
|
44
|
-
| `memory_search(
|
|
45
|
-
| `memory_get_by_id(
|
|
46
|
-
| `memory_get_all(
|
|
47
|
-
| `memory_update(
|
|
48
|
-
| `memory_delete_by_id(
|
|
49
|
-
| `memory_delete_all(
|
|
50
|
-
| `
|
|
42
|
+
| Tool | Purpose |
|
|
43
|
+
|------|---------|
|
|
44
|
+
| `memory_add(text, agent_id, conversation_id, user_id=None, app_id=None, run_id=None, metadata=None, messages=None, datapack_id=None)` | Store fact/preference/entity as long-term memory |
|
|
45
|
+
| `memory_search(query, agent_id, conversation_id="", user_id=None, limit=10, datapack_id=None)` | Semantic search across memories + graph relations. `conversation_id` optional (omit or pass `""` for cross-conversation discovery). |
|
|
46
|
+
| `memory_get_by_id(memory_id, agent_id, conversation_id, datapack_id=None)` | Direct pgvector row lookup by UUID. Preferred over `memory_search` for exact-id verification. |
|
|
47
|
+
| `memory_get_all(agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | List all memories for agent |
|
|
48
|
+
| `memory_update(memory_id, text, agent_id, conversation_id, datapack_id=None)` | Overwrite memory text |
|
|
49
|
+
| `memory_delete_by_id(memory_id, agent_id, conversation_id, datapack_id=None)` | Delete a single memory |
|
|
50
|
+
| `memory_delete_all(agent_id, conversation_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | Delete all memories for agent (destructive) |
|
|
51
|
+
| `memory_promote(conversation_id, memory_ids, agent_id=None, datapack_id=None)` | Promote private memories into the datapack's shared knowledge base (moves them + graph context out of mem0, then evicts from mem0 — one-way). Owners/maintainers only; viewers/contributors get 403.
|
|
51
52
|
|
|
52
53
|
## Conversation Tools (6)
|
|
53
54
|
|
|
54
|
-
| Tool |
|
|
55
|
-
|
|
56
|
-
| `conversation_create(
|
|
57
|
-
| `conversation_add_message(
|
|
58
|
-
| `conversation_get(
|
|
59
|
-
| `conversation_list(
|
|
60
|
-
| `conversation_update(
|
|
61
|
-
| `conversation_delete(
|
|
55
|
+
| Tool | Purpose |
|
|
56
|
+
|------|---------|
|
|
57
|
+
| `conversation_create(agent_id, user_id=None, app_id=None, run_id=None, title=None, metadata=None, session_id="")` | Create conversation container (Langfuse session) |
|
|
58
|
+
| `conversation_add_message(conversation_id, agent_id, input, output=None, reasoning=None, metadata=None, seed=None, trace_id="")` | Add a message turn (Langfuse trace) |
|
|
59
|
+
| `conversation_get(conversation_id, agent_id, include_messages=False, limit=100, offset=0)` | Retrieve conversation, optionally with messages |
|
|
60
|
+
| `conversation_list(agent_id=None, limit=20, offset=0, conversation_id="", datapack_id=None)` | List conversations for agent within a datapack. `datapack_id` (UUID) is optional — defaults to the pinned/tenant datapack; use `datapack_list` to look it up. `conversation_id` optional (omit for browse). |
|
|
61
|
+
| `conversation_update(conversation_id, agent_id, title=None, metadata=None)` | Update title or metadata |
|
|
62
|
+
| `conversation_delete(conversation_id, agent_id)` | Delete entire conversation (destructive) |
|
|
62
63
|
|
|
63
64
|
## Datapack Management Tools (5)
|
|
64
65
|
|
|
65
|
-
| Tool |
|
|
66
|
-
|
|
67
|
-
| `datapack_create(
|
|
68
|
-
| `datapack_list(
|
|
69
|
-
| `datapack_describe(
|
|
70
|
-
| `datapack_update(
|
|
71
|
-
| `datapack_delete(
|
|
66
|
+
| Tool | Purpose |
|
|
67
|
+
|------|---------|
|
|
68
|
+
| `datapack_create(name)` | Create new datapack |
|
|
69
|
+
| `datapack_list()` | List all datapacks |
|
|
70
|
+
| `datapack_describe(datapack_id, include_status=False)` | Describe datapack by UUID |
|
|
71
|
+
| `datapack_update(datapack_id, name=None, description=None)` | Rename a datapack and/or update its description. Pass at least one of `name` / `description`. |
|
|
72
|
+
| `datapack_delete(datapack_id)` | Delete datapack by UUID (irreversible) |
|
|
72
73
|
|
|
73
74
|
## Artifact Tools (2)
|
|
74
75
|
|
|
75
76
|
Content-addressed blob store scoped to a datapack. Files < 1 MB go inline in the DB; files ≥ 1 MB go to S3. Identity is SHA-256 — uploading the same bytes twice returns the same `content_hash`. Free-tier artifacts expire after 30 days of inactivity; pro-tier artifacts have no TTL.
|
|
76
77
|
|
|
77
|
-
| Tool |
|
|
78
|
-
|
|
79
|
-
| `artifact_put(
|
|
80
|
-
| `artifact_get(
|
|
78
|
+
| Tool | Purpose |
|
|
79
|
+
|------|---------|
|
|
80
|
+
| `artifact_put(filename, content_base64, content_type, conversation_id, datapack_id=None, agent_id=None)` | Upload a file to the datapack. Returns `{artifact_id, content_hash, filename, size_bytes, stored_in}`. Max 5 MiB (configurable via `MEKO_MAX_ARTIFACT_UPLOAD_BYTES`). |
|
|
81
|
+
| `artifact_get(content_hash, conversation_id, datapack_id=None, agent_id=None)` | Retrieve a file by SHA-256 hash. Small files return `content_base64` inline; large files (S3) are written to `~/.meko/artifacts/<hash>/<filename>` and `local_path` is returned. |
|
|
81
82
|
|
|
82
83
|
## Observability Tools (1)
|
|
83
84
|
|
|
84
|
-
| Tool |
|
|
85
|
-
|
|
86
|
-
| `track_token_usage(
|
|
85
|
+
| Tool | Purpose |
|
|
86
|
+
|------|---------|
|
|
87
|
+
| `track_token_usage(conversation_id, name, input_tokens=0, output_tokens=0, total_tokens=None, model=None, message_id=None, datapack_id=None)` | Record an LLM-cost GENERATION observation on the conversation's trace. Primarily called by first-party Meko services (e.g. inference_gateway) that know their LLM's exact token counts. Most end-agents (Cursor, Claude Desktop) don't have those counts at the MCP call layer, so this tool is rarely useful for third-party agents. |
|
|
87
88
|
|
|
88
89
|
## Platform capabilities NOT exposed via MCP
|
|
89
90
|
|
|
@@ -102,4 +103,4 @@ For knowledge-base content on Cloud, the canonical path is **UI upload**: Datapa
|
|
|
102
103
|
|
|
103
104
|
## Common Parameter Patterns
|
|
104
105
|
|
|
105
|
-
|
|
106
|
+
Memory and KB tools accept optional `datapack_id` to target a specific datapack. Memory and conversation tools require `agent_id` for namespace isolation (see `tools-agent-id-conventions.md`).
|
|
@@ -16,7 +16,6 @@ creation and ingestion happen out of band — through the **Meko UI**
|
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
knowledgebase_search(
|
|
19
|
-
scope="read",
|
|
20
19
|
query="natural-language question",
|
|
21
20
|
agent_id="claude_desktop",
|
|
22
21
|
conversation_id="<uuid from conversation_create>",
|
|
@@ -24,7 +23,7 @@ knowledgebase_search(
|
|
|
24
23
|
limit=10)
|
|
25
24
|
```
|
|
26
25
|
|
|
27
|
-
Required: `
|
|
26
|
+
Required: `query`, `agent_id`, `conversation_id`, `datapack_id`.
|
|
28
27
|
Unlike the memory tools, `datapack_id` has no default here — you must
|
|
29
28
|
pass it explicitly. `agent_id` is **ignored for filtering** on this
|
|
30
29
|
tool (KB results are team-shared on the datapack), but you still pass
|
|
@@ -7,7 +7,7 @@ These patterns are extracted from real agent sessions. Follow them to avoid wast
|
|
|
7
7
|
1. **Never retry the identical failed call more than once.** If it fails twice with the same error, it's not transient — diagnose the cause.
|
|
8
8
|
2. **Distinguish transient vs persistent failures.** "Connection already closed" is transient (retry once). "Permission denied" is persistent (stop, don't retry).
|
|
9
9
|
3. **Don't guess parameters sequentially.** If a tool fails with one parameter format, don't try 4 variations. Check this skill's docs for the correct format first.
|
|
10
|
-
4. **Use your session's `agent_id` consistently.** For Claude Desktop the default is `claude_desktop`;
|
|
10
|
+
4. **Use your session's `agent_id` consistently on writes.** For Claude Desktop the default is `claude_desktop`; use `meko_agent` when writing cross-project facts. Other clients use `<client>:<repo-basename>` (e.g. `claude_code:meko-mcp-server`). Memory reads and `conversation_list` span all of this user's agents regardless of the value passed; `conversation_get` requires the creating agent's exact value.
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
@@ -26,20 +26,6 @@ These patterns are extracted from real agent sessions. Follow them to avoid wast
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## Scope parameter errors
|
|
30
|
-
|
|
31
|
-
**Error:** `Insufficient scope: 'all'. This tool requires 'read' or higher.`
|
|
32
|
-
|
|
33
|
-
The only valid scope values are: `"read"`, `"write"`, `"admin"`.
|
|
34
|
-
|
|
35
|
-
- Use `"read"` for all read operations (default choice)
|
|
36
|
-
- Use `"write"` for inserts, updates, creates, memory writes
|
|
37
|
-
- Use `"admin"` only for destructive deletes
|
|
38
|
-
|
|
39
|
-
**Never use:** `"all"`, `"readwrite"`, `"rw"`, or any other value.
|
|
40
|
-
|
|
41
|
-
---
|
|
42
|
-
|
|
43
29
|
## agent_id errors
|
|
44
30
|
|
|
45
31
|
On the Cloud multi-tenant schema, `agent_id` is a TEXT column value — not a PostgreSQL identifier — so arbitrary strings are accepted.
|
|
@@ -54,7 +40,7 @@ Fix: always pass a concrete non-empty `agent_id`. For Claude Desktop use `agent_
|
|
|
54
40
|
|
|
55
41
|
### "My reads return fewer results than I expected"
|
|
56
42
|
|
|
57
|
-
`memory_search` and `memory_get_all`
|
|
43
|
+
`memory_search` and `memory_get_all` do not filter by `agent_id`: one call returns this user's memories across every agent. If results seem thin, check the `datapack_id`, confirm the write landed, and remember that mem0 extraction can be lossy. `conversation_get` is agent-owned and requires the exact creating `agent_id`; `conversation_list` is not agent-filtered.
|
|
58
44
|
|
|
59
45
|
### "I'm seeing rows tagged with legacy agent_id values"
|
|
60
46
|
|
|
@@ -66,7 +52,7 @@ Pre-existing data may be tagged `"agent"`, `"claude_code"`, `"cursor:<slug>"`, o
|
|
|
66
52
|
|
|
67
53
|
| Tool | Safe to retry? | Why |
|
|
68
54
|
|------|---------------|-----|
|
|
69
|
-
| All
|
|
55
|
+
| All read-only tools | Yes | Reads are idempotent |
|
|
70
56
|
| `memory_add` | Yes (once) | Mem0 has dedup logic |
|
|
71
57
|
| `memory_update` | Yes (once) | Overwrites same ID |
|
|
72
58
|
| `memory_delete_by_id` | Yes | Deleting already-deleted is a no-op |
|
|
@@ -3,15 +3,15 @@ name: meko-select-datapack-desktop
|
|
|
3
3
|
description: >-
|
|
4
4
|
Lists the user's Meko datapacks, shows authorization, supports search and
|
|
5
5
|
pagination, and pins one as the active datapack on Claude Desktop. Triggers
|
|
6
|
-
when the user says things like "switch datapack", "use datapack
|
|
7
|
-
"list my datapacks", "which datapack am I on", "pin
|
|
6
|
+
when the user says things like "switch datapack", "use the Acme datapack",
|
|
7
|
+
"list my datapacks", "which datapack am I on", "pin Acme", or any request
|
|
8
8
|
to change or inspect the active datapack. Persistence is via memory_add
|
|
9
9
|
(Desktop has no SessionStart hook), so the pin survives across sessions
|
|
10
10
|
until the user clears it.
|
|
11
11
|
license: MIT
|
|
12
12
|
metadata:
|
|
13
13
|
author: Meko
|
|
14
|
-
version: "1.
|
|
14
|
+
version: "1.2.0"
|
|
15
15
|
tags: meko, datapack, selection, project, claude-desktop, desktop
|
|
16
16
|
---
|
|
17
17
|
|
|
@@ -42,10 +42,10 @@ Trigger immediately on any of these signals:
|
|
|
42
42
|
|
|
43
43
|
## On every Meko-touching turn (not just when this skill triggers)
|
|
44
44
|
|
|
45
|
-
Before issuing a Meko MCP write tool call (memory_add,
|
|
45
|
+
Before issuing a Meko MCP write tool call (memory_add, conversation_add_message, artifact_put, etc.), if you don't already know the active pin from this turn's earlier work:
|
|
46
46
|
|
|
47
47
|
```
|
|
48
|
-
memory_search(
|
|
48
|
+
memory_search(
|
|
49
49
|
query="meko_active_datapack",
|
|
50
50
|
agent_id="claude_desktop",
|
|
51
51
|
conversation_id="<this conversation's id>",
|
|
@@ -61,7 +61,7 @@ This is once per turn, not once per call. Cache within the turn.
|
|
|
61
61
|
### 1. List
|
|
62
62
|
|
|
63
63
|
Use a **temporary** conversation for browsing only. Call
|
|
64
|
-
`conversation_create(
|
|
64
|
+
`conversation_create(agent_id="claude_desktop", title="Claude
|
|
65
65
|
Desktop datapack selection")` and use its returned ID for the read-only
|
|
66
66
|
`datapack_list` below and for the pin `memory_add`/`memory_update` in step 4.
|
|
67
67
|
|
|
@@ -72,13 +72,20 @@ must flow through a *new* conversation created in the selected datapack — see
|
|
|
72
72
|
step 5.
|
|
73
73
|
|
|
74
74
|
```
|
|
75
|
-
datapack_list(
|
|
75
|
+
datapack_list(conversation_id="<this conversation's id>")
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
The response is an array; the fields you'll use are `datapack_id`,
|
|
79
|
-
`datapack_name`, `created_at`, and `
|
|
79
|
+
`datapack_name`, `created_at`, `account_id`, and `grant`.
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
`grant` is the caller's actual authorization on the datapack — one of
|
|
82
|
+
`"owner"`, `"maintainer"`, `"contributor"`, `"viewer"`. Display it verbatim in
|
|
83
|
+
the Role column. Do not hardcode "Owner", do not invent or normalize the value
|
|
84
|
+
(render `"maintainer"` as `maintainer`, not `Maintainer`). The deployed
|
|
85
|
+
response is the source of truth — see `references/role-display-future.md` for
|
|
86
|
+
the taxonomy.
|
|
87
|
+
|
|
88
|
+
If the response has zero entries, tell the user: *"You don't have any datapacks yet. Run `datapack_create(name='<name>')` to make one, or visit the Meko Cloud console."* Stop here.
|
|
82
89
|
|
|
83
90
|
If the response has exactly **one** entry, **auto-select it**. Print: *"Only one datapack: `<name>`. Auto-selecting. Run `meko-select-datapack-desktop` again with `clear` to unset."* Skip the table; jump to step 4 (persist) and step 5 (confirm).
|
|
84
91
|
|
|
@@ -89,19 +96,22 @@ For 2+ datapacks, render a numbered table. **Page size 10.** Default sort: `crea
|
|
|
89
96
|
```
|
|
90
97
|
Your datapacks (showing 1-10 of 14):
|
|
91
98
|
|
|
92
|
-
# Name Role
|
|
93
|
-
1 meko-local-setup
|
|
94
|
-
2 meko_default_datapack
|
|
95
|
-
3
|
|
99
|
+
# Name Role Created Status Active?
|
|
100
|
+
1 meko-local-setup owner 2026-04-30 ready ← (pinned)
|
|
101
|
+
2 meko_default_datapack owner 2026-04-30 ready
|
|
102
|
+
3 team-onboarding maintainer 2026-04-08 ready
|
|
103
|
+
4 q2-roadmap viewer 2026-03-22 ready
|
|
96
104
|
…
|
|
97
105
|
|
|
98
106
|
Reply with: a number (1-10) to pin · a substring to search · `next` / `prev` to page
|
|
99
107
|
· `clear` to unset · `cancel` to leave the current pin alone
|
|
100
|
-
|
|
101
|
-
Note: Role is hardcoded to "Owner" today. Shared / Viewer / Contributor /
|
|
102
|
-
Maintainer roles are pending upstream backend work — see references/role-display-future.md.
|
|
103
108
|
```
|
|
104
109
|
|
|
110
|
+
The **Role** column shows each datapack's `grant` value verbatim (`owner`,
|
|
111
|
+
`maintainer`, `contributor`, `viewer`). Never hardcode "Owner" — shared
|
|
112
|
+
datapacks legitimately carry other grants, and misreporting them (e.g. showing
|
|
113
|
+
a `maintainer` grant as "Owner") misleads the user about their own access.
|
|
114
|
+
|
|
105
115
|
Mark the currently-pinned row with `← (pinned)` based on the `memory_search` result (if any).
|
|
106
116
|
|
|
107
117
|
### 3. Parse the user's reply
|
|
@@ -118,7 +128,7 @@ Mark the currently-pinned row with `← (pinned)` based on the `memory_search`
|
|
|
118
128
|
**On first pin (no existing pin memory):**
|
|
119
129
|
|
|
120
130
|
```
|
|
121
|
-
memory_add(
|
|
131
|
+
memory_add(
|
|
122
132
|
text="meko_active_datapack=<uuid> name=<name> selected_at=<iso8601>",
|
|
123
133
|
agent_id="claude_desktop",
|
|
124
134
|
conversation_id="<this conversation's id>",
|
|
@@ -130,7 +140,7 @@ Verify the write with `memory_search` (the standard Meko verify-after-write rule
|
|
|
130
140
|
**On switch (existing pin memory found):**
|
|
131
141
|
|
|
132
142
|
```
|
|
133
|
-
memory_update(
|
|
143
|
+
memory_update(
|
|
134
144
|
memory_id="<existing pin id>",
|
|
135
145
|
text="meko_active_datapack=<new uuid> name=<new name> selected_at=<iso8601>",
|
|
136
146
|
agent_id="claude_desktop",
|
|
@@ -142,7 +152,7 @@ Always update — never `memory_add` a second pin. Two pin memories will produce
|
|
|
142
152
|
**On clear:**
|
|
143
153
|
|
|
144
154
|
```
|
|
145
|
-
memory_delete_by_id(
|
|
155
|
+
memory_delete_by_id(
|
|
146
156
|
memory_id="<existing pin id>",
|
|
147
157
|
agent_id="claude_desktop",
|
|
148
158
|
conversation_id="<this conversation's id>")
|
|
@@ -153,7 +163,7 @@ If `memory_search` returned no pin, there's nothing to delete — print *"No pin
|
|
|
153
163
|
**Conversation transition after a clear (same rule as a switch).** The pin memory is now gone, but the session's current conversation still physically lives in the datapack that was pinned when it was created — a conversation cannot move to the default. You must pick exactly one of these; do not mix them:
|
|
154
164
|
|
|
155
165
|
- **Option A — keep capturing to the current conversation this session.** It stays in its original (now-unpinned) datapack, so you must keep passing that **same old `datapack_id`** on its `conversation_add_message` calls — do NOT switch it to the default (that would fail). The clear only affects *new* sessions. Disclose: *"Pin cleared. This chat keeps saving to `<old datapack name>`; new chats will use the default datapack."*
|
|
156
|
-
- **Option B — start default-datapack capture immediately.** Create a **new** conversation with no `datapack_id` (`conversation_create(
|
|
166
|
+
- **Option B — start default-datapack capture immediately.** Create a **new** conversation with no `datapack_id` (`conversation_create(agent_id="claude_desktop")`) and post all subsequent turns there. Stop posting to the old conversation. Disclose: *"Pin cleared. Started a new chat context saving to the default datapack."*
|
|
157
167
|
|
|
158
168
|
Default to Option A (least disruptive) unless the user wants the switch to take effect right now. Either way, never send `datapack_id=default` to the pre-existing pinned conversation.
|
|
159
169
|
|
|
@@ -173,7 +183,7 @@ right `datapack_id` flows through automatically.
|
|
|
173
183
|
**Then start a fresh conversation for capture in the selected datapack.** The
|
|
174
184
|
temporary selection conversation from step 1 belongs to the datapack that was
|
|
175
185
|
active when it was created and cannot be moved. For subsequent capture this
|
|
176
|
-
session, call `conversation_create(
|
|
186
|
+
session, call `conversation_create(agent_id="claude_desktop",
|
|
177
187
|
datapack_id="<the newly pinned uuid>", title="<topic>")` and post turns
|
|
178
188
|
(`conversation_add_message`) to *that* conversation with the same
|
|
179
189
|
`datapack_id`. Do not keep posting to the selection conversation — doing so
|
|
@@ -11,12 +11,12 @@ Concrete transcripts of the four flows the skill supports on Claude Desktop.
|
|
|
11
11
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
12
12
|
[empty]
|
|
13
13
|
|
|
14
|
-
> datapack_list(
|
|
14
|
+
> datapack_list()
|
|
15
15
|
[14 entries returned, filtering by "prod-research"]
|
|
16
16
|
|
|
17
17
|
One match: `prod-research`. Pinning.
|
|
18
18
|
|
|
19
|
-
> memory_add(
|
|
19
|
+
> memory_add(
|
|
20
20
|
text="meko_active_datapack=8b1c…f4a2 name=prod-research selected_at=2026-05-25T18:42:00Z",
|
|
21
21
|
agent_id="claude_desktop",
|
|
22
22
|
conversation_id="<conv-id>",
|
|
@@ -44,12 +44,12 @@ datapack_id flows through automatically.
|
|
|
44
44
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
45
45
|
[returns id=mem_abc123, text="meko_active_datapack=8b1c…f4a2 name=prod-research …"]
|
|
46
46
|
|
|
47
|
-
> datapack_list(
|
|
47
|
+
> datapack_list()
|
|
48
48
|
[14 entries returned, filtering by "q2-roadmap-deck"]
|
|
49
49
|
|
|
50
50
|
One match: `q2-roadmap-deck`. Switching pin.
|
|
51
51
|
|
|
52
|
-
> memory_update(
|
|
52
|
+
> memory_update(
|
|
53
53
|
memory_id="mem_abc123",
|
|
54
54
|
text="meko_active_datapack=4c2e…a991 name=q2-roadmap-deck selected_at=2026-05-25T19:05:00Z",
|
|
55
55
|
agent_id="claude_desktop",
|
|
@@ -69,12 +69,12 @@ The `memory_update` is critical here — using `memory_add` again would create a
|
|
|
69
69
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
70
70
|
[empty]
|
|
71
71
|
|
|
72
|
-
> datapack_list(
|
|
72
|
+
> datapack_list()
|
|
73
73
|
[1 entry returned]
|
|
74
74
|
|
|
75
75
|
Only one datapack: `meko-local-setup`. Auto-selecting.
|
|
76
76
|
|
|
77
|
-
> memory_add(
|
|
77
|
+
> memory_add(
|
|
78
78
|
text="meko_active_datapack=a17d…cc91 name=meko-local-setup selected_at=…",
|
|
79
79
|
agent_id="claude_desktop",
|
|
80
80
|
conversation_id="<conv-id>",
|
|
@@ -93,7 +93,7 @@ Pinned datapack `meko-local-setup` (`a17d…cc91`). Run this skill again with
|
|
|
93
93
|
> memory_search(query="meko_active_datapack", agent_id="claude_desktop", limit=1)
|
|
94
94
|
[returns id=mem_abc123]
|
|
95
95
|
|
|
96
|
-
> memory_delete_by_id(
|
|
96
|
+
> memory_delete_by_id(
|
|
97
97
|
memory_id="mem_abc123",
|
|
98
98
|
agent_id="claude_desktop",
|
|
99
99
|
conversation_id="<conv-id>")
|
|
@@ -114,7 +114,7 @@ This isn't a user-triggered flow — it's the per-turn lookup the skill teaches
|
|
|
114
114
|
|
|
115
115
|
# Extract UUID after "meko_active_datapack=" → 8b1c…f4a2
|
|
116
116
|
|
|
117
|
-
> memory_add(
|
|
117
|
+
> memory_add(text="…", datapack_id="8b1c…f4a2",
|
|
118
118
|
agent_id="claude_desktop", conversation_id="<conv-id>")
|
|
119
119
|
```
|
|
120
120
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Role display — current state
|
|
2
|
+
|
|
3
|
+
## Today: render `grant` verbatim
|
|
4
|
+
|
|
5
|
+
The deployed Meko `GET /datapacks` response includes a `grant` field on every datapack. Possible values (per maintainer guidance, 2026-05-26):
|
|
6
|
+
|
|
7
|
+
- `"owner"` — datapacks the caller created.
|
|
8
|
+
- `"maintainer"` — write access to a shared datapack including memories AND collective learnings/knowledge.
|
|
9
|
+
- `"contributor"` — write access to a shared datapack: can generate own memories. (Cannot promote / publish collective learnings — that's the maintainer's job.)
|
|
10
|
+
- `"viewer"` — read-only on a shared datapack.
|
|
11
|
+
|
|
12
|
+
Use the field directly in the **Role** column:
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
# Name Role Created Active?
|
|
16
|
+
1 prod-research owner 2026-04-12 ← (pinned)
|
|
17
|
+
2 team-onboarding contributor 2026-04-08
|
|
18
|
+
3 q2-roadmap viewer 2026-03-22
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Do not invent values, do not normalize the casing, do not display `"Owner"` if the field says `"owner"`. The deployed schema is the source of truth.
|
|
22
|
+
|
|
23
|
+
Note that the upstream Go source (the `Datapack` struct in `api_server/internal/models/models.go` of the `meko` API-server repo) does NOT declare `grant` — the deployed server enriches the response beyond what the public Go code lists. Don't rely on the public struct for the wire schema; trust the actual response.
|
|
24
|
+
|
|
25
|
+
## Other fields the live response includes
|
|
26
|
+
|
|
27
|
+
Beyond the columns the skill renders by default, `datapack_list` returns counts that may be useful in some flows:
|
|
28
|
+
|
|
29
|
+
- `memory_count` — total memories the caller has under this datapack (per `(user_id, agent_id)` scoping).
|
|
30
|
+
- `knowledge_count` — knowledge-base entries on the datapack.
|
|
31
|
+
- `learnings_count` — promoted-to-shared memories on the datapack.
|
|
32
|
+
|
|
33
|
+
These aren't in the spec column set. Don't add them silently. If the user asks for counts, render them on request — and read the numbers from the live response, never invent them.
|
|
34
|
+
|
|
35
|
+
## Sharing UI vs API state
|
|
36
|
+
|
|
37
|
+
The Cloud console "Share <datapack>" page (`meko_ui/src/features/datapacks/pages/DatapackSharePage.tsx`) shows interactive controls with "Coming Soon" overlays on a few specific actions (e.g. invite-by-email link sharing, transfer-ownership). Those overlays mean *those specific UI affordances* aren't shipped — NOT that the underlying `grant`/sharing model is absent. Contributor/maintainer/viewer grants are functional in the data layer today; only the user-facing self-serve invite flow is gated.
|
|
38
|
+
|
|
39
|
+
## Why the skill ships without Mine / Shared / All filter tabs
|
|
40
|
+
|
|
41
|
+
The tagged pin memory (re-read via `memory_search` before each Meko write) delivers the user's actual ask ("don't make me remember a UUID"). Filter tabs are useful when the response is genuinely mixed-grant; for users with only owner-grant rows they're decorative. We add tabs when there's evidence users with mixed-grant responses want them.
|
|
@@ -40,7 +40,7 @@ The user has zero datapacks. Print:
|
|
|
40
40
|
```
|
|
41
41
|
You don't have any datapacks yet. Create one with:
|
|
42
42
|
|
|
43
|
-
datapack_create(
|
|
43
|
+
datapack_create(name="<your-datapack-name>")
|
|
44
44
|
|
|
45
45
|
Or visit the Meko Cloud console (Datapacks → New datapack).
|
|
46
46
|
```
|
|
@@ -7,9 +7,14 @@ import { dirname, join } from 'node:path';
|
|
|
7
7
|
|
|
8
8
|
import { install, uninstall } from '../lib/installer.mjs';
|
|
9
9
|
import { askChoice, askMultiChoice, askText, askSecret, askYesNo, close as closePrompts } from '../lib/prompt.mjs';
|
|
10
|
-
import { banner, error, dim, info } from '../lib/logger.mjs';
|
|
11
|
-
import {
|
|
10
|
+
import { banner, error, dim, info, warn } from '../lib/logger.mjs';
|
|
11
|
+
import {
|
|
12
|
+
isPackagedInstall,
|
|
13
|
+
MEKO_PRODUCTION_CONSOLE_URL,
|
|
14
|
+
selfInvocation,
|
|
15
|
+
} from '../lib/clients/common.mjs';
|
|
12
16
|
import { getClientAdapters } from '../lib/clients/index.mjs';
|
|
17
|
+
import { resolveSuggestedMcpUrl } from '../lib/url-selection.mjs';
|
|
13
18
|
import { parseClientList } from '../lib/clients/aliases.mjs';
|
|
14
19
|
import { startMigration, runChildMigration, readStatus, stopMigration } from '../lib/migrate.mjs';
|
|
15
20
|
import { checkLatest } from '../lib/version-check.mjs';
|
|
@@ -81,7 +86,7 @@ Examples:
|
|
|
81
86
|
create-meko-setup
|
|
82
87
|
|
|
83
88
|
# Cloud Meko for Claude Code (non-interactive):
|
|
84
|
-
create-meko-setup --url https://
|
|
89
|
+
create-meko-setup --url https://mcp.mekodata.ai/mcp --api-key "$MEKO_API_KEY" --yes
|
|
85
90
|
|
|
86
91
|
# Local Meko with Cursor config:
|
|
87
92
|
create-meko-setup --client cursor --local --scope project --yes
|
|
@@ -104,7 +109,7 @@ Options:
|
|
|
104
109
|
Comma-separated, or "all" to target every supported client (default: claude-code)
|
|
105
110
|
codex covers BOTH the OpenAI Codex CLI and the Codex Desktop App
|
|
106
111
|
(they share ~/.codex/config.toml).
|
|
107
|
-
--url <url> MCP server URL (from
|
|
112
|
+
--url <url> MCP server URL (from cloud.mekodata.ai > Datapacks > Connect)
|
|
108
113
|
--api-key <key> API key for Cloud Meko authentication
|
|
109
114
|
--local Use local Meko at http://localhost:8000/mcp
|
|
110
115
|
--scope <scope> Config scope: user or project (default: user)
|
|
@@ -465,6 +470,28 @@ async function main() {
|
|
|
465
470
|
}
|
|
466
471
|
}
|
|
467
472
|
|
|
473
|
+
let suggestedUrl = null;
|
|
474
|
+
if (!url && !flags.local) {
|
|
475
|
+
suggestedUrl = resolveSuggestedMcpUrl({
|
|
476
|
+
adapters: getClientAdapters(),
|
|
477
|
+
clients,
|
|
478
|
+
name: flags.name,
|
|
479
|
+
scope: flags.scope,
|
|
480
|
+
projectRoot,
|
|
481
|
+
});
|
|
482
|
+
if (flags.yes) {
|
|
483
|
+
if (suggestedUrl.source === 'conflict') {
|
|
484
|
+
const conflicts = suggestedUrl.existingUrls.map((existingUrl) => `\n - ${existingUrl}`).join('');
|
|
485
|
+
error(
|
|
486
|
+
`Selected clients have different existing Meko URLs:${conflicts}\n` +
|
|
487
|
+
'Pass --url explicitly to choose which endpoint to install.',
|
|
488
|
+
);
|
|
489
|
+
process.exit(1);
|
|
490
|
+
}
|
|
491
|
+
url = suggestedUrl.url;
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
468
495
|
// Interactive mode: URL not provided and not auto-accepting defaults
|
|
469
496
|
if (!url && !flags.yes) {
|
|
470
497
|
banner('Meko Setup');
|
|
@@ -475,7 +502,7 @@ async function main() {
|
|
|
475
502
|
// When only Cloud is available, skip the prompt entirely — asking to
|
|
476
503
|
// pick between one option is pointless UX.
|
|
477
504
|
const connectionOptions = [
|
|
478
|
-
{ label: 'Cloud Meko', description: 'Hosted at
|
|
505
|
+
{ label: 'Cloud Meko', description: 'Hosted at mekodata.ai (requires an API key)' },
|
|
479
506
|
];
|
|
480
507
|
if (!isPackagedInstall()) {
|
|
481
508
|
connectionOptions.push({
|
|
@@ -490,7 +517,19 @@ async function main() {
|
|
|
490
517
|
|
|
491
518
|
if (connectionType === 'Cloud Meko') {
|
|
492
519
|
// Step 2 — MCP URL
|
|
493
|
-
|
|
520
|
+
if (suggestedUrl?.source === 'existing') {
|
|
521
|
+
dim(`Using the existing Meko endpoint as the default: ${suggestedUrl.url}`);
|
|
522
|
+
} else if (suggestedUrl?.source === 'conflict') {
|
|
523
|
+
const conflicts = suggestedUrl.existingUrls.map((existingUrl) => `\n - ${existingUrl}`).join('');
|
|
524
|
+
warn(
|
|
525
|
+
`Selected clients use different Meko endpoints:${conflicts}\n` +
|
|
526
|
+
'Enter the endpoint to use for this install.',
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
url = await askText(
|
|
530
|
+
`MCP server URL (from ${MEKO_PRODUCTION_CONSOLE_URL} > Datapacks > Connect):`,
|
|
531
|
+
suggestedUrl?.url ?? undefined,
|
|
532
|
+
);
|
|
494
533
|
|
|
495
534
|
// Step 3 — API key. Normalize: terminal paste can drag in trailing
|
|
496
535
|
// whitespace/CR or accidental surrounding quotes, all of which would
|
|
@@ -288,13 +288,17 @@ export function createClaudeCodeAdapter(options = {}) {
|
|
|
288
288
|
// leaving the marketplace.json missing. Full clone is small
|
|
289
289
|
// (~few MB, mostly markdown) and is the only way that reliably
|
|
290
290
|
// succeeds today.
|
|
291
|
-
// Marketplace source is normally the
|
|
291
|
+
// Marketplace source is normally the public generated skills repo. Use
|
|
292
|
+
// an explicit HTTPS URL: GitHub's owner/repo shorthand makes Claude Code
|
|
293
|
+
// clone over SSH, which fails for users without GitHub SSH credentials.
|
|
294
|
+
// A dev/e2e
|
|
292
295
|
// override lets a test install the plugin from a LOCAL working-tree
|
|
293
296
|
// checkout (a directory path) so unreleased skill changes can be
|
|
294
|
-
// exercised end-to-end before they
|
|
295
|
-
//
|
|
297
|
+
// exercised end-to-end before they are published to `yugabyte/meko-skills`.
|
|
298
|
+
// Only set MEKO_PLUGIN_MARKETPLACE_SOURCE in tests.
|
|
296
299
|
const marketplaceSource =
|
|
297
|
-
process.env.MEKO_PLUGIN_MARKETPLACE_SOURCE
|
|
300
|
+
process.env.MEKO_PLUGIN_MARKETPLACE_SOURCE
|
|
301
|
+
|| "https://github.com/yugabyte/meko-skills.git";
|
|
298
302
|
const marketplaceCmd =
|
|
299
303
|
`claude plugin marketplace add ${shellQuote(marketplaceSource)} --scope ${shellQuote(scope)}`;
|
|
300
304
|
// `claude plugin list` dropped --scope in CLI 2.1.x; it prints all
|
|
@@ -99,9 +99,11 @@ export function createClaudeDesktopAdapter(options = {}) {
|
|
|
99
99
|
const fromMcpb =
|
|
100
100
|
/\bClaude\b[^ ]*\bExtensions\b/i.test(commandJoined) ||
|
|
101
101
|
/mcp-remote-launcher\.js/.test(commandJoined);
|
|
102
|
+
const url = getMcpRemoteEntryUrl(entry);
|
|
102
103
|
return {
|
|
103
104
|
found: true,
|
|
104
105
|
status: fromMcpb ? "Configured (via .mcpb extension)" : "Configured",
|
|
106
|
+
...(url ? { url } : {}),
|
|
105
107
|
};
|
|
106
108
|
},
|
|
107
109
|
removeRegistration(name) {
|
|
@@ -300,6 +302,18 @@ export function buildMcpRemoteEntry({ url, apiKey }) {
|
|
|
300
302
|
return entry;
|
|
301
303
|
}
|
|
302
304
|
|
|
305
|
+
/** Read the remote URL from installer-managed or MCPB Claude Desktop entries. */
|
|
306
|
+
export function getMcpRemoteEntryUrl(entry) {
|
|
307
|
+
if (typeof entry?.env?.MEKO_MCP_URL === "string") {
|
|
308
|
+
return entry.env.MEKO_MCP_URL;
|
|
309
|
+
}
|
|
310
|
+
if (typeof entry?.url === "string") return entry.url;
|
|
311
|
+
if (!Array.isArray(entry?.args)) return undefined;
|
|
312
|
+
const remoteIndex = entry.args.indexOf("mcp-remote");
|
|
313
|
+
const candidate = remoteIndex >= 0 ? entry.args[remoteIndex + 1] : undefined;
|
|
314
|
+
return typeof candidate === "string" ? candidate : undefined;
|
|
315
|
+
}
|
|
316
|
+
|
|
303
317
|
function defaultRunPackageScript(scriptPath) {
|
|
304
318
|
if (!statSync(scriptPath).isFile()) {
|
|
305
319
|
throw new Error(`Not a file: ${scriptPath}`);
|