@gizmodata/gizmosql-mcp 0.1.0
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.
- package/CHANGELOG.md +39 -0
- package/LICENSE +201 -0
- package/README.md +295 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +107 -0
- package/dist/cli.js.map +1 -0
- package/dist/connection.d.ts +120 -0
- package/dist/connection.js +349 -0
- package/dist/connection.js.map +1 -0
- package/dist/format.d.ts +56 -0
- package/dist/format.js +240 -0
- package/dist/format.js.map +1 -0
- package/dist/params.d.ts +59 -0
- package/dist/params.js +160 -0
- package/dist/params.js.map +1 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.js +446 -0
- package/dist/server.js.map +1 -0
- package/dist/sql-guard.d.ts +57 -0
- package/dist/sql-guard.js +429 -0
- package/dist/sql-guard.js.map +1 -0
- package/dist/sso.d.ts +22 -0
- package/dist/sso.js +143 -0
- package/dist/sso.js.map +1 -0
- package/dist/transports.d.ts +18 -0
- package/dist/transports.js +119 -0
- package/dist/transports.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.js +8 -0
- package/dist/version.js.map +1 -0
- package/package.json +69 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.0] - 2026-09-03
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- Initial MCP server for GizmoSQL built on `@gizmodata/gizmosql-client` 2.x
|
|
14
|
+
(native GizmoSQL ADBC driver) and `@modelcontextprotocol/sdk`.
|
|
15
|
+
- Tools: `list_catalogs`, `list_schemas`, `list_tables`, `describe_table`,
|
|
16
|
+
`run_query` (parameter binding, row cap, cell truncation, structured JSON
|
|
17
|
+
output), `explain_query`, `server_info`, and `execute_statement` (only
|
|
18
|
+
when `GIZMOSQL_ALLOW_WRITES=true`).
|
|
19
|
+
- Optional `login_sso` tool (`GIZMOSQL_ENABLE_SSO=true`) implementing the
|
|
20
|
+
GizmoSQL OAuth/SSO browser flow; the identity token is kept in memory only.
|
|
21
|
+
- `gizmosql://schema/{catalog}/{schema}/{table}` resource returning table/view
|
|
22
|
+
DDL.
|
|
23
|
+
- Read-only guard (`sql-guard.ts`) that rejects non-read statements,
|
|
24
|
+
including CTEs ending in DML, `COPY`, `ATTACH`, `INSTALL`, `SET`, etc.
|
|
25
|
+
- Row cap enforced server-side by wrapping reads in
|
|
26
|
+
`SELECT * FROM (...) LIMIT n+1` and by streaming batches that stop at the
|
|
27
|
+
cap (`executeStream`); query timeout enforced server-side via
|
|
28
|
+
`SET gizmosql.query_timeout` with a client-side `AbortSignal` deadline as
|
|
29
|
+
backstop (requires `@gizmodata/gizmosql-client` 2.2.0).
|
|
30
|
+
- Transports: stdio (default) and stateless Streamable HTTP (`--transport http`,
|
|
31
|
+
`/mcp`) with optional `GIZMOSQL_MCP_BEARER_TOKEN` authentication.
|
|
32
|
+
- Claude Desktop extension packaging (`manifest.json`, `scripts/build-mcpb.sh`)
|
|
33
|
+
bundling the native driver for macOS (arm64/x64), Linux (x64/arm64) and
|
|
34
|
+
Windows x64, verified against the client's `driver-manifest.json`.
|
|
35
|
+
- Privacy Policy section in the README and `privacy_policies` in the manifest
|
|
36
|
+
(required for Anthropic's Connectors Directory).
|
|
37
|
+
- Unit tests (guard, formatting, parameters, config) and Docker-based
|
|
38
|
+
integration tests; GitHub Actions CI and tag-triggered release workflow
|
|
39
|
+
(GitHub Release with `.mcpb` + checksum, npm publish).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
# gizmosql-mcp
|
|
2
|
+
|
|
3
|
+
[](https://github.com/gizmodata/gizmosql-mcp)
|
|
4
|
+
[](https://www.npmjs.com/package/@gizmodata/gizmosql-mcp)
|
|
5
|
+
|
|
6
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server and Claude Desktop
|
|
7
|
+
extension for [GizmoSQL](https://gizmosql.com), the Arrow Flight SQL server built on DuckDB.
|
|
8
|
+
It lets Claude Desktop, Claude Code and any other MCP client explore your schema and run
|
|
9
|
+
SQL against a GizmoSQL server you can reach from your machine (including private
|
|
10
|
+
networks over VPN).
|
|
11
|
+
|
|
12
|
+
Connectivity uses the official [`@gizmodata/gizmosql-client`](https://www.npmjs.com/package/@gizmodata/gizmosql-client)
|
|
13
|
+
and the native [GizmoSQL ADBC driver](https://github.com/gizmodata/gizmosql-adbc), which
|
|
14
|
+
the extension bundles for macOS (Apple Silicon and Intel), Linux (x64 and arm64) and
|
|
15
|
+
Windows x64.
|
|
16
|
+
|
|
17
|
+
## Tools
|
|
18
|
+
|
|
19
|
+
| Tool | What it does |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `list_catalogs` | Catalogs (attached databases) visible to the user |
|
|
22
|
+
| `list_schemas(catalog?)` | Schemas, optionally in one catalog |
|
|
23
|
+
| `list_tables(catalog?, schema?, like?)` | Tables and views with their type; `like` is a SQL LIKE pattern |
|
|
24
|
+
| `describe_table(table, schema?, catalog?)` | Columns, types, nullability, constraints, estimated row count |
|
|
25
|
+
| `run_query(sql, params?, max_rows?)` | Runs a query; returns a Markdown table plus structured JSON, capped at `max_rows` |
|
|
26
|
+
| `explain_query(sql)` | DuckDB `EXPLAIN` plan without executing |
|
|
27
|
+
| `execute_statement(sql, params?)` | DML/DDL with affected-row count. Only registered when writes are enabled |
|
|
28
|
+
| `server_info()` | GizmoSQL/DuckDB versions, redacted connection URI, effective limits, extension version |
|
|
29
|
+
| `login_sso(wait_seconds?)` | Browser-based OAuth/SSO sign-in. Only registered when SSO is enabled |
|
|
30
|
+
|
|
31
|
+
It also exposes a resource template, `gizmosql://schema/{catalog}/{schema}/{table}`, that
|
|
32
|
+
returns the DDL of a table or view.
|
|
33
|
+
|
|
34
|
+
### Query parameters
|
|
35
|
+
|
|
36
|
+
`run_query` and `execute_statement` accept a `params` array bound positionally to `?` (or
|
|
37
|
+
`$1`, `$2`, ...) placeholders. Values travel to the server as typed Arrow data, never as
|
|
38
|
+
interpolated SQL text, so use placeholders for any literal that comes from user input or
|
|
39
|
+
from data returned by an earlier query.
|
|
40
|
+
|
|
41
|
+
- Plain JSON values: string, number, boolean, `null`. Strings in ISO-8601 date or timestamp
|
|
42
|
+
form (`2024-01-02`, `2024-01-02T03:04:05Z`) are bound as timestamps.
|
|
43
|
+
- Explicit types: `{"type": "bigint", "value": "9223372036854775807"}`,
|
|
44
|
+
`{"type": "string", "value": "2024-01-02"}` (keep a date-looking string as text),
|
|
45
|
+
`{"type": "binary", "value": "<base64>"}`, plus `date`, `timestamp`, `number`,
|
|
46
|
+
`boolean` and `null`.
|
|
47
|
+
- A placeholder whose type the server cannot infer from context, such as `SELECT ?`, must
|
|
48
|
+
be cast: `SELECT ?::INTEGER`.
|
|
49
|
+
|
|
50
|
+
Example call:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"sql": "SELECT id, name FROM customers WHERE created_at >= ? AND region = ? LIMIT 20",
|
|
55
|
+
"params": ["2024-01-01", "EMEA"]
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Installation
|
|
60
|
+
|
|
61
|
+
### Claude Desktop extension (`.mcpb`)
|
|
62
|
+
|
|
63
|
+
1. Download `gizmosql-mcp-<version>.mcpb` from the
|
|
64
|
+
[GitHub Releases](https://github.com/gizmodata/gizmosql-mcp/releases) page. The `.sha256`
|
|
65
|
+
file next to it lets you verify the download.
|
|
66
|
+
2. Either double-click the file, or in Claude Desktop open **Settings → Extensions →
|
|
67
|
+
Advanced settings → Install Extension…** and pick the file.
|
|
68
|
+
3. Fill in the settings (host, port, credentials, limits). Credentials are marked sensitive
|
|
69
|
+
and are stored in your operating system's keychain.
|
|
70
|
+
4. In a chat, open the **+** menu, choose **Connectors** and make sure **GizmoSQL** is
|
|
71
|
+
turned on. Tools become available immediately.
|
|
72
|
+
|
|
73
|
+
No Node.js installation is needed: Claude Desktop runs the extension with its bundled
|
|
74
|
+
runtime (Node 24 in current builds), and the native driver for your platform is inside the
|
|
75
|
+
bundle.
|
|
76
|
+
|
|
77
|
+
### Claude Code
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
claude mcp add gizmosql \
|
|
81
|
+
-e GIZMOSQL_HOST=gizmosql.internal.example.com \
|
|
82
|
+
-e GIZMOSQL_PORT=31337 \
|
|
83
|
+
-e GIZMOSQL_USERNAME=analyst \
|
|
84
|
+
-e GIZMOSQL_PASSWORD='your-password' \
|
|
85
|
+
-- npx -y @gizmodata/gizmosql-mcp
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Use `-s user` to make it available in every project. Node.js 22 or newer is required
|
|
89
|
+
when running through `npx`; the client downloads the native driver for your platform on
|
|
90
|
+
first install.
|
|
91
|
+
|
|
92
|
+
### `claude_desktop_config.json` (manual JSON)
|
|
93
|
+
|
|
94
|
+
```json
|
|
95
|
+
{
|
|
96
|
+
"mcpServers": {
|
|
97
|
+
"gizmosql": {
|
|
98
|
+
"command": "npx",
|
|
99
|
+
"args": ["-y", "@gizmodata/gizmosql-mcp"],
|
|
100
|
+
"env": {
|
|
101
|
+
"GIZMOSQL_HOST": "gizmosql.internal.example.com",
|
|
102
|
+
"GIZMOSQL_PORT": "31337",
|
|
103
|
+
"GIZMOSQL_USERNAME": "analyst",
|
|
104
|
+
"GIZMOSQL_PASSWORD": "your-password"
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Streamable HTTP (remote connector)
|
|
112
|
+
|
|
113
|
+
The same server can listen over Streamable HTTP for MCP clients that connect over the
|
|
114
|
+
network, such as a Claude.ai custom connector:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
GIZMOSQL_HOST=gizmosql.internal.example.com \
|
|
118
|
+
GIZMOSQL_USERNAME=analyst GIZMOSQL_PASSWORD='your-password' \
|
|
119
|
+
GIZMOSQL_MCP_BEARER_TOKEN='a-long-random-secret' \
|
|
120
|
+
npx -y @gizmodata/gizmosql-mcp --transport http --host 0.0.0.0 --port 3000
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The MCP endpoint is `http://<host>:3000/mcp` (there is also `/healthz`). When
|
|
124
|
+
`GIZMOSQL_MCP_BEARER_TOKEN` is set, every request must send
|
|
125
|
+
`Authorization: Bearer <token>`; configure that header in the connector's request-header
|
|
126
|
+
settings. Put the server behind TLS (a reverse proxy) before exposing it beyond localhost.
|
|
127
|
+
OAuth for the MCP endpoint itself is not implemented yet; `transports.ts` has the single
|
|
128
|
+
`authorize()` hook where it would go.
|
|
129
|
+
|
|
130
|
+
## Configuration
|
|
131
|
+
|
|
132
|
+
All settings are environment variables. The extension's settings screen maps onto the
|
|
133
|
+
same names.
|
|
134
|
+
|
|
135
|
+
| Variable | Default | Description |
|
|
136
|
+
| --- | --- | --- |
|
|
137
|
+
| `GIZMOSQL_HOST` | required | Hostname or IP of the GizmoSQL server |
|
|
138
|
+
| `GIZMOSQL_PORT` | `31337` | Flight SQL port |
|
|
139
|
+
| `GIZMOSQL_USERNAME` / `GIZMOSQL_PASSWORD` | | Basic authentication |
|
|
140
|
+
| `GIZMOSQL_TOKEN` | | Bearer/JWT token authentication (alternative to username/password) |
|
|
141
|
+
| `GIZMOSQL_PLAINTEXT` | `false` | Connect without TLS (development servers only) |
|
|
142
|
+
| `GIZMOSQL_TLS_SKIP_VERIFY` | `false` | Accept self-signed or untrusted certificates |
|
|
143
|
+
| `GIZMOSQL_ALLOW_WRITES` | `false` | Register `execute_statement` and let `run_query` run non-read statements |
|
|
144
|
+
| `GIZMOSQL_MAX_ROWS` | `500` | Hard cap on rows returned by `run_query` |
|
|
145
|
+
| `GIZMOSQL_MAX_CELL_CHARS` | `200` | Cells longer than this are truncated with `…` |
|
|
146
|
+
| `GIZMOSQL_QUERY_TIMEOUT_SECONDS` | `60` | Per-statement timeout; `0` disables it |
|
|
147
|
+
| `GIZMOSQL_OAUTH_PORT` | `31339` | OAuth HTTP port used by `login_sso` |
|
|
148
|
+
| `GIZMOSQL_ENABLE_SSO` | `false` | Register the `login_sso` tool (credentials may then be left empty) |
|
|
149
|
+
| `GIZMOSQL_MCP_BEARER_TOKEN` | | HTTP transport only: required bearer token |
|
|
150
|
+
|
|
151
|
+
Exactly one authentication method must be configured: username and password, a token, or
|
|
152
|
+
SSO. `GIZMOSQL_DRIVER_LIB` can point at a custom `libadbc_driver_gizmosql` build if you
|
|
153
|
+
need one (see the client README).
|
|
154
|
+
|
|
155
|
+
## Read-only model and security
|
|
156
|
+
|
|
157
|
+
By default the server refuses anything that is not a read. `sql-guard.ts` classifies each
|
|
158
|
+
statement and only lets `SELECT`, `WITH … SELECT`, `FROM`, `VALUES`, `SHOW`, `DESCRIBE`,
|
|
159
|
+
`SUMMARIZE`, `EXPLAIN` and read-style `PRAGMA` through. CTEs that end in DML, `COPY`,
|
|
160
|
+
`ATTACH`, `INSTALL`, `LOAD`, `SET`, `CALL`, transactions and multi-statement input are all
|
|
161
|
+
rejected. Setting `GIZMOSQL_ALLOW_WRITES=true` lifts that restriction and adds
|
|
162
|
+
`execute_statement`, which is annotated as destructive so clients ask before running it.
|
|
163
|
+
|
|
164
|
+
Treat the guard as defense in depth, not as the security boundary. The real boundary is
|
|
165
|
+
the privileges of the GizmoSQL user the server connects as:
|
|
166
|
+
|
|
167
|
+
- With username/password authentication every session has the `admin` role in GizmoSQL.
|
|
168
|
+
- With [token authentication](https://docs.gizmosql.com/token_authentication/) the JWT's
|
|
169
|
+
`role` claim (or the server's `--token-default-role`) decides the role, and GizmoSQL's
|
|
170
|
+
built-in `readonly` role only permits `SELECT` queries. Mint a token with
|
|
171
|
+
`role: readonly` (for example with
|
|
172
|
+
[`generate-gizmosql-token`](https://docs.gizmosql.com/token_authentication/)) and set
|
|
173
|
+
`GIZMOSQL_TOKEN`. GizmoSQL Enterprise adds per-catalog read/write/none permissions in the
|
|
174
|
+
token as well. See the [security guide](https://docs.gizmosql.com/security/).
|
|
175
|
+
|
|
176
|
+
Other guarantees:
|
|
177
|
+
|
|
178
|
+
- Credentials never appear in tool output, `server_info` or error messages; every message
|
|
179
|
+
that reaches the client is redacted.
|
|
180
|
+
- The row cap is enforced by the server: reads are executed as
|
|
181
|
+
`SELECT * FROM (<your query>) LIMIT max_rows + 1`, and the result is streamed in
|
|
182
|
+
batches that stop at the cap, never fetched whole and sliced.
|
|
183
|
+
- The timeout is enforced by the server too, via `SET gizmosql.query_timeout` on the
|
|
184
|
+
session, with a client-side deadline a few seconds later as a backstop that cancels the
|
|
185
|
+
statement (GizmoSQL 1.38.0 or newer interrupts it server-side). DML/DDL run through
|
|
186
|
+
`execute_statement` rely on the server-side timeout alone.
|
|
187
|
+
- One connection per process, opened lazily and reconnected once after a connection-level
|
|
188
|
+
failure. The server has no tools that touch the local filesystem or any network endpoint
|
|
189
|
+
other than the configured GizmoSQL host (and, for `login_sso`, its OAuth endpoint).
|
|
190
|
+
|
|
191
|
+
## Troubleshooting
|
|
192
|
+
|
|
193
|
+
**TLS errors (`certificate verify failed`, `x509`, `unknown authority`).** GizmoSQL uses
|
|
194
|
+
TLS by default. For servers with self-signed certificates enable **Skip TLS certificate
|
|
195
|
+
verification** (`GIZMOSQL_TLS_SKIP_VERIFY=true`). For servers started without TLS enable
|
|
196
|
+
**Plaintext** (`GIZMOSQL_PLAINTEXT=true`) instead.
|
|
197
|
+
|
|
198
|
+
**`connection refused` / `Unavailable` / timeouts to a `10.x`, `172.16.x` or `192.168.x`
|
|
199
|
+
address.** The extension runs on your machine and connects directly, so you must be on the
|
|
200
|
+
same network as the server. Connect your VPN first, then start a new chat. Check with
|
|
201
|
+
`nc -vz <host> 31337` from a terminal.
|
|
202
|
+
|
|
203
|
+
**Port-forward setups.** If the server is only reachable through SSH or Kubernetes, forward
|
|
204
|
+
the port locally and point the extension at `localhost`:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
ssh -N -L 31337:gizmosql.internal:31337 bastion.example.com
|
|
208
|
+
kubectl port-forward svc/gizmosql 31337:31337
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
TLS still works through the tunnel; the certificate is validated against the hostname you
|
|
212
|
+
connect to, so you may need `GIZMOSQL_TLS_SKIP_VERIFY=true` when the certificate was issued
|
|
213
|
+
for the internal name.
|
|
214
|
+
|
|
215
|
+
**Authentication failures.** `server_info` shows the user and auth method the server is
|
|
216
|
+
using. Basic auth needs both username and password; token auth uses only
|
|
217
|
+
`GIZMOSQL_TOKEN`. With SSO, run `login_sso` first.
|
|
218
|
+
|
|
219
|
+
**Tools do not appear in the chat.** Open the **+** menu in the chat, choose Connectors and
|
|
220
|
+
enable GizmoSQL. After changing settings, start a new chat.
|
|
221
|
+
|
|
222
|
+
**"No bundled GizmoSQL ADBC driver for this platform".** The `.mcpb` bundles drivers for
|
|
223
|
+
darwin-arm64, darwin-x64, linux-x64, linux-arm64 and win32-x64. Windows on ARM is not
|
|
224
|
+
supported yet because the ADBC driver manager has no arm64 build.
|
|
225
|
+
|
|
226
|
+
**Logs.** Claude Desktop writes the server's stderr to
|
|
227
|
+
`~/Library/Logs/Claude/mcp-server-gizmosql.log` on macOS and `%APPDATA%\Claude\logs\` on
|
|
228
|
+
Windows. Native driver messages appear there as JSON lines.
|
|
229
|
+
|
|
230
|
+
**`npx` install did not download the driver.** npm 11.19+ asks you to approve install
|
|
231
|
+
scripts: run `npm install-scripts approve @gizmodata/gizmosql-client` in the project, or
|
|
232
|
+
re-run `node node_modules/@gizmodata/gizmosql-client/scripts/download-driver.cjs`.
|
|
233
|
+
|
|
234
|
+
## Development
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
npm install
|
|
238
|
+
npm run build # compile to dist/
|
|
239
|
+
npm test # unit tests (node:test)
|
|
240
|
+
npm run test:integration # starts gizmodata/gizmosql:v1.38.1 in Docker (skips without Docker)
|
|
241
|
+
npm run lint # eslint --fix
|
|
242
|
+
npm run typecheck
|
|
243
|
+
npm run build:mcpb # build/gizmosql-mcp-<version>.mcpb + .sha256
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
Run the server locally against a container:
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
docker run --name gizmosql --detach --tty --init --publish 31337:31337 \
|
|
250
|
+
--env TLS_ENABLED=1 --env GIZMOSQL_USERNAME=gizmosql --env GIZMOSQL_PASSWORD=gizmosql_password \
|
|
251
|
+
gizmodata/gizmosql:v1.38.1
|
|
252
|
+
|
|
253
|
+
GIZMOSQL_HOST=localhost GIZMOSQL_USERNAME=gizmosql GIZMOSQL_PASSWORD=gizmosql_password \
|
|
254
|
+
GIZMOSQL_TLS_SKIP_VERIFY=true node dist/cli.js
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
The integration tests can target an existing server instead of Docker with
|
|
258
|
+
`GIZMOSQL_TEST_HOST`, `GIZMOSQL_TEST_PORT`, `GIZMOSQL_TEST_USERNAME` and
|
|
259
|
+
`GIZMOSQL_TEST_PASSWORD` (TLS with an untrusted certificate is assumed).
|
|
260
|
+
|
|
261
|
+
### Releasing
|
|
262
|
+
|
|
263
|
+
1. Move the `[Unreleased]` entries in `CHANGELOG.md` into a new `## [X.Y.Z] - YYYY-MM-DD`
|
|
264
|
+
section and set the same version in `package.json` and `manifest.json`.
|
|
265
|
+
2. Commit, tag `vX.Y.Z`, and push: `git push origin main vX.Y.Z`.
|
|
266
|
+
3. The release workflow runs the tests, builds the `.mcpb`, creates a GitHub Release with
|
|
267
|
+
the bundle, its checksum and the npm tarball (release notes come from the CHANGELOG
|
|
268
|
+
section), and publishes `@gizmodata/gizmosql-mcp` to npm.
|
|
269
|
+
|
|
270
|
+
See [NOTES.md](NOTES.md) for implementation notes, known limitations and follow-ups.
|
|
271
|
+
|
|
272
|
+
## Privacy Policy
|
|
273
|
+
|
|
274
|
+
This extension runs entirely on your computer and talks only to the GizmoSQL server you
|
|
275
|
+
configure (and, when you use `login_sso`, that server's OAuth endpoint and your identity
|
|
276
|
+
provider in your browser).
|
|
277
|
+
|
|
278
|
+
- **Data collection.** The extension collects nothing. It does not send telemetry,
|
|
279
|
+
analytics or crash reports to GizmoData or anyone else.
|
|
280
|
+
- **Usage and storage.** The SQL your MCP client sends and the rows the server returns
|
|
281
|
+
pass through the extension in memory and are handed back to the client; nothing is
|
|
282
|
+
written to disk. Connection settings are stored by Claude Desktop; credentials marked
|
|
283
|
+
sensitive are kept in your operating system's keychain. An SSO identity token is held
|
|
284
|
+
in process memory only and discarded when the extension exits.
|
|
285
|
+
- **Third-party sharing.** Data is shared only with the GizmoSQL server you configured.
|
|
286
|
+
What your MCP client (for example Claude) does with tool results is governed by that
|
|
287
|
+
client's own privacy policy.
|
|
288
|
+
- **Data retention.** The extension retains no data between runs. Your GizmoSQL server
|
|
289
|
+
may log queries according to its own configuration.
|
|
290
|
+
- **Contact.** privacy questions: info@gizmodata.com. GizmoData's general privacy policy is
|
|
291
|
+
at <https://gizmodata.com/privacy-policy>.
|
|
292
|
+
|
|
293
|
+
## License
|
|
294
|
+
|
|
295
|
+
Apache License 2.0
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Entrypoint: `gizmosql-mcp [--transport stdio|http] [--port N] [--host H]`.
|
|
3
|
+
//
|
|
4
|
+
// Bundled-driver resolution happens here, before the client is imported:
|
|
5
|
+
// when a `drivers/<platform>-<arch>/` directory sits next to this file
|
|
6
|
+
// (the .mcpb layout), point the client at it and disable downloads.
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
import { parseArgs } from "node:util";
|
|
11
|
+
const DRIVER_EXT = { darwin: ".dylib", linux: ".so", win32: ".dll" };
|
|
12
|
+
function configureBundledDriver() {
|
|
13
|
+
if (process.env.GIZMOSQL_DRIVER_LIB)
|
|
14
|
+
return;
|
|
15
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
+
const driversDir = path.join(here, "drivers");
|
|
17
|
+
if (!fs.existsSync(driversDir))
|
|
18
|
+
return; // npm layout: the client's own download is used
|
|
19
|
+
const key = `${process.platform}-${process.arch}`;
|
|
20
|
+
const ext = DRIVER_EXT[process.platform];
|
|
21
|
+
const lib = ext ? path.join(driversDir, key, `libadbc_driver_gizmosql${ext}`) : undefined;
|
|
22
|
+
if (!lib || !fs.existsSync(lib)) {
|
|
23
|
+
let available = [];
|
|
24
|
+
try {
|
|
25
|
+
available = fs.readdirSync(driversDir).filter((d) => !d.startsWith("."));
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// ignore
|
|
29
|
+
}
|
|
30
|
+
console.error(`[gizmosql-mcp] No bundled GizmoSQL ADBC driver for this platform (${key}). ` +
|
|
31
|
+
`Bundled platforms: ${available.join(", ") || "none"}. ` +
|
|
32
|
+
"Set GIZMOSQL_DRIVER_LIB to a libadbc_driver_gizmosql library built for this platform " +
|
|
33
|
+
"(https://github.com/gizmodata/gizmosql-adbc).");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
process.env.GIZMOSQL_DRIVER_SKIP_DOWNLOAD = "1";
|
|
37
|
+
process.env.GIZMOSQL_DRIVER_LIB = lib;
|
|
38
|
+
}
|
|
39
|
+
function usage() {
|
|
40
|
+
return [
|
|
41
|
+
"Usage: gizmosql-mcp [--transport stdio|http] [--port N] [--host H]",
|
|
42
|
+
"",
|
|
43
|
+
" --transport stdio (default) or http (Streamable HTTP on /mcp)",
|
|
44
|
+
" --port HTTP port (default 3000; http transport only)",
|
|
45
|
+
" --host HTTP bind address (default 127.0.0.1; http transport only)",
|
|
46
|
+
" --help show this help",
|
|
47
|
+
"",
|
|
48
|
+
"Configuration is read from GIZMOSQL_* environment variables (see README).",
|
|
49
|
+
].join("\n");
|
|
50
|
+
}
|
|
51
|
+
async function main() {
|
|
52
|
+
const { values } = parseArgs({
|
|
53
|
+
args: process.argv.slice(2),
|
|
54
|
+
options: {
|
|
55
|
+
transport: { type: "string", default: "stdio" },
|
|
56
|
+
port: { type: "string", default: "3000" },
|
|
57
|
+
host: { type: "string", default: "127.0.0.1" },
|
|
58
|
+
help: { type: "boolean", default: false },
|
|
59
|
+
version: { type: "boolean", default: false },
|
|
60
|
+
},
|
|
61
|
+
strict: true,
|
|
62
|
+
});
|
|
63
|
+
if (values.help) {
|
|
64
|
+
console.log(usage());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
configureBundledDriver();
|
|
68
|
+
const { PACKAGE_VERSION } = await import("./version.js");
|
|
69
|
+
if (values.version) {
|
|
70
|
+
console.log(PACKAGE_VERSION);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const transport = values.transport;
|
|
74
|
+
if (transport !== "stdio" && transport !== "http") {
|
|
75
|
+
console.error(`Unknown --transport "${transport}".\n\n${usage()}`);
|
|
76
|
+
process.exit(2);
|
|
77
|
+
}
|
|
78
|
+
const port = Number(values.port);
|
|
79
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
80
|
+
console.error(`Invalid --port "${values.port}".`);
|
|
81
|
+
process.exit(2);
|
|
82
|
+
}
|
|
83
|
+
const { parseConfig, ConfigError } = await import("./connection.js");
|
|
84
|
+
let config;
|
|
85
|
+
try {
|
|
86
|
+
config = parseConfig(process.env);
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
if (err instanceof ConfigError) {
|
|
90
|
+
console.error(`[gizmosql-mcp] configuration error: ${err.message}`);
|
|
91
|
+
process.exit(2);
|
|
92
|
+
}
|
|
93
|
+
throw err;
|
|
94
|
+
}
|
|
95
|
+
const { startStdio, startHttp } = await import("./transports.js");
|
|
96
|
+
if (transport === "stdio") {
|
|
97
|
+
await startStdio(config);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
await startHttp(config, { host: values.host, port });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
main().catch((err) => {
|
|
104
|
+
console.error(`[gizmosql-mcp] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
|
|
105
|
+
process.exit(1);
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|