MigrationPilot
This server is a MigrationPilot MCP server for analyzing, fixing, and understanding PostgreSQL migrations before they are applied, acting as a safety gate for DDL.
check_before_apply: Safety gate to run before writing or executing DDL; resolves project config and returns pass/fail with blocking violations.
analyze_migration: Analyzes a single migration SQL for violations, risk level, risk score, and lock analysis for a specified PostgreSQL version.
analyze_migration_dir: Analyzes a directory of migration files, returning per-file results and an aggregate summary.
suggest_fix: Auto-fixes safe/fixable violations and returns corrected SQL plus changes made.
explain_lock: Explains the PostgreSQL lock a DDL statement acquires and its impact.
get_rule: Returns full documentation for a specific rule, including what it reports, why it matters, auto-fix ability, and configuration; optionally runs it against SQL.
list_rules: Lists all 112 available safety rules with descriptions.
Provides tools for analyzing PostgreSQL migrations, including locking risk, rule violations, and safe alternatives.
MigrationPilot
Block unsafe Postgres migrations before merge.
Local, deterministic analysis for PostgreSQL migrations. Uses PostgreSQL's parser, checks 112 rules, and exits non-zero in CI. No account required. MIT.
npx migrationpilot analyze migration.sqlTry it in your browser · GitHub Action · Documentation
Benchmark
Tool | Strict detection | False positives |
MigrationPilot | 31/33 (93.9%) | 1/17 (5.9%) |
Squawk | 20/33 (60.6%) | 1/17 (5.9%) |
pgfence | 25/33 (75.8%) | 3/17 (17.6%) |
56 labelled files. Author-built corpus. Tools pinned.
Methodology · Corpus · What MigrationPilot missed · Reproduce: pnpm build && node bench/run.mjs
Related MCP server: pg-dash
A finding
-- migration.sql
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email);$ migrationpilot analyze migration.sql
✗ MigrationPilot — RED Score: 80/100
migration.sql
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
1 statement · 2 critical · rollback GREEN
┌─────┬─────────────────────────────────────────────┬─────────────────────────┬────────┬────────────┐
│ # │ Statement │ Lock Type │ Risk │ Long lock? │
├─────┼─────────────────────────────────────────────┼─────────────────────────┼────────┼────────────┤
│ 1 │ ALTER TABLE users ADD CONSTRAINT users_e... │ ACCESS EXCLUSIVE │ RED │ YES │
└─────┴─────────────────────────────────────────────┴─────────────────────────┴────────┴────────────┘
Violations:
✗ [MP004] CRITICAL (line 1)
DDL statement acquires ACCESS EXCLUSIVE lock without a preceding SET lock_timeout. Without a timeout, this statement could block the lock queue indefinitely if it can't acquire the lock, causing cascading query failures.
Safe alternative:
-- Set a timeout so DDL fails fast instead of blocking the queue
SET lock_timeout = '5s';
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE (email)
RESET lock_timeout;
Why: Without lock_timeout, if the table is locked by another query, your DDL waits indefinitely. All subsequent queries pile up behind it in the lock queue, causing cascading timeouts across your application. GoCardless enforces a 750ms lock_timeout for this reason.
Docs: https://migrationpilot.dev/rules/mp004
✗ [MP027] CRITICAL (line 1)
Adding UNIQUE constraint "users_email_unique" on "users" scans the entire table under ACCESS EXCLUSIVE lock. Create the index concurrently first, then use USING INDEX.
Safe alternative:
-- Step 1: Create the unique index concurrently (non-blocking)
CREATE UNIQUE INDEX CONCURRENTLY users_email_unique_idx ON users (...);
-- Step 2: Add the constraint using the pre-built index (instant)
ALTER TABLE users ADD CONSTRAINT users_email_unique UNIQUE USING INDEX users_email_unique_idx;
Why: ALTER TABLE ADD CONSTRAINT UNIQUE builds a unique index while holding ACCESS EXCLUSIVE lock, blocking all reads and writes for the entire scan. Instead, create the unique index concurrently (non-blocking), then attach it as a constraint with USING INDEX.
Docs: https://migrationpilot.dev/rules/mp027
Risk Factors:
Lock Severity ██████████ 40/40 — ACCESS EXCLUSIVE (long-held)
Rule Violations ████████░░ 80/100 — 2 critical
112 rules checked in 11msExit code is 2. The Risk column combines what a statement's lock does with what the rules found in it, so a statement carrying a critical violation reads RED whatever its lock costs. The lock half of that is capped without a database connection — table size and query frequency need one. See Production context.
Contents
Install · AI coding agents · CI · What it checks · Beyond one file · Configuration · Output · Production context · Comparison · Pricing · Architecture · API
Install
npx migrationpilot analyze migration.sql # no install
npm install -g migrationpilot # globalNode 22 or newer. The PostgreSQL parser ships compiled in, so there is nothing else to set up. Exit codes are the same everywhere: 0 clean, 1 warnings under --fail-on warning, 2 critical.
Packaged builds land with each release, including single-file executables for Linux, macOS and Windows on the release page for machines without Node. The Windows .exe is not code-signed, so SmartScreen and most browsers will warn about it on download — SHA256SUMS on the same release is how you check you got the file we published, not a signature.
brew install mickelsamuel/migrationpilot/migrationpilot
docker run --rm -v "$PWD:/work" ghcr.io/mickelsamuel/migrationpilot:1 analyze migration.sqlOn Windows in Git Bash, MSYS rewrites paths inside the mount flag, so use the Windows-form working directory instead:
docker run --rm -v "$(pwd -W):/work" ghcr.io/mickelsamuel/migrationpilot:1 analyze migration.sqlAI coding agents
Agents write migrations now. They are good at SQL and bad at knowing which statement takes an ACCESS EXCLUSIVE lock on a table with 40 million rows, and by then the outage has already happened.
MCP server. Seven tools, the important one being check_before_apply: a pass/fail gate the agent calls before it writes or runs DDL. It resolves your .migrationpilotrc.yml exactly like the CLI does, so its verdict is the verdict CI will give.
{
"mcpServers": {
"migrationpilot": { "command": "npx", "args": ["migrationpilot-mcp"] }
}
}Tool | Purpose |
|
|
| Violations, risk score and lock analysis for one migration |
| Per-file results plus an aggregate for a whole folder |
| What a rule reports, why it matters, whether it auto-fixes |
| Auto-fixed SQL plus the violations that need a human |
| The lock one DDL statement takes and what it blocks |
| The full catalogue |
Claude Code plugin. integrations/claude-code/ pairs a skill that tells Claude to check migrations with a PreToolUse hook that blocks the tool call when it doesn't. It fails open on purpose: a missing install, unparseable SQL, or a timeout lets the call through with a note on stderr, because a guardrail that breaks your workflow when it can't run gets uninstalled.
claude plugin install ./integrations/claude-codeCursor and Copilot. Copy integrations/cursor/migrationpilot.mdc into .cursor/rules/, or paste integrations/copilot/copilot-instructions-snippet.md into .github/copilot-instructions.md. Both tell the agent when to run MigrationPilot and that suppressing a rule to get past a violation is the user's call, not the agent's.
CI
GitHub Action
# .github/workflows/migration-check.yml
name: Migration Safety Check
on: [pull_request]
# New repositories default the workflow token to read-only; the report comment
# needs pull-request write.
permissions:
contents: read
pull-requests: write
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: mickelsamuel/migrationpilot@v1
with:
migration-path: "migrations/*.sql"
fail-on: criticalPosts a report as a PR comment, fails the check on critical violations, and writes a SARIF file. To feed it into Code Scanning, add an upload step (needs Advanced Security on private repos):
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: migrationpilot-results.sarifWithout the permissions block the Action still runs. It warns, analyzes every file matching the glob instead of only the ones the PR changed, and skips the comment. The check verdict, the SARIF file and the inline annotations come from the analysis either way.
Input | Description | Default |
| Glob for SQL files (required) | |
| Token for PR comments |
|
| Target PostgreSQL version |
|
|
|
|
| Comma-separated rule IDs to skip | |
| Path to | auto-detected |
| Connection for production context | |
| Org plan license key |
Outputs: risk-level, violations, sarif-file.
Pre-commit
migrationpilot hook install writes a plain git hook and is Husky-aware. With the pre-commit framework instead:
repos:
- repo: https://github.com/mickelsamuel/migrationpilot
rev: v1.6.0
hooks:
- id: migrationpilot
args: [--fail-on, warning]Clean files print nothing. Only migrations with violations are reported.
If pre-commit install answers Cowardly refusing to install hooks with 'core.hooksPath' set, something else already owns your hooks directory — Husky sets it. Check with git config core.hooksPath, then either git config --unset-all core.hooksPath and let pre-commit manage the hooks, or keep Husky and run migrationpilot hook install, which appends to .husky/pre-commit instead of fighting it.
GitLab CI
include:
- remote: 'https://raw.githubusercontent.com/mickelsamuel/migrationpilot/v1.6.0/integrations/gitlab/.gitlab-ci-migrationpilot.yml'
migrationpilot:
variables:
MIGRATIONPILOT_PATH: db/migrateRuns on merge requests that touch migrations, keeps the JSON report as an artifact, and annotates the MR diff through GitLab Code Quality.
What it checks
112 rules: 34 critical, 78 warning, 20 auto-fixable with --fix. Ten that matter most:
Rule | Fix | What it catches |
MP001 | Yes |
|
MP002 |
| |
MP003 |
| |
MP007 |
| |
MP008 | Several DDL statements in one transaction compound the lock duration | |
MP025 | Yes |
|
MP027 |
| |
MP055 | Dropping a primary key breaks logical replication | |
MP070 | A failed concurrent build leaves an invalid index the retry silently inherits | |
MP097 | Dropping the index behind a constraint is rejected and aborts the migration |
Browse all 112 rules, or run migrationpilot explain MP027 for one. The handbook is 20 chapters on why each hazard bites and what to do instead.
Rules adapt to --pg-version (9 through 18): REINDEX CONCURRENTLY from 12, DETACH PARTITION CONCURRENTLY from 14, the native NOT NULL ... NOT VALID path from 18.
Beyond one file
analyze --fix rewrites the 20 fixable violations in place. The rest of the surface:
Command | What it does |
| Whole directory, plus cross-file sequence analysis |
Runs the migration against an ephemeral in-process PostgreSQL 18 (PGlite) and reports what actually happened | |
Step-by-step expand-contract plan for violations with no one-line fix, with deploy boundaries | |
Mutates passing migrations into dangerous near-neighbours to find holes in your config | |
| Duration estimate for an operation, calibrated by |
| Generates expand-contract SQL for renames, type changes, |
| Visual execution timeline: lock, duration, blocking impact, transaction boundaries |
| Reverse DDL, graded by how recoverable it is |
| Diffs two live schemas |
| Multi-file entry point the pre-commit framework calls |
Twenty-four commands in total. migrationpilot --help lists them.
Sequence analysis is what a per-file linter cannot see. Three migrations that each look fine can still take one table down together:
$ migrationpilot check migrations/
⚠ [SQ001] WARNING cumulative-lock-budget
"orders" is locked for an estimated 2m across 2 statements in 2 files — over the 1m budget for one deploy.
⚠ [SQ002] WARNING hot-table-multi-touch
"orders" is locked by 3 files in this sequence. Each one queues behind live traffic on its own — fold them into one migration so the table takes the hit once.Tune it with --lock-budget <seconds> and --hot-table-threshold <files>, turn it off with --no-sequence, and make it blocking with --fail-on-sequence.
--fail-on irreversible is stricter than critical: it also blocks migrations that destroy data with no down file.
Configuration
Zero-config is the default. check with no directory detects your framework, finds its migrations, and analyzes them in apply order. Fourteen are supported: Flyway, Liquibase, Alembic, Django, Knex, Prisma, TypeORM, Drizzle, Sequelize, goose, dbmate, Sqitch, Rails, Ecto. Force one with --framework prisma, or pipe any generator through --from-command:
migrationpilot check --from-command "python manage.py sqlmigrate myapp 0042"# .migrationpilotrc.yml
extends: "migrationpilot:strict"
pgVersion: 16
failOn: warning
rules:
MP037: false # off
MP004: { severity: warning } # downgrade
MP013: { threshold: 5000 } # retune
ignore:
- "migrations/seed_*.sql"Five presets: recommended (default), strict, ci, startup, enterprise. Inline, -- migrationpilot-disable MP001 suppresses a rule for the next statement and -- migrationpilot-disable-file MP001 does it for the whole file. Name no rule and it suppresses all of them.
Ed25519 license keys validate client-side. --offline skips update checks and every other network call. There is no telemetry.
Output
--format text (default), json, sarif, or markdown, plus --quiet for one gcc-style line per violation and --verbose for per-statement pass/fail.
{
"$schema": "https://migrationpilot.dev/schemas/report-v1.json",
"version": "1.6.0",
"file": "migrations/001.sql",
"riskLevel": "RED",
"riskScore": 80,
"violations": []
}SARIF feeds GitHub Code Scanning, VS Code and IntelliJ: migrationpilot analyze migration.sql --format sarif --output results.sarif.
Production context
Pass --database-url and MigrationPilot opens one read-only connection to read pg_class, pg_stat_statements and pg_stat_activity. It reads no user data and runs no DDL.
That turns risk scoring from a guess into a measurement, and gives three rules the numbers they have nothing to say without: MP013 (DDL on a high-traffic table), MP014 (long-held locks on a table with millions of rows), MP019 (ACCESS EXCLUSIVE while connections are piling up).
Factor | Weight | Needs |
Lock severity | 0-40 | No |
Table size | 0-30 | Yes |
Query frequency | 0-30 | Yes |
GREEN is 0-24, YELLOW 25-49, RED 50-100.
Comparison
MigrationPilot | Squawk | Atlas | |
Rules, all free | 112 | 40 | 50+ analyzers, lock analyzers Pro-only |
Auto-fix | 20 rules | 0 | 0 |
Cross-file sequence analysis | Yes | No | No |
Real execution against ephemeral PG | Yes | No | Yes, needs Docker |
MCP server for agents | Yes | No | No |
Framework detection | 14 | 0 | 0 |
Config presets | 5 | 0 | 0 |
SARIF for Code Scanning | Yes | No | No |
License | MIT | Apache-2.0 / MIT | Apache-2.0 core, no free lint |
Squawk: 40 rules as of v2.62.0 (Aug 2026). Atlas gates migrate lint behind a Pro login in the official binary since v0.38 (Oct 2025); the Community build keeps a basic analyzer set, but the PostgreSQL lock analyzers are Pro-only. It could not be benchmarked without a paid account. The methodology records the exact command and its refusal.
Pricing
Everything the linter does is free and unmetered: all 112 rules including the production-context ones, auto-fix, sequence analysis, simulate, every output format, the GitHub Action, the MCP server. No account, no seat count, no telemetry, MIT.
The $499/year Org plan turns the free linter into an enforceable control: one policy across repositories that developers cannot quietly disable, a JSONL audit trail of every check, and direct support from the maintainer.
Architecture
src/
├── parser/ locks/ # libpg-query WASM, lock classification
├── rules/ fixer/ # 112 rules and the 20-rule auto-fixer
├── analysis/ scoring/ # shared pipeline, transaction boundaries, risk 0-100
├── sequence/ lockqueue/ # cross-file SQ rules, lock queue modelling
├── simulate/ mutate/ # PGlite execution, mutation-testing operators
├── cascade/ graph/ schema/ prediction/ templates/
├── production/ frameworks/ plugins/ output/ generator/
├── mcp/ action/ config/ hooks/ watch/ drift/ history/
├── policy/ auth/ license/ team/ audit/ billing/ usage/ doctor/
├── index.ts # programmatic API, 69 value exports plus types
└── cli.ts # 24 commandsProgrammatic API
import { analyzeSQL, allRules, parseMigration, classifyLock } from 'migrationpilot';
const result = await analyzeSQL(sql, 'migration.sql', 17, allRules);
console.log(result.violations, result.overallRisk);Sixty-nine value exports plus full TypeScript types. allRules is the same rule set the CLI runs.
Development
pnpm install
pnpm test # 1945 tests across 72 files
pnpm build # CLI 1.4MB, Action 1.7MB, API 639KB, MCP 1.7MB
pnpm lint && pnpm typecheck
pnpm dev analyze path/to/migration.sqlCONTRIBUTING.md · SECURITY.md · CHANGELOG.md
License
MIT
Available Tools
7 toolsanalyze_migrationA
Analyze a PostgreSQL migration SQL for safety issues. Returns violations, risk level, and lock analysis.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | The SQL migration to analyze | |
| pg_version | No | Target PostgreSQL version (default: 17) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the transparency burden. It discloses that the tool performs analysis and returns violations, risk level, and lock analysis, which is useful. However, it does not explicitly state whether it is read-only, requires a database connection, or executes the SQL, leaving some behavioral ambiguity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the purpose and mentions key return values. Every word earns its place, with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two parameters, full schema coverage, and no output schema, the description adequately covers purpose and high-level outputs. It lacks detailed guidance on the structure of violations or risk level, but this is not critical for selection and invocation given the schema coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and both parameters (sql and pg_version) have meaningful descriptions in the schema. The tool description adds no additional parameter semantics beyond what the schema provides, which aligns with the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool analyzes a PostgreSQL migration SQL for safety issues and specifies its outputs (violations, risk level, lock analysis). It is specific enough to distinguish from siblings like analyze_migration_dir, though it does not explicitly name alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when you have a single migration SQL to analyze, but provides no explicit guidance on when to use this tool versus sibling tools like check_before_apply or suggest_fix. No when-not or alternative mentions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
analyze_migration_dirA
Analyze every migration file in a directory. Returns per-file results plus an aggregate summary. Use this to audit a whole migrations folder before a release, or to find which existing migration introduced a risky pattern.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the migrations directory | |
| pattern | No | Glob pattern for SQL files, relative to path (default: **/*.sql, or the config's migrationPath) | |
| pgVersion | No | Target PostgreSQL version. Defaults to the config's pgVersion, or 17. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosure. It mentions the output structure (per-file results plus aggregate summary) and implies a read-only analysis, but it does not explicitly state that files are not modified, nor does it mention any requirements or side effects. This is useful context but leaves gaps about safety and exact behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action, and includes return format and usage guidance without any fluff. Every word adds value, making it highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 parameters, no output schema, and no annotations, the description covers the main purpose, output shape, and suggested use cases. It stops short of explaining what 'analyze' means in terms of rules or checks, but the sibling tools like 'list_rules' and 'get_rule' imply a rule system. Overall, it is fairly complete for making an informed selection.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 100%, so the input schema already documents all three parameters (path, pattern, pgVersion) with clear descriptions. The tool description adds no additional parameter-level meaning, so a baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Analyze every migration file in a directory' with a specific verb and resource scope, distinguishing it from the sibling 'analyze_migration' by emphasizing directory-wide analysis. It also notes the return format (per-file results plus aggregate summary), making the purpose unmistakable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit usage context: 'Use this to audit a whole migrations folder before a release, or to find which existing migration introduced a risky pattern.' This clearly indicates when to choose this tool over alternatives, though it does not explicitly name the single-file sibling or give exclusion criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_before_applyA
Safety gate: call this BEFORE writing or executing any PostgreSQL DDL or migration. Resolves the project's own MigrationPilot config (rule toggles, severity overrides, failOn threshold) exactly like the CLI, then returns a pass/fail verdict. On "fail", do not apply the migration — fix the blocking violations and check again.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | The exact SQL that is about to be written or executed | |
| pgVersion | No | Target PostgreSQL version. Defaults to the config's pgVersion, or 17. | |
| configPath | No | Path to a config file, or a directory to resolve config from. Defaults to searching upward from the working directory, exactly like the CLI. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden. It discloses that the tool is non-mutating (it is a 'check' that returns a verdict), explains config resolution ('exactly like the CLI'), and instructs the agent on failure behavior. It doesn't explicitly state it makes no writes to the database, but the safety-gate framing and 'returns a verdict' imply it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three compact sentences, front-loaded with 'Safety gate.' Each sentence provides necessary context: when to call, what it does, and how to handle the verdict. No redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 params and no output schema, the description covers the critical points: use case, behavior, and outcome ('pass/fail verdict'). It could describe the verdict structure or error cases, but for a safety gate the essential info is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description adds only minor reinforcement (e.g., 'exactly like the CLI' for configPath, 'exact SQL' for sql) but no substantive meaning beyond the schema's own descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as a 'Safety gate' with the specific verb 'call this BEFORE writing or executing any PostgreSQL DDL or migration.' It states the function (resolves config, returns verdict) and differentiates from siblings like analyze_migration or suggest_fix because it is explicitly a gate that blocks application.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly states when to use ('BEFORE writing or executing any PostgreSQL DDL or migration') and provides the rule for fail ('do not apply the migration'). However, it doesn't explicitly state when NOT to use it (e.g., for read-only queries), leaving the exclusion to interpretation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
explain_lockA
Explain what PostgreSQL lock a DDL statement acquires and its impact.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | A single DDL statement to analyze | |
| pg_version | No | Target PostgreSQL version (default: 17) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It only states the tool 'explains' lock acquisition, without disclosing whether the DDL is executed, if a database connection is needed, or if there are any side effects. This is a significant gap for a tool that could potentially run DDL.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence of 13 words, front-loading the action and the resource. It contains no filler or redundant wording.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema or annotations, the description provides only the core function. It does not explain what the explanation looks like, how pg_version changes behavior, or what 'impact' refers to. Adequate but with clear room for additional context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides full descriptions for both parameters (sql and pg_version) with 100% coverage. The tool description adds no additional parameter detail beyond its core purpose, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Explain') and a clear resource ('PostgreSQL lock a DDL statement acquires'), distinguishing it from sibling tools that focus on migration analysis or fixes. It unambiguously states the tool's function.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for analyzing lock behavior of DDL statements, but provides no explicit context or alternatives. It does not mention when to use this tool versus sibling tools like analyze_migration or check_before_apply.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_ruleA
Get the full documentation for one MigrationPilot rule: what it reports, why it matters, whether it can be auto-fixed, and how to configure it. Call this when a violation ID appears and you need the reasoning behind it before rewriting a migration.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | No | Optional SQL to run this one rule against. When the rule fires, the response carries the exact violation message and the concrete safe alternative for that statement. | |
| ruleId | Yes | Rule ID, e.g. MP001 (case-insensitive) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It reveals that the tool returns documentation details (what it reports, why it matters, auto-fix capability, configuration) and implies it is a read-only lookup operation. It does not state potential side effects or permissions, but for a documentation retrieval tool, the behavior is clear and appropriately disclosed. The addition of specific return content adds value beyond the name.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, each earning its place. The first sentence defines the tool's output comprehensively, and the second sentence gives the exact usage trigger. There is no redundancy or fluff, making it highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with only two parameters and no output schema, the description is complete. It explains what the tool does, what content it returns, when to use it, and how it relates to the migration workflow. The lack of an output schema is mitigated by the description's clear enumeration of return contents. Sibling tools are implicitly distinguished, and no critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both parameters ('ruleId' and 'sql') well-documented in the schema. The description does not add parameter-specific information, but it also does not need to because the schema already provides clear examples and semantics. The baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with a specific verb ('Get') and resource ('full documentation for one MigrationPilot rule'), and enumerates exactly what the documentation includes. It also distinguishes the tool from siblings by emphasizing 'one rule' and the use case of needing reasoning before rewriting, which is unique among the listed sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use the tool: 'Call this when a violation ID appears and you need the reasoning behind it before rewriting a migration.' This provides a clear trigger, but it does not explicitly name alternative tools or contrast with them. Since it gives a direct use case without exclusions, it earns a 4 rather than a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_rulesA
List all available MigrationPilot safety rules with descriptions.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden. 'List' implies a read-only operation, and the phrase 'with descriptions' indicates return content. However, it does not disclose potential auth requirements, pagination, or ordering behavior. For a simple listing tool this is minimally adequate but lacks richer behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence, front-loaded with the action verb 'List', and every word earns its place. It is succinct and clearly structured, with no redundant or vague language.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only listing tool, the description covers the core purpose and return essence. It could optionally mention how the output relates to get_rule or describe the expected response structure, but given the low complexity, it is nearly complete. The absence of an output schema is partially mitigated by the note about descriptions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema has zero parameters, so the baseline is 4 per the rubric. The description adds no parameter-specific info, but none is needed since the tool takes no inputs. Schema coverage is effectively 100% with no properties, so there is no gap to compensate for.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses the specific verb 'List' with a clear resource: 'all available MigrationPilot safety rules with descriptions.' This distinguishes it from sibling tools like get_rule, which presumably fetches a single rule, and from analysis or fix tools. It unambiguously states the scope and output content.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for enumerating all safety rules, but it does not explicitly state when to prefer this over alternatives. The sibling get_rule suggests a complementary use case (retrieving a specific rule), but no explicit when-to-use or alternatives are mentioned, leaving the guidance implicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
suggest_fixA
Auto-fix safe violations in a PostgreSQL migration SQL. Returns the fixed SQL and list of changes.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | The SQL migration to fix | |
| pg_version | No | Target PostgreSQL version (default: 17) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It does add useful context by stating that it returns fixed SQL and a list of changes, but 'safe violations' is vaguely defined, and there is no disclosure of side effects, permissions, or whether changes are applied directly. This is adequate but not rich.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that is front-loaded with the action and scope, and it includes the return value. Every word earns its place, with no fluff or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, so the description must explain the return value; it does say it returns fixed SQL and a list of changes, but without detailing the structure of the changes list. It also doesn't clarify the definition of 'safe violations' or how this tool relates to check_before_apply, which could be important given the sibling tools. Overall, it is functional but leaves several gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% for both parameters (sql and pg_version), so the baseline is 3. The description adds no additional parameter-specific semantics beyond what the schema already provides, and no extra context about how the parameters affect the fix behavior.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Auto-fix' with a clear resource ('PostgreSQL migration SQL') and scope ('safe violations'). It also states what it returns (fixed SQL and list of changes), making it clearly distinguishable from siblings like analyze_migration and check_before_apply.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use this tool (when there are safe violations to fix) but does not explicitly mention alternatives or exclusions. No context about when to choose suggest_fix over check_before_apply or analyze_migration is provided, so the usage guidance is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct operation: single-file analysis, directory analysis, fix suggestion, lock explanation, rule listing, rule documentation, and pre-apply gate. There is no meaningful overlap between tool purposes.
All tool names follow a clear verb_noun snake_case pattern (analyze_migration, suggest_fix, explain_lock, list_rules, check_before_apply, analyze_migration_dir, get_rule). The naming is consistent and predictable.
With 7 tools, the server is well-scoped for its purpose. Each tool earns its place, covering analysis, fixing, explanation, rule management, and pre-apply checks without unnecessary bloat.
The tool surface covers the full migration safety workflow: analyzing individual migrations, auditing directories, understanding rules, getting rule details, auto-fixing issues, explaining locks, and gatekeeping before apply. No critical gaps are evident.
Maintenance
Related MCP Connectors
Deterministic safety, correctness & cost gate that vets Postgres SQL before your AI agent runs it.
Query PostgreSQL databases in plain English — LLM-generated, safety-validated SQL.
API governance for AI agents. Detects breaking changes, scores blast radius, blocks unsafe calls.
AI agents need permission before production SQL writes. Pilot $100 · Gateway $299. Lint≠authorize.
Related MCP Servers
- AlicenseAqualityDmaintenanceAnalyzes database migrations for risks like lock contention and data loss before they run. Supports Flyway and Liquibase formats, providing risk scores and rollback generation.618MIT
- AlicenseNot gradedqualityCmaintenanceAI-native PostgreSQL health checker with 26 MCP tools for query analysis, bloat detection, migration safety, and CI integration.161MIT

terrabaseofficial
AlicenseNot gradedqualityDmaintenanceLLM-assisted, safety-gated Postgres migrations exposed as an MCP server, using a deterministic rule engine over Postgres's own parser AST for safety enforcement, with two-phase approval and append-only audit ledger.Apache 2.0- AlicenseAqualityAmaintenanceGoverned PostgreSQL DBA operations — slow-query, bloat, and blocking-lock RCA, index management, vacuum/analyze, and replication lag, with unbypassable audit logging (MCP + CLI), budget/runaway guards, dry-run, and undo/rollback.35MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mickelsamuel/migrationpilot'
If you have feedback or need assistance with the MCP directory API, please join our Discord server