@superglue/cli 1.1.29 → 1.1.30

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.
@@ -272,7 +272,8 @@ sg mcp edit --id <serverId> --auth-mode creator_api_key
272
272
 
273
273
  ```bash
274
274
  sg run list --tool my-tool --status failed --limit 20
275
- sg run get <runId> --fetch-results
275
+ sg run get <runId> --full
276
+ sg run get <runId> --fetch-results # alias for --full
276
277
  ```
277
278
 
278
279
  **File attachments:**
@@ -397,16 +398,14 @@ sourceData = {
397
398
 
398
399
  ### Naming Rules — Avoiding Key Collisions
399
400
 
400
- Everything in `sourceData` shares ONE flat namespace, and the runtime does not detect collisions — when two sources use the same key, one silently wins and the tool misbehaves with no error. Prevent collisions at design time:
401
+ Everything in `sourceData` shares ONE flat namespace. Saving a tool rejects payload input keys and step ids that collide with it:
401
402
 
402
- Never use these as payload input keys or step ids:
403
+ - `__files__`, `currentItem`, `sg_auth_email` — injected by the runtime
404
+ - `page`, `offset`, `cursor`, `limit`, `pageSize` — rejected only when the tool has a paginated step, because they would shadow the live pagination counters; on non-paginated tools they are allowed but discouraged (a later edit that adds pagination will force a rename)
405
+ - the tool's own step ids — the step result overwrites a same-named payload key
406
+ - anything starting with `<systemId>_` for a system the tool uses — the entire prefix is reserved for namespaced credentials (`<systemId>_<credKey>`, `<systemId>_url`), even names that don't match an existing credential, because credentials added to the system later would silently shadow the input
403
407
 
404
- - `__files__`, `currentItem`, `sg_auth_email` — overwritten by the runtime
405
- - `page`, `offset`, `cursor`, `limit`, `pageSize` — a payload key with one of these names shadows the live pagination counters; paginated steps silently stop advancing past the first page
406
- - the tool's own step ids — the step result overwrites a same-named payload key for all subsequent steps
407
- - credential keys available to a step (`<systemId>_<credKey>`, `<systemId>_url`, and any runtime-supplied credential names) — the credential value silently replaces the payload value
408
-
409
- Safe naming: payload inputs get specific, domain-flavored names (`customerId`, `reportMonth`, `maxResults` — never `page`, `limit`, `cursor`, `data`); step ids are verb-prefixed camelCase (`fetchUsers`) and distinct from every payload key. If the user asks for an input named like a reserved key, use a safe alternative and explain why.
408
+ Safe naming: payload inputs get specific, domain-flavored names (`customerId`, `reportMonth`, `maxResults` — prefer `maxResults` over `limit` even on non-paginated tools, and never prefix an input with a referenced system's id); step ids are verb-prefixed camelCase (`fetchUsers`) and distinct from every payload key. If the user asks for an input named like a reserved key, use a safe alternative and explain why.
410
409
 
411
410
  ### Step Result Envelopes
412
411
 
@@ -559,7 +558,7 @@ sg system create --name "My API" --url https://api.example.com \
559
558
 
560
559
  ### Draft Management
561
560
 
562
- Drafts live in `.superglue/drafts/<draftId>.json`. Created by `sg tool build`, updated by `sg tool edit`, deleted by `sg tool save`. Ephemeral — not persisted across sessions.
561
+ Drafts live under the active CLI config directory: local `.superglue/drafts/` when a project config exists, otherwise `~/.superglue/drafts/`. Draft filenames are base64url-encoded draft IDs, so use the `draftPath` returned by `sg tool build` and `sg tool edit` when inspecting raw draft files. Created by `sg tool build`, updated by `sg tool edit`, deleted by `sg tool save`. Ephemeral — not persisted to the superglue API until saved.
563
562
 
564
563
  ### Deployment
565
564
 
@@ -602,7 +601,7 @@ curl -X POST "https://api.superglue.cloud/v1/hooks/{toolId}?token=$SUPERGLUE_API
602
601
  - **POST for read-only ops** — GraphQL queries via POST should have `modify: false`. Don't rely on HTTP method alone
603
602
  - **Saving without approval** — always present `sg tool run` results and ask before `sg tool save`
604
603
  - **`sg_auth_email` in scheduled runs** — not available in scheduler-triggered executions. Tools using `<<sg_auth_email>>` will fail
605
- - **Reserved key collisions** — payload inputs or step ids named after reserved/injected keys (see Naming Rules) fail silently with wrong values, never with an error
604
+ - **Reserved key collisions** — payload inputs or step ids named after reserved/injected keys (see Naming Rules) are rejected at save time; pick a different name instead of retrying
606
605
 
607
606
  ---
608
607
 
@@ -612,7 +611,7 @@ For protocol-specific error recovery (HTTP, Postgres, MSSQL, Redis, GraphQL, SFT
612
611
 
613
612
  ### Tool build fails validation
614
613
 
615
- `sg tool build` returns a validation error. Read the message, fix the config, and re-run. Common causes: missing `id`, empty `steps`, missing `url` on request steps, missing `transformCode` on transform steps, `systemId` on the step object instead of `step.config.systemId`.
614
+ `sg tool build` returns a validation error. Read the message, fix the config, and re-run. Common causes: missing `id`, empty `steps`, missing `url` on request steps, missing `transformCode` on transform steps, `systemId` on the step object instead of `step.config.systemId`, or a key name collision (see Naming Rules) — rename the flagged input or step id.
616
615
 
617
616
  ### Tool runs but a step fails
618
617
 
@@ -642,7 +641,6 @@ For protocol-specific error recovery (HTTP, Postgres, MSSQL, Redis, GraphQL, SFT
642
641
  2. Re-run with `--include-step-results` to see the exact envelope shape
643
642
  3. Paginated steps merge into a single `.data` field — do not `.map()` over them
644
643
  4. Verify `sourceData.currentItem` is only referenced inside looping steps (set by the step's own `dataSelector`, not upstream)
645
- 5. If a step silently received the wrong value (no error thrown) or pagination stopped after one page, check for a key collision between payload inputs, step ids, credential keys, and reserved runtime keys — see Naming Rules. Fix by renaming the input, not by working around it
646
644
 
647
645
  ### Persistent failures
648
646
 
@@ -196,11 +196,14 @@ pagination: {
196
196
  | cursorBased | `<<cursor>>` | null | extracted via cursorPath |
197
197
  | all | `<<limit>>` / `<<pageSize>>` | pageSize | — |
198
198
 
199
- **Stop conditions** — JS expression evaluated in sandbox. Receives `(response, pageInfo)`:
199
+ **Stop conditions** — JS expression evaluated in sandbox. Receives `(response, pageInfo, sourceData)`:
200
200
 
201
201
  - `response.data` = parsed API response body
202
202
  - `response.headers` = response headers
203
- - `pageInfo = { page, offset, cursor, totalFetched }`
203
+ - `pageInfo = { page, offset, cursor, totalFetched, mergedResult }`
204
+ - `pageInfo.totalFetched` counts the merged paginated result including the current page
205
+ - `pageInfo.mergedResult` is the accumulated paginated result including the current page
206
+ - `sourceData` contains the current step input data, with payload fields at the root plus previous step results
204
207
  - Return `true` to STOP
205
208
 
206
209
  ```javascript
@@ -208,6 +211,7 @@ pagination: {
208
211
  "response.data.items.length === 0";
209
212
  "response.data.hasMore === false";
210
213
  "pageInfo.totalFetched >= 1000";
214
+ "pageInfo.totalFetched >= sourceData.maxResults";
211
215
  ```
212
216
 
213
217
  **Cursor extraction:** `cursorPath` is a simple dot-separated property path (e.g. `meta.next_cursor`, `data.0.id`) resolved against the parsed response body. It is not a JSONPath expression — wildcards, filters, and `$.` prefixes are not supported. For property names containing `@` (e.g. OData `@odata.nextLink`), use the name directly as the path. Null/undefined cursor stops pagination.
@@ -233,7 +237,7 @@ When an HTTP step downloads a file (PDF, CSV, binary response), set `outputFile:
233
237
 
234
238
  ## Common Pitfalls
235
239
 
236
- - Hardcoding base URLs that match the system's base URL instead of using `<<systemId_url>>`
240
+ - Hardcoding base URLs that match the system's base URL instead of using `<<systemId_url>>`. Check with `sg system call` what format the URL is and if it contains e.g. a trailing slash.
237
241
  - Forgetting auth headers entirely — nothing is injected automatically, including for OAuth systems (only token refresh is automatic)
238
242
  - Forgetting `outputFile: true` on steps that download files the user wants
239
243
  - Putting pagination variables in the config but not setting a `pagination` block, or vice versa
@@ -1,5 +1,7 @@
1
1
  # MSSQL
2
2
 
3
+ **This skill is for Microsoft SQL Server and Azure SQL only.** For SAP ASE (Sybase), use the `odbc` skill — SAP ASE requires the ODBC strategy with `odbc://` URLs, not `mssql://`.
4
+
3
5
  ## Step Configuration
4
6
 
5
7
  ```typescript
@@ -44,17 +46,29 @@ Azure SQL usernames often include `@servername` suffix (e.g., `myuser@myserver`)
44
46
  mssql://myuser%40myserver:mypassword@myserver.database.windows.net:1433/mydatabase
45
47
  ```
46
48
 
49
+ **Named instances** (common for on-prem servers, e.g. ProLaw's `SERVER\PROLAW`) — use the `instanceName` query parameter. Backslash syntax (`SERVER\PROLAW`) in the host is rejected with an error; always translate it to the query parameter:
50
+
51
+ ```
52
+ mssql://user:password@SERVER/database?instanceName=PROLAW
53
+ ```
54
+
55
+ When an instance name is set, the port is ignored — the instance's port is resolved via the SQL Browser service (UDP 1434), which must be running and reachable. If SQL Browser is unavailable (or the server is reached through the Secure Gateway tunnel, which forwards a single TCP port and cannot carry UDP), have the DBA assign a static TCP port to the instance and connect with `host:port` without an instance name instead.
56
+
47
57
  **Connection parameters** can be appended as query strings:
48
58
 
49
59
  ```
50
60
  mssql://user:password@host:port/database?encrypt=true&trustServerCertificate=false
51
61
  ```
52
62
 
53
- | Parameter | Default | Notes |
54
- | ------------------------ | ------- | --------------------------------------- |
55
- | `encrypt` | `true` | Required for Azure SQL |
56
- | `trustServerCertificate` | `false` | Whether to trust the server certificate |
57
- | `database` | — | Can be in URL path or query parameter |
63
+ | Parameter | Default | Notes |
64
+ | ------------------------ | ------- | --------------------------------------------------- |
65
+ | `encrypt` | `true` | Required for Azure SQL |
66
+ | `trustServerCertificate` | `false` | Whether to trust the server certificate |
67
+ | `database` | — | Can be in URL path or query parameter |
68
+ | `instanceName` | — | SQL Server named instance (case-sensitive spelling) |
69
+ | `domain` | — | Windows domain — switches to NTLM authentication |
70
+
71
+ Unknown connection parameters cause an error rather than being silently ignored.
58
72
 
59
73
  ### Body Format
60
74
 
@@ -77,6 +91,24 @@ Credentials are embedded directly in the connection URL using `<<systemId_creden
77
91
  mssql://<<my_db_user>>:<<my_db_password>>@<<my_db_host>>:<<my_db_port>>/<<my_db_database>>
78
92
  ```
79
93
 
94
+ ### Windows Authentication (NTLM)
95
+
96
+ For on-prem SQL Servers that only accept Windows domain logins (no SQL auth), store these credential keys on the system:
97
+
98
+ | Credential Key | Required | Notes |
99
+ | -------------- | -------- | ----------------------------------------------------- |
100
+ | `authType` | yes | `ntlm` |
101
+ | `domain` | yes | Windows domain (e.g. `CORP`) |
102
+ | `user` | yes | Windows username (also accepts `username`, or in URL) |
103
+ | `password` | yes | Windows password (or in URL) |
104
+
105
+ ```
106
+ URL: mssql://<<sys_user>>:<<sys_password>>@<<sys_host>>:<<sys_port>>/<<sys_database>>
107
+ Credentials: { authType: "ntlm", domain, user, password, host, port, database }
108
+ ```
109
+
110
+ Alternatively, pass the domain as a `?domain=CORP` query parameter on the URL — any URL with a `domain` set authenticates via NTLM. Kerberos-only environments are not supported; ask the DBA to permit NTLM or create a SQL login.
111
+
80
112
  ### Azure Active Directory Authentication
81
113
 
82
114
  For Azure AD auth, store the following credential keys on the system alongside the standard connection fields:
@@ -91,7 +123,7 @@ For Azure AD auth, store the following credential keys on the system alongside t
91
123
  | `user` | yes | Azure AD username (also accepts `username`, or in URL) |
92
124
  | `password` | yes | Azure AD password (or in URL) |
93
125
 
94
- `user` and `password` can be stored as credentials or embedded in the URL — credentials take precedence.
126
+ `user` and `password` can be stored as credentials or embedded in the URL — values resolved into the URL take precedence; stored credentials only fill gaps the URL omits.
95
127
 
96
128
  ```
97
129
  URL: mssql://<<sys_user>>:<<sys_password>>@myserver.database.windows.net:1433/mydb
@@ -160,11 +192,14 @@ With OUTPUT (MSSQL equivalent of RETURNING):
160
192
 
161
193
  ### Return Value
162
194
 
163
- Returns the recordset — array of row objects with column names as keys.
195
+ The shape depends on what the query produces:
164
196
 
165
- - `SELECT`: array of matching rows
197
+ - `SELECT` (single recordset): array of row objects with column names as keys
166
198
  - `INSERT/UPDATE/DELETE` with `OUTPUT`: array of returned rows
167
- - Mutations without `OUTPUT`: empty array
199
+ - Mutations without `OUTPUT`: `{ "rowsAffected": [n] }` — one count per statement
200
+ - Stored procedures / batches returning multiple recordsets: array of recordset arrays (e.g. `[[...rows], [...rows]]`)
201
+
202
+ Check the shape before indexing: a multi-recordset result is an array of arrays, not a flat row list.
168
203
 
169
204
  ### Batch Operations
170
205
 
@@ -182,6 +217,15 @@ Use a data selector returning an array to execute a query per item:
182
217
  - Idle pools cleaned up automatically
183
218
  - SSL/TLS encryption enabled by default for Azure SQL
184
219
 
220
+ ### On-Prem SQL Server (e.g. ProLaw, legacy ERP)
221
+
222
+ Defaults are tuned for Azure SQL; on-prem servers usually need adjustments:
223
+
224
+ - **Self-signed certificates** — on-prem servers rarely have CA-signed certs, so the default `trustServerCertificate=false` fails the TLS handshake. Add `?trustServerCertificate=true` (keeps encryption, skips CA validation).
225
+ - **Old SQL Server versions** — SQL Server 2008/2008 R2 without TLS 1.2 patches cannot complete a modern TLS handshake. Use `?encrypt=false` as a last resort, preferably only over the Secure Gateway tunnel.
226
+ - **Named instances** — use the `?instanceName=` query parameter (see URL Format above); remember SQL Browser (UDP 1434) is required for instance resolution and does not work through the Secure Gateway tunnel.
227
+ - **Firewalled servers** — on-prem databases are typically not internet-reachable; configure the system with a Secure Gateway tunnel.
228
+
185
229
  ### Retry Behavior
186
230
 
187
231
  Default retries from server config. On final failure, error includes query text and params.
@@ -189,9 +233,12 @@ Default retries from server config. On final failure, error includes query text
189
233
  ## Common Pitfalls
190
234
 
191
235
  - Using `$1`, `$2` (PostgreSQL syntax) instead of `@param1`, `@param2` — MSSQL uses named `@param` parameters
192
- - Forgetting `OUTPUT INSERTED.*` on INSERT/UPDATE/DELETE when you need the result — without it the step returns an empty array
236
+ - Forgetting `OUTPUT INSERTED.*` on INSERT/UPDATE/DELETE when you need the row data — without it the step returns `{ "rowsAffected": [n] }`, not rows
237
+ - Treating a multi-recordset stored procedure result as a flat row array — it is an array of recordset arrays
193
238
  - Accessing step result directly instead of via `.data` — database results follow the same envelope as all steps: `sourceData.stepId.data`
194
239
  - Not URL-encoding `@` in Azure SQL usernames — `myuser@myserver` must be `myuser%40myserver` in the connection URL
240
+ - Using a named instance through the Secure Gateway tunnel — instance resolution needs UDP 1434, which the tunnel does not forward; use a static TCP port instead
241
+ - Forgetting `?trustServerCertificate=true` for on-prem servers with self-signed certificates
195
242
 
196
243
  ## Error Recovery
197
244
 
@@ -204,4 +251,8 @@ When an MSSQL step fails and the cause is not obvious:
204
251
  - Confirm the client IP is allowed in the Azure SQL firewall rules
205
252
  - Verify the username includes the `@servername` suffix if required, properly encoded as `%40`
206
253
  - Confirm `encrypt=true` is set (required for Azure SQL)
207
- 5. **Verify parameter types** — MSSQL infers types from the values passed. Passing a string where a number is expected may cause implicit conversion errors. Ensure `params` values match expected column types.
254
+ 5. **Check on-prem connection issues** — if connecting to an on-prem server:
255
+ - TLS handshake errors (`self signed certificate`, `unable to verify`) → add `?trustServerCertificate=true`; for unpatched SQL Server 2008-era hosts, `?encrypt=false`
256
+ - `Failed to connect ... in 15000ms` with a named instance → SQL Browser (UDP 1434) is unreachable; use a static TCP port instead
257
+ - `Login failed` with Windows-auth-only servers → set `authType: "ntlm"` and `domain` in credentials, or ask the DBA for a SQL login
258
+ 6. **Verify parameter types** — MSSQL infers types from the values passed. Passing a string where a number is expected may cause implicit conversion errors. Ensure `params` values match expected column types.
@@ -51,18 +51,18 @@ Use this section as the source of truth for high-level web app navigation. Do no
51
51
  The persistent left sidebar contains these top-level items:
52
52
 
53
53
  - **Agent** (`/`) — primary AI chat assistant for building and debugging tools and systems.
54
- - **Landscape** (`/landscape`) — graph overview of tools, systems, and their connections.
55
54
  - **Tools** (`/tools`, detail at `/tools/{toolId}`) — saved tools; opens the tool playground for editing, testing, and running.
56
55
  - **Systems** (`/systems`, detail at `/systems/{systemId}`) — connected external systems with credentials and documentation.
57
56
  - **My Credentials** (`/credentials`) — credential management. The **My Credentials** section is for personal user-owned system credentials; the **superglue API keys** section is for API keys. Admins and members open it inside the normal app shell from the sidebar.
58
57
  - **Runs** (`/runs`, detail at `/runs/{runId}`) — execution history for full, draft, and single-step tool runs. Runs is a top-level sidebar item, not a Control Panel sub-item.
59
58
  - **Control Panel** (`/admin`) — expandable group for organization and account administration:
60
59
  - **Overview** (`/admin`) — dashboard summary, including failed-run and schedule summaries.
60
+ - **Landscape** (`/landscape`) — graph overview of tools, systems, and their connections.
61
61
  - **Schedules** (`/admin?view=schedules`) — scheduled and recurring tool runs.
62
62
  - **Access Rules** (`/admin/access`) — role and access-rule configuration; visible to admins on paid tiers. Use the access-rules reference for RBAC behavior, base roles, and personal roles.
63
- - **Organization** (`/admin?view=organization`) — organization members, invites, and org-level settings; visible on paid tiers. Member management actions are admin-gated.
63
+ - **Organization** (`/admin?view=organization`) — visible on paid tiers, tabbed page: **Members** (members, invites, role assignment; management actions admin-gated), **Settings** (`?tab=settings`, admin-only: organization name and logo, run preferences like draft/single-step run visibility, run result storage, member run visibility, and delete-all-runs), and **Notifications** (`?tab=notifications`, admin-only: failure-alert channels for Slack and email).
64
64
  - **MCP Servers** (`/admin?view=mcp-servers`) — manage and export named MCP server endpoints. Use the MCP documentation for behavior, permissions, and client setup.
65
- - **Notifications** (`/admin?view=notifications`) — user notification preferences and failure-alert channels.
65
+ - **Notifications** (`/admin?view=notifications`) — failure-alert channels; shown as a Control Panel sub-item only on the free tier. On paid tiers this lives in the Organization page's Notifications tab instead.
66
66
 
67
67
  Below the navigation, the sidebar shows the organization switcher and Sign Out. Depending on the plan, it also shows **Upgrade Plan** or **Subscription**; Subscription opens the external Stripe billing portal. There is no standalone Settings, Profile, or in-app Billing page.
68
68
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@superglue/cli",
3
- "version": "1.1.29",
3
+ "version": "1.1.30",
4
4
  "bin": {
5
5
  "sg": "./dist/cli.js"
6
6
  },
@@ -272,7 +272,8 @@ sg mcp edit --id <serverId> --auth-mode creator_api_key
272
272
 
273
273
  ```bash
274
274
  sg run list --tool my-tool --status failed --limit 20
275
- sg run get <runId> --fetch-results
275
+ sg run get <runId> --full
276
+ sg run get <runId> --fetch-results # alias for --full
276
277
  ```
277
278
 
278
279
  **File attachments:**
@@ -397,16 +398,14 @@ sourceData = {
397
398
 
398
399
  ### Naming Rules — Avoiding Key Collisions
399
400
 
400
- Everything in `sourceData` shares ONE flat namespace, and the runtime does not detect collisions — when two sources use the same key, one silently wins and the tool misbehaves with no error. Prevent collisions at design time:
401
+ Everything in `sourceData` shares ONE flat namespace. Saving a tool rejects payload input keys and step ids that collide with it:
401
402
 
402
- Never use these as payload input keys or step ids:
403
+ - `__files__`, `currentItem`, `sg_auth_email` — injected by the runtime
404
+ - `page`, `offset`, `cursor`, `limit`, `pageSize` — rejected only when the tool has a paginated step, because they would shadow the live pagination counters; on non-paginated tools they are allowed but discouraged (a later edit that adds pagination will force a rename)
405
+ - the tool's own step ids — the step result overwrites a same-named payload key
406
+ - anything starting with `<systemId>_` for a system the tool uses — the entire prefix is reserved for namespaced credentials (`<systemId>_<credKey>`, `<systemId>_url`), even names that don't match an existing credential, because credentials added to the system later would silently shadow the input
403
407
 
404
- - `__files__`, `currentItem`, `sg_auth_email` — overwritten by the runtime
405
- - `page`, `offset`, `cursor`, `limit`, `pageSize` — a payload key with one of these names shadows the live pagination counters; paginated steps silently stop advancing past the first page
406
- - the tool's own step ids — the step result overwrites a same-named payload key for all subsequent steps
407
- - credential keys available to a step (`<systemId>_<credKey>`, `<systemId>_url`, and any runtime-supplied credential names) — the credential value silently replaces the payload value
408
-
409
- Safe naming: payload inputs get specific, domain-flavored names (`customerId`, `reportMonth`, `maxResults` — never `page`, `limit`, `cursor`, `data`); step ids are verb-prefixed camelCase (`fetchUsers`) and distinct from every payload key. If the user asks for an input named like a reserved key, use a safe alternative and explain why.
408
+ Safe naming: payload inputs get specific, domain-flavored names (`customerId`, `reportMonth`, `maxResults` — prefer `maxResults` over `limit` even on non-paginated tools, and never prefix an input with a referenced system's id); step ids are verb-prefixed camelCase (`fetchUsers`) and distinct from every payload key. If the user asks for an input named like a reserved key, use a safe alternative and explain why.
410
409
 
411
410
  ### Step Result Envelopes
412
411
 
@@ -559,7 +558,7 @@ sg system create --name "My API" --url https://api.example.com \
559
558
 
560
559
  ### Draft Management
561
560
 
562
- Drafts live in `.superglue/drafts/<draftId>.json`. Created by `sg tool build`, updated by `sg tool edit`, deleted by `sg tool save`. Ephemeral — not persisted across sessions.
561
+ Drafts live under the active CLI config directory: local `.superglue/drafts/` when a project config exists, otherwise `~/.superglue/drafts/`. Draft filenames are base64url-encoded draft IDs, so use the `draftPath` returned by `sg tool build` and `sg tool edit` when inspecting raw draft files. Created by `sg tool build`, updated by `sg tool edit`, deleted by `sg tool save`. Ephemeral — not persisted to the superglue API until saved.
563
562
 
564
563
  ### Deployment
565
564
 
@@ -602,7 +601,7 @@ curl -X POST "https://api.superglue.cloud/v1/hooks/{toolId}?token=$SUPERGLUE_API
602
601
  - **POST for read-only ops** — GraphQL queries via POST should have `modify: false`. Don't rely on HTTP method alone
603
602
  - **Saving without approval** — always present `sg tool run` results and ask before `sg tool save`
604
603
  - **`sg_auth_email` in scheduled runs** — not available in scheduler-triggered executions. Tools using `<<sg_auth_email>>` will fail
605
- - **Reserved key collisions** — payload inputs or step ids named after reserved/injected keys (see Naming Rules) fail silently with wrong values, never with an error
604
+ - **Reserved key collisions** — payload inputs or step ids named after reserved/injected keys (see Naming Rules) are rejected at save time; pick a different name instead of retrying
606
605
 
607
606
  ---
608
607
 
@@ -612,7 +611,7 @@ For protocol-specific error recovery (HTTP, Postgres, MSSQL, Redis, GraphQL, SFT
612
611
 
613
612
  ### Tool build fails validation
614
613
 
615
- `sg tool build` returns a validation error. Read the message, fix the config, and re-run. Common causes: missing `id`, empty `steps`, missing `url` on request steps, missing `transformCode` on transform steps, `systemId` on the step object instead of `step.config.systemId`.
614
+ `sg tool build` returns a validation error. Read the message, fix the config, and re-run. Common causes: missing `id`, empty `steps`, missing `url` on request steps, missing `transformCode` on transform steps, `systemId` on the step object instead of `step.config.systemId`, or a key name collision (see Naming Rules) — rename the flagged input or step id.
616
615
 
617
616
  ### Tool runs but a step fails
618
617
 
@@ -642,7 +641,6 @@ For protocol-specific error recovery (HTTP, Postgres, MSSQL, Redis, GraphQL, SFT
642
641
  2. Re-run with `--include-step-results` to see the exact envelope shape
643
642
  3. Paginated steps merge into a single `.data` field — do not `.map()` over them
644
643
  4. Verify `sourceData.currentItem` is only referenced inside looping steps (set by the step's own `dataSelector`, not upstream)
645
- 5. If a step silently received the wrong value (no error thrown) or pagination stopped after one page, check for a key collision between payload inputs, step ids, credential keys, and reserved runtime keys — see Naming Rules. Fix by renaming the input, not by working around it
646
644
 
647
645
  ### Persistent failures
648
646
 
@@ -196,11 +196,14 @@ pagination: {
196
196
  | cursorBased | `<<cursor>>` | null | extracted via cursorPath |
197
197
  | all | `<<limit>>` / `<<pageSize>>` | pageSize | — |
198
198
 
199
- **Stop conditions** — JS expression evaluated in sandbox. Receives `(response, pageInfo)`:
199
+ **Stop conditions** — JS expression evaluated in sandbox. Receives `(response, pageInfo, sourceData)`:
200
200
 
201
201
  - `response.data` = parsed API response body
202
202
  - `response.headers` = response headers
203
- - `pageInfo = { page, offset, cursor, totalFetched }`
203
+ - `pageInfo = { page, offset, cursor, totalFetched, mergedResult }`
204
+ - `pageInfo.totalFetched` counts the merged paginated result including the current page
205
+ - `pageInfo.mergedResult` is the accumulated paginated result including the current page
206
+ - `sourceData` contains the current step input data, with payload fields at the root plus previous step results
204
207
  - Return `true` to STOP
205
208
 
206
209
  ```javascript
@@ -208,6 +211,7 @@ pagination: {
208
211
  "response.data.items.length === 0";
209
212
  "response.data.hasMore === false";
210
213
  "pageInfo.totalFetched >= 1000";
214
+ "pageInfo.totalFetched >= sourceData.maxResults";
211
215
  ```
212
216
 
213
217
  **Cursor extraction:** `cursorPath` is a simple dot-separated property path (e.g. `meta.next_cursor`, `data.0.id`) resolved against the parsed response body. It is not a JSONPath expression — wildcards, filters, and `$.` prefixes are not supported. For property names containing `@` (e.g. OData `@odata.nextLink`), use the name directly as the path. Null/undefined cursor stops pagination.
@@ -233,7 +237,7 @@ When an HTTP step downloads a file (PDF, CSV, binary response), set `outputFile:
233
237
 
234
238
  ## Common Pitfalls
235
239
 
236
- - Hardcoding base URLs that match the system's base URL instead of using `<<systemId_url>>`
240
+ - Hardcoding base URLs that match the system's base URL instead of using `<<systemId_url>>`. Check with `sg system call` what format the URL is and if it contains e.g. a trailing slash.
237
241
  - Forgetting auth headers entirely — nothing is injected automatically, including for OAuth systems (only token refresh is automatic)
238
242
  - Forgetting `outputFile: true` on steps that download files the user wants
239
243
  - Putting pagination variables in the config but not setting a `pagination` block, or vice versa
@@ -1,5 +1,7 @@
1
1
  # MSSQL
2
2
 
3
+ **This skill is for Microsoft SQL Server and Azure SQL only.** For SAP ASE (Sybase), use the `odbc` skill — SAP ASE requires the ODBC strategy with `odbc://` URLs, not `mssql://`.
4
+
3
5
  ## Step Configuration
4
6
 
5
7
  ```typescript
@@ -44,17 +46,29 @@ Azure SQL usernames often include `@servername` suffix (e.g., `myuser@myserver`)
44
46
  mssql://myuser%40myserver:mypassword@myserver.database.windows.net:1433/mydatabase
45
47
  ```
46
48
 
49
+ **Named instances** (common for on-prem servers, e.g. ProLaw's `SERVER\PROLAW`) — use the `instanceName` query parameter. Backslash syntax (`SERVER\PROLAW`) in the host is rejected with an error; always translate it to the query parameter:
50
+
51
+ ```
52
+ mssql://user:password@SERVER/database?instanceName=PROLAW
53
+ ```
54
+
55
+ When an instance name is set, the port is ignored — the instance's port is resolved via the SQL Browser service (UDP 1434), which must be running and reachable. If SQL Browser is unavailable (or the server is reached through the Secure Gateway tunnel, which forwards a single TCP port and cannot carry UDP), have the DBA assign a static TCP port to the instance and connect with `host:port` without an instance name instead.
56
+
47
57
  **Connection parameters** can be appended as query strings:
48
58
 
49
59
  ```
50
60
  mssql://user:password@host:port/database?encrypt=true&trustServerCertificate=false
51
61
  ```
52
62
 
53
- | Parameter | Default | Notes |
54
- | ------------------------ | ------- | --------------------------------------- |
55
- | `encrypt` | `true` | Required for Azure SQL |
56
- | `trustServerCertificate` | `false` | Whether to trust the server certificate |
57
- | `database` | — | Can be in URL path or query parameter |
63
+ | Parameter | Default | Notes |
64
+ | ------------------------ | ------- | --------------------------------------------------- |
65
+ | `encrypt` | `true` | Required for Azure SQL |
66
+ | `trustServerCertificate` | `false` | Whether to trust the server certificate |
67
+ | `database` | — | Can be in URL path or query parameter |
68
+ | `instanceName` | — | SQL Server named instance (case-sensitive spelling) |
69
+ | `domain` | — | Windows domain — switches to NTLM authentication |
70
+
71
+ Unknown connection parameters cause an error rather than being silently ignored.
58
72
 
59
73
  ### Body Format
60
74
 
@@ -77,6 +91,24 @@ Credentials are embedded directly in the connection URL using `<<systemId_creden
77
91
  mssql://<<my_db_user>>:<<my_db_password>>@<<my_db_host>>:<<my_db_port>>/<<my_db_database>>
78
92
  ```
79
93
 
94
+ ### Windows Authentication (NTLM)
95
+
96
+ For on-prem SQL Servers that only accept Windows domain logins (no SQL auth), store these credential keys on the system:
97
+
98
+ | Credential Key | Required | Notes |
99
+ | -------------- | -------- | ----------------------------------------------------- |
100
+ | `authType` | yes | `ntlm` |
101
+ | `domain` | yes | Windows domain (e.g. `CORP`) |
102
+ | `user` | yes | Windows username (also accepts `username`, or in URL) |
103
+ | `password` | yes | Windows password (or in URL) |
104
+
105
+ ```
106
+ URL: mssql://<<sys_user>>:<<sys_password>>@<<sys_host>>:<<sys_port>>/<<sys_database>>
107
+ Credentials: { authType: "ntlm", domain, user, password, host, port, database }
108
+ ```
109
+
110
+ Alternatively, pass the domain as a `?domain=CORP` query parameter on the URL — any URL with a `domain` set authenticates via NTLM. Kerberos-only environments are not supported; ask the DBA to permit NTLM or create a SQL login.
111
+
80
112
  ### Azure Active Directory Authentication
81
113
 
82
114
  For Azure AD auth, store the following credential keys on the system alongside the standard connection fields:
@@ -91,7 +123,7 @@ For Azure AD auth, store the following credential keys on the system alongside t
91
123
  | `user` | yes | Azure AD username (also accepts `username`, or in URL) |
92
124
  | `password` | yes | Azure AD password (or in URL) |
93
125
 
94
- `user` and `password` can be stored as credentials or embedded in the URL — credentials take precedence.
126
+ `user` and `password` can be stored as credentials or embedded in the URL — values resolved into the URL take precedence; stored credentials only fill gaps the URL omits.
95
127
 
96
128
  ```
97
129
  URL: mssql://<<sys_user>>:<<sys_password>>@myserver.database.windows.net:1433/mydb
@@ -160,11 +192,14 @@ With OUTPUT (MSSQL equivalent of RETURNING):
160
192
 
161
193
  ### Return Value
162
194
 
163
- Returns the recordset — array of row objects with column names as keys.
195
+ The shape depends on what the query produces:
164
196
 
165
- - `SELECT`: array of matching rows
197
+ - `SELECT` (single recordset): array of row objects with column names as keys
166
198
  - `INSERT/UPDATE/DELETE` with `OUTPUT`: array of returned rows
167
- - Mutations without `OUTPUT`: empty array
199
+ - Mutations without `OUTPUT`: `{ "rowsAffected": [n] }` — one count per statement
200
+ - Stored procedures / batches returning multiple recordsets: array of recordset arrays (e.g. `[[...rows], [...rows]]`)
201
+
202
+ Check the shape before indexing: a multi-recordset result is an array of arrays, not a flat row list.
168
203
 
169
204
  ### Batch Operations
170
205
 
@@ -182,6 +217,15 @@ Use a data selector returning an array to execute a query per item:
182
217
  - Idle pools cleaned up automatically
183
218
  - SSL/TLS encryption enabled by default for Azure SQL
184
219
 
220
+ ### On-Prem SQL Server (e.g. ProLaw, legacy ERP)
221
+
222
+ Defaults are tuned for Azure SQL; on-prem servers usually need adjustments:
223
+
224
+ - **Self-signed certificates** — on-prem servers rarely have CA-signed certs, so the default `trustServerCertificate=false` fails the TLS handshake. Add `?trustServerCertificate=true` (keeps encryption, skips CA validation).
225
+ - **Old SQL Server versions** — SQL Server 2008/2008 R2 without TLS 1.2 patches cannot complete a modern TLS handshake. Use `?encrypt=false` as a last resort, preferably only over the Secure Gateway tunnel.
226
+ - **Named instances** — use the `?instanceName=` query parameter (see URL Format above); remember SQL Browser (UDP 1434) is required for instance resolution and does not work through the Secure Gateway tunnel.
227
+ - **Firewalled servers** — on-prem databases are typically not internet-reachable; configure the system with a Secure Gateway tunnel.
228
+
185
229
  ### Retry Behavior
186
230
 
187
231
  Default retries from server config. On final failure, error includes query text and params.
@@ -189,9 +233,12 @@ Default retries from server config. On final failure, error includes query text
189
233
  ## Common Pitfalls
190
234
 
191
235
  - Using `$1`, `$2` (PostgreSQL syntax) instead of `@param1`, `@param2` — MSSQL uses named `@param` parameters
192
- - Forgetting `OUTPUT INSERTED.*` on INSERT/UPDATE/DELETE when you need the result — without it the step returns an empty array
236
+ - Forgetting `OUTPUT INSERTED.*` on INSERT/UPDATE/DELETE when you need the row data — without it the step returns `{ "rowsAffected": [n] }`, not rows
237
+ - Treating a multi-recordset stored procedure result as a flat row array — it is an array of recordset arrays
193
238
  - Accessing step result directly instead of via `.data` — database results follow the same envelope as all steps: `sourceData.stepId.data`
194
239
  - Not URL-encoding `@` in Azure SQL usernames — `myuser@myserver` must be `myuser%40myserver` in the connection URL
240
+ - Using a named instance through the Secure Gateway tunnel — instance resolution needs UDP 1434, which the tunnel does not forward; use a static TCP port instead
241
+ - Forgetting `?trustServerCertificate=true` for on-prem servers with self-signed certificates
195
242
 
196
243
  ## Error Recovery
197
244
 
@@ -204,4 +251,8 @@ When an MSSQL step fails and the cause is not obvious:
204
251
  - Confirm the client IP is allowed in the Azure SQL firewall rules
205
252
  - Verify the username includes the `@servername` suffix if required, properly encoded as `%40`
206
253
  - Confirm `encrypt=true` is set (required for Azure SQL)
207
- 5. **Verify parameter types** — MSSQL infers types from the values passed. Passing a string where a number is expected may cause implicit conversion errors. Ensure `params` values match expected column types.
254
+ 5. **Check on-prem connection issues** — if connecting to an on-prem server:
255
+ - TLS handshake errors (`self signed certificate`, `unable to verify`) → add `?trustServerCertificate=true`; for unpatched SQL Server 2008-era hosts, `?encrypt=false`
256
+ - `Failed to connect ... in 15000ms` with a named instance → SQL Browser (UDP 1434) is unreachable; use a static TCP port instead
257
+ - `Login failed` with Windows-auth-only servers → set `authType: "ntlm"` and `domain` in credentials, or ask the DBA for a SQL login
258
+ 6. **Verify parameter types** — MSSQL infers types from the values passed. Passing a string where a number is expected may cause implicit conversion errors. Ensure `params` values match expected column types.
@@ -51,18 +51,18 @@ Use this section as the source of truth for high-level web app navigation. Do no
51
51
  The persistent left sidebar contains these top-level items:
52
52
 
53
53
  - **Agent** (`/`) — primary AI chat assistant for building and debugging tools and systems.
54
- - **Landscape** (`/landscape`) — graph overview of tools, systems, and their connections.
55
54
  - **Tools** (`/tools`, detail at `/tools/{toolId}`) — saved tools; opens the tool playground for editing, testing, and running.
56
55
  - **Systems** (`/systems`, detail at `/systems/{systemId}`) — connected external systems with credentials and documentation.
57
56
  - **My Credentials** (`/credentials`) — credential management. The **My Credentials** section is for personal user-owned system credentials; the **superglue API keys** section is for API keys. Admins and members open it inside the normal app shell from the sidebar.
58
57
  - **Runs** (`/runs`, detail at `/runs/{runId}`) — execution history for full, draft, and single-step tool runs. Runs is a top-level sidebar item, not a Control Panel sub-item.
59
58
  - **Control Panel** (`/admin`) — expandable group for organization and account administration:
60
59
  - **Overview** (`/admin`) — dashboard summary, including failed-run and schedule summaries.
60
+ - **Landscape** (`/landscape`) — graph overview of tools, systems, and their connections.
61
61
  - **Schedules** (`/admin?view=schedules`) — scheduled and recurring tool runs.
62
62
  - **Access Rules** (`/admin/access`) — role and access-rule configuration; visible to admins on paid tiers. Use the access-rules reference for RBAC behavior, base roles, and personal roles.
63
- - **Organization** (`/admin?view=organization`) — organization members, invites, and org-level settings; visible on paid tiers. Member management actions are admin-gated.
63
+ - **Organization** (`/admin?view=organization`) — visible on paid tiers, tabbed page: **Members** (members, invites, role assignment; management actions admin-gated), **Settings** (`?tab=settings`, admin-only: organization name and logo, run preferences like draft/single-step run visibility, run result storage, member run visibility, and delete-all-runs), and **Notifications** (`?tab=notifications`, admin-only: failure-alert channels for Slack and email).
64
64
  - **MCP Servers** (`/admin?view=mcp-servers`) — manage and export named MCP server endpoints. Use the MCP documentation for behavior, permissions, and client setup.
65
- - **Notifications** (`/admin?view=notifications`) — user notification preferences and failure-alert channels.
65
+ - **Notifications** (`/admin?view=notifications`) — failure-alert channels; shown as a Control Panel sub-item only on the free tier. On paid tiers this lives in the Organization page's Notifications tab instead.
66
66
 
67
67
  Below the navigation, the sidebar shows the organization switcher and Sign Out. Depending on the plan, it also shows **Upgrade Plan** or **Subscription**; Subscription opens the external Stripe billing portal. There is no standalone Settings, Profile, or in-app Billing page.
68
68