You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add project_id parameter to MCP tools for cloud workspace disambiguation
Adds optional `project_id: Optional[str] = None` (UUID) parameter to all 14
project-scoped MCP tools so callers can address projects unambiguously across
cloud workspaces without depending on name resolution.
What changed:
- Canonicalize UUID input via str(UUID(...)) in resolve_workspace_project_identifier
so uppercase, brace-wrapped, urn:uuid, and unhyphenated forms all match the
stored external_id (Codex P2)
- Add project_id parameter to: read_note, write_note, search_notes, edit_note,
delete_note, view_note, read_content, move_note, list_directory, canvas,
recent_activity, build_context, schema_validate/infer/diff, search_notes_ui,
read_note_ui. project_id takes precedence over project when both are passed.
- Update get_project_client to route UUID identifiers correctly in pure local
mode. Without this, get_project_mode(uuid) defaults to CLOUD and fails for
users without cloud credentials. Fix gates the cloud-by-default branch on
cloud actually being available, and skips per-project routing for UUIDs in
Step 4 (local mode routes everything via the same ASGI client; the API
resolves the UUID via /v2/projects/resolve)
- Wire read_note._search_candidates to pass project_id=active_project.external_id
to the inner search_notes call so workspace selection from the outer
get_project_client is preserved across re-resolution. Without this, names
that collide across workspaces could re-resolve to a different tenant via
the default-workspace fallback in CLI/context=None paths (Codex P1)
- Switch resolve_project_and_path callers (read_note, read_content, search)
to pass active_project.name instead of the raw project arg so cache hits
even when project_id was used or project name was wrong/ambiguous
Documentation:
- AI assistant guide (live MCP resource) explains project vs project_id and
when to prefer the UUID
- Extended guide adds a dedicated `project` vs `project_id` section
- list_memory_projects docstring points LLMs at external_id for unambiguous
addressing
- Per-tool project_id docstring is directive ("Prefer this over `project`
when known") rather than conditional ("Use this when...")
Tests:
- 6 new unit tests in test_project_context.py covering UUID lookup, four
normalization variants, project_id precedence, and pure-local UUID routing
- 2 new integration tests verify project_id end-to-end through MCP transport
- Tool signature contract test and telemetry tests updated for new parameter
Closesbasicmachines-co/basic-memory-cloud#673
Signed-off-by: phernandez <paul@basicmachines.co>
-**`project`** — human-readable name (e.g., `"main"`). Easy to use, but can collide across cloud workspaces.
174
+
-**`project_id`** — stable `external_id` UUID. Always unambiguous; takes precedence over `project` when both are passed.
175
+
176
+
**When to prefer `project_id`:**
177
+
178
+
1.**Cloud multi-workspace setups.** If the user belongs to more than one workspace (personal + organization, or several organizations) and the same project name might exist in more than one of them, pass `project_id` to route to the exact project. Without it, name resolution falls back to the default workspace, which may not be the one the user means.
179
+
2.**After `list_memory_projects()`.** Once you have the `external_id`, prefer using it — it's the same number of characters in JSON and saves a name-resolution round-trip.
180
+
3.**When persisting a project choice across a long session.** UUIDs are stable; names can be renamed.
181
+
182
+
**When `project` (name) is fine:**
183
+
184
+
- Local single-workspace setups (no collision risk).
185
+
- One-off operations where the name is clearly visible to the user (e.g., quick `search_notes(project="main", ...)`).
186
+
- The user explicitly references a project by name in their message.
187
+
188
+
**Example — cloud multi-workspace pattern:**
189
+
190
+
```python
191
+
# Discover and pick the right project for this user
192
+
projects =await list_memory_projects()
193
+
target =next(p for p in projects if p["name"] =="research"and p["workspace"]["slug"] =="acme")
194
+
195
+
# Use the UUID for all subsequent operations — no ambiguity
**Precedence rule:** When both are passed, `project_id` wins. This lets you safely supply `project="main"` for backward compatibility while still routing precisely with `project_id`.
206
+
167
207
### Cross-Project Operations
168
208
169
209
**Some tools work across all projects when project parameter omitted:**
Copy file name to clipboardExpand all lines: src/basic_memory/mcp/resources/ai_assistant_guide.md
+12-2Lines changed: 12 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,13 +18,15 @@ Basic Memory creates a semantic knowledge graph from markdown files. Focus on bu
18
18
19
19
**Resolution priority:**
20
20
1. CLI constraint: `BASIC_MEMORY_MCP_PROJECT` env var (highest priority)
21
-
2. Explicit parameter: `project="name"` in tool calls
21
+
2. Explicit parameter: `project_id="<uuid>"` (preferred when known) or `project="name"` in tool calls
22
22
3. Default project: `default_project` in config (fallback)
23
23
24
+
**`project` vs `project_id`:** Every project has a stable `external_id` (UUID) returned by `list_memory_projects()`. Pass it as `project_id=...` to address a project unambiguously — required when the same project name exists in multiple cloud workspaces. For local single-project setups, the `project` name is fine.
25
+
24
26
### Quick Setup Check
25
27
26
28
```python
27
-
# Discover projects
29
+
# Discover projects (each entry includes external_id you can pass as project_id)
28
30
projects =await list_memory_projects()
29
31
```
30
32
@@ -169,6 +171,14 @@ await write_note(
169
171
**Multi-project users:**
170
172
- Always specify project explicitly in tool calls
171
173
174
+
**Cloud multi-workspace users:** project names can collide across workspaces. After calling `list_memory_projects()`, prefer the project's `external_id` via `project_id=...` for any subsequent tool calls — it routes to the exact project regardless of name collisions. The `project` name parameter falls back to the default workspace on ambiguity, which may not be what you want.
175
+
176
+
```python
177
+
# Cloud / multi-workspace: prefer project_id (UUID) once you've discovered it
0 commit comments