mcp-migration-advisor 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/index.js CHANGED
@@ -19,6 +19,21 @@ import { detectConflicts, formatConflictReport } from "./analyzers/conflicts.js"
19
19
  import { validateLicense, formatUpgradePrompt } from "./license.js";
20
20
  // License check (reads MCP_LICENSE_KEY env var once at startup)
21
21
  const license = validateLicense(process.env.MCP_LICENSE_KEY, "migration-advisor");
22
+ /**
23
+ * Format parser warnings into a markdown section.
24
+ * Returns empty string if there are no warnings.
25
+ */
26
+ function formatParserWarnings(migration) {
27
+ if (migration.warnings.length === 0)
28
+ return "";
29
+ let output = "### Parser Warnings\n\n";
30
+ output += `> ${migration.warnings.length} DDL statement(s) could not be fully parsed and were classified as OTHER\n\n`;
31
+ for (const w of migration.warnings) {
32
+ output += `- \`${w.snippet}\`\n`;
33
+ }
34
+ output += "\n";
35
+ return output;
36
+ }
22
37
  // Handle --help
23
38
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
24
39
  console.log(`mcp-migration-advisor v0.1.0 — MCP server for database migration risk analysis
@@ -94,6 +109,7 @@ server.tool("analyze_migration", "Analyze a SQL migration file for lock risks, d
94
109
  else {
95
110
  output += "### Data Loss Analysis\n\nNo data loss risks detected.\n\n";
96
111
  }
112
+ output += formatParserWarnings(migration);
97
113
  return {
98
114
  content: [{ type: "text", text: output }],
99
115
  };
@@ -134,6 +150,7 @@ server.tool("analyze_liquibase", "Analyze a Liquibase XML changelog for lock ris
134
150
  if (lockRisks.length === 0 && dataLossIssues.length === 0) {
135
151
  output += "### No risks detected.\n";
136
152
  }
153
+ output += formatParserWarnings(migration);
137
154
  return { content: [{ type: "text", text: output }] };
138
155
  });
139
156
  // Tool 3: analyze_liquibase_yaml
@@ -172,6 +189,7 @@ server.tool("analyze_liquibase_yaml", "Analyze a Liquibase YAML changelog for lo
172
189
  if (lockRisks.length === 0 && dataLossIssues.length === 0) {
173
190
  output += "### No risks detected.\n";
174
191
  }
192
+ output += formatParserWarnings(migration);
175
193
  return { content: [{ type: "text", text: output }] };
176
194
  });
177
195
  // Tool 4: score_risk
@@ -171,6 +171,30 @@ function classifyStatement(raw) {
171
171
  }
172
172
  return { type: "OTHER", raw, tableName: null, columnName: null, details };
173
173
  }
174
+ /**
175
+ * Build a snippet of up to ~80 characters from a raw statement for debugging.
176
+ */
177
+ export function truncateSnippet(raw, maxLen = 80) {
178
+ const oneLine = raw.replace(/\s+/g, " ").trim();
179
+ if (oneLine.length <= maxLen)
180
+ return oneLine;
181
+ return oneLine.substring(0, maxLen) + "...";
182
+ }
183
+ /**
184
+ * Collect warnings for statements classified as OTHER.
185
+ */
186
+ export function collectParserWarnings(statements) {
187
+ const warnings = [];
188
+ for (const stmt of statements) {
189
+ if (stmt.type === "OTHER") {
190
+ warnings.push({
191
+ message: "Unrecognized DDL statement classified as OTHER",
192
+ snippet: truncateSnippet(stmt.raw),
193
+ });
194
+ }
195
+ }
196
+ return warnings;
197
+ }
174
198
  /**
175
199
  * Parse a complete Flyway migration file.
176
200
  */
@@ -178,12 +202,14 @@ export function parseMigration(filename, sql) {
178
202
  const { version, description, isRepeatable } = parseFlywayFilename(filename);
179
203
  const rawStatements = splitStatements(sql);
180
204
  const statements = rawStatements.map(classifyStatement);
205
+ const warnings = collectParserWarnings(statements);
181
206
  return {
182
207
  version,
183
208
  description,
184
209
  filename,
185
210
  isRepeatable,
186
211
  statements,
212
+ warnings,
187
213
  };
188
214
  }
189
215
  //# sourceMappingURL=flyway-sql.js.map
@@ -4,6 +4,7 @@
4
4
  * Parses Liquibase XML changelogs and extracts DDL operations
5
5
  * compatible with the same DDLStatement interface used by Flyway.
6
6
  */
7
+ import { collectParserWarnings } from "./flyway-sql.js";
7
8
  /**
8
9
  * Parse a Liquibase XML changelog and extract DDL statements.
9
10
  *
@@ -23,6 +24,7 @@ export function parseLiquibaseXml(xml) {
23
24
  filename: "changelog.xml",
24
25
  isRepeatable: false,
25
26
  statements: allStatements,
27
+ warnings: collectParserWarnings(allStatements),
26
28
  };
27
29
  }
28
30
  function extractChangeSets(xml) {
@@ -4,6 +4,7 @@
4
4
  * Parses Liquibase YAML changelogs and extracts DDL operations
5
5
  * compatible with the same DDLStatement interface used by Flyway and XML.
6
6
  */
7
+ import { collectParserWarnings } from "./flyway-sql.js";
7
8
  /**
8
9
  * Parse a Liquibase YAML changelog and extract DDL statements.
9
10
  *
@@ -23,6 +24,7 @@ export function parseLiquibaseYaml(yaml) {
23
24
  filename: "changelog.yaml",
24
25
  isRepeatable: false,
25
26
  statements: allStatements,
27
+ warnings: collectParserWarnings(allStatements),
26
28
  };
27
29
  }
28
30
  function extractChangeSets(yaml) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-migration-advisor",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "MCP server for database migration risk analysis — Flyway and Liquibase XML/YAML/SQL support with lock detection and conflict analysis",
5
5
  "main": "build/index.js",
6
6
  "bin": {
@@ -20,17 +20,21 @@
20
20
  ],
21
21
  "keywords": [
22
22
  "mcp",
23
+ "mcp-server",
23
24
  "model-context-protocol",
24
- "database",
25
+ "ai",
26
+ "claude",
27
+ "anthropic",
25
28
  "migration",
29
+ "database-migration",
30
+ "schema-migration",
31
+ "database",
26
32
  "flyway",
27
33
  "liquibase",
28
34
  "schema",
29
35
  "risk-analysis",
30
36
  "postgresql",
31
- "mysql",
32
- "ai",
33
- "claude"
37
+ "mysql"
34
38
  ],
35
39
  "author": "Dmytro Lisnichenko",
36
40
  "license": "MIT",