normalizeFilename uses platform-dependent path.resolve, so Edge Function file names are wrong on Windows (5 tests fail on main)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 91/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- node.js, typescript
- Domain
- backend, testing-qa
Research direction
Start in packages/mcp-server-supabase/src/edge-function.ts and inspect normalizeFilename and its path import. Run the unit tests in src/edge-function.test.ts and src/server.test.ts, ideally on Windows or with the reported setup. Done means all 215 tests pass and edge-function tool output uses filenames such as index.ts rather than absolute Windows paths.
Written by the indexing model from the issue text.
Description
- I confirm this is a bug with Supabase, not with my own application.
- I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
normalizeFilename in packages/mcp-server-supabase/src/edge-function.ts imports resolve from node:path, which is platform-dispatched, but strips a hardcoded POSIX prefix. On Windows resolve returns a backslash-separated path, so neither prefix strip can ever match and the full absolute path is returned instead of the file name.
For a developer running the MCP server locally on Windows, get_edge_function and list_edge_functions report entrypoint_path and files[].name as C:\tmp\user_fn_<deployment>\index.ts rather than index.ts.
This is confined to locally-run servers - the hosted server runs on Linux, where resolve is already POSIX, so hosted users are unaffected. It is also invisible to CI, which is Linux-only.
To Reproduce
Clone main on Windows and run the unit suite. No changes needed:
git clone https://github.com/supabase/mcp.git
cd mcp
pnpm install
pnpm run build
cd packages/mcp-server-supabase
set CI=true && pnpm vitest run --project unit
5 tests across 2 files fail on untouched main (30baa1f):
FAIL src/edge-function.test.ts > normalizeFilename > handles deno 1 paths
Expected: "index.ts"
Received: "C:\tmp\user_fn_xnzcmvwhvqonuunmwgdz_2b72daae-...-46f2df0463d1_2\source\index.ts"
FAIL src/edge-function.test.ts > normalizeFilename > handles deno 2 paths
FAIL src/edge-function.test.ts > normalizeFilename > doesn't interfere with nested directories
Expected: "/my/local/source/index.ts"
Received: "C:\my\local\source\index.ts"
FAIL src/server.test.ts > tools > list edge functions
FAIL src/server.test.ts > tools > get edge function
- "entrypoint_path": "index.ts",
+ "entrypoint_path": "C:\\tmp\\user_fn_wnibtrpkkvmuyxpollho_74bb898d-...-4f777d13e75a_1\\index.ts",
- "name": "index.ts",
+ "name": "C:\\tmp\\user_fn_fdkdaergfyvyekhgnrct_3a12780f-...-a6e57ae4a7f1_1\\index.ts",
Test Files 2 failed | 12 passed (14)
Tests 5 failed | 210 passed (215)
The last two are the tool output itself, so this is not only a test-harness artifact - it is what an MCP client on Windows actually receives.
Root cause
packages/mcp-server-supabase/src/edge-function.ts:
import { resolve } from 'node:path'; // platform-dispatched
export function getPathPrefix(deploymentId: string) {
return `/tmp/user_fn_${deploymentId}/`; // always POSIX
}
const filenameAbsolute = resolve(pathPrefix, filename);
let filenameWithoutPrefix = filenameAbsolute;
filenameWithoutPrefix = withoutPrefix(filenameWithoutPrefix, pathPrefix);
filenameWithoutPrefix = withoutPrefix(filenameWithoutPrefix, 'source/');
pathPrefix is always POSIX - it describes a path inside the Deno sandbox on the server, not on the developer's machine - but resolve follows the host OS. On Windows it returns C:\tmp\user_fn_...\source\index.ts, so startsWith(pathPrefix) is false for both /tmp/user_fn_.../ and source/, both strips are no-ops, and the whole absolute path falls through.
The intent is unambiguous elsewhere in the codebase: every caller in platform/api-platform.ts already forces POSIX semantics with fileURLToPath(..., { windows: false }) before calling in. That one platform-dependent import undoes it.
Expected behavior
normalizeFilename should return index.ts, and leave genuinely nested paths alone, regardless of host OS.
Suggested fix
One line - import the POSIX variant, since every path this function touches is POSIX by construction:
-import { resolve } from 'node:path';
+import { resolve } from 'node:path/posix';
Verified on Windows against main at 30baa1f:
| result | |
|---|---|
untouched main |
5 failed | 210 passed (215) |
| same tree, one-line change | 215 passed (215) |
All five failures clear, including the two in server.test.ts, and nothing else changes.
System information
- OS: Windows 11 (10.0.26200)
- Node.js 22 LTS, pnpm 10.34.5
supabase/mcpatmain, commit30baa1f
Additional context
This looks like a regression of a bug that was already fixed once. 8e9a447 ("fix: edge function path parsing on windows", May 2025) added { windows: false } to the fileURLToPath calls in api-platform.ts - those are still there, and are what I'm referring to above when I say the callers already force POSIX. normalizeFilename was added later in #138 ("consistent edge function filenames for deno 1 & 2", Sept 2025) and reintroduced the same class of bug at a new call site downstream of them.
That's really an argument for a regression test rather than just the one-line change: the current tests only pass POSIX strings, so they succeed on Linux whichever import is used, and nothing in a Linux-only CI can catch this class of bug before it lands a third time.
Happy to open a PR with the one-line change plus a platform-independent test if that's useful.
- Dominant language
- TypeScript
- Stars
- 2.9k
- Forks
- 406
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 24
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from supabase/mcp
-
Difficulty 4/5 3-5 days Newbie friendliness 55/100
-
Difficulty 1/5 Under an hour Newbie friendliness 30/100
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 45/100
-
Difficulty 4/5 3-5 days Newbie friendliness 48/100
-
bug
Difficulty 4/5 3-5 days Newbie friendliness 55/100
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100