@yugabytedb/meko-mcp 1.0.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.
Files changed (51) hide show
  1. package/README.md +505 -0
  2. package/assets/hooks-handlers/lib/capture.js +863 -0
  3. package/assets/hooks-handlers/lib/checkpoint-timer.js +72 -0
  4. package/assets/hooks-handlers/pre-compact.sh +3 -0
  5. package/assets/hooks-handlers/session-end.sh +27 -0
  6. package/assets/hooks-handlers/session-start.sh +24 -0
  7. package/assets/hooks-handlers/test_single_conversation.sh +169 -0
  8. package/assets/skills/meko-mcp-tools/SKILL.md +192 -0
  9. package/assets/skills/meko-mcp-tools/references/_sections.md +31 -0
  10. package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +39 -0
  11. package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +49 -0
  12. package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +373 -0
  13. package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +56 -0
  14. package/assets/skills/meko-mcp-tools/references/tools-db-query-patterns.md +38 -0
  15. package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +61 -0
  16. package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +128 -0
  17. package/assets/skills/meko-mcp-tools/references/tools-overview.md +97 -0
  18. package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +63 -0
  19. package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +79 -0
  20. package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +143 -0
  21. package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +93 -0
  22. package/assets/skills/meko-mcp-tools/references/tools-write-guardrails.md +30 -0
  23. package/bin/create-meko-setup.mjs +499 -0
  24. package/lib/claude-code.mjs +14 -0
  25. package/lib/clients/claude-code.mjs +265 -0
  26. package/lib/clients/claude-desktop.mjs +256 -0
  27. package/lib/clients/common.mjs +107 -0
  28. package/lib/clients/cursor.mjs +332 -0
  29. package/lib/clients/index.mjs +14 -0
  30. package/lib/config.mjs +369 -0
  31. package/lib/detect.mjs +125 -0
  32. package/lib/installer.mjs +255 -0
  33. package/lib/logger.mjs +97 -0
  34. package/lib/mcp-transport.mjs +204 -0
  35. package/lib/migrate/adapters/claude-code.mjs +165 -0
  36. package/lib/migrate/adapters/cursor.mjs +221 -0
  37. package/lib/migrate/adapters/memory-md.mjs +230 -0
  38. package/lib/migrate/claude-parser.mjs +306 -0
  39. package/lib/migrate/daemon.mjs +67 -0
  40. package/lib/migrate/id.mjs +83 -0
  41. package/lib/migrate/lockfile.mjs +121 -0
  42. package/lib/migrate/logger.mjs +79 -0
  43. package/lib/migrate/mcp-client.mjs +224 -0
  44. package/lib/migrate/orchestrator.mjs +443 -0
  45. package/lib/migrate/progress.mjs +76 -0
  46. package/lib/migrate/state.mjs +177 -0
  47. package/lib/migrate.mjs +328 -0
  48. package/lib/prompt.mjs +212 -0
  49. package/lib/validate.mjs +259 -0
  50. package/package.json +49 -0
  51. package/scripts/bundle-assets.mjs +49 -0
