Skip to content

Changelog

One line per change, newest on top: YYYY-MM-DD — what was done.


2026-10-25 — 0.3.0: PostgreSQL, each engine’s driver an extra (the agent, at the author’s word: the site would otherwise promise what PyPI did not have) 2026-10-25 — PostgreSQL (engine: postgres, the postgres extra): every query in a read-only transaction with its statement timeout, rows through a server-side cursor one past the limit, a superuser and the roles that reach the server’s files refused at start, functions a read-only transaction does not stop refused by name, the plan’s tables held to readable through the views a query names; tested against PostgreSQL 17 in a container and in CI; make_shop.py --postgres and examples/config.postgres.example.yaml; real Claude Code answered April revenue by country through it, numbers checked 2026-10-25 — PostgreSQL refuted by a second reader: index maintenance (brin_*, gin_clean_pending_list) wrote past the read-only transaction for an owner — refused by name now, and a user that owns anything refused at start; a user that may read beyond readable, or holds pg_read_all_data / BYPASSRLS, noted in --check and the log (a function defined in the database reads with its grants); the statistics of any table (pg_stat_get_*) and snapshot exports refused 2026-10-25 — each engine’s driver an extra, as in detectkit (the author): [postgres], [duckdb], [all] (ClickHouse needs none); a missing driver named with its extra at start; the image and the dev environment hold every driver 2026-10-24 — 0.2.0 published (PyPI, GHCR); prepared (the author): skills, context and skills from git repositories, the hardening of the second reader — published when its tag v0.2.0 is pushed 2026-10-24 — the docs site (milestone 4): website/ on the pattern of repo-reader-mcp’s and detectkit’s — Astro + Starlight from docs/ (10 pages, a page not listed stops the build), a landing page whose every panel is an answer the server gave on the made-up shop, an indigo accent and a mark of its own; website.yml builds ghcr.io/alexeiveselov92/semantic-warehouse-mcp-web and tells pipelab; pipelab’s swm-web at swm.pipelab.dev committed there 2026-10-24 — skills and repositories refuted by a second reader: 10 findings and 7 sentences of the guide closed — git’s output in no encoding crashing the start and silently killing the refresh thread, a folder and a path inside it refused, a token pasted for its variable’s name or in the URL’s query repeated, get_skill past the cap, the offline check needing git, a race between two looks at a listing, copies left on SIGTERM, a proxy seeing the token over http, names not UTF-8 listed but unreadable, misleading errors (./docs, HTTP://, a BOM, an empty repository, a typo in {repository, path} now named with the likely key); a variable’s name that looks like a value never repeated, for ClickHouse and --token-env too 2026-10-24 — the dialect question decided (the author): a model’s expression runs as written in its connection’s dialect, never translated — sqlglot’s ANSI-to-ClickHouse measured not neutral; variants per engine in our own custom_extensions; built with the metrics (milestone 6) 2026-10-24 — context and skills straight from a git repository: repositories: declared once by name, entries {repository, path}; fetched by git at start (one commit, only the named paths), refreshed every refresh_minutes in the background, a commit that breaks the checks never served; the token as a header through git’s environment, never on a command line or repeated; no redirect, https only, symbolic links as files; fetched_from and commit in answers, the repositories’ state in list_connections; git in the image (without Perl); a git server on loopback in the tests; checked live from GitHub, in the image too; 30 protections removed, 30 caught 2026-10-24 — skills: list_skills, get_skill — folders in the Agent Skills format for the whole server and per connection, checked at start by the format’s rules, read anew; a skill’s text files served by the names its listing gives, the rest listed apart; real Claude Code followed the example skill and its file, numbers checked by a direct query 2026-10-24 — 0.1.0 published: on PyPI (installed and run with uvx semantic-warehouse-mcp==0.1.0), the image on GHCR (:0.1.0, :sha-fe2b2e0, amd64 and arm64, pulled without signing in) 2026-10-24 — 0.1.0, the first release (pre-alpha): the package on PyPI by trusted publishing (publish.yml, for a tag that is the package’s version) and the image on GHCR; the README rewritten for what works now 2026-10-24 — ClickHouse readonly = 1 users served within their profile (the author: use the read-only user employees have): no limit sent, the answer read no further than one row past what is shown, the query stopped by its id once enough is read or past its time; a profile that cuts silently, or a user that could not stop a query and has no time limit, refused at start; errors met mid-answer in each version’s form refused 2026-10-24 — ClickHouse 22.11 served: the resolved tree asked for (EXPLAIN QUERY TREE run_passes = 1), settings a server does not know not sent, 64-bit integers it quotes read back; missing_tables: leave_out for a model ahead of its database; checked live on two real warehouses with their read-only users 2026-10-24 — --check --offline: the configuration, its models and vocabularies checked without reaching a database or reading a secret, for CI 2026-10-24 — Streamable HTTP for a server a team shares: --http, a token every request carries (required off loopback), /health without a token or a database, stateless JSON answers; the container image (non-root, read-only root filesystem) built on every change and published to GHCR for a release tag; docs/reference/running.md; real Claude Code answered through the image over HTTP, its numbers checked 2026-10-24 — ClickHouse before 24.3 refused at start by checking that its query tree is resolved, and a query whose tree holds an unresolved name refused: such servers (22.11, 23.8 measured) explain a query naming no table, which would have passed for a reading that found none — until now they stopped only because they did not know a setting 2026-10-24 — ClickHouse: a user with readonly = 1 (it may change no setting, so no limit reaches its queries) stops the server at start, naming the fix — readonly = 2; a user of each kind in the ClickHouse tests 2026-10-24 — the dbt importer: semantic-warehouse-mcp import-dbt writes a dbt project’s tables, descriptions, meta and tags as an Ossie document (--strict: the strict export; --check: for CI), the team’s mapping in its configuration (tables, vendor_name, dbt_tags, places), dbt’s own primary keys, event_time and relationships tests read by code; a made-up dbt project, its real manifest and output in examples/dbt/; real Claude Code answered April revenue by country through it, numbers checked by a direct query 2026-10-24 — the importer checked on a large real catalog in a scratch copy (715 datasets, 8,092 fields, every tag against the team’s own rules, a planted typo named), nothing committed; refuted by a second reader: 10 findings closed (quoted columns, another database, collapsing relationships, lone surrogates now refused everywhere, tracebacks, secrets in problems, NaN, NEL, --strict NaN, retyped JSON numbers, backslashes); every protection held by a test that fails when removed 2026-10-24 — semantic models in Apache Ossie per connection (0.2.0.dev0, 0.1.1 unwrapped), checked at start against the bundled schema of their version, Ossie’s own rules and their connection (a source readable and existing, a query through the guard); list_datasets, describe_dataset (live columns beside), list_metrics, describe_metric, all served as written 2026-10-24 — vocabularies: your own metadata in custom_extensions (a YAML mapping or Ossie’s JSON string) checked at start — keys, levels, types, closed values with the likely one for a typo — and served with the definitions of the values an answer uses 2026-10-24 — files read as written (YAML 1.2 booleans, dates as text, UTF-8, aliases capped, line and column only in an error, a URL’s password redacted); answers shrunk in order and, last, their longest values cut; real Claude Code answered March revenue through the model, its numbers checked by a direct query 2026-10-24 — refuted by a second reader: 9 findings closed (answers past the cap, values JSON cannot hold, secrets in errors, tracebacks at start, a vendor’s case slipping past its vocabulary, DuckDB’s catalog lost, YAML 1.1 booleans and dates, alias explosion, sources neither a name nor a query); a cut of long values that could loop forever, found by removing protections, closed; 54 removals, 54 caught

2026-10-24 — the team’s own instructions and context documents, for the whole server and per connection: instructions in the server’s instructions and list_connections, documents by list_context / get_context (as written, read anew, in parts); real Claude Code cited each rule’s source 2026-10-24 — milestone 2 done: the ClickHouse adapter (GET — read-only by ClickHouse’s own rule; every overflow mode throw, a cutting profile overridden; the extra row that shows a cut; EXPLAIN QUERY TREE naming the tables read; dictionaries checked against readable), DuckDB’s own reading naming tables, tests against a real ClickHouse (a container; CI’s service), the made-up shop loadable into ClickHouse; real Claude Code answered over DuckDB and ClickHouse at once, numbers checked 2026-10-24 — your own metadata decided (option B: YAML in Ossie’s custom_extensions, a vocabulary per vendor, nothing of one catalog in code); the plan reordered: ClickHouse, then the semantic layer with the dbt importer, then the site; a production dbt catalog’s shapes studied (generalised in dev/RESEARCH.md)

2026-10-24 — milestone 1 done: the configuration and its check (every problem named at once, typos with the likely key, duplicate YAML keys refused, secrets never repeated), the adapter interface and DuckDB (read-only file, external access off, configuration locked, its own parser asked), the guard on sqlglot (one read-only SELECT, readable tables wherever read, large tables bounded from below, settings/table functions/denied function families refused — 12 refusal codes, each a test case), list_connections, list_tables, describe_table, run_query with provenance, exact numbers and capped answers; a made-up shop (examples/data/make_shop.py); the guide’s reference for configuration, the guard and engines, and getting started, held by tests; real Claude Code answered over stdio, its numbers checked by a direct query 2026-10-24 — the guard refuted by a second reader: a table in parentheses (FROM (secret.t) x) and ClickHouse’s x IN db.table read past it, then dictGet* / joinGetOrNull — all closed; every table node is now a table read unless proven a CTE’s name

2026-10-24 — ready to start: the guide’s rule with a test (every tool in docs/reference/tools.md), /close checks the guide; the site moved to milestone 2; the hosting (pipelab) and where a company’s requirements come from written in CLAUDE.md; context and parallel-work rules 2026-10-24 — the metrics layer designed beside Ossie: populations, filters bound per population (every metric filtered through another entity), roll-up rules, templates, presets, scenarios — from a production registry studied 2026-10-24 — docs/ is the public documentation’s source (a site to come, Astro + Starlight like detectkit’s, hosted through pipelab); design, plan, decisions, research moved to dev/ ; renamed from warehouse-mcp 2026-10-24 — groundwork: the repository, README, design, plan, decisions (Apache Ossie as the semantic layer — the 0.2 shape, 0.1.1 read too), research, the session flow; examples (a made-up shop’s Ossie model, context, a skill, a saved query set); a skeleton server (stdio, about) with tests, ruff and CI