node-autotask 0.21.0 → 0.24.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 +44 -21
- package/CHANGELOG.md +44 -0
- package/MCP_TOOL_CATALOG.json +90 -10
- package/MCP_TOOL_MANIFEST.md +24 -20
- package/MCP_TOOL_OVERRIDES.json +6 -6
- package/N8N_MCP_MANIFEST.json +65 -10
- package/N8N_MCP_MANIFEST.md +10 -8
- package/README.md +9 -9
- package/capabilities.json +3247 -7575
- package/capabilities.schema.json +0 -12
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.d.cts +0 -2
- package/dist/capabilities.d.ts +0 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-CBUY3MKB.cjs → chunk-4VAC2Z55.cjs} +3246 -7574
- package/dist/{chunk-KD6LOSAK.js → chunk-BBQBWVBE.js} +3496 -3082
- package/dist/{chunk-JRSU6PKP.js → chunk-ICCU2S62.js} +2 -2
- package/dist/{chunk-GBVUXAUA.js → chunk-IOVFTIW6.js} +2257 -1426
- package/dist/{chunk-QWAWNQEZ.cjs → chunk-LVBFLSPL.cjs} +3044 -2630
- package/dist/{chunk-PMPFQDVM.cjs → chunk-SOHQ6SDI.cjs} +135 -135
- package/dist/{chunk-HEW4WJLC.cjs → chunk-SW66OWM5.cjs} +2645 -1814
- package/dist/{chunk-DM67SXCO.js → chunk-WJD26CPN.js} +3246 -7574
- package/dist/{index-BXtKN1M5.d.cts → index-BVtycq-6.d.cts} +1 -1
- package/dist/{index-BXtKN1M5.d.ts → index-BVtycq-6.d.ts} +1 -1
- package/dist/{index-ByWYfNog.d.cts → index-C0OwQhon.d.cts} +486 -962
- package/dist/{index-DSnuyiTr.d.ts → index-CZ94y401.d.ts} +486 -962
- package/dist/index.cjs +91 -62
- package/dist/index.d.cts +360 -5
- package/dist/index.d.ts +360 -5
- package/dist/index.js +74 -45
- package/dist/operations/index.cjs +462 -462
- package/dist/operations/index.d.cts +78 -84
- package/dist/operations/index.d.ts +78 -84
- package/dist/operations/index.js +382 -382
- package/dist/pool.cjs +8 -8
- package/dist/pool.d.cts +2 -2
- package/dist/pool.d.ts +2 -2
- package/dist/pool.js +4 -4
- package/dist/resources/index.cjs +4 -4
- package/dist/resources/index.d.cts +2 -2
- package/dist/resources/index.d.ts +2 -2
- package/dist/resources/index.js +3 -3
- package/dist/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/API.md +170 -49
- package/docs/N8N-ADAPTER.md +3 -3
- package/examples/mcp/errors.ts +135 -0
- package/examples/mcp/manifest.ts +168 -0
- package/examples/mcp/register.ts +66 -0
- package/examples/mcp/schemas.ts +203 -0
- package/examples/mcp/tools-meta.ts +120 -0
- package/examples/mcp/tools-mode.ts +177 -0
- package/examples/mcp/tools-read.ts +264 -0
- package/examples/mcp/types.ts +34 -0
- package/examples/mcp-register.ts +9 -1074
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AutotaskClient
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ICCU2S62.js";
|
|
4
4
|
import "./chunk-DMMMWO6A.js";
|
|
5
5
|
import {
|
|
6
6
|
AppointmentsResource,
|
|
@@ -131,7 +131,7 @@ import {
|
|
|
131
131
|
VersionInformationResource,
|
|
132
132
|
VersionResource,
|
|
133
133
|
ZoneInformationResource
|
|
134
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-IOVFTIW6.js";
|
|
135
135
|
import {
|
|
136
136
|
AGENT_PROFILE,
|
|
137
137
|
AUTH_HEADERS,
|
|
@@ -191,6 +191,7 @@ import {
|
|
|
191
191
|
MAX_UDF_PER_QUERY,
|
|
192
192
|
MIN_PREFIX_SUMMARY_LENGTH,
|
|
193
193
|
MarkerUnsafeIdError,
|
|
194
|
+
MoveRefusedError,
|
|
194
195
|
NoopLogger,
|
|
195
196
|
NotFoundError,
|
|
196
197
|
PERSONAL_RESPONSE_FIELDS,
|
|
@@ -267,8 +268,8 @@ import {
|
|
|
267
268
|
validateFilter,
|
|
268
269
|
withAuthHeaders,
|
|
269
270
|
zoneUrl
|
|
270
|
-
} from "./chunk-
|
|
271
|
-
import "./chunk-
|
|
271
|
+
} from "./chunk-BBQBWVBE.js";
|
|
272
|
+
import "./chunk-WJD26CPN.js";
|
|
272
273
|
import "./chunk-UPQIUWOS.js";
|
|
273
274
|
|
|
274
275
|
// src/credentials.ts
|
|
@@ -481,15 +482,33 @@ async function timeCheck(id, fn) {
|
|
|
481
482
|
};
|
|
482
483
|
}
|
|
483
484
|
}
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
485
|
+
function failFrom(err, what) {
|
|
486
|
+
if (err instanceof RateLimitError && (err.code === "RATE_LIMITED_COOLDOWN" || err.notSent === true)) {
|
|
487
|
+
return {
|
|
488
|
+
status: "fail",
|
|
489
|
+
message: `${what} \u2014 refused LOCALLY by the tenant 429 cooldown gate (the call was NOT sent)`,
|
|
490
|
+
hint: err.suggestedAction
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (err.code === "RATE_LIMITED") {
|
|
494
|
+
return {
|
|
495
|
+
status: "fail",
|
|
496
|
+
message: `${what} \u2014 refused by the LOCAL client-side rate limiter (per-process budget; not a vendor 429)`,
|
|
497
|
+
hint: err.suggestedAction
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
const statusLabel = err.httpStatus !== void 0 ? ` (HTTP ${err.httpStatus})` : "";
|
|
501
|
+
return { status: "fail", message: `${what} failed${statusLabel} \u2014 machine code ${err.code}`, hint: err.suggestedAction };
|
|
502
|
+
}
|
|
503
|
+
function skip(why) {
|
|
504
|
+
return { status: "skip", message: `skipped: ${why}` };
|
|
505
|
+
}
|
|
506
|
+
var ZONE_UNAVAILABLE_SKIP = "zone discovery proved the API or credentials unavailable (check #zone)";
|
|
507
|
+
function makeWire(run, timeoutMs) {
|
|
489
508
|
const wire = async (method, path, operation, extra = {}) => {
|
|
490
|
-
issued += 1;
|
|
509
|
+
run.issued += 1;
|
|
491
510
|
try {
|
|
492
|
-
const body = await client.http.request({
|
|
511
|
+
const body = await run.client.http.request({
|
|
493
512
|
method,
|
|
494
513
|
path,
|
|
495
514
|
query: extra.query,
|
|
@@ -507,25 +526,10 @@ async function runDoctor(client, opts = {}) {
|
|
|
507
526
|
throw err;
|
|
508
527
|
}
|
|
509
528
|
};
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
message: `${what} \u2014 refused LOCALLY by the tenant 429 cooldown gate (the call was NOT sent)`,
|
|
515
|
-
hint: err.suggestedAction
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
if (err.code === "RATE_LIMITED") {
|
|
519
|
-
return {
|
|
520
|
-
status: "fail",
|
|
521
|
-
message: `${what} \u2014 refused by the LOCAL client-side rate limiter (per-process budget; not a vendor 429)`,
|
|
522
|
-
hint: err.suggestedAction
|
|
523
|
-
};
|
|
524
|
-
}
|
|
525
|
-
const statusLabel = err.httpStatus !== void 0 ? ` (HTTP ${err.httpStatus})` : "";
|
|
526
|
-
return { status: "fail", message: `${what} failed${statusLabel} \u2014 machine code ${err.code}`, hint: err.suggestedAction };
|
|
527
|
-
};
|
|
528
|
-
const configCheck = await timeCheck("config", async () => {
|
|
529
|
+
return wire;
|
|
530
|
+
}
|
|
531
|
+
async function checkConfig(cfg) {
|
|
532
|
+
return timeCheck("config", async () => {
|
|
529
533
|
const zone = cfg.zone ?? "custom baseUrl";
|
|
530
534
|
const host = new URL(cfg.baseUrl).host;
|
|
531
535
|
const bits = [`configuration complete (zone ${zone} \u2192 ${host})`];
|
|
@@ -533,8 +537,11 @@ async function runDoctor(client, opts = {}) {
|
|
|
533
537
|
if (cfg.rateLimit !== void 0) bits.push(`client-side rate limiter ENABLED (${cfg.rateLimit.perHour}/hr \u2014 the doctor's calls count against it)`);
|
|
534
538
|
return { status: "pass", message: bits.join("; ") };
|
|
535
539
|
});
|
|
536
|
-
|
|
537
|
-
|
|
540
|
+
}
|
|
541
|
+
async function checkZone(run) {
|
|
542
|
+
const cfg = run.client.config;
|
|
543
|
+
return timeCheck("zone", async () => {
|
|
544
|
+
const out = await run.wire("GET", "/V1.0/ZoneInformation", "doctor.zone", { query: { user: cfg.userName } });
|
|
538
545
|
if (out.error) {
|
|
539
546
|
const f = failFrom(out.error, "zone discovery (zoneInformation.get)");
|
|
540
547
|
return { ...f, value: { code: out.error.code, httpStatus: out.error.httpStatus } };
|
|
@@ -551,25 +558,31 @@ async function runDoctor(client, opts = {}) {
|
|
|
551
558
|
}
|
|
552
559
|
return { status: "pass", message: `zone discovery OK: "${body.zoneName}" (actual host: ${actualHost})`, value: body };
|
|
553
560
|
});
|
|
561
|
+
}
|
|
562
|
+
function isZoneUnavailable(zoneOutcome) {
|
|
554
563
|
const zoneFailCode = zoneOutcome.check.status === "fail" && zoneOutcome.value !== void 0 && "code" in zoneOutcome.value ? zoneOutcome.value : void 0;
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
564
|
+
return zoneFailCode !== void 0 && (zoneFailCode.code === "NETWORK_ERROR" || zoneFailCode.code === "TIMEOUT" || zoneFailCode.httpStatus === 401 || zoneFailCode.httpStatus === 403 || zoneFailCode.code === "RATE_LIMITED_COOLDOWN" || zoneFailCode.code === "RATE_LIMITED");
|
|
565
|
+
}
|
|
566
|
+
async function checkConnectivity(run, zoneUnavailable) {
|
|
567
|
+
return timeCheck("connectivity", async () => {
|
|
568
|
+
if (zoneUnavailable) return skip(ZONE_UNAVAILABLE_SKIP);
|
|
559
569
|
const t0 = Date.now();
|
|
560
|
-
const out = await wire("GET", "/V1.0/Version", "doctor.connectivity");
|
|
570
|
+
const out = await run.wire("GET", "/V1.0/Version", "doctor.connectivity");
|
|
561
571
|
const ms = Date.now() - t0;
|
|
562
572
|
if (out.error) return failFrom(out.error, "API reachability (version.get)");
|
|
563
573
|
const body = out.body;
|
|
564
574
|
return { status: "pass", message: `API reachable (version ${body.majorVersion}.${body.minorVersion} build ${body.build}, ${ms}ms round trip)` };
|
|
565
575
|
});
|
|
576
|
+
}
|
|
577
|
+
async function checkReads(run, zoneUnavailable) {
|
|
578
|
+
const cfg = run.client.config;
|
|
566
579
|
const readChecks = [];
|
|
567
580
|
for (const entity of DOCTOR_ENTITIES) {
|
|
568
581
|
const id = `read.${entity.key}`;
|
|
569
582
|
const result = await timeCheck(id, async () => {
|
|
570
|
-
if (zoneUnavailable) return skip(
|
|
583
|
+
if (zoneUnavailable) return skip(ZONE_UNAVAILABLE_SKIP);
|
|
571
584
|
const req = buildQueryRequest(cfg.baseUrl, entity.path, { maxRecords: 1 });
|
|
572
|
-
const out = await wire(req.method, req.path, `doctor.${id}`, { body: req.body, idempotent: req.idempotent });
|
|
585
|
+
const out = await run.wire(req.method, req.path, `doctor.${id}`, { body: req.body, idempotent: req.idempotent });
|
|
573
586
|
if (out.error) {
|
|
574
587
|
const f = failFrom(out.error, `read access to ${entity.label}`);
|
|
575
588
|
if (out.error.httpStatus === 403) {
|
|
@@ -585,9 +598,12 @@ async function runDoctor(client, opts = {}) {
|
|
|
585
598
|
});
|
|
586
599
|
readChecks.push(result.check);
|
|
587
600
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
601
|
+
return readChecks;
|
|
602
|
+
}
|
|
603
|
+
async function checkThreshold(run, zoneUnavailable) {
|
|
604
|
+
return timeCheck("threshold", async () => {
|
|
605
|
+
if (zoneUnavailable) return skip(ZONE_UNAVAILABLE_SKIP);
|
|
606
|
+
const out = await run.wire(
|
|
591
607
|
"GET",
|
|
592
608
|
"/V1.0/ThresholdInformation",
|
|
593
609
|
"doctor.threshold",
|
|
@@ -596,7 +612,7 @@ async function runDoctor(client, opts = {}) {
|
|
|
596
612
|
if (out.error) return failFrom(out.error, "API usage headroom (thresholdInformation.get)");
|
|
597
613
|
const body = out.body;
|
|
598
614
|
const headroom = body.externalRequestThreshold - body.currentTimeframeRequestCount;
|
|
599
|
-
tenantBudget = {
|
|
615
|
+
run.tenantBudget = {
|
|
600
616
|
threshold: body.externalRequestThreshold,
|
|
601
617
|
timeframeSeconds: body.requestThresholdTimeframe,
|
|
602
618
|
used: body.currentTimeframeRequestCount,
|
|
@@ -610,6 +626,18 @@ async function runDoctor(client, opts = {}) {
|
|
|
610
626
|
}
|
|
611
627
|
return { status: "pass", message: `API usage headroom OK: ${headroom}/${body.externalRequestThreshold} requests remaining in the current timeframe` };
|
|
612
628
|
});
|
|
629
|
+
}
|
|
630
|
+
async function runDoctor(client, opts = {}) {
|
|
631
|
+
const cfg = client.config;
|
|
632
|
+
const timeoutMs = opts.timeoutMs ?? DOCTOR_CHECK_TIMEOUT_MS;
|
|
633
|
+
const run = { client, issued: 0, tenantBudget: null };
|
|
634
|
+
run.wire = makeWire(run, timeoutMs);
|
|
635
|
+
const configCheck = await checkConfig(cfg);
|
|
636
|
+
const zoneOutcome = await checkZone(run);
|
|
637
|
+
const zoneUnavailable = isZoneUnavailable(zoneOutcome);
|
|
638
|
+
const connectivity = await checkConnectivity(run, zoneUnavailable);
|
|
639
|
+
const readChecks = await checkReads(run, zoneUnavailable);
|
|
640
|
+
const threshold = await checkThreshold(run, zoneUnavailable);
|
|
613
641
|
const checks = [
|
|
614
642
|
configCheck.check,
|
|
615
643
|
zoneOutcome.check,
|
|
@@ -625,8 +653,8 @@ async function runDoctor(client, opts = {}) {
|
|
|
625
653
|
checks,
|
|
626
654
|
budget: {
|
|
627
655
|
localLimiter: { enabled: cfg.rateLimit !== void 0, perHour: cfg.rateLimit?.perHour ?? null },
|
|
628
|
-
tenant: tenantBudget,
|
|
629
|
-
requestBudget: { max: DOCTOR_MAX_REQUESTS, issued }
|
|
656
|
+
tenant: run.tenantBudget,
|
|
657
|
+
requestBudget: { max: DOCTOR_MAX_REQUESTS, issued: run.issued }
|
|
630
658
|
},
|
|
631
659
|
summary
|
|
632
660
|
};
|
|
@@ -797,6 +825,7 @@ export {
|
|
|
797
825
|
MIN_PREFIX_SUMMARY_LENGTH,
|
|
798
826
|
MarkerUnsafeIdError,
|
|
799
827
|
ModulesResource,
|
|
828
|
+
MoveRefusedError,
|
|
800
829
|
NoopLogger,
|
|
801
830
|
NotFoundError,
|
|
802
831
|
NotificationHistoryResource,
|