From 2ea2159d80ccb26b4fcde194a6d6837ba15ebb33 Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 20 May 2026 13:02:00 +0900 Subject: [PATCH] fix(ast-grep-mcp): allow absolute paths whose realpath is inside the workspace Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus --- packages/ast-grep-mcp/src/workspace-paths.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/ast-grep-mcp/src/workspace-paths.ts b/packages/ast-grep-mcp/src/workspace-paths.ts index b3be6bc6e..1afb76887 100644 --- a/packages/ast-grep-mcp/src/workspace-paths.ts +++ b/packages/ast-grep-mcp/src/workspace-paths.ts @@ -15,7 +15,7 @@ function resolveWorkspacePath(rawPath: string, workspaceDirectory: string): stri if (rawPath.length === 0) throw new Error("paths entries must be non-empty strings"); if (rawPath.startsWith("-")) throw new Error(`paths entries must not start with '-': ${rawPath}`); if (rawPath.includes("\0")) throw new Error("paths entries must not contain null bytes"); - if (isAbsolute(rawPath)) throw new Error(`paths entries must be relative to the workspace: ${rawPath}`); + if (isAbsolute(rawPath)) return resolveAbsoluteWorkspacePath(rawPath, workspaceDirectory); const absolutePath = resolve(workspaceDirectory, rawPath); assertInsideWorkspace(absolutePath, workspaceDirectory, rawPath); @@ -29,6 +29,20 @@ function resolveWorkspacePath(rawPath: string, workspaceDirectory: string): stri return normalizedPath === "" ? "." : normalizedPath; } +function resolveAbsoluteWorkspacePath(rawPath: string, workspaceDirectory: string): string { + let realPath: string; + try { + realPath = realpathSync(rawPath); + } catch { + throw new Error(`absolute path entry does not exist: ${rawPath}`); + } + + assertInsideWorkspace(realPath, workspaceDirectory, rawPath); + + const normalizedPath = relative(workspaceDirectory, realPath); + return normalizedPath === "" ? "." : normalizedPath; +} + function assertInsideWorkspace(candidatePath: string, workspaceDirectory: string, rawPath: string): void { const workspaceRelativePath = relative(workspaceDirectory, candidatePath); if (workspaceRelativePath === "" || (!workspaceRelativePath.startsWith("..") && !isAbsolute(workspaceRelativePath))) return;