fix(mcp): route mixed local/cloud projects correctly#837
Conversation
|
Claude finished @groksrc's task in 2m 43s —— View job PR Review: Fix mixed local/cloud MCP project routing
OverviewThis PR fixes three distinct edge cases in the MCP project routing layer for mixed local+cloud configurations. The changes are well-scoped, well-commented, and address real bugs. The logic is correct; my notes below are mostly nits and one behavioral concern worth discussing. Code Quality & Architecture
|
| Item | Status |
|---|---|
| Follows Basic Memory coding conventions (CLAUDE.md) | ✅ |
| Python 3.12+ type annotations and async patterns | ✅ |
| SQLAlchemy 2.0 best practices | ✅ N/A |
| FastAPI and Typer conventions followed | ✅ N/A |
| 100-character line length maintained | ✅ |
| No commented-out code blocks | ✅ |
| Unit tests for new functions/methods | ✅ |
| Integration tests for new MCP tool behavior | ✅ |
| Test coverage for edge cases | ✅ |
| 100% test coverage maintained | ✅ (new code paths fully covered) |
| Documentation updated | ✅ N/A (internal routing logic) |
| CLAUDE.md updated if conventions change | ✅ N/A |
| MCP tools follow atomic, composable design | ✅ |
| Database changes include Alembic migrations | ✅ N/A |
| Preserves local-first architecture principles | ✅ |
| Knowledge graph operations maintain consistency | ✅ |
| Markdown file handling preserves integrity | ✅ |
| No hardcoded secrets or credentials | ✅ |
| Input validation for MCP tools | ✅ |
| Proper error handling and logging | ✅ |
| Performance considerations addressed | |
| No sensitive data in logs/commits | ✅ |
| File path comparisons are Windows compatible | ✅ N/A |
| No emojis/unicode in console/log output | ✅ |
Summary
The fixes are correct and the test coverage is thorough. Two nits worth acting on:
- Add a comment to the modified
test_detect_project_from_memory_url_prefix_skips_workspace_discovery_for_local_configexplaining why the identifier was shortened. - Extract the repeated
_ContextStatetest stub into a conftest fixture.
Neither is a blocker. Approve with optional cleanup.
Signed-off-by: Drew Cain <groksrc@gmail.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
Signed-off-by: Drew Cain <groksrc@gmail.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a98e2b5ce8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if _workspace_identifier_discovery_available(identifier, config): | ||
| workspace_resolution = await resolve_workspace_qualified_identifier( | ||
| identifier, | ||
| context=context, |
There was a problem hiding this comment.
Guard workspace discovery failures for mixed local routing
In mixed local+cloud setups (config.projects present with a saved cloud_api_key), this new branch now runs workspace discovery for any 3-segment identifier, but the resolve_workspace_qualified_identifier(...) call is not wrapped for discovery errors. If cloud access is unavailable (expired key, network outage, or no accessible workspaces), _ensure_workspace_project_index raises and the tool fails instead of falling back to normal local resolution for identifiers like docs/topic/note. Before this change those local identifiers did not trigger cloud discovery in this mode, so this is a regression that can break read/search/edit flows when cloud credentials are stale.
Useful? React with 👍 / 👎.
a98e2b5 to
1460535
Compare
|
Claude finished @groksrc's task in 3m 46s —— View job PR Review: fix(mcp): route mixed local/cloud projects correctly
OverviewThis PR fixes three distinct edge cases in the MCP project routing layer for mixed local+cloud configurations. The changes are well-targeted and the test coverage is solid. However, the Codex P1 concern is real and confirmed — there is an unhandled error path introduced by the new P1: Unhandled discovery failure in
|
| Item | Status |
|---|---|
| Follows Basic Memory coding conventions (CLAUDE.md) | ✅ |
| Python 3.12+ type annotations and async patterns | ✅ |
| SQLAlchemy 2.0 best practices | ✅ N/A |
| FastAPI and Typer conventions followed | ✅ N/A |
| 100-character line length maintained | ✅ |
| No commented-out code blocks | ✅ |
| Unit tests for new functions/methods | ✅ |
| Integration tests for new MCP tool behavior | ✅ |
| Test coverage for edge cases | _workspace_identifier_discovery_available path |
| 100% test coverage maintained | ✅ (new code paths covered; gap is behavioral, not coverage) |
| Documentation updated | ✅ N/A |
| CLAUDE.md updated if conventions change | ✅ N/A |
| MCP tools follow atomic, composable design | ✅ |
| Database changes include Alembic migrations | ✅ N/A |
| Preserves local-first architecture principles | ✅ |
| Knowledge graph operations maintain consistency | ✅ |
| Markdown file handling preserves integrity | ✅ |
| No hardcoded secrets or credentials | ✅ |
| Input validation for MCP tools | ✅ |
| Proper error handling | ❌ resolve_workspace_qualified_identifier call in detect_project_from_identifier_prefix is unhandled (P1) |
| Performance considerations addressed | |
| No sensitive data in logs/commits | ✅ |
| File path comparisons are Windows compatible | ✅ N/A |
| No emojis/unicode in console/log output | ✅ |
Summary
The routing fixes are logically correct and the test coverage for the happy paths is thorough. One real issue must be addressed before merge:
Blocker: resolve_workspace_qualified_identifier at project_context.py:1360 can raise ValueError when cloud credentials are stale or the network is unavailable, breaking read/search/edit flows for any 3-segment identifier in mixed local+cloud configs. This is a regression from the _workspace_identifier_discovery_available expansion. The fix is a try/except around that call mirroring the one already present for resolve_workspace_project_identifier below it.
Two optional nits: add a comment to the shortened test identifier, and extract _ContextState to conftest.
Signed-off-by: Drew Cain <groksrc@gmail.com>
|
Claude finished @groksrc's task in 3m 7s —— View job PR Review: fix(mcp): route mixed local/cloud projects correctly
Status of Previous Review ItemsAll three items raised in prior reviews have been addressed in the latest push ( P1 — Unhandled The call to Nit — Missing comment explaining 2-segment test identifier ✅ Fixed
Nit —
One Remaining Minor Gap
This is the same class of failure as the P1 that was fixed, but in a narrower code path — it's only reached from If cloud credentials are stale and a user edits a note using a workspace-qualified plain identifier, the The fix mirrors what was done in # in detect_project_from_workspace_identifier_prefix, after line 47
workspace_discovery_fallback_errors = (
"not found",
"no accessible workspaces",
"unable to discover",
)
try:
workspace_resolution = await resolve_workspace_qualified_identifier(
identifier,
context=context,
)
except ValueError as exc:
if any(error in str(exc).lower() for error in workspace_discovery_fallback_errors):
return None
raiseThis is not a blocker — the affected surface is narrow (explicit workspace-qualified plain identifiers in Team Checklist
SummaryThe P1 blocker and both nits from previous reviews are resolved. The code is logically correct, the test coverage for happy paths and the key failure paths is thorough, and the The only remaining gap is the missing error guard in Recommend: Approve with optional follow-up on the |
Signed-off-by: Drew Cain <groksrc@gmail.com>
|
Claude finished @groksrc's task in 1m 42s —— View job PR Review: fix(mcp): route mixed local/cloud projects correctly
Status of Previous Review ItemsAll items from prior reviews are now resolved. The latest commit ( Remaining minor gap —
Test coverage added in
The pattern is exactly consistent with the Final Team Checklist
SummaryAll blockers and nits across three review cycles have been addressed:
The routing fixes are logically correct, the test suite is thorough across all new code paths, and the code follows Basic Memory conventions. Approve. |
Summary
Fixes mixed local+cloud MCP routing edge cases around workspace-qualified identifiers and project IDs:
project_idUUIDs locally when cloud credentials/workspaces are present but the UUID is not in the cloud workspace index.memory://workspace/project/pathand plain route detection in mixed local+cloud configs when the identifier shape is explicit.external_id, preventing same-name project cache reuse across tenants.edit_note/link resolver plain workspace-qualified detection to use the same identifier-aware workspace discovery gate.read_note,read_content,search_notes,edit_note, link resolution, stale workspace/project cache, and local/cloud UUID routing.AGENTS.mdso future changes include typecheck, DCO signoff, and semantic PR title checks before review.Fixes #834.
Fixes #836.
Tests
just typecheckuv run ruff check AGENTS.md tests/mcp/test_tool_read_note.py tests/mcp/test_tool_search.pyuv run pytest tests/mcp/test_tool_read_note.py tests/mcp/test_tool_search.py -quv run ruff check src/basic_memory/mcp/project_context.py src/basic_memory/mcp/tools/edit_note.py src/basic_memory/services/link_resolver.py tests/mcp/test_project_context.py tests/services/test_link_resolver.py tests/mcp/test_tool_edit_note.py tests/mcp/test_tool_read_note.py tests/mcp/test_tool_read_content.py tests/mcp/test_tool_search.pyuv run pytest tests/mcp/test_project_context.py tests/services/test_link_resolver.py tests/mcp/test_tool_edit_note.py tests/mcp/test_tool_read_note.py tests/mcp/test_tool_read_content.py tests/mcp/test_tool_search.py -quv run pytest tests/mcp/test_tool_recent_activity.py tests/mcp/tools/test_search_notes_multi_project.py -q