wlens 0.1.0__tar.gz

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 (59) hide show
  1. wlens-0.1.0/.github/workflows/ci.yml +34 -0
  2. wlens-0.1.0/.github/workflows/release.yml +78 -0
  3. wlens-0.1.0/.gitignore +24 -0
  4. wlens-0.1.0/.python-version +1 -0
  5. wlens-0.1.0/LICENSE +21 -0
  6. wlens-0.1.0/PKG-INFO +305 -0
  7. wlens-0.1.0/README.md +249 -0
  8. wlens-0.1.0/RELEASING.md +44 -0
  9. wlens-0.1.0/docs/mcp.md +217 -0
  10. wlens-0.1.0/docs/quickstart.md +181 -0
  11. wlens-0.1.0/docs/table-catalogs.md +315 -0
  12. wlens-0.1.0/docs/wlens-yml-reference.md +157 -0
  13. wlens-0.1.0/examples/events.py +115 -0
  14. wlens-0.1.0/examples/plans.py +112 -0
  15. wlens-0.1.0/pyproject.toml +65 -0
  16. wlens-0.1.0/src/wlens/__init__.py +3 -0
  17. wlens-0.1.0/src/wlens/adapters/__init__.py +5 -0
  18. wlens-0.1.0/src/wlens/adapters/base.py +49 -0
  19. wlens-0.1.0/src/wlens/adapters/dbt.py +262 -0
  20. wlens-0.1.0/src/wlens/cli.py +549 -0
  21. wlens-0.1.0/src/wlens/config.py +195 -0
  22. wlens-0.1.0/src/wlens/entities/__init__.py +5 -0
  23. wlens-0.1.0/src/wlens/entities/loader.py +179 -0
  24. wlens-0.1.0/src/wlens/executor/__init__.py +33 -0
  25. wlens-0.1.0/src/wlens/executor/base.py +219 -0
  26. wlens-0.1.0/src/wlens/executor/duckdb.py +50 -0
  27. wlens-0.1.0/src/wlens/executor/postgres.py +29 -0
  28. wlens-0.1.0/src/wlens/executor/redshift.py +30 -0
  29. wlens-0.1.0/src/wlens/mcp/__init__.py +1 -0
  30. wlens-0.1.0/src/wlens/mcp/app.py +173 -0
  31. wlens-0.1.0/src/wlens/mcp/auth.py +106 -0
  32. wlens-0.1.0/src/wlens/mcp/logs.py +49 -0
  33. wlens-0.1.0/src/wlens/mcp/proxy.py +78 -0
  34. wlens-0.1.0/src/wlens/mcp/server.py +375 -0
  35. wlens-0.1.0/src/wlens/mcp/share.py +520 -0
  36. wlens-0.1.0/src/wlens/render/__init__.py +1 -0
  37. wlens-0.1.0/src/wlens/render/markdown.py +245 -0
  38. wlens-0.1.0/src/wlens/render/pii.py +169 -0
  39. wlens-0.1.0/src/wlens/render/preserve.py +23 -0
  40. wlens-0.1.0/src/wlens/templates/SKILL.md +156 -0
  41. wlens-0.1.0/src/wlens/templates/__init__.py +1 -0
  42. wlens-0.1.0/src/wlens/templates/wlens.yml +17 -0
  43. wlens-0.1.0/tests/__init__.py +0 -0
  44. wlens-0.1.0/tests/conftest.py +25 -0
  45. wlens-0.1.0/tests/fixtures/events.tiny.yml +10 -0
  46. wlens-0.1.0/tests/fixtures/manifest.tiny.json +146 -0
  47. wlens-0.1.0/tests/test_adapters_dbt.py +99 -0
  48. wlens-0.1.0/tests/test_cli.py +206 -0
  49. wlens-0.1.0/tests/test_cli_clean.py +170 -0
  50. wlens-0.1.0/tests/test_config.py +59 -0
  51. wlens-0.1.0/tests/test_executor_duckdb.py +105 -0
  52. wlens-0.1.0/tests/test_executor_readonly.py +58 -0
  53. wlens-0.1.0/tests/test_mcp_auth.py +146 -0
  54. wlens-0.1.0/tests/test_mcp_refresh.py +73 -0
  55. wlens-0.1.0/tests/test_mcp_server.py +348 -0
  56. wlens-0.1.0/tests/test_mcp_share.py +253 -0
  57. wlens-0.1.0/tests/test_render_markdown.py +285 -0
  58. wlens-0.1.0/tests/test_render_pii.py +97 -0
  59. wlens-0.1.0/uv.lock +1198 -0
