Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Releases: ginkida/dbecho

v0.5.0

11 Jun 08:45
@ginkida ginkida

Choose a tag to compare

What's new in 0.5.0

Features

  • trend JSON output — the trend tool gains a format="table"|"json" parameter, mirroring query.
  • dbecho --version — print the installed version.
  • dbecho --check — validate the config and ping every configured database, printing an [OK]/[FAIL] <name> line per database and exiting non-zero if any is unreachable. Drops straight into a CI or healthcheck script.
  • find tool (first published release) — locate tables and columns by name substring across all configured databases at once.

Hardening

  • publish.yml now fails the publish if the release tag and pyproject version disagree (PyPI versions are immutable, so a mismatch would burn the number permanently).

Full test suite: 224 tests, all passing. No Postgres required (mocked connections).

Assets 2
Loading

v0.3.0 — Per-database schema support

05 Jun 12:43
@ginkida ginkida

Choose a tag to compare

Apps that keep tables outside public (a dedicated analytics schema, multi-tenant layouts, ...) are now first-class citizens.

✨ New: per-database schema config option

[databases.events]
url = "${EVENTS_DATABASE_URL}"
schema = "analytics"
  • All metadata tools target the configured schemaschema, describe, analyze, anomalies, trend, sample, erd, indexes, and foreign keys now parametrize the schema instead of hardcoding public (default remains public; existing configs are unaffected).
  • Raw queries work unqualified — for non-public schemas the connection sets search_path=<schema>,public, so SELECT count(*) FROM events just works; public stays second so extensions (pgvector operators etc.) keep resolving.
  • Clearer errors — "table not found" and empty-schema messages now name the schema they looked in.

🔒 Safety

  • The schema name is validated at config load as a plain lowercase identifier (^[a-z_][a-z0-9_]*\Z) — it is the one identifier-shaped value embedded outside psycopg.sql.Identifier() (in the libpq search_path option), so it is held to a stricter shape than table/column identifiers. Lowercase-only because unquoted search_path case-folds: an uppercase schema would silently diverge from the case-preserving parametrized metadata queries. \Z anchor keeps a trailing newline out of the options string.
  • All schema-scoped catalog queries use %s parameters — never string interpolation.

✅ Tests

  • Test suite expanded 179 → 199: config validation (uppercase/trailing-newline/non-string rejection), per-tool schema scoping, anti-mutant "no hardcoded public" asserts, search_path option assembly.

Backward-compatible: without schema in the config nothing changes.

Install: pip install dbecho

Loading

v0.2.0 — Security hardening + new tools

04 Jun 14:19
@ginkida ginkida

Choose a tag to compare

A security-hardening and capability release. No live exploit existed in 0.1.x, but the SQL whitelist relied entirely on the read-only connection; this release makes the validator independently sufficient, closes information-leak channels, fixes two correctness crashers, and adds two new tools.

🔒 Security (defense-in-depth)

  • Validator no longer depends on the read-only GUC alone — rejects data-modifying CTEs (WITH x AS (DELETE ... RETURNING *) ...), SELECT ... INTO, and EXPLAIN ANALYZE over write statements.
  • Blocked dangerous function callspg_read_file, lo_*, dblink, set_config (exfiltration/escape vectors even under read-only).
  • Sensitive-column redaction (default on) — values of password/token/api_key/secret-like columns are replaced with <redacted> in query/sample/analyze. Metadata columns (token_count, password_changed_at, otp_enabled) are not affected. Disable with redact_sensitive = false.
  • Sanitized connection errors — host/user/dbname no longer leak to the agent; full detail goes to the server log only.
  • Resource boundsmax_profile_rows gate for analyze/anomalies, schema/FK/index caps, compare dedup + cap (with a visible note), config upper bounds, session statement_timeout + idle_in_transaction backstops.
  • Identifier regex uses \Z (trailing-newline safe); 1ドル is treated as a positional parameter, not a dollar-quote tag.

🐛 Correctness

  • Fixed numeric(20,2) overflow on large SUM/AVG in analyze/trend.
  • Per-column probes run inside savepoints — a failed probe is skipped (reported via skipped_columns) instead of aborting the whole profile; timeouts still propagate.
  • trend validates column types up front (clear errors instead of opaque failures).
  • Row counts are labeled as planner estimates (~N rows est.).

✨ New capabilities

  • describe — single-table schema + indexes (much cheaper than schema on large databases).
  • explain — query plan cost/row estimates without executing the query.
  • query gains offset paging and format="json".
  • Cells render NULL/bytes/JSON safely; display truncation is marked with an ellipsis.

🧰 Robustness / ops

  • main() validates config eagerly at startup and forces logging to stderr (stdout is the MCP channel).
  • ${ VAR } placeholders tolerate inner whitespace.

✅ Tests / CI

  • Test suite expanded 89 → 179 (read-only option, redaction, savepoint isolation, timeout budget, identifier-injection boundaries, new tools, full server tool layer).
  • CI pins ruff via dev extras and adds a build + wheel-import job.

Tools: 11 → 13 (added describe, explain). Backward-compatible; the one behavior change is redaction defaulting on.

Install: `pip install dbecho`

Loading

v0.1.1 — bug fixes

17 Apr 07:13
@ginkida ginkida

Choose a tag to compare

Fixed

  • SQL validation: ; inside string literals (e.g. SELECT 'a;b' FROM t) and leading comments (-- foo\nSELECT 1, /* */ SELECT 1) no longer trigger false rejections. A new scanner strips strings (single/double/dollar-quoted) and comments (line + nested block) before the structural check.
  • EXPLAIN parser: the parenthesized form EXPLAIN (ANALYZE) DELETE ... is now correctly blocked. Previously it slipped past the inner whitelist (read-only transaction still caught it, but the tool-level error message now arrives earlier with a clear reason).
  • Anomaly detection: anomalies no longer false-flags columns like paid, void, candidate, guide, solid as possible duplicates. The old check used "id" in col_name.lower() which matched those as substrings. Now uses token-level matching: exact id, or email/uuid as a whole underscore-separated token. *_id FK columns are intentionally excluded (their duplicates are legitimate).
  • Schema cache: get_schema(use_cache=True) returns a fresh copy and stores a copy internally — caller mutation no longer corrupts the cache.
  • Error handling: schema and erd tools now catch ValueError/TimeoutError/Exception and return friendly error strings, matching the other tools. TimeoutError is handled specifically across every tool — user sees "query timeout exceeded" instead of "unexpected failure".
  • Config validation: unknown keys in [databases.<name>] (e.g. typo descreption = ...) and non-string description values are now rejected at load time.

Internal

  • +17 tests (72 → 89)
  • No public API changes; drop-in upgrade from 0.1.0
Loading

v0.1.0

11 Mar 12:58
@ginkida ginkida

Choose a tag to compare

Initial release of dbecho — MCP server for multi-database PostgreSQL analytics.

Features

  • 11 tools: schema, query, analyze, compare, trend, anomalies, sample, erd, health, summary, list_databases
  • 3 MCP resources and 3 MCP prompts
  • Read-only connections with SQL injection prevention
  • Query timeouts and row limits
  • Multi-database support with TOML config
  • Environment variable expansion (${VAR} syntax)

Install

pip install dbecho

Quick start

See README for setup instructions.

Loading

AltStyle によって変換されたページ (->オリジナル) /