@gizmodata/hardcharger-mcp 0.0.0 → 2.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 +129 -0
- package/LICENSE +201 -0
- package/NOTICE +8 -0
- package/README.md +490 -3
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +75 -0
- package/dist/cli.js.map +1 -0
- package/dist/connection.d.ts +260 -0
- package/dist/connection.js +797 -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/oauth-facade.d.ts +50 -0
- package/dist/oauth-facade.js +223 -0
- package/dist/oauth-facade.js.map +1 -0
- package/dist/oauth.d.ts +94 -0
- package/dist/oauth.js +228 -0
- package/dist/oauth.js.map +1 -0
- package/dist/params.d.ts +61 -0
- package/dist/params.js +200 -0
- package/dist/params.js.map +1 -0
- package/dist/registry.d.ts +45 -0
- package/dist/registry.js +91 -0
- package/dist/registry.js.map +1 -0
- package/dist/server.d.ts +38 -0
- package/dist/server.js +753 -0
- package/dist/server.js.map +1 -0
- package/dist/sessions.d.ts +52 -0
- package/dist/sessions.js +113 -0
- package/dist/sessions.js.map +1 -0
- package/dist/sql-guard.d.ts +62 -0
- package/dist/sql-guard.js +460 -0
- package/dist/sql-guard.js.map +1 -0
- package/dist/sso.d.ts +29 -0
- package/dist/sso.js +145 -0
- package/dist/sso.js.map +1 -0
- package/dist/transports.d.ts +29 -0
- package/dist/transports.js +308 -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 +65 -9
package/README.md
CHANGED
|
@@ -1,5 +1,492 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://github.com/gizmodata/hardcharger">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="docs/assets/hardcharger-banner-dark.png">
|
|
5
|
+
<img src="docs/assets/hardcharger-banner-light.png" alt="Hardcharger™" width="400">
|
|
6
|
+
</picture>
|
|
7
|
+
</a>
|
|
8
|
+
</p>
|
|
2
9
|
|
|
3
|
-
|
|
10
|
+
<p align="center">
|
|
11
|
+
<img src="https://img.shields.io/badge/npm-%40gizmodata%2Fhardcharger--mcp-cb3837.svg?logo=npm" alt="npm: @gizmodata/hardcharger-mcp">
|
|
12
|
+
<img src="https://img.shields.io/badge/MCP-server%20%2B%20Claude%20Desktop%20extension-d97757.svg" alt="MCP server and Claude Desktop extension">
|
|
13
|
+
<img src="https://img.shields.io/badge/TypeScript-ESM-3178C6.svg?logo=typescript&logoColor=white" alt="TypeScript, ESM">
|
|
14
|
+
<img src="https://img.shields.io/badge/Node-%E2%89%A522.19-339933.svg?logo=node.js&logoColor=white" alt="Node 22.19 or later">
|
|
15
|
+
<a href="https://github.com/gizmodata/chargewire"><img src="https://img.shields.io/badge/protocol-Chargewire%201.0.0-31a8db.svg" alt="Chargewire protocol"></a>
|
|
16
|
+
<a href="https://github.com/gizmodata/hardcharger-js"><img src="https://img.shields.io/badge/built%20on-Hardcharger%20JS-31a8db.svg" alt="Built on the Hardcharger JavaScript client"></a>
|
|
17
|
+
<a href="https://github.com/gizmodata/hardcharger"><img src="https://img.shields.io/badge/server-Hardcharger-f15a24.svg" alt="Hardcharger"></a>
|
|
18
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg" alt="Apache 2.0 license"></a>
|
|
19
|
+
<a href="https://gizmodata.com"><img src="https://img.shields.io/badge/by-GizmoData%E2%84%A2-f15a24.svg" alt="GizmoData™"></a>
|
|
20
|
+
</p>
|
|
4
21
|
|
|
5
|
-
|
|
22
|
+
<h3 align="center">Explore and query Hardcharger™ from Claude Desktop, Claude Code and any MCP client.</h3>
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## 🔌 What is it?
|
|
27
|
+
|
|
28
|
+
A [Model Context Protocol](https://modelcontextprotocol.io) server and Claude Desktop extension
|
|
29
|
+
for [Hardcharger™](https://github.com/gizmodata/hardcharger), GizmoData™'s DuckDB 2.0 server. It
|
|
30
|
+
lets Claude Desktop, Claude Code and any other MCP client explore your schema and run SQL against
|
|
31
|
+
a Hardcharger server you can reach from your machine (including private networks over VPN), or,
|
|
32
|
+
over Streamable HTTP, serves a whole team behind OAuth.
|
|
33
|
+
|
|
34
|
+
It speaks [Chargewire](https://github.com/gizmodata/chargewire), Hardcharger's HTTP protocol, through
|
|
35
|
+
the Hardcharger JavaScript client ([`@gizmodata/hardcharger`](https://github.com/gizmodata/hardcharger-js)):
|
|
36
|
+
pure JavaScript, no native driver, so one extension bundle serves every platform Claude Desktop
|
|
37
|
+
runs on. It is the Hardcharger port of
|
|
38
|
+
[gizmosql-mcp](https://github.com/gizmodata/gizmosql-mcp), with the same tools and settings
|
|
39
|
+
(`HARDCHARGER_*` instead of `GIZMOSQL_*`; see [CHANGELOG.md](CHANGELOG.md) for what changed).
|
|
40
|
+
|
|
41
|
+
> **Status: 2.1.0, with Hardcharger 2.3.0.** Built on `@gizmodata/hardcharger` 2.1.0 (hardcharger-js
|
|
42
|
+
> `1a524f6`, on `@gizmodata/chargewire` 2.0.0, chargewire-js `1ea10dd`, Chargewire protocol 1.0.0);
|
|
43
|
+
> tested against the image of Hardcharger's main branch and against Hardcharger 2.2.0, released
|
|
44
|
+
> before the protocol was renamed to Chargewire.
|
|
45
|
+
|
|
46
|
+
## 🧰 Tools
|
|
47
|
+
|
|
48
|
+
| Tool | What it does |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `list_connections()` | Configured Hardcharger connections and which one is current (never credentials) |
|
|
51
|
+
| `use_connection(name)` | Makes a connection the default for subsequent calls |
|
|
52
|
+
| `list_catalogs` | Catalogs (attached databases) visible to the user |
|
|
53
|
+
| `list_schemas(catalog?, include_system?)` | Schemas, optionally in one catalog; system schemas (`information_schema`, `pg_catalog`, `pg_toast`, `pg_temp_*`) are hidden unless `include_system` is true |
|
|
54
|
+
| `list_tables(catalog?, schema?, like?)` | Tables and views with their type; `like` is a SQL LIKE pattern |
|
|
55
|
+
| `describe_table(table, schema?, catalog?)` | Columns, types, nullability, constraints, estimated row count |
|
|
56
|
+
| `use_schema(catalog?, schema?)` | Sets the session's default catalog/schema for unqualified table names |
|
|
57
|
+
| `run_query(sql, params?, max_rows?)` | Runs a query; returns a Markdown table plus structured JSON, capped at `max_rows` |
|
|
58
|
+
| `explain_query(sql)` | DuckDB `EXPLAIN` plan without executing |
|
|
59
|
+
| `execute_statement(sql, params?)` | DML/DDL with affected-row count. Only registered when writes are enabled |
|
|
60
|
+
| `server_info()` | Hardcharger/DuckDB versions, signed-in user and role, connection URI, limits, extension version |
|
|
61
|
+
| `login_sso(wait_seconds?)` | Browser sign-in through the server's identity provider. Only registered when SSO is enabled |
|
|
62
|
+
|
|
63
|
+
Every tool except `list_connections` and `use_connection` also accepts an optional `connection`
|
|
64
|
+
argument naming one of the configured servers (see [Multiple connections](#-multiple-connections)).
|
|
65
|
+
A resource template, `hardcharger://{connection}/schema/{catalog}/{schema}/{table}`, returns the
|
|
66
|
+
DDL of a table or view.
|
|
67
|
+
|
|
68
|
+
### Query parameters
|
|
69
|
+
|
|
70
|
+
`run_query` and `execute_statement` accept a `params` array bound positionally to `?` (or `$1`,
|
|
71
|
+
`$2`, ...) placeholders. Values travel to the server as bound parameters, never as interpolated SQL
|
|
72
|
+
text, so use placeholders for any literal that comes from user input or from data returned by an
|
|
73
|
+
earlier query.
|
|
74
|
+
|
|
75
|
+
- Plain JSON values: string, number, boolean, `null`. The server types each value from where it is
|
|
76
|
+
used, so a date string compared with (or inserted into) a `DATE` or `TIMESTAMP` column is read as
|
|
77
|
+
a date.
|
|
78
|
+
- Explicit types: `{"type": "bigint", "value": "9223372036854775807"}` (exact beyond 2^53),
|
|
79
|
+
`{"type": "date", "value": "2024-01-02"}`, `{"type": "timestamp", ...}`,
|
|
80
|
+
`{"type": "binary", "value": "<base64>"}`, plus `string`, `number`, `boolean` and `null`. A date,
|
|
81
|
+
timestamp or binary parameter binds the row as Arrow data through a prepared statement.
|
|
82
|
+
- A placeholder whose type nothing gives, such as `SELECT ?`, is text unless typed or cast:
|
|
83
|
+
`SELECT ?::INTEGER`.
|
|
84
|
+
|
|
85
|
+
Example `run_query` arguments:
|
|
86
|
+
|
|
87
|
+
<!-- example: tool-call -->
|
|
88
|
+
```json
|
|
89
|
+
{
|
|
90
|
+
"sql": "SELECT id, name FROM customers WHERE created_at >= ? AND region = ? LIMIT 20",
|
|
91
|
+
"params": ["2024-01-01", "EMEA"]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## 🚀 Installation
|
|
96
|
+
|
|
97
|
+
### Claude Desktop extension (`.mcpb`)
|
|
98
|
+
|
|
99
|
+
1. Download `hardcharger-mcp.mcpb` from this repository's
|
|
100
|
+
[Releases](https://github.com/gizmodata/hardcharger-mcp/releases) (each release also carries a
|
|
101
|
+
versioned `hardcharger-mcp-<version>.mcpb` and `.sha256` checksums), or build it with
|
|
102
|
+
`npm run build:mcpb` (see [Building and testing](#%EF%B8%8F-building-and-testing)).
|
|
103
|
+
2. Double-click the file, or in Claude Desktop open **Settings → Extensions → Advanced settings →
|
|
104
|
+
Install Extension…** and pick it.
|
|
105
|
+
3. Fill in the settings: the server's URI (`hardcharger://db.example.com`) and one credential.
|
|
106
|
+
Credentials are marked sensitive and kept in your operating system's keychain.
|
|
107
|
+
4. In a chat, open the **+** menu, choose **Connectors** and make sure **Hardcharger** is on.
|
|
108
|
+
|
|
109
|
+
No Node.js installation is needed: Claude Desktop runs the extension with its own runtime, and the
|
|
110
|
+
bundle holds no native code.
|
|
111
|
+
|
|
112
|
+
### Claude Code
|
|
113
|
+
|
|
114
|
+
<!-- example: claude-code -->
|
|
115
|
+
```bash
|
|
116
|
+
claude mcp add hardcharger \
|
|
117
|
+
-e HARDCHARGER_URI='hardcharger://localhost?tls=false' \
|
|
118
|
+
-e HARDCHARGER_USERNAME=hardcharger \
|
|
119
|
+
-e HARDCHARGER_PASSWORD=change-me \
|
|
120
|
+
-- npx -y @gizmodata/hardcharger-mcp
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Use `-s user` to make it available in every project. Node.js 22.19 or newer is required when
|
|
124
|
+
running through `npx`. Installed globally (`npm install -g @gizmodata/hardcharger-mcp`), the command
|
|
125
|
+
is `hardcharger-mcp`: use `-- hardcharger-mcp` instead of `npx -y @gizmodata/hardcharger-mcp`.
|
|
126
|
+
|
|
127
|
+
### `claude_desktop_config.json` (manual JSON)
|
|
128
|
+
|
|
129
|
+
<!-- example: desktop-json -->
|
|
130
|
+
```json
|
|
131
|
+
{
|
|
132
|
+
"mcpServers": {
|
|
133
|
+
"hardcharger": {
|
|
134
|
+
"command": "npx",
|
|
135
|
+
"args": ["-y", "@gizmodata/hardcharger-mcp"],
|
|
136
|
+
"env": {
|
|
137
|
+
"HARDCHARGER_URI": "hardcharger://localhost?tls=false",
|
|
138
|
+
"HARDCHARGER_USERNAME": "hardcharger",
|
|
139
|
+
"HARDCHARGER_PASSWORD": "change-me"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
These examples connect to a local development server started with
|
|
147
|
+
`HARDCHARGER_ADMIN_USERNAME=hardcharger HARDCHARGER_ADMIN_PASSWORD=change-me hardcharger-server`
|
|
148
|
+
(the [Hardcharger README](https://github.com/gizmodata/hardcharger) has Docker and the
|
|
149
|
+
installers). A real server uses TLS: `hardcharger://db.example.com`.
|
|
150
|
+
|
|
151
|
+
## 🔐 Signing in
|
|
152
|
+
|
|
153
|
+
Each connection takes one credential:
|
|
154
|
+
|
|
155
|
+
| Setting | Sign-in |
|
|
156
|
+
| --- | --- |
|
|
157
|
+
| `HARDCHARGER_USERNAME` + `HARDCHARGER_PASSWORD` | Password (any character, `:` and `@` included) |
|
|
158
|
+
| `HARDCHARGER_TOKEN` | A signed sign-in token the server trusts (`--token-allowed-issuer` with `--token-jwks-uri` or `--token-signature-verify-cert-path`), sent with Chargewire's `token_exchange` grant. The same token also works as the password of user `token`. Its `role` claim (`admin`, `user`, `readonly`) decides what it may do |
|
|
159
|
+
| `HARDCHARGER_MTLS_CERT` + `HARDCHARGER_MTLS_KEY` | Client certificate sign-in (mutual TLS) on a server started with `--mtls-certificate-sign-in`: the certificate is the credential. With a password or token beside them, the certificate only admits the connection |
|
|
160
|
+
| `HARDCHARGER_ENABLE_SSO=true` | No stored credential: `login_sso` signs in through the server's identity provider in your browser |
|
|
161
|
+
|
|
162
|
+
A client certificate from a private CA usually comes with that CA for the server's certificate:
|
|
163
|
+
|
|
164
|
+
<!-- example: mtls -->
|
|
165
|
+
```bash
|
|
166
|
+
HARDCHARGER_URI=hardcharger://localhost \
|
|
167
|
+
HARDCHARGER_MTLS_CERT=client.pem HARDCHARGER_MTLS_KEY=client-key.pem \
|
|
168
|
+
HARDCHARGER_TLS_ROOTS=server-ca.pem \
|
|
169
|
+
npx -y @gizmodata/hardcharger-mcp
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
The identity is the certificate's e-mail SAN unless the server says otherwise; it must be one of
|
|
173
|
+
the server's `--mtls-admin-identities` or, under access control, a user of its store. Refusals keep
|
|
174
|
+
the server's codes: `unknown_certificate_identity` (401) for a certificate that names no user, and
|
|
175
|
+
`client_transport_error` when the handshake fails (an untrusted server certificate without
|
|
176
|
+
`HARDCHARGER_TLS_ROOTS` or `HARDCHARGER_TLS_SKIP_VERIFY`).
|
|
177
|
+
|
|
178
|
+
**Browser sign-in (`login_sso`).** On a server started with `--oauth-client-id` (and its identity
|
|
179
|
+
provider settings), `login_sso` opens the provider's login page through the server's Chargewire
|
|
180
|
+
browser sign-in (on the connection's own URI and port), waits for you to finish, and connects with
|
|
181
|
+
the Hardcharger access token the server hands out, kept in memory only; when it expires, call
|
|
182
|
+
`login_sso` again. A refusal names its code (`access_denied`, `identity_provider_error`,
|
|
183
|
+
`invalid_credentials` for a user the server doesn't allow).
|
|
184
|
+
`HARDCHARGER_BROWSER` names the program that opens the page (default: `open`, `xdg-open`, or the
|
|
185
|
+
Windows URL handler), as in the Hardcharger CLI. It runs on the stdio transport only (over HTTP it
|
|
186
|
+
would open a browser on the server).
|
|
187
|
+
|
|
188
|
+
## 🌐 Streamable HTTP (remote connector)
|
|
189
|
+
|
|
190
|
+
The same server can listen over Streamable HTTP for MCP clients that connect over the network,
|
|
191
|
+
such as a Claude.ai custom connector. The MCP endpoint is `/mcp`; `/healthz` answers health checks.
|
|
192
|
+
Put it behind TLS (an ingress or reverse proxy) before exposing it beyond localhost. Requests are
|
|
193
|
+
authenticated in one of two ways.
|
|
194
|
+
|
|
195
|
+
**OAuth (recommended).** Any OpenID Connect provider that issues signed JWT access tokens works:
|
|
196
|
+
Microsoft Entra ID, Okta (custom authorization server), Auth0, Keycloak, Cognito, Clerk. The server
|
|
197
|
+
is an OAuth 2.1 *resource server*: it verifies each bearer token against the provider's JWKS
|
|
198
|
+
(issuer, audience, signature, expiry) and serves the RFC 9728 metadata at
|
|
199
|
+
`/.well-known/oauth-protected-resource[/mcp]` so clients find the provider on their own. The token
|
|
200
|
+
is never forwarded; the Hardcharger connection uses the configured service credentials.
|
|
201
|
+
|
|
202
|
+
<!-- example: http-oauth -->
|
|
203
|
+
```bash
|
|
204
|
+
HARDCHARGER_URI=hardcharger://hardcharger.internal.example.com \
|
|
205
|
+
HARDCHARGER_USERNAME=mcp_service HARDCHARGER_PASSWORD='service-password' \
|
|
206
|
+
HARDCHARGER_MCP_PUBLIC_URL=https://mcp.example.com/mcp \
|
|
207
|
+
HARDCHARGER_MCP_OAUTH_ISSUER=https://login.microsoftonline.com/<tenant-id>/v2.0 \
|
|
208
|
+
HARDCHARGER_MCP_OAUTH_AUDIENCE=<application-client-id> \
|
|
209
|
+
HARDCHARGER_MCP_OAUTH_SCOPES='https://mcp.example.com/mcp/access_as_user openid profile email offline_access' \
|
|
210
|
+
HARDCHARGER_MCP_OAUTH_TOKEN_PROXY=true \
|
|
211
|
+
HARDCHARGER_MCP_OAUTH_AUTHORIZED_EMAILS='*@example.com' \
|
|
212
|
+
npx -y @gizmodata/hardcharger-mcp --transport http --host 0.0.0.0 --port 3000
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Then add `https://mcp.example.com/mcp` as a custom connector in Claude (Customize > Connectors).
|
|
216
|
+
Claude sends that URL as the OAuth `resource`, discovers the provider from the metadata, runs the
|
|
217
|
+
authorization-code flow with PKCE, and retries with the token. Each tool call is logged with the
|
|
218
|
+
caller's identity, and `server_info` reports it as `authenticated_user`. Each user gets their own
|
|
219
|
+
Hardcharger session, current connection and search path (`HARDCHARGER_MCP_SESSION_IDLE_SECONDS`,
|
|
220
|
+
`HARDCHARGER_MCP_MAX_SESSIONS`); the first result after an expired session says so.
|
|
221
|
+
|
|
222
|
+
Claude requests exactly the scopes named in `HARDCHARGER_MCP_OAUTH_SCOPES`, so include
|
|
223
|
+
`offline_access` alongside the API scope: it is what makes the provider issue a refresh token. The
|
|
224
|
+
server warns at startup when the scope list lacks it and logs every rejected token with the reason.
|
|
225
|
+
|
|
226
|
+
**Token proxy (required for Microsoft Entra ID).** Claude's refresh request carries only the OpenID
|
|
227
|
+
Connect scopes, and Entra refuses it with `AADSTS90009` because it names no resource, so the
|
|
228
|
+
connector stops working when the access token expires (about an hour). With
|
|
229
|
+
`HARDCHARGER_MCP_OAUTH_TOKEN_PROXY=true` the server publishes an authorization-server metadata
|
|
230
|
+
document at `<public origin>/oauth` and proxies the token endpoint at `<public origin>/oauth/token`:
|
|
231
|
+
`refresh_token` grants get the configured API scope and `offline_access` added, everything else
|
|
232
|
+
passes through, and sign-in still happens at the provider. See
|
|
233
|
+
[anthropics/claude-ai-mcp#840](https://github.com/anthropics/claude-ai-mcp/issues/840).
|
|
234
|
+
|
|
235
|
+
Provider notes: **Microsoft Entra ID** has no dynamic client registration, so the person adding the
|
|
236
|
+
connector enters the app registration's client ID and secret under *Advanced settings* (redirect URI
|
|
237
|
+
`https://claude.ai/api/mcp/auth_callback`, *Expose an API* with the MCP URL as Application ID URI
|
|
238
|
+
and a scope such as `access_as_user`, `requestedAccessTokenVersion` 2; v2 tokens carry the client ID
|
|
239
|
+
as `aud`). **Okta** needs a custom authorization server; **Auth0** an API with the audience;
|
|
240
|
+
**Keycloak** works out of the box; **Clerk** issues JWT access tokens by default. Providers with
|
|
241
|
+
opaque access tokens (Google) are not supported in this mode.
|
|
242
|
+
|
|
243
|
+
**Static bearer token.** For a quick shared secret instead of OAuth, set
|
|
244
|
+
`HARDCHARGER_MCP_BEARER_TOKEN`; every request must then send `Authorization: Bearer <token>`. The
|
|
245
|
+
two modes are mutually exclusive. With neither set the endpoint is unauthenticated, for local use
|
|
246
|
+
only.
|
|
247
|
+
|
|
248
|
+
<!-- example: http-bearer -->
|
|
249
|
+
```bash
|
|
250
|
+
HARDCHARGER_URI='hardcharger://localhost?tls=false' \
|
|
251
|
+
HARDCHARGER_USERNAME=hardcharger HARDCHARGER_PASSWORD=change-me \
|
|
252
|
+
HARDCHARGER_MCP_BEARER_TOKEN=a-long-random-secret \
|
|
253
|
+
npx -y @gizmodata/hardcharger-mcp --transport http --port 3000
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### Container image and Helm chart
|
|
257
|
+
|
|
258
|
+
[`Dockerfile`](Dockerfile) builds an image whose entrypoint runs the HTTP transport on port 3000, and
|
|
259
|
+
[`charts/hardcharger-mcp`](charts/hardcharger-mcp) deploys it with a ConfigMap for the
|
|
260
|
+
`HARDCHARGER_*` settings, a Secret (or `existingSecret`) for credentials, and an optional Ingress.
|
|
261
|
+
The release workflow builds both and attaches the packaged chart to the GitHub Release, and pushes
|
|
262
|
+
the image and chart to GHCR when the repository variable `IMAGE_PUBLISH_ENABLED` is `true`.
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
helm upgrade --install hardcharger-mcp charts/hardcharger-mcp \
|
|
266
|
+
--namespace hardcharger-mcp --create-namespace --values values.yaml
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## ⚙️ Configuration
|
|
270
|
+
|
|
271
|
+
All settings are environment variables; the extension's settings screen maps onto the same names.
|
|
272
|
+
Only `HARDCHARGER_*` names are read.
|
|
273
|
+
|
|
274
|
+
| Variable | Default | Description |
|
|
275
|
+
| --- | --- | --- |
|
|
276
|
+
| `HARDCHARGER_URI` | required | `hardcharger://host[:port][/prefix][?tls=false]`: TLS to port 31337 unless the URI says otherwise |
|
|
277
|
+
| `HARDCHARGER_CONNECTION_NAME` | `default` | Name of this connection (used with the `connection` tool argument) |
|
|
278
|
+
| `HARDCHARGER_USERNAME` / `HARDCHARGER_PASSWORD` | | Password sign-in |
|
|
279
|
+
| `HARDCHARGER_TOKEN` | | A signed sign-in token (the `token_exchange` grant) |
|
|
280
|
+
| `HARDCHARGER_MTLS_CERT` / `HARDCHARGER_MTLS_KEY` | | Client certificate and key (PEM files) for mutual TLS; alone, certificate sign-in |
|
|
281
|
+
| `HARDCHARGER_TLS_ROOTS` | system | CA bundle (PEM file) for the server's certificate |
|
|
282
|
+
| `HARDCHARGER_TLS_SKIP_VERIFY` | `false` | Accept self-signed or untrusted certificates |
|
|
283
|
+
| `HARDCHARGER_DEFAULT_CATALOG` | | Catalog for unqualified table names (optional) |
|
|
284
|
+
| `HARDCHARGER_DEFAULT_SCHEMA` | | Schema for unqualified table names (optional) |
|
|
285
|
+
| `HARDCHARGER_ALLOW_WRITES` | `false` | Register `execute_statement` and let `run_query` run non-read statements |
|
|
286
|
+
| `HARDCHARGER_MAX_ROWS` | `500` | Hard cap on rows returned by `run_query` |
|
|
287
|
+
| `HARDCHARGER_MAX_CELL_CHARS` | `200` | Cells longer than this are truncated with `…` |
|
|
288
|
+
| `HARDCHARGER_QUERY_TIMEOUT_SECONDS` | `60` | Per-statement timeout, enforced by the server; `0` disables it |
|
|
289
|
+
| `HARDCHARGER_ENABLE_SSO` | `false` | Register the `login_sso` tool (credentials may then be left empty) |
|
|
290
|
+
| `HARDCHARGER_BROWSER` | platform's | Program that opens the sign-in page for `login_sso` |
|
|
291
|
+
| `HARDCHARGER_MCP_BEARER_TOKEN` | | HTTP transport: static bearer token (mutually exclusive with OAuth) |
|
|
292
|
+
| `HARDCHARGER_MCP_PUBLIC_URL` | | HTTP transport with OAuth: public URL of the `/mcp` endpoint, the OAuth resource identifier |
|
|
293
|
+
| `HARDCHARGER_MCP_OAUTH_ISSUER` | | HTTP transport: OpenID Connect issuer URL; setting it enables OAuth |
|
|
294
|
+
| `HARDCHARGER_MCP_OAUTH_AUDIENCE` | public URL | Accepted `aud` values, comma-separated (Entra ID v2 tokens: the client ID) |
|
|
295
|
+
| `HARDCHARGER_MCP_OAUTH_SCOPES` | | Scopes advertised to clients; include `offline_access` so a refresh token is issued |
|
|
296
|
+
| `HARDCHARGER_MCP_OAUTH_AUTHORIZED_EMAILS` | | Glob allowlist of sign-in emails, e.g. `*@example.com` |
|
|
297
|
+
| `HARDCHARGER_MCP_OAUTH_TOKEN_PROXY` | `false` | Proxy the token endpoint so `refresh_token` grants carry the API scope (required for Entra ID) |
|
|
298
|
+
| `HARDCHARGER_MCP_OAUTH_JWKS_URI` | discovered | JWKS endpoint, when discovery from the issuer is not possible |
|
|
299
|
+
| `HARDCHARGER_MCP_OAUTH_USER_CLAIM` | `email,preferred_username,upn,name,sub` | Claims tried in order to name the caller |
|
|
300
|
+
| `HARDCHARGER_MCP_OAUTH_ALLOW_INSECURE` | `false` | Accept `http://` issuer and public URLs (local testing only) |
|
|
301
|
+
| `HARDCHARGER_MCP_SESSION_IDLE_SECONDS` | `1800` | HTTP transport with OAuth: close a user's session after this long without a request |
|
|
302
|
+
| `HARDCHARGER_MCP_MAX_SESSIONS` | `200` | HTTP transport with OAuth: cap on concurrent user sessions |
|
|
303
|
+
| `HARDCHARGER_2_URI`, `HARDCHARGER_3_URI`, … | | Additional connections, see below |
|
|
304
|
+
| `HARDCHARGER_CONNECTIONS` | | Comma-separated names of further connections, see below |
|
|
305
|
+
|
|
306
|
+
The default catalog and schema are optional session options: if one does not exist, the server
|
|
307
|
+
still starts and reports the problem (with the catalogs it found) in `server_info`. In a chat,
|
|
308
|
+
`use_schema` or a plain `USE catalog.schema` switches for the rest of the session.
|
|
309
|
+
|
|
310
|
+
### 🔀 Multiple connections
|
|
311
|
+
|
|
312
|
+
- **Claude Desktop extension.** The settings screen has two extra slots, *Connection 2* and
|
|
313
|
+
*Connection 3*, each with its own name, URI, credentials and default catalog/schema. Leave a
|
|
314
|
+
slot's URI blank to disable it.
|
|
315
|
+
- **Environment variables.** The slots map to `HARDCHARGER_2_*` and `HARDCHARGER_3_*`
|
|
316
|
+
(`HARDCHARGER_2_URI`, `HARDCHARGER_2_NAME`, `HARDCHARGER_2_USERNAME`, `HARDCHARGER_2_PASSWORD`,
|
|
317
|
+
`HARDCHARGER_2_TOKEN`, ...). For any number of servers, list names in `HARDCHARGER_CONNECTIONS`
|
|
318
|
+
and define each one with the same variables prefixed by the upper-cased name (non-alphanumerics
|
|
319
|
+
become `_`; `mcp` is reserved):
|
|
320
|
+
|
|
321
|
+
<!-- example: multi -->
|
|
322
|
+
```bash
|
|
323
|
+
HARDCHARGER_URI='hardcharger://localhost?tls=false' \
|
|
324
|
+
HARDCHARGER_USERNAME=hardcharger HARDCHARGER_PASSWORD=change-me \
|
|
325
|
+
HARDCHARGER_CONNECTIONS=staging,dev-eu \
|
|
326
|
+
HARDCHARGER_STAGING_URI=hardcharger://hardcharger.staging.example.com \
|
|
327
|
+
HARDCHARGER_STAGING_TOKEN='<a sign-in token>' \
|
|
328
|
+
HARDCHARGER_DEV_EU_URI='hardcharger://localhost?tls=false' \
|
|
329
|
+
HARDCHARGER_DEV_EU_USERNAME=hardcharger HARDCHARGER_DEV_EU_PASSWORD=change-me \
|
|
330
|
+
npx -y @gizmodata/hardcharger-mcp
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
In a chat, `list_connections` shows what is configured, `use_connection` switches the default, and
|
|
334
|
+
every tool accepts a per-call `connection` argument. Connections open lazily; the row cap, timeout
|
|
335
|
+
and read-only settings apply to all of them, while each server's user privileges still govern what
|
|
336
|
+
that connection may do.
|
|
337
|
+
|
|
338
|
+
## 🛡️ Read-only model and security
|
|
339
|
+
|
|
340
|
+
By default the server refuses anything that is not a read. `sql-guard.ts` classifies each statement
|
|
341
|
+
and only lets `SELECT`, `WITH … SELECT`, `FROM`, `VALUES`, `SHOW`, `DESCRIBE`, `SUMMARIZE`,
|
|
342
|
+
`EXPLAIN`, read-style `PRAGMA` and `USE` (search path only) through. CTEs that end in DML, `COPY`,
|
|
343
|
+
`ATTACH`, `INSTALL`, `LOAD`, `SET`, `CALL`, transactions and multi-statement input are rejected.
|
|
344
|
+
`HARDCHARGER_ALLOW_WRITES=true` lifts that and adds `execute_statement`, annotated as destructive so
|
|
345
|
+
clients ask before running it.
|
|
346
|
+
|
|
347
|
+
The guard is defense in depth; the real boundary is the privileges of the Hardcharger user the
|
|
348
|
+
server signs in as. A sign-in token with `role: readonly` can only read (Hardcharger refuses
|
|
349
|
+
anything else with `permission_denied`), and under Hardcharger's access control a store user's
|
|
350
|
+
grants decide what each table allows.
|
|
351
|
+
|
|
352
|
+
- Credentials never appear in tool output, `server_info` or error messages: every message that
|
|
353
|
+
reaches the client is redacted.
|
|
354
|
+
- The row cap is enforced by the server: reads run as `SELECT * FROM (<your query>) LIMIT
|
|
355
|
+
max_rows + 1`, over one result stream that is closed at the cap, which stops the statement.
|
|
356
|
+
- The timeout is the server's (Chargewire `statementTimeoutMs`): it cancels a statement that runs too
|
|
357
|
+
long, `execute_statement` included, and the error says `statement_timeout`. A client-side cancel
|
|
358
|
+
a few seconds later is the backstop.
|
|
359
|
+
- Lost sessions: when Hardcharger evicts an idle session, the client opens a replacement with the
|
|
360
|
+
same catalog and schema (also those set by `use_schema` or `USE`), says so in the log, and counts
|
|
361
|
+
it in `server_info` (`session_replacements`); temporary tables and SQL-level settings of the old
|
|
362
|
+
session are gone. A session an administrator killed, a closed connection or a transport failure
|
|
363
|
+
reopens the connection once and retries (`reconnects`); a refused credential is never retried,
|
|
364
|
+
and neither is a session ended because the sign-in was withdrawn (`token_revoked`,
|
|
365
|
+
`credentials_changed`, `principal_dropped`).
|
|
366
|
+
- The server has no tools that touch the local filesystem or any network endpoint other than the
|
|
367
|
+
configured Hardcharger servers (and, for `login_sso`, the server's sign-in routes and your
|
|
368
|
+
identity provider in your browser).
|
|
369
|
+
|
|
370
|
+
## 🧯 Troubleshooting
|
|
371
|
+
|
|
372
|
+
**`speaks plain HTTP, not TLS: add ?tls=false`.** A `hardcharger://` URI uses TLS unless it says
|
|
373
|
+
`?tls=false`; a development server started without `--tls-cert` needs it.
|
|
374
|
+
|
|
375
|
+
**TLS errors (`self-signed certificate`, `unable to verify`, `client_transport_error`).** Set
|
|
376
|
+
`HARDCHARGER_TLS_ROOTS` to the CA that issued the server's certificate, or (for a throwaway server)
|
|
377
|
+
`HARDCHARGER_TLS_SKIP_VERIFY=true`.
|
|
378
|
+
|
|
379
|
+
**`client_transport_error` to a `10.x`, `172.16.x` or `192.168.x` address.** The extension connects
|
|
380
|
+
directly from your machine: connect your VPN first, then start a new chat. For a server reachable
|
|
381
|
+
only through SSH or Kubernetes, forward the port and use `hardcharger://localhost:31337` (with
|
|
382
|
+
`HARDCHARGER_TLS_SKIP_VERIFY=true` if the certificate names the internal host):
|
|
383
|
+
|
|
384
|
+
```bash
|
|
385
|
+
ssh -N -L 31337:hardcharger.internal:31337 bastion.example.com
|
|
386
|
+
kubectl port-forward svc/hardcharger 31337:31337
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
**`invalid_credentials`, `unknown_certificate_identity`, `permission_denied`.** `server_info` shows
|
|
390
|
+
the user and role the server signed in. Username and password must both be set; a token's issuer,
|
|
391
|
+
audience and e-mail must be ones the server accepts; with SSO, run `login_sso` first.
|
|
392
|
+
|
|
393
|
+
**Tools do not appear in the chat.** Open the **+** menu, choose Connectors and enable Hardcharger.
|
|
394
|
+
After changing settings, start a new chat.
|
|
395
|
+
|
|
396
|
+
**Logs.** Claude Desktop writes the server's stderr to
|
|
397
|
+
`~/Library/Logs/Claude/mcp-server-hardcharger.log` on macOS and `%APPDATA%\Claude\logs\` on Windows.
|
|
398
|
+
|
|
399
|
+
## 🛠️ Building and testing
|
|
400
|
+
|
|
401
|
+
Node 22.19 or later. For development and CI, `@gizmodata/hardcharger` and `@gizmodata/chargewire` are
|
|
402
|
+
built from [gizmodata/hardcharger-js](https://github.com/gizmodata/hardcharger-js) and
|
|
403
|
+
[gizmodata/chargewire-js](https://github.com/gizmodata/chargewire-js) at the commits pinned in
|
|
404
|
+
[scripts/hardcharger-js.commit](scripts/hardcharger-js.commit) and
|
|
405
|
+
[scripts/chargewire-js.commit](scripts/chargewire-js.commit), and packed to `.clients/`, where
|
|
406
|
+
`package-lock.json` finds them, so the tests run against those exact clients. `package.json`, and
|
|
407
|
+
so the published package, names the npm package and its range (`^2.1.0`); the tarballs are a
|
|
408
|
+
stand-in for development and CI only (`scripts/check-lock.mjs` checks both).
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
npm run clients # clone both clients, build and pack the pinned commits
|
|
412
|
+
npm ci
|
|
413
|
+
npm run lint:ci # eslint and the lock's shape
|
|
414
|
+
npm run typecheck # src and tests
|
|
415
|
+
npm test # unit tests (no server)
|
|
416
|
+
npm run build:mcpb # build/hardcharger-mcp-<version>.mcpb + .sha256
|
|
417
|
+
docker build -t hardcharger-mcp . # container image for the HTTP transport
|
|
418
|
+
helm lint charts/hardcharger-mcp # Helm chart
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
`HARDCHARGER_MCP_CHARGEWIRE_JS_REPO` and `HARDCHARGER_MCP_HARDCHARGER_JS_REPO` point
|
|
422
|
+
`npm run clients` at local checkouts.
|
|
423
|
+
|
|
424
|
+
The live suites start `hardcharger-server` themselves, on free loopback ports, with a fresh
|
|
425
|
+
administrator password that contains `:` and `@`, an empty home directory (DuckDB's secrets
|
|
426
|
+
directory included), and only `PATH`, `HOME`, `TMPDIR` and the password in its environment; the MCP
|
|
427
|
+
server under test gets `PATH`, `HOME` and the settings each test names, never your shell's. Without
|
|
428
|
+
the binary they fail; they never skip, and a run in which no test passed fails too. One suite
|
|
429
|
+
checks a Hardcharger released before the protocol was renamed to Chargewire (the
|
|
430
|
+
`ghcr.io/gizmodata/hardcharger:2.2.0` image, already running, plain HTTP), named by
|
|
431
|
+
`HARDCHARGER_MCP_TEST_OLD_SERVER` (`host:port`, with `HARDCHARGER_MCP_TEST_OLD_SERVER_PASSWORD`);
|
|
432
|
+
CI starts one. Without it a full local run leaves that suite out and says so; in CI it fails.
|
|
433
|
+
|
|
434
|
+
```bash
|
|
435
|
+
export HARDCHARGER_MCP_TEST_SERVER_BINARY=/path/to/hardcharger-server
|
|
436
|
+
npm run test:live # every tool over stdio and HTTP, OAuth sessions, every sign-in
|
|
437
|
+
# (password, token, login_sso with a throwaway identity provider,
|
|
438
|
+
# client certificates), lost sessions (eviction, KILL SESSION, restart)
|
|
439
|
+
npm run test:examples # this README's examples, installed from the packed tarball, on 31337
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Negative tests assert the error code (`invalid_credentials`, `permission_denied`,
|
|
443
|
+
`unknown_certificate_identity`, `statement_timeout`, `sql_error`, `client_transport_error`,
|
|
444
|
+
`invalid_option_value`), each beside a positive twin. CI runs everything against the image of
|
|
445
|
+
Hardcharger's main branch (`ghcr.io/gizmodata/hardcharger:main`), pulled with the workflow's
|
|
446
|
+
`GITHUB_TOKEN`; while the image is private the package must grant this repository read access
|
|
447
|
+
(package settings, "Manage Actions access"), or the live jobs fail. CI clones both clients
|
|
448
|
+
anonymously over https.
|
|
449
|
+
|
|
450
|
+
## 📦 Releasing
|
|
451
|
+
|
|
452
|
+
Releases follow [semantic versioning](https://semver.org) and [CHANGELOG.md](CHANGELOG.md): move the
|
|
453
|
+
`[Unreleased]` entries into a `## [X.Y.Z] - YYYY-MM-DD` section, set the same version in
|
|
454
|
+
`package.json`, `manifest.json` and `charts/hardcharger-mcp/Chart.yaml` (`version` and
|
|
455
|
+
`appVersion`), commit, and push `main` and `vX.Y.Z` together. `release.yml` runs the full CI on the
|
|
456
|
+
tagged commit, then makes a GitHub Release with the `.mcpb` bundles, their checksums, the Helm chart
|
|
457
|
+
and the npm tarball, and the CHANGELOG section as notes. Publishing to npm (public; trusted
|
|
458
|
+
publishing, OIDC) runs when the repository variable `NPM_PUBLISH_ENABLED` is `true`, after a check
|
|
459
|
+
that `@gizmodata/hardcharger` is on npm in the range `package.json` names; the image and chart go
|
|
460
|
+
to GHCR when `IMAGE_PUBLISH_ENABLED` is `true`. `npm publish` from a laptop refuses to run.
|
|
461
|
+
|
|
462
|
+
## 🔒 Privacy Policy
|
|
463
|
+
|
|
464
|
+
This extension runs entirely on your computer and talks only to the Hardcharger servers you
|
|
465
|
+
configure (and, when you use `login_sso`, that server's sign-in routes and your identity provider in
|
|
466
|
+
your browser).
|
|
467
|
+
|
|
468
|
+
- **Data collection.** The extension collects nothing. It sends no telemetry, analytics or crash
|
|
469
|
+
reports to GizmoData or anyone else.
|
|
470
|
+
- **Usage and storage.** The SQL your MCP client sends and the rows the server returns pass through
|
|
471
|
+
the extension in memory and are handed back to the client; nothing is written to disk. Connection
|
|
472
|
+
settings are stored by Claude Desktop; credentials marked sensitive are kept in your operating
|
|
473
|
+
system's keychain. An SSO access token is held in process memory only.
|
|
474
|
+
- **Third-party sharing.** Data is shared only with the Hardcharger server you configured. What your
|
|
475
|
+
MCP client (for example Claude) does with tool results is governed by that client's own privacy
|
|
476
|
+
policy.
|
|
477
|
+
- **Data retention.** The extension retains no data between runs. Your Hardcharger server may log
|
|
478
|
+
queries according to its own configuration.
|
|
479
|
+
- **Contact.** Privacy questions: info@gizmodata.com. GizmoData's general privacy policy is at
|
|
480
|
+
<https://gizmodata.com/privacy-policy>.
|
|
481
|
+
|
|
482
|
+
## 📄 License
|
|
483
|
+
|
|
484
|
+
[Apache License 2.0](LICENSE).
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
<p align="center">
|
|
489
|
+
<a href="https://gizmodata.com"><img src="docs/assets/gizmodata-logo.png" alt="GizmoData™" width="56"></a><br>
|
|
490
|
+
<sub>Built by <a href="https://gizmodata.com">GizmoData™</a></sub><br>
|
|
491
|
+
<sub>Hardcharger™ and GizmoData™ are trademarks of GizmoData LLC.</sub>
|
|
492
|
+
</p>
|
package/dist/cli.d.ts
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Entrypoint: `hardcharger-mcp [--transport stdio|http] [--port N] [--host H]`.
|
|
3
|
+
import { parseArgs } from "node:util";
|
|
4
|
+
function usage() {
|
|
5
|
+
return [
|
|
6
|
+
"Usage: hardcharger-mcp [--transport stdio|http] [--port N] [--host H]",
|
|
7
|
+
"",
|
|
8
|
+
" --transport stdio (default) or http (Streamable HTTP on /mcp)",
|
|
9
|
+
" --port HTTP port (default 3000; http transport only)",
|
|
10
|
+
" --host HTTP bind address (default 127.0.0.1; http transport only)",
|
|
11
|
+
" --version print the version",
|
|
12
|
+
" --help show this help",
|
|
13
|
+
"",
|
|
14
|
+
"Configuration is read from HARDCHARGER_* environment variables (see README):",
|
|
15
|
+
"HARDCHARGER_URI=hardcharger://host[:port][?tls=false] and one credential.",
|
|
16
|
+
"HTTP transport authentication: HARDCHARGER_MCP_OAUTH_ISSUER (+ HARDCHARGER_MCP_PUBLIC_URL) for OAuth,",
|
|
17
|
+
"or HARDCHARGER_MCP_BEARER_TOKEN for a static token.",
|
|
18
|
+
].join("\n");
|
|
19
|
+
}
|
|
20
|
+
async function main() {
|
|
21
|
+
const { values } = parseArgs({
|
|
22
|
+
args: process.argv.slice(2),
|
|
23
|
+
options: {
|
|
24
|
+
transport: { type: "string", default: "stdio" },
|
|
25
|
+
port: { type: "string", default: "3000" },
|
|
26
|
+
host: { type: "string", default: "127.0.0.1" },
|
|
27
|
+
help: { type: "boolean", default: false },
|
|
28
|
+
version: { type: "boolean", default: false },
|
|
29
|
+
},
|
|
30
|
+
strict: true,
|
|
31
|
+
});
|
|
32
|
+
if (values.help) {
|
|
33
|
+
console.log(usage());
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const { PACKAGE_VERSION } = await import("./version.js");
|
|
37
|
+
if (values.version) {
|
|
38
|
+
console.log(PACKAGE_VERSION);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const transport = values.transport;
|
|
42
|
+
if (transport !== "stdio" && transport !== "http") {
|
|
43
|
+
console.error(`Unknown --transport "${transport}".\n\n${usage()}`);
|
|
44
|
+
process.exit(2);
|
|
45
|
+
}
|
|
46
|
+
const port = Number(values.port);
|
|
47
|
+
if (!Number.isInteger(port) || port < 0 || port > 65535) {
|
|
48
|
+
console.error(`Invalid --port "${values.port}".`);
|
|
49
|
+
process.exit(2);
|
|
50
|
+
}
|
|
51
|
+
const { parseConfig, ConfigError } = await import("./connection.js");
|
|
52
|
+
let config;
|
|
53
|
+
try {
|
|
54
|
+
config = parseConfig(process.env);
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
if (err instanceof ConfigError) {
|
|
58
|
+
console.error(`[hardcharger-mcp] configuration error: ${err.message}`);
|
|
59
|
+
process.exit(2);
|
|
60
|
+
}
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
const { startStdio, startHttp } = await import("./transports.js");
|
|
64
|
+
if (transport === "stdio") {
|
|
65
|
+
await startStdio(config);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
await startHttp(config, { host: values.host, port });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
main().catch((err) => {
|
|
72
|
+
console.error(`[hardcharger-mcp] fatal: ${err instanceof Error ? err.stack ?? err.message : String(err)}`);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
});
|
|
75
|
+
//# 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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"}
|