fix(mcp): resolve projects by external_id, remove workspace from MCP tools (#777)

Signed-off-by: phernandez <paul@basicmachines.co>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Paul Hernandez
2026-05-01 05:15:44 -05:00
committed by GitHub
parent 2fccc74a20
commit 0b335476d6
31 changed files with 688 additions and 447 deletions
+12 -4
View File
@@ -164,7 +164,7 @@ async def read_content(
Field(validation_alias=AliasChoices("path", "file_path", "filepath", "file")),
],
project: Optional[str] = None,
workspace: Optional[str] = None,
project_id: Optional[str] = None,
context: Context | None = None,
) -> dict:
"""Read a file's raw content by path or permalink.
@@ -185,6 +185,9 @@ async def read_content(
- A permalink (docs/example)
project: Project name to read from. Optional - server will resolve using hierarchy.
If unknown, use list_memory_projects() to discover available projects.
project_id: Project external_id (UUID). Prefer this over `project` when known —
it routes to the exact project regardless of name collisions across cloud
workspaces. Takes precedence over `project`. Get from list_memory_projects().
context: Optional FastMCP context for performance caching.
Returns:
@@ -222,9 +225,14 @@ async def read_content(
logger.info(f"MCP tool call tool=read_content project={project} path={path}")
async with get_project_client(project, workspace, context) as (client, active_project):
# Resolve path with project-prefix awareness for memory:// URLs
_, url, _ = await resolve_project_and_path(client, path, project, context)
async with get_project_client(project, context=context, project_id=project_id) as (
client,
active_project,
):
# Resolve path with project-prefix awareness for memory:// URLs.
# Use active_project.name so resolution stays consistent when project_id
# was used or `project` was wrong/ambiguous (matches the cached resolution).
_, url, _ = await resolve_project_and_path(client, path, active_project.name, context)
# Validate path to prevent path traversal attacks
# For memory:// URLs, validate the extracted path (not the raw URL which