Problem
apply_migration generates its own timestamp server-side via POST /v1/projects/{ref}/database/migrations. This timestamp never matches the local migration file's timestamp, creating orphan remote-only entries in supabase_migrations.schema_migrations.
This forces manual reconciliation after every call:
supabase migration repair --status applied <local_version> --linked
supabase migration repair --status reverted <mcp_generated_version> --linked
Without reconciliation, orphan entries accumulate silently and make the database non-reproducible from local migration files.
Real-world impact
We accumulated 37 orphan remote-only migrations before noticing. The only fix was a full squash: dump the entire schema, delete all migration files, and rebuild from scratch.
Proposed solution
Add an optional version parameter to apply_migration:
{
"name": "my_migration",
"query": "ALTER TABLE ...",
"version": "20260320140000"
}
When provided, this version should be used as the migration's timestamp in schema_migrations instead of a server-generated one. This allows the MCP-applied migration to match the local file exactly.
The underlying Management API (POST /v1/projects/{ref}/database/migrations) would also need to support this parameter — so this may require an upstream change to the Supabase API as well.
Workaround
Use supabase db push --linked instead of MCP apply_migration. It applies local migration files and registers them with the correct timestamp automatically, without requiring Docker.
Problem
apply_migrationgenerates its own timestamp server-side viaPOST /v1/projects/{ref}/database/migrations. This timestamp never matches the local migration file's timestamp, creating orphan remote-only entries insupabase_migrations.schema_migrations.This forces manual reconciliation after every call:
Without reconciliation, orphan entries accumulate silently and make the database non-reproducible from local migration files.
Real-world impact
We accumulated 37 orphan remote-only migrations before noticing. The only fix was a full squash: dump the entire schema, delete all migration files, and rebuild from scratch.
Proposed solution
Add an optional
versionparameter toapply_migration:{ "name": "my_migration", "query": "ALTER TABLE ...", "version": "20260320140000" }When provided, this version should be used as the migration's timestamp in
schema_migrationsinstead of a server-generated one. This allows the MCP-applied migration to match the local file exactly.The underlying Management API (
POST /v1/projects/{ref}/database/migrations) would also need to support this parameter — so this may require an upstream change to the Supabase API as well.Workaround
Use
supabase db push --linkedinstead of MCPapply_migration. It applies local migration files and registers them with the correct timestamp automatically, without requiring Docker.