node-autotask 0.13.0 → 0.15.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/ARCHITECTURE.md +43 -7
- package/MCP_TOOL_CATALOG.json +1 -1
- package/MCP_TOOL_MANIFEST.md +2 -2
- package/N8N_MCP_MANIFEST.json +2 -2
- package/N8N_MCP_MANIFEST.md +3 -3
- package/README.md +9 -8
- package/capabilities.json +2132 -2740
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.d.cts +9 -4
- package/dist/capabilities.d.ts +9 -4
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-Y6O5VVQ4.js → chunk-AXVYQPTB.js} +136 -126
- package/dist/{chunk-IKJLIDK3.js → chunk-CSA6QSV6.js} +37 -25
- package/dist/{chunk-CXXNONRP.cjs → chunk-EWMG3HHU.cjs} +2131 -2739
- package/dist/{chunk-OZD5FQM4.js → chunk-JIDR3NPV.js} +2131 -2739
- package/dist/{chunk-DDZXN6LN.js → chunk-LH5BXQ7A.js} +2 -2
- package/dist/{chunk-CJA6L6NR.cjs → chunk-V7QPZA7L.cjs} +135 -135
- package/dist/{chunk-MTDCLVQQ.cjs → chunk-VLIUHEPE.cjs} +558 -548
- package/dist/{chunk-KB2ANVVR.cjs → chunk-Z7YT72SS.cjs} +42 -30
- package/dist/{index-DbMKWnEX.d.cts → index-BXIwhAN4.d.cts} +67 -13
- package/dist/{index-TuqNq3Ro.d.ts → index-M0qJIiRt.d.ts} +67 -13
- package/dist/index.cjs +61 -19
- package/dist/index.d.cts +83 -3
- package/dist/index.d.ts +83 -3
- package/dist/index.js +46 -4
- package/dist/operations/index.cjs +110 -107
- package/dist/operations/index.d.cts +9 -2
- package/dist/operations/index.d.ts +9 -2
- package/dist/operations/index.js +9 -6
- package/dist/pool.cjs +8 -8
- package/dist/pool.d.cts +1 -1
- package/dist/pool.d.ts +1 -1
- package/dist/pool.js +4 -4
- package/dist/resources/index.cjs +4 -4
- package/dist/resources/index.d.cts +1 -1
- package/dist/resources/index.d.ts +1 -1
- package/dist/resources/index.js +3 -3
- package/dist/untrusted.cjs +3 -1
- package/dist/untrusted.d.cts +9 -4
- package/dist/untrusted.d.ts +9 -4
- package/dist/untrusted.js +3 -1
- package/docs/API.md +112 -22
- package/docs/LIVE-TESTING.md +1 -1
- package/package.json +2 -2
package/ARCHITECTURE.md
CHANGED
|
@@ -304,7 +304,7 @@ export interface AutotaskConfig {
|
|
|
304
304
|
pageSize?: number;
|
|
305
305
|
/** HTTP timeout in ms (whole-call budget). Default 30_000. */
|
|
306
306
|
timeoutMs?: number;
|
|
307
|
-
/**
|
|
307
|
+
/** The client's retry budget (default 3; 0 disables auto-retry). Three legs, two rules (issues #105/#109): the 429 leg retries on the pre-#105 retriable set (GET/PUT/DELETE + idempotent-flagged calls); the 5xx/network leg and the non-JSON-2xx (#24) leg retry GET + idempotent-flagged calls only. A per-call override rides `InvokeOptions.maxRetries` / `MutationOpts.maxRetries`. */
|
|
308
308
|
maxRetries?: number;
|
|
309
309
|
/** Optional request log sink. Default: no-op. */
|
|
310
310
|
logger?: Logger;
|
|
@@ -510,10 +510,36 @@ export interface RequestOptions {
|
|
|
510
510
|
- `2xx` → parse JSON (if body present); empty body → resolve `undefined`.
|
|
511
511
|
- non-2xx → throw via `errorFromStatus(status, body, url, operation)` (§10).
|
|
512
512
|
- network/AbortError → `AutotaskNetworkError` / `AutotaskTimeoutError`.
|
|
513
|
-
6. **Retries
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
513
|
+
6. **Retries** (issues #105/#109 — three legs, two rules, retry up to `maxRetries` with
|
|
514
|
+
exponential backoff + jitter, base 200 ms, cap 30 s, honouring `Retry-After`):
|
|
515
|
+
- **429 leg — UNCHANGED by #105.** A `429` is a **pre-processing refusal** (the
|
|
516
|
+
vendor rate limiter rejected the call before executing it); it is retried on the
|
|
517
|
+
pre-#105 retriable set — `GET`/`PUT`/`DELETE` + explicitly idempotent-flagged
|
|
518
|
+
calls (`IDEMPOTENT_METHODS`, kept exported for the public-surface baseline). A
|
|
519
|
+
429 on an unflagged `POST`/`PATCH` surfaces at once, exactly as before #105.
|
|
520
|
+
- **5xx / network leg — FLIPPED by #105.** Only `GET` and explicitly
|
|
521
|
+
idempotent-flagged calls retry; a mutation (`POST`/`PUT`/`PATCH`/`DELETE`) makes
|
|
522
|
+
exactly one send — the write-outcome is unknown once the body was written (the
|
|
523
|
+
#104 classifier: never blindly resend). An explicit `idempotent: true` on a
|
|
524
|
+
transport-level `RequestOptions` (not exposed on the mutation helpers) opts
|
|
525
|
+
back into the pre-#105 auto-retry on both legs. The parent-scoped
|
|
526
|
+
`GET .../Approve` is a `GET` and therefore retried like any GET; the
|
|
527
|
+
`POST .../Reject` is never retried on either leg — it is an unflagged `POST`, so a
|
|
528
|
+
`429` surfaces at once as well (`time_off_requests.reject` lists no retryable
|
|
529
|
+
statuses in the registry).
|
|
530
|
+
- **`#24` leg (non-JSON `2xx`, an edge maintenance page) — follows the write
|
|
531
|
+
rule (issue #109).** A `GET` / explicitly idempotent-flagged call retries; a
|
|
532
|
+
mutation makes ONE send and throws `UNEXPECTED_CONTENT_TYPE` with the residue
|
|
533
|
+
`suggestedAction`. The transport no longer assumes the edge served the page —
|
|
534
|
+
that premise is unprovable from the response, and the #104 classifier pins this
|
|
535
|
+
code as `unknown` for a write (never blindly resend). `idempotent: true` /
|
|
536
|
+
`maxRetries` remain the explicit opt-ins.
|
|
537
|
+
- **Per-call budget override:** `InvokeOptions.maxRetries` / `MutationOpts.maxRetries`
|
|
538
|
+
threads the transport's per-request override through a mutation (and its
|
|
539
|
+
auxiliary reads, e.g. a partial-update merge read); `0` = exactly one send per
|
|
540
|
+
request the call performs (default: the client's configured `maxRetries`). The
|
|
541
|
+
optional stale-object guard's verification read (only with a
|
|
542
|
+
`lastModifiedDate` token) keeps the client budget.
|
|
517
543
|
7. **Concurrency guard**: an in-process semaphore bounds concurrent in-flight requests to
|
|
518
544
|
`maxConcurrent` (default 10 — the API's limit; the node self-limits to 3 per endpoint
|
|
519
545
|
under post-2023.1 guidance — the SDK default is the API limit and is configurable).
|
|
@@ -673,8 +699,12 @@ export function isAutotaskError(err: unknown): err is AutotaskError;
|
|
|
673
699
|
GETs) return 200 with `{ item: null }`. The SDK converts that to `NotFoundError`
|
|
674
700
|
(`category: not_found`, `httpStatus: 200`, `resourceIds: [id]`). This is the vendor's
|
|
675
701
|
not-found signal and must not be surfaced as a successful empty record.
|
|
676
|
-
- **Agent decision mapping** (fields, not string parsing): retry on `retryable: true
|
|
677
|
-
|
|
702
|
+
- **Agent decision mapping** (fields, not string parsing): retry on `retryable: true`
|
|
703
|
+
**for reads**; for a WRITE decide with `classifyWriteOutcome` (docs/API.md §2.2) — its
|
|
704
|
+
`unknown` state is never retryable and is resolved with a read-back (issues #105/#107:
|
|
705
|
+
the transport's `retryable` on a plain 5xx `ServerError` serves the read path, not the
|
|
706
|
+
writer); change input on `category: 'validation'` (`suggestedAction` names the field);
|
|
707
|
+
ask the
|
|
678
708
|
user on `category: 'resolution'` with candidates in `resourceIds`; resolve a parent
|
|
679
709
|
first on `category: 'validation'` with the missing parent in `resourceIds`; request
|
|
680
710
|
approval on the registry's `flags.requiresApproval` / `effect: 'destructive'`; stop on
|
|
@@ -1118,6 +1148,12 @@ Floor (plan rows pre-declare it; G6 implements):
|
|
|
1118
1148
|
candidates per resource).
|
|
1119
1149
|
|
|
1120
1150
|
### 19.3 Mutation safety
|
|
1151
|
+
- **Write outcome (issues #105/#107)**: a mutation makes EXACTLY ONE send on a
|
|
1152
|
+
5xx/network error (two-leg retry policy, §8 "Behaviour" item 6 — a 429 is still retried on
|
|
1153
|
+
the pre-#105 set). A writer classifying a write error uses
|
|
1154
|
+
`classifyWriteOutcome` (docs/API.md §2.2): `failed` = definitely not
|
|
1155
|
+
applied; `unknown` = outcome unprovable — resolve with a read-back, NEVER
|
|
1156
|
+
a blind resend (the vendor offers no idempotency keys).
|
|
1121
1157
|
- **Classification** (registry `effect` + `flags`, never one combined enum):
|
|
1122
1158
|
`effect: read | write | destructive`; `flags: sensitive | idempotent | requiresApproval`.
|
|
1123
1159
|
Plan defaults: `create` = write (non-idempotent), `update` = write + idempotent (PUT
|
package/MCP_TOOL_CATALOG.json
CHANGED
package/MCP_TOOL_MANIFEST.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# MCP Tool Manifest — node-autotask
|
|
2
2
|
|
|
3
|
-
<!-- GENERATED by scripts/project-mcp-tools.mjs at 2026-10-
|
|
3
|
+
<!-- GENERATED by scripts/project-mcp-tools.mjs at 2026-10-17T13:48:43.787Z — do not hand-edit. -->
|
|
4
4
|
|
|
5
5
|
Mechanical MCP projection of the capability registry (generator-design section 7, ARCHITECTURE section 19.5).
|
|
6
6
|
Tool names are the plan `mcpTool` columns (entity-first `autotask_<entity>_<verb>`); descriptions are the
|
|
@@ -947,7 +947,7 @@ singleton, so no helper tier is expected there; G8, 2026-09-26.)
|
|
|
947
947
|
|
|
948
948
|
## Meta
|
|
949
949
|
|
|
950
|
-
- generatedAt: 2026-10-
|
|
950
|
+
- generatedAt: 2026-10-17T13:48:43.787Z
|
|
951
951
|
- planHash: bd88648453f58ede018062ce66acefacb672fecaa450af89f421057809971e14
|
|
952
952
|
- registry records: 1213
|
|
953
953
|
- projected tools: 850
|
package/N8N_MCP_MANIFEST.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "node-autotask n8n consumer mcp projection v1",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-17T13:48:43.907Z",
|
|
4
4
|
"generator": "scripts/project-n8n-mcp.mjs",
|
|
5
5
|
"inputs": {
|
|
6
6
|
"capabilities": "capabilities.json (the capability registry — the single source of truth)",
|
|
@@ -3667,6 +3667,6 @@
|
|
|
3667
3667
|
"approvalGatedWrites": 2,
|
|
3668
3668
|
"destructiveExcluded": 3
|
|
3669
3669
|
},
|
|
3670
|
-
"capabilitiesHash": "
|
|
3670
|
+
"capabilitiesHash": "fd92667b96dd9c74d9bbda2a34bf50b9791e2f236a6d2bb50b50a02a1d064882",
|
|
3671
3671
|
"curationHash": "e19117ce73e38d9aded3be7e7f077a4e185d2e10294622b76c17d67f63cf9e3b"
|
|
3672
3672
|
}
|
package/N8N_MCP_MANIFEST.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# N8N MCP Manifest — node-autotask (consumer projection)
|
|
2
2
|
|
|
3
|
-
<!-- GENERATED by scripts/project-n8n-mcp.mjs at 2026-10-
|
|
3
|
+
<!-- GENERATED by scripts/project-n8n-mcp.mjs at 2026-10-17T13:48:43.907Z — do not hand-edit. -->
|
|
4
4
|
|
|
5
5
|
The n8n CONSUMER projection of the capability registry: the canonical source for what the
|
|
6
6
|
n8n-side MCP tools must expose. The SDK is canonical — this is a projection of it, never a
|
|
@@ -282,6 +282,6 @@ only via a recorded change to `n8n-mcp.curation.json`.
|
|
|
282
282
|
|
|
283
283
|
## Meta
|
|
284
284
|
|
|
285
|
-
- generatedAt: 2026-10-
|
|
286
|
-
- capabilitiesHash:
|
|
285
|
+
- generatedAt: 2026-10-17T13:48:43.907Z
|
|
286
|
+
- capabilitiesHash: fd92667b96dd9c74d9bbda2a34bf50b9791e2f236a6d2bb50b50a02a1d064882
|
|
287
287
|
- curationHash: e19117ce73e38d9aded3be7e7f077a4e185d2e10294622b76c17d67f63cf9e3b
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Fully-typed TypeScript SDK for the Autotask (Datto) PSA REST API. Zero runtime
|
|
|
4
4
|
dependencies. Built for building MCP servers and integrations.
|
|
5
5
|
|
|
6
6
|
The SDK is also the **deterministic execution layer for agents** (ARCHITECTURE
|
|
7
|
-
section 19): a generated capability registry (
|
|
7
|
+
section 19): a generated capability registry (1213 operations across the 121-entity
|
|
8
8
|
MVP set), a mechanical MCP substrate (registry → manifest → overrides → core tier +
|
|
9
9
|
catalog meta-tool), and a write governor (dry-run-first, destructive
|
|
10
10
|
confirmation). The SDK boundary also redacts response field values — the
|
|
@@ -397,9 +397,9 @@ The SDK ships the mechanical substrate, not a server (no MCP imports, no zod):
|
|
|
397
397
|
gains two server-category codes: `UNEXPECTED_CONTENT_TYPE` (a non-JSON 2xx
|
|
398
398
|
whose `Content-Type` is not a JSON media type — the vendor maintenance
|
|
399
399
|
page; `details` carries the content-type + a 256-byte truncated snippet
|
|
400
|
-
that the MCP servers wrap as untrusted host text;
|
|
401
|
-
|
|
402
|
-
effect) and `EMPTY_RESPONSE` (a blank 2xx on a call that expects a result
|
|
400
|
+
that the MCP servers wrap as untrusted host text; a `GET` or an explicitly
|
|
401
|
+
`idempotent`-flagged call retries, a write makes ONE call and says the write
|
|
402
|
+
may have taken effect) and `EMPTY_RESPONSE` (a blank 2xx on a call that expects a result
|
|
403
403
|
— `expectBody`, non-DELETE by default; `DELETE` / 204 keep `undefined` and
|
|
404
404
|
the delete ops synthesize `{ id }` from the path id on a blank answer). A
|
|
405
405
|
vendor field-validation 500 matching the documented phrases (`exceeds
|
|
@@ -477,7 +477,7 @@ node-parity paths the vendored swagger lacks, all UNVERIFIED-live this run), and
|
|
|
477
477
|
| `npm run capabilities:check` | `scripts/check-capabilities.mjs` — the batch gate (missing/incomplete/stale records → exit 1) |
|
|
478
478
|
| `npm run public-surface` | `scripts/public-surface.mjs` — capture (`--write`) / verify the public API surface baseline; default mode fails on unannounced removals, **and** checks the BUILT surface: every tsup entry has a matching `exports` key (and vice versa), every declared target was emitted and loads (ESM+CJS), and no runtime dependency leaks into `dist` |
|
|
479
479
|
| `npm run live-smoke` | `scripts/live-smoke.mjs` — read-only live smoke: 5 vendor probes (5-6 wire calls worst case: 4 GET + 1 bounded query that may walk a 2nd, empty page) + a zero-network shape guard; `--dry` prints the plan with no calls (DRY-RUN-ONLY verdict, exit 0); live via `AUTOTASK_*` env — missing/partial credentials hard-fail exit 2 |
|
|
480
|
-
| `npm run live-coverage` | `scripts/live-coverage.mjs` — the live coverage sweep over all
|
|
480
|
+
| `npm run live-coverage` | `scripts/live-coverage.mjs` — the live coverage sweep over all 1213 registry ops (`--dry`: full call plan, no calls; live: bounded reads for real, mutations `dryRun: true` only — zero mutating requests, every governor-gated row (the 54 delete dry-runs included) routed through invoke with `confirm`; budget <= 1159 plan-honest / <= 1311 wire-honest worst case) |
|
|
481
481
|
| `npm run mcp:project` | `scripts/project-mcp-tools.mjs` — mechanical MCP projection → `MCP_TOOL_MANIFEST.md` (`:check` verifies) |
|
|
482
482
|
| `npm run n8n:project` / `n8n:project:check` | `scripts/project-n8n-mcp.mjs` — the n8n consumer projection from the SAME registry → `N8N_MCP_MANIFEST.json`/`.md` (`--check` rebuilds and diffs; the gate is wired into `verify`) |
|
|
483
483
|
| `npm run catalog:build` / `catalog:check` | `scripts/build-tool-catalog.mjs` — the catalog meta-tool row data → `MCP_TOOL_CATALOG.json` + mechanical CORE profile (`--check` verifies drift) |
|
|
@@ -526,9 +526,10 @@ thresholds: 90/90/80/90 (lines/functions/branches/statements). The public API
|
|
|
526
526
|
surface baseline (`test/__fixtures__/public-surface.json`) proves "additive only":
|
|
527
527
|
a captured name that disappears fails `public-surface`. The two live scripts
|
|
528
528
|
(`live-smoke`, `live-coverage`) close the mocked-vs-live gap where credentials
|
|
529
|
-
exist;
|
|
530
|
-
full live-coverage sweep
|
|
531
|
-
|
|
529
|
+
exist; the live path has been verified end-to-end against a real tenant
|
|
530
|
+
(live-smoke 6/6; a full live-coverage sweep with 0 error rows). Re-run both
|
|
531
|
+
commands with your credentials to re-verify against your tenant — the mocked
|
|
532
|
+
suites are the release gate, the live scripts are the ground-truth check.
|
|
532
533
|
|
|
533
534
|
## Roadmap
|
|
534
535
|
|