@yawlabs/postgres-mcp 0.3.1 → 0.3.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.
Files changed (2) hide show
  1. package/dist/index.js +38 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -35361,6 +35361,30 @@ async function runReadWrite(sql, params = []) {
35361
35361
  client.release();
35362
35362
  }
35363
35363
  }
35364
+ async function runReadWriteRollback(sql, params = []) {
35365
+ if (!isWritesAllowed()) {
35366
+ return {
35367
+ ok: false,
35368
+ error: "Write blocked: ALLOW_WRITES is not set. Set ALLOW_WRITES=1 in the MCP server env to enable DML/DDL."
35369
+ };
35370
+ }
35371
+ const client = await getPool().connect();
35372
+ const maxRows = getMaxRows();
35373
+ try {
35374
+ await client.query("BEGIN");
35375
+ const result = await client.query(sql, params);
35376
+ await client.query("ROLLBACK");
35377
+ return { ok: true, data: toQueryResult(result, maxRows) };
35378
+ } catch (err) {
35379
+ try {
35380
+ await client.query("ROLLBACK");
35381
+ } catch {
35382
+ }
35383
+ return { ok: false, error: formatPgError(err) };
35384
+ } finally {
35385
+ client.release();
35386
+ }
35387
+ }
35364
35388
  async function runInternal(sql, params = []) {
35365
35389
  try {
35366
35390
  const result = await getPool().query(sql, params);
@@ -35637,14 +35661,16 @@ var adminTools = [
35637
35661
  }
35638
35662
  ];
35639
35663
 
35640
- // src/tools/explain.ts
35664
+ // src/tools/params.ts
35641
35665
  var paramValue = external_exports3.lazy(
35642
35666
  () => external_exports3.union([external_exports3.string(), external_exports3.number(), external_exports3.boolean(), external_exports3.null(), external_exports3.array(paramValue), external_exports3.record(external_exports3.string(), paramValue)])
35643
35667
  );
35668
+
35669
+ // src/tools/explain.ts
35644
35670
  var explainTools = [
35645
35671
  {
35646
35672
  name: "pg_explain",
35647
- description: "Get the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution). Set `analyze: true` to run the query with EXPLAIN ANALYZE \u2014 for non-SELECT statements, ALLOW_WRITES=1 is required (since ANALYZE actually executes the statement). Format is `text` (default) or `json`. Pass the raw SQL (not an EXPLAIN-prefixed statement).",
35673
+ description: "Get the query plan for a SQL statement. By default, this uses plain EXPLAIN (no execution). Set `analyze: true` to run the query with EXPLAIN ANALYZE \u2014 for non-SELECT statements, ALLOW_WRITES=1 is required (since ANALYZE actually executes the statement). Writes executed during EXPLAIN ANALYZE are always rolled back, so you can inspect a plan for an INSERT/UPDATE/DELETE without persisting the mutation. Format is `text` (default) or `json`. Pass the raw SQL (not an EXPLAIN-prefixed statement).",
35648
35674
  annotations: {
35649
35675
  title: "Explain query plan",
35650
35676
  readOnlyHint: false,
@@ -35670,7 +35696,7 @@ var explainTools = [
35670
35696
  if (analyze) flags.push("ANALYZE");
35671
35697
  if (format === "json") flags.push("FORMAT JSON");
35672
35698
  const explainSql = flags.length > 0 ? `EXPLAIN (${flags.join(", ")}) ${sql}` : `EXPLAIN ${sql}`;
35673
- const result = analyze && isWritesAllowed() ? await runReadWrite(explainSql, params ?? []) : await runReadOnly(explainSql, params ?? []);
35699
+ const result = analyze && isWritesAllowed() ? await runReadWriteRollback(explainSql, params ?? []) : await runReadOnly(explainSql, params ?? []);
35674
35700
  if (!result.ok) return result;
35675
35701
  const data = result.data;
35676
35702
  const rows = data?.rows ?? [];
@@ -35740,7 +35766,8 @@ var healthTools = [
35740
35766
  JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
35741
35767
  WHERE c.relkind IN ('r', 'p')
35742
35768
  AND n.nspname NOT IN ('pg_catalog', 'information_schema')
35743
- AND n.nspname NOT LIKE 'pg_toast%'`
35769
+ AND n.nspname NOT LIKE 'pg_toast%'
35770
+ AND n.nspname NOT LIKE 'pg_temp_%'`
35744
35771
  )
35745
35772
  ]);
35746
35773
  if (!versionRes.ok) return versionRes;
@@ -35760,9 +35787,6 @@ var healthTools = [
35760
35787
  ];
35761
35788
 
35762
35789
  // src/tools/query.ts
35763
- var paramValue2 = external_exports3.lazy(
35764
- () => external_exports3.union([external_exports3.string(), external_exports3.number(), external_exports3.boolean(), external_exports3.null(), external_exports3.array(paramValue2), external_exports3.record(external_exports3.string(), paramValue2)])
35765
- );
35766
35790
  var queryTools = [
35767
35791
  {
35768
35792
  name: "pg_query",
@@ -35777,7 +35801,7 @@ var queryTools = [
35777
35801
  },
35778
35802
  inputSchema: external_exports3.object({
35779
35803
  sql: external_exports3.string().min(1).max(1e6).describe("The SQL statement to execute. Hard cap of 1 MB."),
35780
- params: external_exports3.array(paramValue2).optional().describe("Positional parameters referenced as $1, $2, ... in the SQL.")
35804
+ params: external_exports3.array(paramValue).optional().describe("Positional parameters referenced as $1, $2, ... in the SQL.")
35781
35805
  }),
35782
35806
  handler: async (input) => {
35783
35807
  const { sql, params } = input;
@@ -36192,9 +36216,8 @@ var statsTools = [
36192
36216
  n_live_tup::text AS live_tuples,
36193
36217
  seq_tup_read::text AS seq_tup_read,
36194
36218
  CASE
36195
- WHEN COALESCE(idx_scan, 0) = 0 AND seq_scan > 0 THEN NULL
36196
- WHEN COALESCE(idx_scan, 0) = 0 THEN 0
36197
- ELSE (seq_scan::numeric / NULLIF(idx_scan, 0))::numeric(10, 2)::float8
36219
+ WHEN COALESCE(idx_scan, 0) = 0 THEN NULL
36220
+ ELSE (seq_scan::numeric / idx_scan)::numeric(10, 2)::float8
36198
36221
  END AS ratio
36199
36222
  FROM pg_catalog.pg_stat_user_tables
36200
36223
  WHERE n_live_tup >= $1
@@ -36260,7 +36283,7 @@ function compareVersions(a, b) {
36260
36283
  }
36261
36284
 
36262
36285
  // src/index.ts
36263
- var version2 = true ? "0.3.1" : (await null).createRequire(import.meta.url)("../package.json").version;
36286
+ var version2 = true ? "0.3.2" : (await null).createRequire(import.meta.url)("../package.json").version;
36264
36287
  var subcommand = process.argv[2];
36265
36288
  if (subcommand === "version" || subcommand === "--version") {
36266
36289
  console.log(version2);
@@ -36322,4 +36345,7 @@ process.on("SIGINT", () => {
36322
36345
  process.on("SIGTERM", () => {
36323
36346
  void cleanup().finally(() => process.exit(0));
36324
36347
  });
36348
+ process.stdin.on("end", () => {
36349
+ void cleanup().finally(() => process.exit(0));
36350
+ });
36325
36351
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yawlabs/postgres-mcp",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "PostgreSQL MCP server — query, schema introspection, explain, and health checks for AI assistants",
5
5
  "license": "MIT",
6
6
  "author": "YawLabs <contact@yaw.sh>",