Skip to content

Releases: kouko/redshift-comment-mcp

v0.10.0 — get_setup_status reports inline mode truthfully

Choose a tag to compare

@kouko kouko released this 21 Jun 03:45
092bf19

Fixes a false configured: false from the get_setup_status MCP tool when the server runs in legacy inline mode (the launch shape the Claude Code plugin UI uses: --host/--user/--dbname + REDSHIFT_PASSWORD env). The status tool now detects inline mode and adds a source: "inline" | "profile" field so agents can tell which config mechanism is live. The password value is never materialized in the response (presence-only bool).

See #39.

Pre-release: triggers TestPyPI smoke test. PyPI-live promotion follows after the dry-run goes green.

v0.9.0

Choose a tag to compare

@kouko kouko released this 12 Jun 10:02
6968e39

What's Changed

  • feat(plugin): connection-config userConfig form (reverse D2) by @kouko in #36
  • feat(plugin): default-disabled install (opt-in connector) by @kouko in #37
  • feat(mcpb): companion Desktop Extension — Claude Desktop config form by @kouko in #38

Full Changelog: v0.7.1...v0.9.0

v0.7.1 — v0.7.0 catch-up + workflow idempotency fix

Choose a tag to compare

@kouko kouko released this 28 May 23:15
c27ea4c

🎯 In-band MCP setup — no log-spelunking, no restart

