@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.
- package/README.md +505 -0
- package/assets/hooks-handlers/lib/capture.js +863 -0
- package/assets/hooks-handlers/lib/checkpoint-timer.js +72 -0
- package/assets/hooks-handlers/pre-compact.sh +3 -0
- package/assets/hooks-handlers/session-end.sh +27 -0
- package/assets/hooks-handlers/session-start.sh +24 -0
- package/assets/hooks-handlers/test_single_conversation.sh +169 -0
- package/assets/skills/meko-mcp-tools/SKILL.md +192 -0
- package/assets/skills/meko-mcp-tools/references/_sections.md +31 -0
- package/assets/skills/meko-mcp-tools/references/tools-agent-id-conventions.md +39 -0
- package/assets/skills/meko-mcp-tools/references/tools-conversation-dedup.md +49 -0
- package/assets/skills/meko-mcp-tools/references/tools-cookbook.md +373 -0
- package/assets/skills/meko-mcp-tools/references/tools-datapack-workflow.md +56 -0
- package/assets/skills/meko-mcp-tools/references/tools-db-query-patterns.md +38 -0
- package/assets/skills/meko-mcp-tools/references/tools-known-limitations.md +61 -0
- package/assets/skills/meko-mcp-tools/references/tools-memory-vs-conversation.md +128 -0
- package/assets/skills/meko-mcp-tools/references/tools-overview.md +97 -0
- package/assets/skills/meko-mcp-tools/references/tools-rag-workflow.md +63 -0
- package/assets/skills/meko-mcp-tools/references/tools-scope-permissions.md +79 -0
- package/assets/skills/meko-mcp-tools/references/tools-troubleshooting.md +143 -0
- package/assets/skills/meko-mcp-tools/references/tools-user-id-conventions.md +93 -0
- package/assets/skills/meko-mcp-tools/references/tools-write-guardrails.md +30 -0
- package/bin/create-meko-setup.mjs +499 -0
- package/lib/claude-code.mjs +14 -0
- package/lib/clients/claude-code.mjs +265 -0
- package/lib/clients/claude-desktop.mjs +256 -0
- package/lib/clients/common.mjs +107 -0
- package/lib/clients/cursor.mjs +332 -0
- package/lib/clients/index.mjs +14 -0
- package/lib/config.mjs +369 -0
- package/lib/detect.mjs +125 -0
- package/lib/installer.mjs +255 -0
- package/lib/logger.mjs +97 -0
- package/lib/mcp-transport.mjs +204 -0
- package/lib/migrate/adapters/claude-code.mjs +165 -0
- package/lib/migrate/adapters/cursor.mjs +221 -0
- package/lib/migrate/adapters/memory-md.mjs +230 -0
- package/lib/migrate/claude-parser.mjs +306 -0
- package/lib/migrate/daemon.mjs +67 -0
- package/lib/migrate/id.mjs +83 -0
- package/lib/migrate/lockfile.mjs +121 -0
- package/lib/migrate/logger.mjs +79 -0
- package/lib/migrate/mcp-client.mjs +224 -0
- package/lib/migrate/orchestrator.mjs +443 -0
- package/lib/migrate/progress.mjs +76 -0
- package/lib/migrate/state.mjs +177 -0
- package/lib/migrate.mjs +328 -0
- package/lib/prompt.mjs +212 -0
- package/lib/validate.mjs +259 -0
- package/package.json +49 -0
- 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.
|