@@ -0,0 +1,97 @@
1
+ # Complete Tool Catalog and Decision Tree
2
+
3
+ ## Quick health check before using tools
4
+
5
+ Before starting a session, verify that the Meko MCP tools are working:
6
+
7
+ 1. `db_summarize_database(scope="read")` — Confirms DB connection is working. Also doubles as the `agent_id` discovery step (see the main SKILL.md) — look for `<x>_mem0_collection` tables with rows.
8
+ 2. `memory_search(scope="read", query="test", agent_id="<discovered>")` — Confirms memory subsystem is up. Substitute the `agent_id` you found in step 1. May fail with "connection already closed" — see `tools-troubleshooting.md`.
9
+ 3. `datapack_list(scope="read")` — Confirms Meko API connectivity
10
+
11
+ If memory tools fail but DB tools work, you can read memory data directly:
12
+ ```
13
+ db_run_read_only_query(scope="read", query="SELECT id, payload FROM default_mem0_collection LIMIT 20")
14
+ ```
15
+
16
+ ## Decision tree: which tool do I need?
17
+
18
+ ```
19
+ User wants to...
20
+ ├── Query or explore the database?
21
+ │ ├── See what tables exist? ---------> db_summarize_database (read)
22
+ │ ├── Run a SELECT / read query? -----> db_run_read_only_query (read)
23
+ │ └── INSERT / UPDATE / DELETE? -------> db_run_write_query (write)
24
+ ├── Build or check a knowledge base (RAG)?
25
+ │ ├── Create a new index from sources? -> knowledgebase_trigger_index_creation (write)
26
+ │ ├── Add source to existing index? ---> knowledgebase_add_source_to_index (write)
27
+ │ └── Check build progress? -----------> knowledgebase_check_index_status (read)
28
+ ├── Store or recall information?
29
+ │ ├── Store a fact/preference/entity? -----------> memory_add (write)
30
+ │ ├── Store a full conversation (multi-turn)? ---> conversation_create + conversation_add_message (write)
31
+ │ ├── Search past knowledge? --------------------> memory_search (read)
32
+ │ └── Retrieve a past conversation? -------------> conversation_get (read)
33
+ └── Manage datapacks?
34
+ ├── CRUD datapack? -> datapack_create/list/describe/update/delete
35
+ ├── Manage agents? -> datapack_create_agent/list_agents/delete_agent
36
+ └── Manage KB sources? -> datapack_add_knowledge_base/list/delete_knowledge_base
37
+ ```
38
+
39
+ ## Database Tools (3)
40
+
41
+ | Tool | Scope | Purpose |
42
+ |------|-------|---------|
43
+ | `db_summarize_database(scope, schema="public", datapack_id=None)` | read | List tables with column schemas and row counts |
44
+ | `db_run_read_only_query(scope, query, datapack_id=None)` | read | Run SELECT, returns JSON. Uses `BEGIN READ ONLY` + `ROLLBACK` |
45
+ | `db_run_write_query(scope, query, datapack_id=None)` | write | Execute INSERT/UPDATE/DELETE/CREATE TABLE. Guardrail-validated. Auto-committed |
46
+
47
+ ## RAG / Knowledge Base Tools (3)
48
+
49
+ | Tool | Scope | Purpose |
50
+ |------|-------|---------|
51
+ | `knowledgebase_trigger_index_creation(scope, source_uris, index_name, ai_provider="OPENAI", embedding_model="text-embedding-3-large", embedding_dimensions=1536, chunk_size=1024, chunk_overlap=256, datapack_id=None)` | write | Register sources + init vector index + trigger build |
52
+ | `knowledgebase_add_source_to_index(scope, index_name, source_id, chunk_size=1024, chunk_overlap=256, datapack_id=None)` | write | Add a new source to an existing index |
53
+ | `knowledgebase_check_index_status(scope, index_name, datapack_id=None)` | read | Check build progress via `dist_rag.vector_index_pipeline_details` |
54
+
55
+ ## Memory Tools (7)
56
+
57
+ | Tool | Scope | Purpose |
58
+ |------|-------|---------|
59
+ | `memory_add(scope, text, agent_id, user_id=None, app_id=None, run_id=None, metadata=None, messages=None, datapack_id=None)` | write | Store fact/preference/entity as long-term memory |
60
+ | `memory_search(scope, query, agent_id, user_id=None, limit=10, datapack_id=None)` | read | Semantic search across memories + graph relations |
61
+ | `memory_get_by_id(scope, memory_id, agent_id, datapack_id=None)` | read | Retrieve a single memory by UUID |
62
+ | `memory_get_all(scope, agent_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | read | List all memories for agent |
63
+ | `memory_update(scope, memory_id, text, agent_id, datapack_id=None)` | write | Overwrite memory text |
64
+ | `memory_delete_by_id(scope, memory_id, agent_id, datapack_id=None)` | write | Delete a single memory |
65
+ | `memory_delete_all(scope, agent_id, user_id=None, app_id=None, run_id=None, datapack_id=None)` | admin | Delete all memories for agent (destructive) |
66
+
67
+ ## Conversation Tools (7)
68
+
69
+ | Tool | Scope | Purpose |
70
+ |------|-------|---------|
71
+ | `conversation_create(scope, agent_id, user_id=None, app_id=None, run_id=None, title=None, metadata=None, session_id="")` | write | Create conversation container (Langfuse session) |
72
+ | `conversation_add_message(scope, conversation_id, agent_id, input, output=None, reasoning=None, metadata=None, seed=None, trace_id="")` | write | Add a message turn (Langfuse trace) |
73
+ | `conversation_get(scope, conversation_id, agent_id, include_messages=False, limit=100, offset=0)` | read | Retrieve conversation, optionally with messages |
74
+ | `conversation_list(scope, agent_id, user_id=None, limit=20, offset=0)` | read | List conversations for agent |
75
+ | `conversation_update(scope, conversation_id, agent_id, title=None, metadata=None)` | write | Update title or metadata |
76
+ | `conversation_delete_message(scope, conversation_id, agent_id, trace_id)` | write | Delete a single message |
77
+ | `conversation_delete(scope, conversation_id, agent_id)` | admin | Delete entire conversation (destructive) |
78
+
79
+ ## Datapack Management Tools (11)
80
+
81
+ | Tool | Scope | Purpose |
82
+ |------|-------|---------|
83
+ | `datapack_create(scope, name)` | write | Create new datapack |
84
+ | `datapack_list(scope)` | read | List all datapacks |
85
+ | `datapack_describe(scope, name, include_status=False)` | read | Describe datapack |
86
+ | `datapack_update(scope, name, connection_string)` | write | Update connection string |
87
+ | `datapack_delete(scope, name)` | admin | Delete datapack (irreversible) |
88
+ | `datapack_create_agent(scope, datapack_name, agent_name, agent_metadata=None)` | write | Create agent in datapack |
89
+ | `datapack_list_agents(scope, datapack_name)` | read | List agents in datapack |
90
+ | `datapack_delete_agent(scope, datapack_name, agent_name)` | admin | Delete agent |
91
+ | `datapack_add_knowledge_base(scope, datapack_name, url)` | write | Add KB source URL |
92
+ | `datapack_list_knowledge_bases(scope, datapack_name)` | read | List KB sources |
93
+ | `datapack_delete_knowledge_base(scope, datapack_name, url)` | admin | Delete KB source |
94
+
95
+ ## Common Parameter Patterns
96
+
97
+ Every tool accepts `scope` as the first parameter. All DB, RAG, and memory tools accept optional `datapack_id` to target a specific datapack's database. Memory and conversation tools require `agent_id` for namespace isolation (see `tools-agent-id-conventions.md`).
@@ -0,0 +1,63 @@
1
+ # End-to-End RAG Pipeline Workflow
2
+
3
+ **WRONG:** Calling `knowledgebase_check_index_status` before creating the index (returns empty), or `knowledgebase_add_source_to_index` for initial creation (fails — index doesn't exist yet).
4
+
5
+ ## Step 1: Create the index from sources
6
+
7
+ `knowledgebase_trigger_index_creation` registers sources, initializes the vector index, and triggers the build in one call:
8
+
9
+ ```
10
+ knowledgebase_trigger_index_creation(
11
+ scope="write",
12
+ source_uris="s3://my-bucket/docs/,s3://my-bucket/reports/",
13
+ index_name="company_docs"
14
+ )
15
+ -- Returns: {"source_ids": [...], "index_name": "company_docs", "status": "build_triggered"}
16
+ ```
17
+
18
+ ## Step 2: Poll for build completion
19
+
20
+ ```
21
+ knowledgebase_check_index_status(scope="read", index_name="company_docs")
22
+ ```
23
+
24
+ Check `completion_rate_percent` in `pipeline_stats` and `document_status` in `pipeline_details` to know when all documents are fully indexed.
25
+
26
+ ## Step 3: Add more sources later
27
+
28
+ Once an index exists, use `knowledgebase_add_source_to_index` with a pre-registered `source_id` (UUID, not URI):
29
+
30
+ ```
31
+ knowledgebase_add_source_to_index(scope="write", index_name="company_docs", source_id="new-source-uuid")
32
+ ```
33
+
34
+ ## Tool selection guide
35
+
36
+ | Situation | Tool |
37
+ |-----------|------|
38
+ | First time creating a RAG index | `knowledgebase_trigger_index_creation` |
39
+ | Adding a source to an existing index | `knowledgebase_add_source_to_index` |
40
+ | Checking if build is complete | `knowledgebase_check_index_status` |
41
+
42
+ ## Troubleshooting: Pipeline stuck at INIT
43
+
44
+ If `knowledgebase_check_index_status` returns empty `pipeline_details` or documents remain at `INIT` status for more than 5 minutes, the build workers have likely stalled.
45
+
46
+ **Diagnosis:** Query the work queue directly:
47
+ ```
48
+ db_run_read_only_query(scope="read",
49
+ query="SELECT task_type, status, lease_expires_at FROM dist_rag.work_queue WHERE index_name = 'your_index' ORDER BY created_at DESC LIMIT 10")
50
+ ```
51
+
52
+ Tasks stuck `IN_PROGRESS` with `lease_expires_at` in the past indicate crashed workers. **Stop polling after 3 consecutive no-progress checks** — continued polling wastes context. See `tools-troubleshooting.md` for full recovery strategies.
53
+
54
+ ## Limitations
55
+
56
+ - There is **no MCP tool to delete** a vector index, remove a source from an index, or reset stuck work queue tasks.
57
+ - There is **no MCP tool to query** a built index — use `db_run_read_only_query` with `dist_rag` SQL functions directly.
58
+ - `knowledgebase_add_source_to_index` has a **known parameter mismatch bug**. Prefer `knowledgebase_trigger_index_creation` with all sources at once.
59
+ - Each `knowledgebase_trigger_index_creation` call creates a new index. **Do not retry on failure** — you'll create duplicates.
60
+
61
+ ## Prerequisite
62
+
63
+ All RAG tools require the `dist_rag` PostgreSQL extension in the target database. Pass `datapack_id` to all calls when targeting a specific datapack.
@@ -0,0 +1,79 @@
1
+ # Scope Permission Hierarchy and Per-Tool Requirements
2
+
3
+ **WRONG:** `db_run_write_query(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 (12 tools)
21
+
22
+ | Tool | Group |
23
+ |------|-------|
24
+ | `db_summarize_database` | Database |
25
+ | `db_run_read_only_query` | Database |
26
+ | `knowledgebase_check_index_status` | RAG |
27
+ | `memory_search` | Memory |
28
+ | `memory_get_by_id` | Memory |
29
+ | `memory_get_all` | Memory |
30
+ | `conversation_get` | Conversation |
31
+ | `conversation_list` | Conversation |
32
+ | `datapack_list` | Datapack |
33
+ | `datapack_describe` | Datapack |
34
+ | `datapack_list_agents` | Datapack |
35
+ | `datapack_list_knowledge_bases` | Datapack |
36
+
37
+ ### write scope (14 tools)
38
+
39
+ | Tool | Group |
40
+ |------|-------|
41
+ | `db_run_write_query` | Database |
42
+ | `knowledgebase_trigger_index_creation` | RAG |
43
+ | `knowledgebase_add_source_to_index` | RAG |
44
+ | `memory_add` | Memory |
45
+ | `memory_update` | Memory |
46
+ | `memory_delete_by_id` | Memory |
47
+ | `conversation_create` | Conversation |
48
+ | `conversation_add_message` | Conversation |
49
+ | `conversation_update` | Conversation |
50
+ | `conversation_delete_message` | Conversation |
51
+ | `datapack_create` | Datapack |
52
+ | `datapack_update` | Datapack |
53
+ | `datapack_create_agent` | Datapack |
54
+ | `datapack_add_knowledge_base` | Datapack |
55
+
56
+ ### admin scope (5 tools — destructive, irreversible)
57
+
58
+ | Tool | Group |
59
+ |------|-------|
60
+ | `memory_delete_all` | Memory |
61
+ | `conversation_delete` | Conversation |
62
+ | `datapack_delete` | Datapack |
63
+ | `datapack_delete_agent` | Datapack |
64
+ | `datapack_delete_knowledge_base` | Datapack |
65
+
66
+ ## Best Practices
67
+
68
+ 1. **Use the minimum scope needed.** `scope="read"` for reads documents intent and prevents accidental writes.
69
+ 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.
70
+
71
+ ## Common Mistakes
72
+
73
+ **WRONG:** `scope="all"` — there is no "all" scope. Valid values are exactly: `"read"`, `"write"`, `"admin"`. Nothing else.
74
+
75
+ Other invalid values that will fail: `"readwrite"`, `"rw"`, `"full"`, `"any"`.
76
+
77
+ 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.
78
+
79
+ **Default choice:** Start with `scope="read"` unless you specifically need to write or delete.
@@ -0,0 +1,143 @@
1
+ # Troubleshooting — Error Recovery and Retry Strategies
2
+
3
+ These patterns are extracted from real agent sessions. Follow them to avoid wasting tool calls and context window on repeated failures.
4
+
5
+ ## General rules
6
+
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
+ 2. **Distinguish transient vs persistent failures.** "Connection already closed" is transient (retry once). "Permission denied" is persistent (stop, don't retry).
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. **Cache what you learn within a session.** Once you've discovered the user's `agent_id` via `db_summarize_database` (see the main SKILL.md), reuse it for every subsequent call in this session. Re-run discovery on the next session.
11
+
12
+ ---
13
+
14
+ ## Connection errors: "connection already closed"
15
+
16
+ **Affects:** Memory tools (`memory_add`, `memory_search`, `memory_get_all`) most frequently. DB tools less often.
17
+
18
+ **Why it happens:** The Python memory subsystem uses a connection cache that doesn't recover from dropped connections (unlike the Go API server which has retry logic with 5 retries and 3-second delays).
19
+
20
+ **What to do:**
21
+
22
+ 1. Retry the same call **once**
23
+ 2. If it fails again, the memory subsystem is unhealthy for this session
24
+ 3. Fall back to direct SQL to read memory data:
25
+ ```
26
+ db_run_read_only_query(scope="read",
27
+ query="SELECT id, payload FROM default_mem0_collection LIMIT 20")
28
+ ```
29
+ Replace `default` with your `agent_id` prefix if using a custom agent.
30
+
31
+ **Anti-pattern from real sessions:** Agent called `memory_add` with 500+ tokens of text, got "connection already closed", retried the identical call 3 more times (each 500+ tokens). Wasted ~2000 tokens on guaranteed failures.
32
+
33
+ ---
34
+
35
+ ## RAG pipeline stuck at INIT
36
+
37
+ **Affects:** `knowledgebase_trigger_index_creation` — the build triggers but never completes.
38
+
39
+ **Symptoms:**
40
+ - `knowledgebase_check_index_status` returns empty `pipeline_details` and `pipeline_stats`
41
+ - Documents remain at `INIT` status indefinitely
42
+ - Work queue tasks are `IN_PROGRESS` with `lease_expires_at` in the past
43
+
44
+ **Diagnosis:** Query the work queue directly:
45
+ ```
46
+ db_run_read_only_query(scope="read",
47
+ query="SELECT task_type, status, lease_expires_at FROM dist_rag.work_queue WHERE index_name = 'your_index' ORDER BY created_at DESC LIMIT 10")
48
+ ```
49
+
50
+ Look for tasks stuck `IN_PROGRESS` with expired leases — these indicate crashed or hung workers.
51
+
52
+ **What to do:**
53
+
54
+ 1. Poll status **at most 3 times** with 1-2 minute intervals
55
+ 2. If no progress after 3 checks, **stop polling** — the pipeline is stuck
56
+ 3. There is **no way to reset or retry stuck tasks via MCP tools**
57
+ 4. Creating a new index with a different name (e.g., `_v2`) is a workaround, but if the workers themselves are down, this will also get stuck
58
+ 5. Recommend the user check worker logs or restart the pipeline service
59
+
60
+ **Anti-pattern from real sessions:** Agent created indexes `v1`, `v2`, `v3` — all stuck with the same symptoms. Even making the S3 bucket public didn't help. The issue was worker infrastructure, not permissions.
61
+
62
+ ---
63
+
64
+ ## db_run_write_query guardrail error
65
+
66
+ **Error:** `'dict' object has no attribute 'guardrail_config'`
67
+
68
+ **Affects:** `db_run_write_query` in some deployments.
69
+
70
+ **What to do:**
71
+
72
+ 1. Try the call once. If it fails with this specific error, write operations are unavailable in this deployment.
73
+ 2. For reads, always use `db_run_read_only_query` (never `db_run_write_query` for SELECT).
74
+ 3. Report the issue — it's a server-side bug, not a parameter problem.
75
+
76
+ ---
77
+
78
+ ## knowledgebase_add_source_to_index failure
79
+
80
+ **Error:** SQL function signature mismatch — the tool passes `r_index_name` (string) but the DB function expects `r_index_id` (UUID).
81
+
82
+ **What to do:**
83
+
84
+ 1. Do NOT try different parameter formats (string name, UUID, etc.) — the bug is in the tool, not your parameters.
85
+ 2. **Workaround:** Use `knowledgebase_trigger_index_creation` with all sources included upfront instead of adding sources incrementally.
86
+
87
+ ---
88
+
89
+ ## Scope parameter errors
90
+
91
+ **Error:** `Insufficient scope: 'all'. This tool requires 'read' or higher.`
92
+
93
+ The only valid scope values are: `"read"`, `"write"`, `"admin"`.
94
+
95
+ - Use `"read"` for all read operations (default choice)
96
+ - Use `"write"` for inserts, updates, creates, memory writes
97
+ - Use `"admin"` only for destructive deletes
98
+
99
+ **Never use:** `"all"`, `"readwrite"`, `"rw"`, or any other value.
100
+
101
+ ---
102
+
103
+ ## agent_id errors
104
+
105
+ **Error:** `syntax error at or near "-"` in table creation.
106
+
107
+ `agent_id` is used in PostgreSQL table names. Hyphens are invalid in unquoted identifiers.
108
+
109
+ **Rule:** Lowercase letters, digits, underscores only.
110
+ - Good: `"claude_code"`, `"support_bot"`, `"agent_001"`
111
+ - Bad: `"claude-code"`, `"my agent"`, `"agent.one"`
112
+
113
+ ---
114
+
115
+ ## Permission denied on data tables
116
+
117
+ **Error:** `permission denied for table customer_complaints`
118
+
119
+ **Why:** The MCP database user may not have read access to all tables, particularly data tables created by the provisioning system within a datapack.
120
+
121
+ **What to do:**
122
+
123
+ 1. This is a server-side configuration issue — not fixable via MCP tools.
124
+ 2. Don't retry. Don't try different query formulations.
125
+ 3. Use `db_summarize_database` to see which tables you CAN access.
126
+ 4. Report the permission gap to the Meko admin.
127
+
128
+ ---
129
+
130
+ ## Safe-to-retry vs not
131
+
132
+ | Tool | Safe to retry? | Why |
133
+ |------|---------------|-----|
134
+ | All `read` scope tools | Yes | Reads are idempotent |
135
+ | `memory_add` | Yes (once) | Mem0 has dedup logic |
136
+ | `memory_update` | Yes (once) | Overwrites same ID |
137
+ | `memory_delete_by_id` | Yes | Deleting already-deleted is a no-op |
138
+ | `db_run_write_query` (INSERT) | **No** | May double-insert rows |
139
+ | `db_run_write_query` (CREATE TABLE) | **No** | "Table already exists" error |
140
+ | `knowledgebase_trigger_index_creation` | **No** | Creates duplicate indexes |
141
+ | `conversation_create` | **No** | Creates duplicate conversations |
142
+ | `conversation_add_message` with `seed` | Yes | Seed-based dedup prevents duplicates |
143
+ | `conversation_add_message` without `seed` | **No** | Creates duplicate messages |
@@ -0,0 +1,93 @@
1
+ # user_id Conventions
2
+
3
+ `user_id` identifies the **human** whose data is being stored or retrieved. It is the user-scoping counterpart to `agent_id`.
4
+
5
+ > **Note on `agent_id`.** In the current schema `agent_id` is overloaded — it's used for both isolation/namespacing and agent labeling. Discover it via `db_summarize_database` at session start rather than defaulting to the current tool's name. See the main SKILL.md section "Discover the user's `agent_id` namespace" and issue [#10](https://github.com/amiramm/meko-mcp-server/issues/10). The examples below use `claude_code` for illustration; substitute the discovered value at runtime.
6
+
7
+ ## Why user_id matters
8
+
9
+ Without `user_id`, the server defaults to `{agent_id}_user` — a single undifferentiated bucket. This works for a solo developer in a single session, but breaks the moment:
10
+
11
+ - A second person uses the same agent
12
+ - An autonomous agent serves multiple end-users
13
+ - You want to retrieve one person's memories without pulling everyone else's
14
+
15
+ **Always pass `user_id` explicitly.** Relying on the default creates data you can't cleanly separate later.
16
+
17
+ ## The two usage patterns
18
+
19
+ ### Interactive coding agent (e.g., Claude Code)
20
+
21
+ You are a coding assistant working with one human at a time. You know who they are — use their identity as `user_id`.
22
+
23
+ ```
24
+ memory_add(scope="write", agent_id="claude_code", user_id="alice",
25
+ text="Prefers concise responses, no emojis.")
26
+
27
+ memory_search(scope="read", query="response preferences", agent_id="claude_code", user_id="alice")
28
+
29
+ conversation_create(scope="write", agent_id="claude_code", user_id="alice",
30
+ title="Debugging auth middleware")
31
+ ```
32
+
33
+ **How to determine user_id:**
34
+ - Use the person's first name, lowercase: `"alice"`, `"bob"`, `"kyle"`
35
+ - If the name is ambiguous within the org, append a qualifier: `"alice_eng"`, `"alice_sales"`
36
+ - Use the same value consistently across all calls in a session — and across sessions
37
+ - If you don't know the user's name yet, ask. Don't fall back to the default.
38
+
39
+ ### Autonomous multi-user agent (e.g., support bot, team assistant)
40
+
41
+ The agent serves many users. Each user's data must be isolated so memories, conversations, and preferences don't leak across users.
42
+
43
+ ```
44
+ # Serving Alice
45
+ memory_add(scope="write", agent_id="support_bot", user_id="alice_123",
46
+ text="Alice prefers email communication. Has Pro plan.")
47
+
48
+ # Serving Bob — completely separate memory space
49
+ memory_add(scope="write", agent_id="support_bot", user_id="bob_456",
50
+ text="Bob prefers Slack. On Enterprise plan.")
51
+
52
+ # Searching only returns Alice's memories
53
+ memory_search(scope="read", query="communication preference",
54
+ agent_id="support_bot", user_id="alice_123")
55
+ ```
56
+
57
+ **How to determine user_id:**
58
+ - Use a stable identifier from your auth/identity system: username, email prefix, or external ID
59
+ - Must be consistent across sessions — the same person must always map to the same `user_id`
60
+ - Keep it human-readable when possible (debugging is easier with `"alice"` than `"usr_8f3a2b"`)
61
+
62
+ ## Scoping behavior
63
+
64
+ `user_id` filters data at the Mem0/Langfuse layer:
65
+
66
+ | Call | What it returns |
67
+ |------|----------------|
68
+ | `memory_search(agent_id="bot", user_id="alice")` | Only Alice's memories for this agent |
69
+ | `memory_search(agent_id="bot")` | Memories stored without a `user_id`, or with the default `bot_user` |
70
+ | `memory_get_all(agent_id="bot", user_id="alice")` | All of Alice's memories |
71
+ | `conversation_list(agent_id="bot", user_id="alice")` | Only Alice's conversations |
72
+
73
+ **Mixing scoped and unscoped calls creates invisible data.** If you store with `user_id="alice"` but search without `user_id`, the search won't find those memories — they live in a different partition. Pick a convention and stick to it.
74
+
75
+ ## Rules summary
76
+
77
+ 1. **Always pass `user_id` explicitly** — never rely on the server default
78
+ 2. **Use the human's identity** — first name lowercase, consistent across sessions
79
+ 3. **Same `user_id` for store and retrieve** — mismatched scoping creates invisible data
80
+ 4. **Ask if you don't know** — it's better to ask the user's name once than to store data you can't find later
81
+ 5. **One human = one `user_id`** — don't create separate IDs for the same person across contexts
82
+
83
+ ## Relationship to other parameters
84
+
85
+ | Parameter | Identifies | Example |
86
+ |-----------|-----------|---------|
87
+ | `agent_id` | The AI agent | `"claude_code"`, `"support_bot"` |
88
+ | `user_id` | The human being served | `"amiram"`, `"alice_123"` |
89
+ | `app_id` | The application/product (optional) | `"second_brain"`, `"helpdesk"` |
90
+ | `run_id` | A specific execution run (optional) | `"run_20260415_001"` |
91
+ | `datapack_id` | The target database/datapack (optional) | `"dp-uuid-123"` |
92
+
93
+ Together, `agent_id` + `user_id` form the primary namespace for memory and conversation isolation. `app_id` and `run_id` provide optional finer-grained grouping within that namespace.
@@ -0,0 +1,30 @@
1
+ # Write Query Guardrails and Blocked Operations
2
+
3
+ **WRONG:** `"INSERT INTO a (...); INSERT INTO b (...)"` → "Multi-statement queries not allowed." Send one statement per call.
4
+ **WRONG:** `"DROP SCHEMA analytics CASCADE"` → "DROP SCHEMA is not allowed."
5
+ **WRONG:** `"\\d users"` → psql meta-commands not supported. Use `information_schema` queries via `db_run_read_only_query`.
6
+
7
+ ## Blocked Operations
8
+
9
+ **Database/schema destruction:** `DROP DATABASE`, `DROP SCHEMA`, `ALTER DATABASE`, `CREATE DATABASE`
10
+ **Role/privilege manipulation:** `GRANT`, `REVOKE`, `CREATE/ALTER/DROP ROLE`, `CREATE/ALTER/DROP USER`
11
+ **Filesystem/code execution:** `COPY TO/FROM`, `LOAD`, `DO $$`, `CREATE EXTENSION`
12
+ **Server configuration:** `ALTER SYSTEM`, `RESET ALL`
13
+ **Dangerous functions:** `pg_sleep`, `pg_read_file`, `pg_write_file`, `lo_import`, `lo_export`, `dblink`
14
+ **Structural rules:** One SQL statement per call (multi-statement rejected). No psql `\` commands.
15
+
16
+ ## Configurable Limits
17
+
18
+ **Bulk INSERT row cap** (default 1000, env: `YB_MCP_MAX_INSERT_ROWS`): Counts parenthesized tuples in VALUES. Does NOT apply to `INSERT ... SELECT`. Split large inserts into batches of 1000 or fewer.
19
+
20
+ **WHERE clause enforcement** (off by default):
21
+ - `YB_MCP_REQUIRE_WHERE_ON_UPDATE=true` → rejects `UPDATE` without top-level `WHERE`
22
+ - `YB_MCP_REQUIRE_WHERE_ON_DELETE=true` → rejects `DELETE` without top-level `WHERE`
23
+
24
+ A `WHERE` inside a subquery does NOT satisfy the check.
25
+
26
+ ## What IS Allowed
27
+
28
+ `INSERT INTO ... VALUES`, `INSERT INTO ... SELECT` (no row limit), `UPDATE ... SET ... WHERE`, `DELETE FROM ... WHERE`, `CREATE TABLE`, `ALTER TABLE`, `DROP TABLE`, `CREATE INDEX`, `TRUNCATE`, `CALL procedure_name(...)`.
29
+
30
+ SQL comments are stripped before guardrail checks — patterns cannot be hidden in comments.