v0.7.1 is the catch-up release that ships v0.7.0's work to PyPI. The
v0.7.0 Pre-release attempt was blocked by two GitHub Actions workflow
quirks (TestPyPI CDN propagation lag + non-idempotent twine upload) that
made test-publish.yml fail spuriously. v0.7.0 was tagged on git and
uploaded to TestPyPI, but never reached PyPI — bumping to 0.7.1 with the
workflow fix (PR #35) is the cleanest path to a green ship, mirroring
the v0.4.0/v0.5.0 → v0.6.0 catch-up pattern.

v0.7.1 = v0.7.0 + workflow fix — functionally identical to v0.7.0
from the user perspective.

agent: list_schemas() → {"error": "not_configured", "exception_class": "ConfigurationError", "next_step": "Call setup_via_dialog..."}
agent: setup_via_dialog(host=..., user=..., dbname=...)
       → OS dialog appears, user types password
       → SELECT 1 against Redshift to verify
       → {"status": "configured", "tested": true}
agent: list_schemas() → works (lazy resolve, no restart)

✨ New MCP tools (11 → 13)

Tool What it does
setup_via_dialog Bootstrap or update a profile in-session. Fields go via tool args (non-secret); password collected via OS-native dialog server-side (macOS osascript / Linux zenity). Tests connection against Redshift before declaring success. Returns one of 7 status codes covering happy path + dialog-cancelled / permission-denied / dialog-unavailable / platform-unsupported / empty-password / connection-failed.
get_setup_status Read-only configuration check (no Redshift touch). Returns whether config.toml fields and keychain password exist; safely callable at session start; never returns the password value.

🆕 Degraded-mode startup

Pre-v0.7.x: server crashed with ValueError("Profile 'default' is not configured...") if no profile existed. Agents had no in-band signal — they had to read ~/Library/Logs/Claude/mcp-server-*.log (client-specific path) to find the recovery hint.

v0.7.x:

  • Server boots regardless of profile state — enters the MCP stdio loop and accepts tool calls
  • DB tools return a structured {"error": "not_configured", ...} response with next_step field pointing at setup_via_dialog
  • Lazy connection resolution: every tool call re-reads config.toml + keychain, so newly written profiles take effect without restarting the MCP client
  • resolve_connection_params now raises ConfigurationError (a ValueError subclass for backward-compat)

🔐 Password collection: OS dialog, never the wire

The same osascript / zenity discipline already used by the Claude Code /redshift-setup skill is now in the CLI + MCP tool:

Subcommand / Tool Password input
redshift-comment-mcp set-password --dialog (CLI) macOS osascript / Linux zenity → keychain
redshift-comment-mcp set-password --stdin (CLI) One line from stdin → keychain (headless / CI)
setup_via_dialog (MCP tool) Same dialog mechanism via subprocess.run(capture_output=True) — Python str → keyring

Password value path: user keyboard → OS dialog process stdout (in-pipe) → Python string in-process → keyring.set_password() → OS keychain. Never touches MCP wire, chat, Bash stdout, process args, or shell history.

🛡️ macOS Apple Events permission detection

v0.7.x distinguishes 3 macOS-specific osascript failure modes that pre-v0.7.x all collapsed to "user cancelled":

Real situation New status code Agent guidance in message
User clicked Cancel button dialog_cancelled Ask user whether intentional; default to retry
macOS Automation > System Events permission denied (error -1743) permission_denied Open System Settings → Privacy & Security → Automation → enable System Events; or tccutil reset AppleEvents to force a fresh prompt
osascript binary not found dialog_unavailable Fall back to set-password --stdin from terminal

Detection uses the locale-stable numeric code (-1743) plus case-insensitive English text fallback ("Not authorized" / "Not authorised").

📋 Unified error-response schema

All four "this is broken" responses now carry the same field set so agents can pattern-match a single shape:

{
  "error": "not_configured" | "write_profile_failed" | "keychain_write_failed" | "missing_field",
  "exception_class": "ConfigurationError" | "PermissionError" | "KeyringLocked" | "ValidationError" | ...,
  "message": "<sanitized agent-actionable text>"
}

Per CWE-209 + OWASP Error Handling Cheat Sheet, raw str(exc) is not included for write_profile_failed / keychain_write_failed (third-party exception args may carry sensitive context). The exception class name is preserved as a separate field for diagnostic branching. Full exception detail is logged server-side with exc_info=True.

⚡ Connection test before declaring success

setup_via_dialog now runs SELECT 1 against Redshift after writing the profile + password. Catches host typos / VPN-not-connected / wrong password / firewall block / paused-cluster early — agent gets either {"status": "configured", "tested": true} or {"status": "configured_but_connection_failed", "connection_error": "..."} instead of a misleading "configured" followed by an immediate DB tool failure.

Failures are also logged server-side at WARNING level with profile + cluster coords + the underlying error, so operators can correlate transcript-reported issues with server log entries.

🤖 FastMCP instructions block updated

The handshake-time instructions= text now describes:

  • The degraded-mode contract (server boots without profile)
  • Both entry points: proactive get_setup_status at session start vs reactive not_configured on tool call
  • All response statuses agents need to handle, including permission_denied and configured_but_connection_failed

Agents see the recovery pattern BEFORE encountering an error, not just inside the error itself.

📚 Trilingual README updates

README.md / README.ja.md / README.zh-TW.md all updated with:

  • Tool count 11 → 13 + new setup_via_dialog and get_setup_status rows
  • Code-agent bootstrap diagram showing the v0.7.x pure-MCP flow
  • Fallback section for headless / no-GUI hosts (--stdin pipe path)

🧪 Test coverage

Tier Before After New tests
Unit 264 passed, 2 skipped 299 passed, 2 skipped +35
Integration (live cluster) 22 passed, 1 skipped 22 passed, 1 skipped unchanged shape
E2E (MCP wire) 4 passed 6 passed +2 (setup_via_dialog wire registration + SETUP RECOVERY instructions handshake)

Highlights:

  • test_bootstrap_then_use_end_to_end — the keystone scenario: server boots without profile → agent calls setup_via_dialog → next DB tool call works without restart
  • test_server_main_does_not_crash_when_no_profile — regression net against re-introducing upfront resolution
  • test_every_db_tool_handles_not_configured — parametric over all 11 DB tools (catches missing @_guarded on new tools)
  • test_get_setup_status_never_returns_password_value — hard security invariant; JSON-serializes response and scans for the password substring
  • test_collect_password_via_dialog_detects_permission_denied — parametric over realistic macOS stderr shapes (numeric, English, British spelling, lowercase, locale-translated)

🔧 Refactor + dev experience

  • RedshiftTools.__init__ now takes a Callable[[], RedshiftConnectionConfig] provider instead of a built config — enables lazy re-resolution. 58 existing RedshiftTools(config) test call sites mechanically rewritten to RedshiftTools(lambda: config).
  • @_guarded decorator on all 11 DB tools centralizes the ConfigurationError → not_configured response conversion. Two new tools (setup_via_dialog, get_setup_status) deliberately skip the guard since they must run when no profile exists; documented inline + behaviorally tested.
  • 5 dialog-failure response builders extracted to module-level functions with a _DIALOG_FAILURE_BUILDERS dispatch dict — setup_via_dialog body shrinks from ~250 → ~164 lines.

🛠️ Release workflow fixes (v0.7.1 only — PR #35)

Two GitHub Actions workflow flaws surfaced by the v0.7.0 release attempt, fixed in v0.7.1:

  1. test-publish.yml "Test installation from TestPyPI" step now retries pip install up to 6× with 30s backoff (3 min total) — absorbs the typical 1-3 min lag between TestPyPI's JSON API and its simple index (which pip uses).
  2. twine upload now uses --skip-existing in both test-publish.yml and publish.yml — re-runs are idempotent (no more 400 Bad Request on duplicate upload). Before this fix, any transient failure during the publish workflow corrupted the version slot until the next bump.

Forward-looking: future releases on the same workflows will not require version skipping just to retry.

📥 Install

# PyPI / generic MCP client
pip install --upgrade redshift-comment-mcp
# or
uvx redshift-comment-mcp

# Claude Code plugin
claude plugin install redshift-comment-mcp

pip install --upgrade from v0.6.0 lands directly on v0.7.1 (v0.7.0 is not on PyPI; see workflow fixes section above).

For multi-cluster claude_desktop_config.json / mcp.json examples and the in-band setup_via_dialog agent flow, see README §"Setting up with uvx".

🔗 Forward look: MCP Elicitation primitive

The MCP 2026-07-28 RC spec introduces an Elicitation primitive — a protocol-level mechanism for servers to request direct user input through the client's native UI. Once GA and FastMCP exposes it, the subprocess + osascript dialog hack here becomes obsolete: the server can request a password via the protocol and the client presents a native secure input widget. Documented in code at redshift_tools.py:1122-1140 so future maintainers know this is interim, not permanent architecture.

📊 External references grounding this release

  • [CWE-2...
Read more

v0.7.0 — In-band MCP setup (degraded-mode + setup_via_dialog)

Choose a tag to compare

@kouko kouko released this 28 May 18:57
fc58615

⚠️ Superseded — never reached PyPI, use v0.7.1 instead

This tag exists in git history and on GitHub Releases, but was never
published to PyPI
. The v0.7.0 release attempt was blocked by two
GitHub Actions workflow flaws:

  1. test-publish.yml's "Test installation from TestPyPI" step ran ~30s
    after upload — TestPyPI's pip-facing simple index typically lags the
    JSON API by 1-3 minutes, so pip couldn't see 0.7.0 yet and the step
    failed spuriously.
  2. The twine upload step wasn't idempotent (--skip-existing missing),
    so gh run rerun --failed hit HTTPError: 400 Bad Request from
    the duplicate-version check.

The first failure was a cosmetic timing issue (TestPyPI actually had
0.7.0); the second made the workflow status permanently stuck on
"failed" with no clean recovery path. Bumping to 0.7.1 + fixing the
workflows (PR #35) was the cleanest path to a green ship — same
pattern as v0.4.0/v0.5.0 → v0.6.0.

Migration: install v0.7.1
or later. v0.7.1 is functionally identical to v0.7.0 from the user
perspective — only the publish workflows differ.

pip install --upgrade redshift-comment-mcp     # → 0.7.1+
# or
uvx redshift-comment-mcp                       # → 0.7.1+

The original v0.7.0 release notes are below for historical reference.


🎯 In-band MCP setup — no log-spelunking, no restart

v0.7.0 collapses the "code-agent provisions a Redshift profile" UX from
7 steps (with log-spelunking + Bash + MCP-client restart) down to
3 steps, pure MCP wire, no Bash needed. The server now boots even
without a configured profile and exposes a dedicated setup_via_dialog
tool that drives an OS-native password dialog server-side — password
never crosses chat / MCP wire / tool args.

agent: list_schemas() → {"error": "not_configured", "exception_class": "ConfigurationError", "next_step": "Call setup_via_dialog..."}
agent: setup_via_dialog(host=..., user=..., dbname=...)
       → OS dialog appears, user types password
       → SELECT 1 against Redshift to verify
       → {"status": "configured", "tested": true}
agent: list_schemas() → works (lazy resolve, no restart)

(Full v0.7.0 changelog identical to v0.7.1's notes minus the §"Release workflow fixes" section that's unique to v0.7.1.)

v0.6.0 — PyPI catch-up + code-agent uvx bootstrap

Choose a tag to compare

@kouko kouko released this 28 May 06:04
04a197a

🎯 PyPI back in sync with the plugin path

First PyPI release since v0.3.0. The Claude Code plugin path shipped
v0.4.0 + v0.5.0 internally from cloned-repo source, but neither was
published to PyPI due to a release-trigger workflow bug — v0.6.0 rolls
up both prior releases plus the uvx UX work that promotes
uvx redshift-comment-mcp to a first-class install path for non-Claude-
Code MCP clients.

The new Release publishing (MUST) discipline (#31) + publish.yml
trigger fix (#33) close the gap that caused the silent v0.5.0
non-publication. v0.5.0 is intentionally skipped on PyPI; v0.6.0 is
its strict superset plus the UX work.

🤖 New in v0.6.0 — code-agent uvx bootstrap (#33)

uvx redshift-comment-mcp becomes truly stand-alone — no Claude Code
plugin required for first-time setup, and the password stays out of
chat / stdout via OS-native dialog.

Subcommand Purpose
set-password --profile X --dialog macOS osascript / Linux zenity password dialog → keychain. Password never enters chat / stdout / argv.
set-password --profile X --stdin Read one line from stdin → keychain (headless / CI use). Mutually exclusive with --dialog.

server.py's "profile not configured" error messages now offer three
setup paths
: Claude Code skill, code-agent pipeline (set-fields +
set-password --dialog), and human terminal (uvx redshift-comment-mcp setup). Before v0.6.0, the error only mentioned the Claude Code skill —
uvx-only users hit a dead-end message.

Trilingual README §"Setting up with uvx" now ships concrete
claude_desktop_config.json snippets (single-profile + multi-cluster)
plus the code-agent bootstrap pipeline (#32 + #33).

✨ New skills (rolled up from v0.4.0)

Skill One-liner PR
/redshift-grep-columns Cross-table column keyword search across one or all schemas #24
/redshift-grep-tables Cross-schema table keyword search across the entire cluster #24
/redshift-switch-profile Switch the active connection profile without re-entering host/user/password #21

🆕 Other new features (v0.4.0 + v0.5.0)

  • execute_sql transparency — response now includes _executed_sql
    (the rewritten SQL the server actually ran) and _user_facing_message
    (a shaped string the agent can show users) (#28).
  • Zero-config plugin installclaude plugin install no longer
    asks for a profile name. The MCP server reads an active-profile
    pointer file written by /redshift-setup (#21, breaking, see
    migration below).

⚡ Performance (rolled up from v0.4.0)

  • Column metadata SQL: ~3.3x at 12K columns. Rewrote correlated-
    subquery pattern to direct LEFT JOIN. Speedup persists at small N (#22).
  • Long-comment safety in multi-item responses. MAX_COMMENT_LEN=1000
    caps each comment with a comment_truncated_count marker; single-item
    getters never truncate (#23).

🐛 Bug fixes

  • Single-profile upgrade rescue (v0.5.0) — pre-PR-22 installs whose
    lone profile was not named default got hard-broken by the active-
    profile pointer file introduction. resolve_active_profile now falls
    back to the lone profile when exactly one exists; explicit
    --profile / env / pointer inputs still resolve verbatim so typos
    surface as typos (#29).
  • uvx-only error UX (v0.6.0) — "no profile configured" error now
    guides ALL setup paths, not just the Claude Code skill (#33).
  • Various skill bug fixes from functional-test pass (#19).

🏠 Housekeeping

  • Removed /redshift-cache-schema — cache layer retired in favor
    of always-fresh catalog SQL + the new performance work (#26).
  • Live-cluster smoke gate. REDSHIFT_INTEGRATION=1 pytest tests/integration/
    exercises every MCP tool against a real Redshift cluster (#25).
  • New tests/e2e/ tier — MCP wire-protocol tests via stdio
    subprocess (#28).
  • README install-link fix (#27).

⚠️ Breaking — Profile system contract (rolled up from v0.4.0, #21)

If you installed v0.3.0 directly via pip install redshift-comment-mcp:

  • Profile pointer file is new. ~/.config/redshift-comment-mcp/active-profile
    is now the source of truth for the active profile. Absence is no longer
    an error — single-profile users get an implicit fallback (after #29).
  • Plugin manifest no longer asks for profile name. Anyone who
    manually set a profile name via client config should switch to
    --profile <name> to override the pointer file, or rely on
    /redshift-setup + /redshift-switch-profile.

If your existing single profile is named anything other than default,
upgrading straight to 0.6.0 (not stopping at any 0.4.x / 0.5.0 point)
is the safe path — the single-profile fallback rescue (#29) is included.

🛠️ Release discipline (v0.6.0 internal)

  • CLAUDE.md now codifies the release-publishing flow as a hard
    discipline (tag → Pre-release → flip-to-Release → PyPI), so the silent
    non-publication that hit v0.4.0 + v0.5.0 doesn't recur (#31).
  • .github/workflows/publish.yml trigger gains released activity
    type, so gh release edit --prerelease=false (the Pre-release →
    Release promotion) actually fires the workflow. v0.5.0 was the worked
    example of this trigger gap — fixed forward in v0.6.0 (#33).

📥 Install

# PyPI / generic MCP client
pip install --upgrade redshift-comment-mcp
# or
uvx redshift-comment-mcp

# Claude Code plugin
claude plugin install redshift-comment-mcp

📊 Full changelog

PRs in this release (v0.3.0…v0.6.0):
#19 · #20 · #21 · #22 · #23 · #24 · #25 · #26 · #27 · #28 · #29 · #30 ·
#31 · #32 · #33

v0.5.0 — PyPI catch-up: 3 new skills + execute_sql transparency + 3.3x perf

Choose a tag to compare

@kouko kouko released this 28 May 05:14
7d37358

⚠️ Never reached PyPI — use v0.6.0 instead

This tag exists in git history and on GitHub Releases, but was never
published to PyPI
. A publish.yml workflow trigger bug (gh release edit --prerelease=false fires the released event, not published)
caused the Pre-release → Release promotion to silently miss the publish
job. PyPI users went straight from v0.3.0 to v0.6.0.

Migration: install v0.6.0
or later. v0.6.0 is a strict superset of v0.5.0 and ships the trigger
fix forward so this can't recur.

pip install --upgrade redshift-comment-mcp     # → 0.6.0+
# or
uvx redshift-comment-mcp                       # → 0.6.0+

The original v0.5.0 release notes are below for historical reference.


🎯 PyPI back in sync with the plugin path

This is the first PyPI release since v0.3.0. The Claude Code plugin path
(claude plugin install, runs from cloned-repo source) shipped v0.4.0 +
v0.5.0 internally, but neither was tagged or released — so PyPI /
uvx redshift-comment-mcp users were stuck on v0.3.0 with no visible
signal. v0.5.0 rolls up both releases' worth of work plus a critical
post-release patch.

Per the new Release publishing (MUST) discipline (#31), this won't
happen again.

✨ New skills

Skill One-liner PR
/redshift-grep-columns Cross-table column keyword search across one or all schemas #24
/redshift-grep-tables Cross-schema table keyword search across the entire cluster #24
/redshift-switch-profile Switch the active connection profile without re-entering host/user/password #21

🆕 New features

  • execute_sql transparency — response now includes _executed_sql
    (the actual rewritten SQL the server ran) and _user_facing_message
    (a shaped string the agent can show users), so the user always knows
    exactly what query hit Redshift (#28)
  • Zero-config plugin installclaude plugin install no longer asks
    for a profile name. The MCP server reads an active-profile pointer file
    written by /redshift-setup. One-time /redshift-setup → done
    (#21, breaking, see migration below)

⚡ Performance

  • Column metadata SQL: ~3.3x at 12K columns. Rewrote the correlated-
    subquery pattern to a direct LEFT JOIN. Speedup persists at small N (#22)
  • Long-comment safety in multi-item responses. MAX_COMMENT_LEN=1000
    caps each comment with a comment_truncated_count marker; single-item
    getters never truncate. Prevents Claude Code's silent ~25K token cap
    from clipping dbt-rich schemas (#23)

🐛 Bug fixes

  • Single-profile upgrade rescue. PR #22 introduced the active-profile
    pointer file with the contract "absent ↔ use default". Pre-PR-22
    installs whose lone profile was not named default (e.g.
    ichef-prod) got hard-broken by the upgrade. resolve_active_profile
    now falls back to the lone profile when exactly one exists; explicit
    --profile / env var / pointer file inputs still resolve verbatim so
    typos surface as typos (#29)
  • Various skill bug fixes from functional-test pass (#19)

🏠 Housekeeping

  • Removed /redshift-cache-schema — cache layer retired in favor of
    always-fresh catalog SQL + the new performance work above (#26)
  • Live-cluster smoke gate. REDSHIFT_INTEGRATION=1 pytest tests/integration/
    exercises every MCP tool against a real Redshift cluster (#25)
  • New tests/e2e/ tier — MCP wire-protocol tests via stdio subprocess (#28)
  • README install-link fix (#27)

⚠️ Breaking — Profile system contract (#21)

If you installed v0.3.0 directly via pip install redshift-comment-mcp:

  • Profile pointer file is new. ~/.config/redshift-comment-mcp/active-profile
    is now the source of truth for the active profile. Absence is no longer
    an error — single-profile users get an implicit fallback (after #29).
  • Plugin manifest no longer asks for profile name. Anyone who manually
    set a profile name via client config should switch to --profile <name>
    to override the pointer file, or rely on /redshift-setup + /redshift-switch-profile.

If your existing single profile is named anything other than default,
upgrading straight to 0.5.0 (not stopping at any 0.4.x point) is the
safe path — the single-profile fallback rescue (#29) is included.

📥 Install

# PyPI / generic MCP client
pip install --upgrade redshift-comment-mcp
# or
uvx redshift-comment-mcp

# Claude Code plugin
claude plugin install redshift-comment-mcp

📊 Full changelog

PRs in this release (v0.3.0…v0.5.0): #19 · #20 · #21 · #22 · #23 · #24 ·
#25 · #26 · #27 · #28 · #29 · #30

v0.3.0 — charter narrowing (BREAKING) + cache-as-LLM-layer + metadata trim

Choose a tag to compare

@kouko kouko released this 07 May 16:20
a2c17be

⚠️ Breaking changes

Two skills are removed in this release. Charter narrowed: skills exist
to help users do natural-language search and analysis of data;
artifact generation falls outside that scope.

Removed Why Migration
/redshift-erd Mermaid ERD generation is a visualization artifact, not chat-based search/analysis Ask the LLM directly given catalog data from /redshift-explore or /redshift-cache-schema. Or use SchemaSpy / DBeaver / dbt-erd for serious ERD work
/redshift-suggest-schema-yml dbt yaml drafting is artifact production for an external toolchain Chain /redshift-profile output and ask the LLM "format this profile JSON as a dbt schema.yml models block"

Final skill set (5): /redshift-setup, /redshift-explore,
/redshift-profile, /redshift-cache-schema, /redshift-lineage-from-stl.

🚀 Cache layer repurposed as LLM-internal lookup

/redshift-cache-schema switches role from human offline-browsing
artifact to an LLM-side metadata cache that other skills actually
consume.

  • New file format: per-table tables/<schema>__<table>.md preserving
    multi-line markdown comments verbatim, plus lossy TSV indices
    (_tables_index.tsv / _columns_index.tsv) for cross-cluster grep,
    plus _meta.json freshness gate (refreshed_at, ttl_hours,
    complete: true|false).
  • Server instructions teach CACHE PROTOCOL: agents prefer Reading
    cache files over MCP round-trips when complete=true and within TTL,
    fall back to live MCP on miss with a chat hint to refresh.
  • /redshift-explore Step 0 + /redshift-profile Step 1 hook into the
    cache-first path. Other consumer skills benefit automatically via the
    server-level CACHE PROTOCOL.

Expected impact when cache is fresh: ~700 tokens saved + 99% latency
reduction per metadata query (Bash grep on TSV vs search_* MCP, or
single-file Read vs list_columns(include_comments=True)).

🔧 Metadata trim (system prompt — every conversation)

Region Before After Δ
7 skill descriptions (now 5) 6,291 2,635 -58%
Server instructions 2,711 1,356 -50%
11 tool docstrings 3,281 1,296 -60%
Total metadata burden 12,283 5,287 -57% / ~1,750 tokens / conversation

Achieved via description-design.md principles
(WHAT + WHEN, not WHAT + WORKFLOW; keyword-belt multi-language triggers
instead of full sentences; no all-caps emphasis density;
deduplicated comment-authoritative rule from 4 places to 1).

📝 Known limits documented

Three-language READMEs now document Claude Code's
~25K token MCP response cap
(silent truncation, no error marker), the two mitigations this plugin
already applies (include_comments=False default + cache layer), and
the MAX_MCP_OUTPUT_TOKENS env-var override.

✅ Test protection: 98 → 142 tests

Three new test files catch the classes of bug encountered during this
refactor cycle:

Tier File Tests Catches
1 tests/test_repo_invariants.py 19 Skill ↔ command pairing breaks; YAML frontmatter invalid; description > 1024-char ceiling; dead skill references in markdown; pyproject.toml fallback_version vs plugin.json version drift; trilingual README parity
2 tests/test_cache_contract.py 6 _meta.json required-field documented; TSV index header column counts; column heading pattern; consumer ↔ producer cache-path alignment; server-level CACHE PROTOCOL present
3 tests/test_skill_descriptions.py 20 Each description has Use when / Triggers belt; third-person voice; no workflow recap; ~800-char soft ceiling

All pure-function tests; run in <100 ms; require no AWS / MCP / DB.

🔐 SQL execute_sql validator (already in v0.2.2, unchanged here)

The validator changes from v0.2.2 (BOM-safe, string/comment-aware,
unterminated-literal rejection, 90.48% coverage gated at 85%) ship as-is
in this release.

📊 Changes Summary

Area Change
Charter Skills narrowed to natural-language search/analysis; 2 artifact-generation skills removed
Cache Repurposed as LLM-internal lookup layer with TTL gate + CACHE PROTOCOL
Metadata 57% trim across skill descriptions, server instructions, tool docstrings
Tests +44 tests (3 new files) covering repo invariants, cache contract, description quality

🔄 Upgrade

pip install --upgrade redshift-comment-mcp
# or
pip install redshift-comment-mcp==0.3.0

If you used /redshift-erd or /redshift-suggest-schema-yml, see the
migration notes above.


Full Changelog: v0.2.2...v0.3.0

🤖 Generated with Claude Code

v0.2.2

Choose a tag to compare

@kouko kouko released this 07 May 02:22
287d0f2

🚀 Claude Code Plugin Support

This release makes redshift-comment-mcp installable as a Claude Code plugin
with a one-shot conversational onboarding flow — no manual MCP server config
required.

  • /redshift-setup slash command (PR #9, refined in PR #13) — 4-question
    conversational flow that configures a connection profile end-to-end. Default
    form silently uses the default profile name; /redshift-setup <name> opts
    into multi-cluster mode and auto-writes ~/.claude/settings.json (with
    BEFORE/AFTER preview)
  • Setup CLI redshift-comment-mcp setup (PR #7) — same flow without the
    conversational layer, for non-Claude-Code users
  • OS-aware password input (PR #9) — system password dialog when GUI is
    available, TTY fallback otherwise
  • 6 MCP-composed skills + tri-lingual docs (EN / JP / 繁中) (PR #9):
    /redshift-profile, /redshift-suggest-schema-yml,
    /redshift-cache-schema, /redshift-erd, /redshift-explore,
    /redshift-lineage-from-stl
  • Plugin runs from cloned repo source via uv run --project (PR #7) —
    no PyPI release required for plugin users (PyPI install path still supported)

🔐 SQL Security Hardening

execute_sql now stands up to a wider class of payloads. Two fixes shipped:

Expanded blocklist (PR #11). Added MERGE, GRANT, REVOKE, COPY,
UNLOAD to the forbidden-keyword list — covers Redshift upsert, ACL
mutation, and S3 import / export (data exfiltration surface even though
the latter doesn't "write to DB" in the strict sense).

Robust validator (PR #14). Reproduces a real failure where a valid
WITH ... SELECT query was rejected because of a transport-layer BOM
prefix breaking str.strip().startswith('WITH'). Now:

Hardening Effect
Strip BOM / ZWSP / ZWNJ / ZWJ / WJ / NBSP before startswith No more false rejection on payloads with invisible prefixes
Sanitize string literals, quoted identifiers, line / block / $$ comments before keyword scan No false positive on WHERE name = 'DELETE me' or -- DROP TABLE old
Reject unterminated string / comment / quoted identifier Closes a potential bypass channel where an open literal could hide a forbidden keyword
Validator extracted to validate_read_only_sql() module-level function Unit-testable without MCP plumbing

29 new parametrized tests covering BOM / ZWSP / NBSP prefixes, string &
comment false-positives, multi-statement piggyback, and unterminated
literals. Validator module coverage at 90.48%, locked behind a CI gate
that fails the build below 85%.

🛠 Build & CI Robustness

  • fallback_version for plugin cache installs (PR #12) — Claude Code
    clones plugins without .git, so setuptools_scm had nothing to read at
    install time. Falls back to a static version string in that case
  • FastMCP 2.x ↔ 3.x compat in test helper (PR #8, refined in PR #14) —
    _get_tool_fn now tries public list_tools() first, falls back to private
    _list_tools. Suite green on both lines
  • Pin fastmcp>=2.11.0 and add pytest-cov to dev deps (PR #14)
  • Coverage gate on redshift_tools.py (≥85%, currently 90.48%) (PR #14)
    blocks regressions in security-critical code
  • Stale comment fix (PR #10) — removed inaccurate claim that startup
    performs a connection test

📊 Changes Summary

Area Change
Plugin Claude Code plugin packaging, /redshift-setup slash command + skill, setup CLI, 6 composed skills
Security execute_sql blocklist expanded; validator now BOM-safe and string/comment-aware; bypass via unterminated literal closed
Build setuptools_scm fallback_version for .git-less installs
Tests FastMCP 3.x compat fallback; 29 new validator cases; CI coverage gate at 85%

✅ Test Coverage

  • 98 tests passing (was 52 in v0.2.0)
  • 90.48% coverage on redshift_tools.py, locked at 85% via CI gate
  • Python 3.10 / 3.11 / 3.12 matrix in CI

Full Changelog: v0.2.0...v0.2.2

🤖 Generated with Claude Code

Version 0.2.0

Choose a tag to compare

@kouko kouko released this 07 Jan 08:37
74e5481

🚀 New Features

Search Tools Enhancements

  • search_schemas - New tool to search schemas by keywords (name or comment)
  • hit_count ranking - Search results now prioritize items matching more keywords
    • Results sorted by hit_count DESC, name ASC
    • hit_count field included in response

List Tools Optimization

  • include_parent_comments parameter - Control whether to fetch parent-level comments
    • list_tables: skip schema comment query when False
    • list_columns: skip table comment query when False
  • include_comments default changed to False for list_tables and list_columns
    • Reduces unnecessary SQL queries
    • list_schemas keeps default True

MCP Instructions Updated

  • Added search_schemas to recommended exploration flow
  • Emphasized keyword language should match user's conversation language

📊 Changes Summary

Tool Changes
search_schemas New tool with hit_count ranking
search_tables Added hit_count ranking
search_columns Added hit_count ranking
list_tables Added include_parent_comments, default include_comments=False
list_columns Added include_parent_comments, default include_comments=False

✅ Test Coverage

  • 52 tests passing
  • New tests for hit_count sorting (3 tests)
  • New tests for include_parent_comments parameter

🤖 Generated with Claude Code

v0.1.1

Choose a tag to compare

@kouko kouko released this 05 Jan 10:16
abf0e73

🔧 修正與改進

Bug 修正

  • SQL 關鍵字驗證修正:使用 \b regex 字元邊界檢查危險 SQL 關鍵字,避免誤擋含有關鍵字的欄位名稱(如 last_update

文件更新

  • README 強化:新增完整的 MCP Client 本地開發設定說明
    • 強調 Python 完整路徑的重要性
    • 新增環境變數隱藏密碼的設定範例
    • 說明更新原始碼後的操作流程

其他

  • 新增 _version.py.gitignore(setuptools-scm 自動生成檔案)

📥 安裝

pip install redshift-comment-mcp==0.1.1

🔄 升級

pip install --upgrade redshift-comment-mcp