@@ -0,0 +1,34 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ci-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ jobs:
14
+ test:
15
+ runs-on: ubuntu-latest
16
+ strategy:
17
+ fail-fast: false
18
+ matrix:
19
+ python-version: ["3.11", "3.12", "3.13"]
20
+
21
+ steps:
22
+ - uses: actions/checkout@v4
23
+
24
+ - name: Install uv
25
+ uses: astral-sh/setup-uv@v4
26
+ with:
27
+ enable-cache: true
28
+ cache-dependency-glob: uv.lock
29
+
30
+ - name: Set up Python ${{ matrix.python-version }}
31
+ run: uv python install ${{ matrix.python-version }}
32
+
33
+ - name: Run tests
34
+ run: uv run --python ${{ matrix.python-version }} --extra dev pytest -v
@@ -0,0 +1,78 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ubuntu-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python-version: ["3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v4
21
+ with:
22
+ enable-cache: true
23
+ cache-dependency-glob: uv.lock
24
+
25
+ - name: Set up Python ${{ matrix.python-version }}
26
+ run: uv python install ${{ matrix.python-version }}
27
+
28
+ - name: Run tests
29
+ run: uv run --python ${{ matrix.python-version }} --extra dev pytest -v
30
+
31
+ build:
32
+ needs: [test]
33
+ runs-on: ubuntu-latest
34
+ steps:
35
+ - uses: actions/checkout@v4
36
+
37
+ - name: Install uv
38
+ uses: astral-sh/setup-uv@v4
39
+ with:
40
+ enable-cache: true
41
+ cache-dependency-glob: uv.lock
42
+
43
+ - name: Verify tag matches package version
44
+ run: |
45
+ tag="${GITHUB_REF_NAME#v}"
46
+ pkg_version=$(python3 -c "import tomllib, pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
47
+ if [ "$tag" != "$pkg_version" ]; then
48
+ echo "::error::Tag '$GITHUB_REF_NAME' does not match pyproject.toml version '$pkg_version'"
49
+ exit 1
50
+ fi
51
+
52
+ - name: Build distributions
53
+ run: uv build
54
+
55
+ - name: Upload dist artifacts
56
+ uses: actions/upload-artifact@v4
57
+ with:
58
+ name: dist
59
+ path: dist/
60
+
61
+ publish:
62
+ needs: [build]
63
+ runs-on: ubuntu-latest
64
+ environment:
65
+ name: pypi
66
+ url: https://pypi.org/p/wlens
67
+ permissions:
68
+ id-token: write
69
+
70
+ steps:
71
+ - name: Download dist artifacts
72
+ uses: actions/download-artifact@v4
73
+ with:
74
+ name: dist
75
+ path: dist/
76
+
77
+ - name: Publish to PyPI
78
+ uses: pypa/gh-action-pypi-publish@release/v1
wlens-0.1.0/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *$py.class
4
+
5
+ *.egg-info/
6
+ .eggs/
7
+ build/
8
+ dist/
9
+ .venv/
10
+ venv/
11
+ env/
12
+ .python-version.local
13
+
14
+ .pytest_cache/
15
+ .ruff_cache/
16
+ .mypy_cache/
17
+ .coverage
18
+ htmlcov/
19
+
20
+ .DS_Store
21
+ .idea/
22
+ .vscode/
23
+
24
+ .wlens-cache/
@@ -0,0 +1 @@
1
+ 3.11
wlens-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Whimsical
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
wlens-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,305 @@
1
+ Metadata-Version: 2.4
2
+ Name: wlens
3
+ Version: 0.1.0
4
+ Summary: Warehouse lens for AI agents — per-table markdown docs + read-only SQL adaptor, zero-runtime schema exploration for Claude Code, Cursor, Continue.
5
+ Project-URL: Homepage, https://github.com/WhimsicalCode/wlens
6
+ Project-URL: Repository, https://github.com/WhimsicalCode/wlens
7
+ Project-URL: Issues, https://github.com/WhimsicalCode/wlens/issues
8
+ Author: Whimsical
9
+ License: MIT License
10
+
11
+ Copyright (c) 2026 Whimsical
12
+
13
+ Permission is hereby granted, free of charge, to any person obtaining a copy
14
+ of this software and associated documentation files (the "Software"), to deal
15
+ in the Software without restriction, including without limitation the rights
16
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17
+ copies of the Software, and to permit persons to whom the Software is
18
+ furnished to do so, subject to the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be included in all
21
+ copies or substantial portions of the Software.
22
+
23
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29
+ SOFTWARE.
30
+ License-File: LICENSE
31
+ Keywords: agent,ai,claude-code,cursor,dbt,llm,postgres,redshift,schema,warehouse
32
+ Classifier: Development Status :: 3 - Alpha
33
+ Classifier: Intended Audience :: Developers
34
+ Classifier: License :: OSI Approved :: MIT License
35
+ Classifier: Programming Language :: Python :: 3
36
+ Classifier: Programming Language :: Python :: 3.11
37
+ Classifier: Programming Language :: Python :: 3.12
38
+ Classifier: Programming Language :: Python :: 3.13
39
+ Classifier: Topic :: Database
40
+ Classifier: Topic :: Software Development :: Libraries
41
+ Requires-Python: >=3.11
42
+ Requires-Dist: anyio>=4.5
43
+ Requires-Dist: duckdb>=1.0
44
+ Requires-Dist: mcp>=1.27.0
45
+ Requires-Dist: psycopg2-binary>=2.9
46
+ Requires-Dist: pyngrok>=8.0.0
47
+ Requires-Dist: pyyaml>=6.0
48
+ Requires-Dist: ruamel-yaml>=0.18
49
+ Requires-Dist: starlette>=0.27
50
+ Requires-Dist: uvicorn[standard]>=0.46.0
51
+ Provides-Extra: dev
52
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
53
+ Requires-Dist: pytest>=8.0; extra == 'dev'
54
+ Requires-Dist: ruff>=0.6; extra == 'dev'
55
+ Description-Content-Type: text/markdown
56
+
57
+ # wlens
58
+
59
+ > Warehouse lens for AI agents.
60
+
61
+ `wlens` turns your dbt project into per-table markdown docs that any AI agent
62
+ can read, and ships a read-only SQL CLI they can run against your warehouse.
63
+ Works locally via a skill + shell command, or remotely via an MCP server.
64
+
65
+ Works with **Claude Code**, **Cursor**, **Continue**, **Codex**, **Claude Desktop**,
66
+ **Pi** and any MCP-speaking client.
67
+
68
+ ## Why
69
+
70
+ Most "semantic layers for AI" make you maintain a parallel schema spec (YAML
71
+ dimensions/measures) and ship a runtime that exposes a fixed menu of queries
72
+ to the LLM. That fights the way modern agents work.
73
+
74
+ wlens goes the other direction. It **exposes the schema as markdown** —
75
+ descriptions, column types, `relationships()` / `accepted_values()` tests,
76
+ parent models, sample rows, compiled SQL — one file per entity. The LLM
77
+ reads like it would any other codebase; when it needs data, it runs a
78
+ read-only SELECT.
79
+
80
+ - **Zero runtime to explore.** Markdown is committed to the repo. No
81
+ warehouse credentials needed until the agent actually runs a query.
82
+ - **Zero parallel definitions.** Reads directly from dbt artifacts.
83
+ - **LLM-optimized format.** Per-column H3 headers for greppability, enum
84
+ values listed inline (via `accepted_values` tests), foreign keys
85
+ surfaced (via `relationships` tests), column-first sample rows,
86
+ one-sentence index summaries.
87
+ - **Human-editable.** The markdown is the data. Team-authored notes
88
+ preserved across regeneration under a marker.
89
+ - **Two deployment modes.** Solo (filesystem + CLI) or team (MCP server
90
+ with bearer auth).
91
+
92
+ ## Extensibility
93
+
94
+ Beyond dbt models and sources, wlens lets you describe **table
95
+ catalogs** — per-table catalogs of named row-instances like analytics
96
+ events, feature flags, customer attributes, subscription plans. The
97
+ library teaches no domains: it ships only the base `TableCatalog`
98
+ class plus a plugin loader. New kinds live in *your* repo, and the
99
+ worked examples in [`examples/`](examples/) are sized to be cloned
100
+ and adapted by an LLM agent (Claude Code, Cursor, Codex).
101
+
102
+ See [`docs/table-catalogs.md`](docs/table-catalogs.md).
103
+
104
+ ## Quickstart
105
+
106
+ ```bash
107
+ # 1. Install
108
+ uv tool install wlens # or: pip install wlens
109
+
110
+ # 2. Initialise at the root of a dbt project
111
+ cd ~/your-dbt-project
112
+ wlens init
113
+
114
+ # 3. Compile the dbt project (needs a profile configured)
115
+ dbt compile
116
+
117
+ # 4. Generate the per-table markdown
118
+ wlens generate
119
+
120
+ # 5. Your AI agent can now explore wlens/schema/ and run queries
121
+ ```
122
+
123
+ `wlens init` auto-detects `dbt_project.yml` (in cwd, then common subdirs
124
+ like `transform/`, `dbt/`) and any `*.duckdb` file, and wires the config
125
+ accordingly. For Redshift / Postgres you edit a few env var names.
126
+
127
+ After init, your project looks like:
128
+
129
+ ```
130
+ your-repo/
131
+ wlens.yml # config (root, like pyproject.toml)
132
+ wlens/
133
+ .gitignore # auto: ignores cache/ and share/
134
+ schema/ # generated per-table markdown (commit this)
135
+ _index.md
136
+ <schema>.<table>.md
137
+ cache/ # query cache (gitignored)
138
+ share/ # ngrok config files (gitignored)
139
+ .claude/
140
+ skills/
141
+ wlens/
142
+ SKILL.md # Claude Code skill (convention location)
143
+ ```
144
+
145
+ ## The three-move pattern
146
+
147
+ Every warehouse question follows the same shape, regardless of client:
148
+
149
+ 1. **Discover** — find candidate tables.
150
+ 2. **Read** — open one table's full docs.
151
+ 3. **Query** — execute a read-only SELECT.
152
+
153
+ ### In filesystem clients (Claude Code, Cursor, Continue, Codex)
154
+
155
+ The LLM uses its built-in `Grep` + `Read` against `wlens/schema/*.md`,
156
+ then shells out to `wlens query "SELECT …"`.
157
+
158
+ ### In MCP clients (Claude Desktop, or any hosted MCP client)
159
+
160
+ The LLM calls four **tools** exposed by the wlens MCP server:
161
+
162
+ - `search_models(keyword)` — keyword-grep the docs, returns matches with snippets.
163
+ - `list_models()` — full catalog when no keyword fits.
164
+ - `read_model(name)` — full markdown for one entity.
165
+ - `execute_sql(query)` — run the SELECT.
166
+
167
+ Same pattern, different primitives.
168
+
169
+ ## Architecture
170
+
171
+ ```
172
+ dbt artifacts → wlens generate → wlens/schema/*.md ─┬─► filesystem agent
173
+ ▲ │ (grep + read + wlens query)
174
+ build-time │
175
+ (creds once) └─► MCP server (wlens mcp)
176
+ → remote agents
177
+ (Claude Desktop, etc.)
178
+ → search_models / read_model
179
+ / execute_sql tools
180
+ → warehouse (read-only, on demand)
181
+ ```
182
+
183
+ ## `wlens query` — the CLI
184
+
185
+ A Bash-invocable SQL runner with a **hard read-only guard**. Parses your
186
+ SQL and rejects anything that isn't a single `SELECT` / `WITH … SELECT`.
187
+ Multi-statement queries are also rejected. Results come back as a
188
+ markdown table, cached under `wlens/cache/sql/` with a daily TTL
189
+ (`CURRENT_DATE`-relative queries refresh each day).
190
+
191
+ ```bash
192
+ wlens query "SELECT count(*) FROM main_marts.fct_invoice"
193
+ ```
194
+
195
+ Multi-line via heredoc:
196
+
197
+ ```bash
198
+ wlens query <<'SQL'
199
+ select date_trunc('month', invoice_date) as month, sum(total) as revenue
200
+ from main_marts.fct_invoice
201
+ group by 1
202
+ order by 1
203
+ SQL
204
+ ```
205
+
206
+ ## CLI reference
207
+
208
+ | Command | Purpose |
209
+ |---|---|
210
+ | `wlens init` | Write `wlens.yml` + `.claude/skills/wlens/SKILL.md` + `wlens/.gitignore`. Auto-detects dbt project and `.duckdb` files. |
211
+ | `wlens generate` | Read dbt's `target/manifest.json`, write per-table markdown into `wlens/schema/`. |
212
+ | `wlens query "SELECT ..."` | Run a read-only query. |
213
+ | `wlens tag-pii` | Scan dbt yml, add `meta: pii: true` to likely-PII columns. |
214
+ | `wlens mcp` | Start the MCP server for team / demo use. |
215
+ | `wlens mcp-proxy <url>` | Stdio↔HTTP bridge; used by Claude Desktop to reach a remote wlens. |
216
+ | `wlens clean` | Remove every file wlens installed in this repo. |
217
+
218
+ ## Supported warehouses
219
+
220
+ | Warehouse | v0.1 | v0.2 |
221
+ |------------|:----:|:----:|
222
+ | DuckDB | ✅ | |
223
+ | Postgres | ✅ | |
224
+ | Redshift | ✅ | |
225
+ | BigQuery | | ⏳ |
226
+ | Snowflake | | ⏳ |
227
+
228
+ ## PII handling
229
+
230
+ Sample rows committed to the repo go through two redaction layers:
231
+
232
+ 1. **Explicit.** Any dbt column with `meta: pii: true` renders as `<pii>`.
233
+ 2. **Regex safety net.** Column names matching built-in PII patterns
234
+ (`email`, `first_name`, `phone`, `ip_address`, etc.) are redacted
235
+ even without the flag.
236
+
237
+ Run `wlens tag-pii` to backfill the explicit flags (`--dry-run` to preview).
238
+
239
+ ## Distribution tiers
240
+
241
+ wlens ships one binary, three escalating modes:
242
+
243
+ ### 1. Solo — `wlens init` + `wlens generate`
244
+
245
+ Install wlens, point it at a dbt project, use Claude Code / Cursor /
246
+ Continue / Codex with the bundled skill + `wlens query`. Works today.
247
+
248
+ ### 2. Demo a teammate — `wlens mcp --dangerously-share`
249
+
250
+ ```bash
251
+ wlens mcp --dangerously-share
252
+ ```
253
+
254
+ Starts the wlens MCP server locally, opens an ngrok tunnel, auto-generates
255
+ a bearer token, and writes three drop-in files under `wlens/share/`:
256
+
257
+ - `wlens.mcpb` — double-click to install into Claude Desktop. mcp-remote
258
+ and Python deps are pre-bundled; recipient needs nothing beyond Claude.
259
+ - `claude_desktop_config.json` — paste into Claude Desktop's config if
260
+ you prefer editing by hand.
261
+ - `.mcp.json` — drop into a project root for Claude Code (native HTTP).
262
+
263
+ Dies when you Ctrl-C the process. The `--dangerously-` prefix is
264
+ deliberate: a public URL fronting a warehouse is not a production posture.
265
+
266
+ ### 3. Team deployment — `wlens mcp` on your infra
267
+
268
+ ```bash
269
+ export WLENS_AUTH_TOKEN=$(openssl rand -hex 32)
270
+ wlens mcp --port 8000 --allowed-host "*"
271
+ ```
272
+
273
+ Team deployments are **your infra's responsibility** — Railway / Fly /
274
+ Cloud Run / VPS / k8s. wlens doesn't ship Terraform or Helm. What it
275
+ does ship: bearer auth, `/health`, `/refresh` for CI-driven doc updates,
276
+ structured logging, fail-closed startup rules.
277
+
278
+ **Before you deploy, check:**
279
+
280
+ - **Read-only warehouse role.** Create a DB user with `SELECT`-only
281
+ grants. The in-app guard is defence in depth — the role is primary.
282
+ - **`WLENS_AUTH_TOKEN`.** Required. `wlens mcp` refuses to start on a
283
+ non-local bind without it.
284
+ - **TLS at the platform layer.** Your platform terminates TLS; wlens
285
+ binds plain HTTP behind it.
286
+ - **CI-driven docs refresh.** After dbt merges, have CI `POST /refresh`
287
+ so docs stay current without redeploying.
288
+ - **Talk to your platform team.** Auth, secrets, network policy — their
289
+ job, not wlens's.
290
+
291
+ See [`docs/mcp.md`](docs/mcp.md) for the full reference.
292
+
293
+ ## Roadmap
294
+
295
+ - **v0.1** (current): dbt adapter; DuckDB + Postgres + Redshift
296
+ executors; `wlens init / generate / query / tag-pii / clean`; MCP
297
+ server (`wlens mcp`) with bearer auth, four tools, resources, prompts,
298
+ `/refresh` endpoint; `--dangerously-share` with `.mcpb` bundle + drop-in
299
+ config files; stdio↔HTTP proxy (`wlens mcp-proxy`).
300
+ - **v0.2**: sqlmesh adapter; BigQuery + Snowflake executors; Claude Code
301
+ plugin; Claude.ai-remote OAuth support.
302
+
303
+ ## License
304
+
305
+ MIT.