node-autotask 0.26.0 → 0.27.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/MCP_TOOL_CATALOG.json +921 -30
  3. package/MCP_TOOL_MANIFEST.md +69 -16
  4. package/N8N_MCP_MANIFEST.json +39 -8
  5. package/N8N_MCP_MANIFEST.md +9 -8
  6. package/README.md +11 -9
  7. package/capabilities.json +13316 -7733
  8. package/capabilities.schema.json +125 -0
  9. package/dist/capabilities.cjs +2 -2
  10. package/dist/capabilities.js +1 -1
  11. package/dist/{chunk-SSUECUVN.js → chunk-42ZUISDH.js} +947 -128
  12. package/dist/{chunk-WM6E5O55.cjs → chunk-5CC7LGNM.cjs} +13315 -7732
  13. package/dist/{chunk-SG4LIVMG.cjs → chunk-5GGCSRT4.cjs} +848 -439
  14. package/dist/{chunk-QXWIQ67O.js → chunk-F7FVOXPQ.js} +13315 -7732
  15. package/dist/{chunk-7DOSJS6S.js → chunk-GURC52J7.js} +23 -2
  16. package/dist/{chunk-5OGJTS2E.cjs → chunk-UHTZLUDE.cjs} +157 -136
  17. package/dist/{chunk-VVQ6NJYZ.js → chunk-ZGTFVZL5.js} +433 -24
  18. package/dist/{chunk-HQGE4WAV.cjs → chunk-ZJ4ONAQF.cjs} +1054 -235
  19. package/dist/{index-CKYr0unq.d.cts → index-BIWy9m-a.d.ts} +379 -49
  20. package/dist/{index-C8QH3BkP.d.ts → index-D4XYtn4s.d.cts} +379 -49
  21. package/dist/{index-1zBdJIEy.d.cts → index-DQ9NgraW.d.cts} +281 -1
  22. package/dist/{index-1zBdJIEy.d.ts → index-DQ9NgraW.d.ts} +281 -1
  23. package/dist/index.cjs +44 -24
  24. package/dist/index.d.cts +11 -5
  25. package/dist/index.d.ts +11 -5
  26. package/dist/index.js +26 -6
  27. package/dist/operations/index.cjs +147 -120
  28. package/dist/operations/index.d.cts +136 -7
  29. package/dist/operations/index.d.ts +136 -7
  30. package/dist/operations/index.js +33 -6
  31. package/dist/pool.cjs +42 -9
  32. package/dist/pool.d.cts +14 -3
  33. package/dist/pool.d.ts +14 -3
  34. package/dist/pool.js +38 -5
  35. package/dist/resources/index.cjs +19 -5
  36. package/dist/resources/index.d.cts +2 -2
  37. package/dist/resources/index.d.ts +2 -2
  38. package/dist/resources/index.js +18 -4
  39. package/dist/types/index.cjs +1 -1
  40. package/dist/types/index.d.cts +1 -1
  41. package/dist/types/index.d.ts +1 -1
  42. package/dist/types/index.js +1 -1
  43. package/docs/API.md +207 -9
  44. package/examples/mcp/schemas.ts +16 -7
  45. package/package.json +1 -1
  46. /package/dist/{chunk-S643FDOR.cjs → chunk-IXF7AKOJ.cjs} +0 -0
  47. /package/dist/{chunk-2TWKEB2L.js → chunk-RMG55JTF.js} +0 -0
  48. /package/dist/{chunk-W3K5BEVY.cjs → chunk-SDYRQFGL.cjs} +0 -0
  49. /package/dist/{chunk-EBCHCNPK.js → chunk-WLTLB2ND.js} +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "generatedBy": "scripts/build-tool-catalog.mjs",
3
- "generatedAt": "2026-10-25T12:41:37.683Z",
4
- "planHash": "930b907e3b06a5ff3b72fd312854a14e5acedaf03effee5ced3c960b1afbf086",
3
+ "generatedAt": "2026-10-26T03:09:40.649Z",
4
+ "planHash": "7318bd56d1c2e0dd4ba45a724bb37cf58f95f73fdd77c0fea6fce919430e17d0",
5
5
  "metaTools": [
6
6
  {
7
7
  "name": "autotask_catalog",
@@ -43,7 +43,7 @@
43
43
  {
44
44
  "name": "autotask_read",
45
45
  "title": "Read One Registry Operation (read mode)",
46
- "description": "Route an effect=read registry operation by its exact name (never fuzzy, never a tool name): the 366 field/entity/UDF-info reads (getEntityInfo/getFieldInfo/getUdfInfo) have no dedicated tool and ride this one, and any read op is routable. For field discovery use operations.fieldCatalog (compact) instead of per-resource getFieldInfo (full dump). Read-only by construction — every op it can route is effect=read (zero mutating requests), and a write or delete op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). Reads have no dry run (a read with dry_run: true is refused). Harness approval policy: approve every tool with readOnlyHint !== true (exactly 256 today); the 608 readOnlyHint: true tools — including this one — are safe ungated; the 57 destructiveHint: true tools (56 dedicated delete tools + autotask_delete) require confirm === the operation key. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. For query/count ops args[0] is a params object (filter/limit); call autotask_describe first for the exact arg shape and filter grammar. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
46
+ "description": "Route an effect=read registry operation by its exact name (never fuzzy, never a tool name): the 384 field/entity/UDF-info reads (getEntityInfo/getFieldInfo/getUdfInfo) have no dedicated tool and ride this one, and any read op is routable. For field discovery use operations.fieldCatalog (compact) instead of per-resource getFieldInfo (full dump). Read-only by construction — every op it can route is effect=read (zero mutating requests), and a write or delete op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). Reads have no dry run (a read with dry_run: true is refused). Harness approval policy: approve every tool with readOnlyHint !== true (exactly 267 today); the 629 readOnlyHint: true tools — including this one — are safe ungated; the 57 destructiveHint: true tools (56 dedicated delete tools + autotask_delete) require confirm === the operation key. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. For query/count ops args[0] is a params object (filter/limit); call autotask_describe first for the exact arg shape and filter grammar. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
47
47
  "input": {
48
48
  "operation": {
49
49
  "type": "string",
@@ -63,7 +63,7 @@
63
63
  {
64
64
  "name": "autotask_write",
65
65
  "title": "Write One Registry Operation (write mode)",
66
- "description": "Route an effect=write registry operation by its exact name (never fuzzy, never a tool name), dry-run-first: the first call always travels dry_run: true (the pinned DryRunResult envelope, simulated: true — the mutating request is never issued); pass dry_run: false to apply. A read or delete op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). The 3 approval-gated writes (configuration_items.moveConfigurationItem, contacts.moveToCompany, resources.transferOwnership) additionally require confirm === the operation key, in BOTH dry-run and apply mode. Harness approval policy: this tool is one of the 256 tools that require approval (readOnlyHint !== true); the 608 readOnlyHint: true tools are safe ungated, and the 57 destructiveHint: true tools (56 dedicated delete tools + autotask_delete) require confirm === the operation key. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. For query/count ops args[0] is a params object (filter/limit); call autotask_describe first for the exact arg shape and filter grammar. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
66
+ "description": "Route an effect=write registry operation by its exact name (never fuzzy, never a tool name), dry-run-first: the first call always travels dry_run: true (the pinned DryRunResult envelope, simulated: true — the mutating request is never issued); pass dry_run: false to apply. A read or delete op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). The 3 approval-gated writes (configuration_items.moveConfigurationItem, contacts.moveToCompany, resources.transferOwnership) additionally require confirm === the operation key, in BOTH dry-run and apply mode. Harness approval policy: this tool is one of the 267 tools that require approval (readOnlyHint !== true); the 629 readOnlyHint: true tools are safe ungated, and the 57 destructiveHint: true tools (56 dedicated delete tools + autotask_delete) require confirm === the operation key. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. For query/count ops args[0] is a params object (filter/limit); call autotask_describe first for the exact arg shape and filter grammar. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
67
67
  "input": {
68
68
  "operation": {
69
69
  "type": "string",
@@ -93,7 +93,7 @@
93
93
  {
94
94
  "name": "autotask_delete",
95
95
  "title": "Delete One Registry Operation (delete mode)",
96
- "description": "Route an effect=destructive (delete) registry operation by its exact name (never fuzzy, never a tool name), dry-run-first: the first call always travels dry_run: true (the pinned DryRunResult envelope, simulated: true); pass dry_run: false to apply. confirm === the operation key is REQUIRED for every delete (all 56), in BOTH dry-run and apply mode — the deliberate act is the call, not the delete. A read or write op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). Harness approval policy: this tool is one of the 57 destructiveHint: true tools that require approval + confirm; approve every tool with readOnlyHint !== true (exactly 256 today); the 608 readOnlyHint: true tools are safe ungated. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
96
+ "description": "Route an effect=destructive (delete) registry operation by its exact name (never fuzzy, never a tool name), dry-run-first: the first call always travels dry_run: true (the pinned DryRunResult envelope, simulated: true); pass dry_run: false to apply. confirm === the operation key is REQUIRED for every delete (all 56), in BOTH dry-run and apply mode — the deliberate act is the call, not the delete. A read or write op is refused BEFORE any request (cross-mode refusal; the message names the correct tool). Harness approval policy: this tool is one of the 57 destructiveHint: true tools that require approval + confirm; approve every tool with readOnlyHint !== true (exactly 267 today); the 629 readOnlyHint: true tools are safe ungated. Migration: autotask_invoke is REPLACED by autotask_read/autotask_write/autotask_delete — update harness config. The argument set is CLOSED at the top level: an unknown argument is refused before any request, with a typed error naming the key and the valid keys.",
97
97
  "input": {
98
98
  "operation": {
99
99
  "type": "string",
@@ -557,6 +557,78 @@
557
557
  "reachReason": null,
558
558
  "boundedAlternative": null
559
559
  },
560
+ {
561
+ "operation": "billing_item_approval_levels.count",
562
+ "core": false,
563
+ "tool": "autotask_billingItemApprovalLevel_count",
564
+ "purpose": "Count billing item approval level records matching a JSON filter.",
565
+ "preferredWhen": null,
566
+ "backingOperation": "billing_item_approval_levels.count",
567
+ "effect": "read",
568
+ "dryRunFirst": false,
569
+ "confirm": false,
570
+ "requiredArgs": [],
571
+ "tier": "extended",
572
+ "reachable": true,
573
+ "reach": "dedicated tool",
574
+ "reachReason": null,
575
+ "boundedAlternative": null
576
+ },
577
+ {
578
+ "operation": "billing_item_approval_levels.create",
579
+ "core": false,
580
+ "tool": "autotask_billingItemApprovalLevel_create",
581
+ "purpose": "Create a billing item approval level (the REST-only approval write for a time entry).",
582
+ "preferredWhen": "Prefer time_entries.approve: it performs this create AND the documented follow-up update, then verifies the read-back. Use this raw create only when the follow-up update must be controlled separately.",
583
+ "backingOperation": "billing_item_approval_levels.create",
584
+ "effect": "write",
585
+ "dryRunFirst": true,
586
+ "confirm": false,
587
+ "requiredArgs": [
588
+ "data"
589
+ ],
590
+ "tier": "extended",
591
+ "reachable": true,
592
+ "reach": "dedicated tool",
593
+ "reachReason": null,
594
+ "boundedAlternative": null
595
+ },
596
+ {
597
+ "operation": "billing_item_approval_levels.get",
598
+ "core": false,
599
+ "tool": "autotask_billingItemApprovalLevel_get",
600
+ "purpose": "Get one billing item approval level by id.",
601
+ "preferredWhen": "Preferred when the numeric id is known (e.g. the id time_entries.approve returned); query by timeEntryID when it is not.",
602
+ "backingOperation": "billing_item_approval_levels.get",
603
+ "effect": "read",
604
+ "dryRunFirst": false,
605
+ "confirm": false,
606
+ "requiredArgs": [
607
+ "id"
608
+ ],
609
+ "tier": "extended",
610
+ "reachable": true,
611
+ "reach": "dedicated tool",
612
+ "reachReason": null,
613
+ "boundedAlternative": null
614
+ },
615
+ {
616
+ "operation": "billing_item_approval_levels.query",
617
+ "core": false,
618
+ "tool": "autotask_billingItemApprovalLevel_query",
619
+ "purpose": "Query BillingItemApprovalLevel records with a JSON filter.",
620
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
621
+ "backingOperation": "billing_item_approval_levels.query",
622
+ "effect": "read",
623
+ "dryRunFirst": false,
624
+ "confirm": false,
625
+ "requiredArgs": [],
626
+ "tier": "extended",
627
+ "reachable": true,
628
+ "reach": "dedicated tool",
629
+ "reachReason": null,
630
+ "boundedAlternative": null
631
+ },
560
632
  {
561
633
  "operation": "billing_items.count",
562
634
  "core": false,
@@ -4947,6 +5019,110 @@
4947
5019
  "reachReason": null,
4948
5020
  "boundedAlternative": null
4949
5021
  },
5022
+ {
5023
+ "operation": "invoice_templates.count",
5024
+ "core": false,
5025
+ "tool": "autotask_invoiceTemplate_count",
5026
+ "purpose": "Count invoice template records matching a JSON filter.",
5027
+ "preferredWhen": null,
5028
+ "backingOperation": "invoice_templates.count",
5029
+ "effect": "read",
5030
+ "dryRunFirst": false,
5031
+ "confirm": false,
5032
+ "requiredArgs": [],
5033
+ "tier": "advanced",
5034
+ "reachable": true,
5035
+ "reach": "dedicated tool",
5036
+ "reachReason": null,
5037
+ "boundedAlternative": null
5038
+ },
5039
+ {
5040
+ "operation": "invoice_templates.get",
5041
+ "core": false,
5042
+ "tool": "autotask_invoiceTemplate_get",
5043
+ "purpose": "Get one InvoiceTemplate by id.",
5044
+ "preferredWhen": "Preferred when the numeric id is already known.",
5045
+ "backingOperation": "invoice_templates.get",
5046
+ "effect": "read",
5047
+ "dryRunFirst": false,
5048
+ "confirm": false,
5049
+ "requiredArgs": [
5050
+ "id"
5051
+ ],
5052
+ "tier": "advanced",
5053
+ "reachable": true,
5054
+ "reach": "dedicated tool",
5055
+ "reachReason": null,
5056
+ "boundedAlternative": null
5057
+ },
5058
+ {
5059
+ "operation": "invoice_templates.getEntityInfo",
5060
+ "core": false,
5061
+ "tool": null,
5062
+ "purpose": "Get the InvoiceTemplate capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
5063
+ "preferredWhen": null,
5064
+ "backingOperation": "invoice_templates.getEntityInfo",
5065
+ "effect": "read",
5066
+ "dryRunFirst": false,
5067
+ "confirm": false,
5068
+ "requiredArgs": [],
5069
+ "tier": "advanced",
5070
+ "reachable": true,
5071
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5072
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5073
+ "boundedAlternative": null
5074
+ },
5075
+ {
5076
+ "operation": "invoice_templates.getFieldInfo",
5077
+ "core": false,
5078
+ "tool": null,
5079
+ "purpose": "Get the InvoiceTemplate field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
5080
+ "preferredWhen": null,
5081
+ "backingOperation": "invoice_templates.getFieldInfo",
5082
+ "effect": "read",
5083
+ "dryRunFirst": false,
5084
+ "confirm": false,
5085
+ "requiredArgs": [],
5086
+ "tier": "advanced",
5087
+ "reachable": true,
5088
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5089
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5090
+ "boundedAlternative": null
5091
+ },
5092
+ {
5093
+ "operation": "invoice_templates.getUdfInfo",
5094
+ "core": false,
5095
+ "tool": null,
5096
+ "purpose": "Get the InvoiceTemplate user-defined-field catalog.",
5097
+ "preferredWhen": null,
5098
+ "backingOperation": "invoice_templates.getUdfInfo",
5099
+ "effect": "read",
5100
+ "dryRunFirst": false,
5101
+ "confirm": false,
5102
+ "requiredArgs": [],
5103
+ "tier": "advanced",
5104
+ "reachable": true,
5105
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5106
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5107
+ "boundedAlternative": null
5108
+ },
5109
+ {
5110
+ "operation": "invoice_templates.query",
5111
+ "core": false,
5112
+ "tool": "autotask_invoiceTemplate_query",
5113
+ "purpose": "Query InvoiceTemplate records with a JSON filter.",
5114
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
5115
+ "backingOperation": "invoice_templates.query",
5116
+ "effect": "read",
5117
+ "dryRunFirst": false,
5118
+ "confirm": false,
5119
+ "requiredArgs": [],
5120
+ "tier": "advanced",
5121
+ "reachable": true,
5122
+ "reach": "dedicated tool",
5123
+ "reachReason": null,
5124
+ "boundedAlternative": null
5125
+ },
4950
5126
  {
4951
5127
  "operation": "modules.get",
4952
5128
  "core": false,
@@ -5197,45 +5373,474 @@
5197
5373
  "tool": "autotask_opportunityCategories_resolve",
5198
5374
  "purpose": "Resolve an opportunity category from a numeric id (the direct fetch, tried first) or an exact value of its primary text field(s) (name — exact match only). Returns the Opportunity category record with the numeric id for get/update/delete. Other identifier forms (e.g. an email address) are NOT tried by resolve — use the resource's dedicated lookup op where one exists (see autotask_catalog).",
5199
5375
  "preferredWhen": null,
5200
- "backingOperation": "opportunity_categories.resolve",
5376
+ "backingOperation": "opportunity_categories.resolve",
5377
+ "effect": "read",
5378
+ "dryRunFirst": false,
5379
+ "confirm": false,
5380
+ "requiredArgs": [
5381
+ "identifier"
5382
+ ],
5383
+ "tier": "extended",
5384
+ "reachable": true,
5385
+ "reach": "dedicated tool",
5386
+ "reachReason": null,
5387
+ "boundedAlternative": null
5388
+ },
5389
+ {
5390
+ "operation": "opportunity_categories.search",
5391
+ "core": false,
5392
+ "tool": "autotask_opportunityCategories_search",
5393
+ "purpose": "Search opportunity category records by text (contains on the searchable fields).",
5394
+ "preferredWhen": null,
5395
+ "backingOperation": "opportunity_categories.search",
5396
+ "effect": "read",
5397
+ "dryRunFirst": false,
5398
+ "confirm": false,
5399
+ "requiredArgs": [
5400
+ "query"
5401
+ ],
5402
+ "tier": "extended",
5403
+ "reachable": true,
5404
+ "reach": "dedicated tool",
5405
+ "reachReason": null,
5406
+ "boundedAlternative": null
5407
+ },
5408
+ {
5409
+ "operation": "opportunity_categories.update",
5410
+ "core": false,
5411
+ "tool": "autotask_opportunityCategories_update",
5412
+ "purpose": "Update an opportunity category.",
5413
+ "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
5414
+ "backingOperation": "opportunity_categories.update",
5415
+ "effect": "write",
5416
+ "dryRunFirst": true,
5417
+ "confirm": false,
5418
+ "requiredArgs": [
5419
+ "id",
5420
+ "data"
5421
+ ],
5422
+ "tier": "extended",
5423
+ "reachable": true,
5424
+ "reach": "dedicated tool",
5425
+ "reachReason": null,
5426
+ "boundedAlternative": null
5427
+ },
5428
+ {
5429
+ "operation": "organizational_level_associations.count",
5430
+ "core": false,
5431
+ "tool": "autotask_organizationalLevelAssociation_count",
5432
+ "purpose": "Count organizational level association records matching a JSON filter.",
5433
+ "preferredWhen": null,
5434
+ "backingOperation": "organizational_level_associations.count",
5435
+ "effect": "read",
5436
+ "dryRunFirst": false,
5437
+ "confirm": false,
5438
+ "requiredArgs": [],
5439
+ "tier": "advanced",
5440
+ "reachable": true,
5441
+ "reach": "dedicated tool",
5442
+ "reachReason": null,
5443
+ "boundedAlternative": null
5444
+ },
5445
+ {
5446
+ "operation": "organizational_level_associations.create",
5447
+ "core": false,
5448
+ "tool": "autotask_organizationalLevelAssociation_create",
5449
+ "purpose": "Create an organizational level association.",
5450
+ "preferredWhen": "Only for a record that does not exist yet; prefer update for an id you already have.",
5451
+ "backingOperation": "organizational_level_associations.create",
5452
+ "effect": "write",
5453
+ "dryRunFirst": true,
5454
+ "confirm": false,
5455
+ "requiredArgs": [
5456
+ "data"
5457
+ ],
5458
+ "tier": "advanced",
5459
+ "reachable": true,
5460
+ "reach": "dedicated tool",
5461
+ "reachReason": null,
5462
+ "boundedAlternative": null
5463
+ },
5464
+ {
5465
+ "operation": "organizational_level_associations.get",
5466
+ "core": false,
5467
+ "tool": "autotask_organizationalLevelAssociation_get",
5468
+ "purpose": "Get one OrganizationalLevelAssociation by id.",
5469
+ "preferredWhen": "Preferred when the numeric id is already known.",
5470
+ "backingOperation": "organizational_level_associations.get",
5471
+ "effect": "read",
5472
+ "dryRunFirst": false,
5473
+ "confirm": false,
5474
+ "requiredArgs": [
5475
+ "id"
5476
+ ],
5477
+ "tier": "advanced",
5478
+ "reachable": true,
5479
+ "reach": "dedicated tool",
5480
+ "reachReason": null,
5481
+ "boundedAlternative": null
5482
+ },
5483
+ {
5484
+ "operation": "organizational_level_associations.getEntityInfo",
5485
+ "core": false,
5486
+ "tool": null,
5487
+ "purpose": "Get the OrganizationalLevelAssociation capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
5488
+ "preferredWhen": null,
5489
+ "backingOperation": "organizational_level_associations.getEntityInfo",
5490
+ "effect": "read",
5491
+ "dryRunFirst": false,
5492
+ "confirm": false,
5493
+ "requiredArgs": [],
5494
+ "tier": "advanced",
5495
+ "reachable": true,
5496
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5497
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5498
+ "boundedAlternative": null
5499
+ },
5500
+ {
5501
+ "operation": "organizational_level_associations.getFieldInfo",
5502
+ "core": false,
5503
+ "tool": null,
5504
+ "purpose": "Get the OrganizationalLevelAssociation field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
5505
+ "preferredWhen": null,
5506
+ "backingOperation": "organizational_level_associations.getFieldInfo",
5507
+ "effect": "read",
5508
+ "dryRunFirst": false,
5509
+ "confirm": false,
5510
+ "requiredArgs": [],
5511
+ "tier": "advanced",
5512
+ "reachable": true,
5513
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5514
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5515
+ "boundedAlternative": null
5516
+ },
5517
+ {
5518
+ "operation": "organizational_level_associations.getUdfInfo",
5519
+ "core": false,
5520
+ "tool": null,
5521
+ "purpose": "Get the OrganizationalLevelAssociation user-defined-field catalog.",
5522
+ "preferredWhen": null,
5523
+ "backingOperation": "organizational_level_associations.getUdfInfo",
5524
+ "effect": "read",
5525
+ "dryRunFirst": false,
5526
+ "confirm": false,
5527
+ "requiredArgs": [],
5528
+ "tier": "advanced",
5529
+ "reachable": true,
5530
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5531
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5532
+ "boundedAlternative": null
5533
+ },
5534
+ {
5535
+ "operation": "organizational_level_associations.query",
5536
+ "core": false,
5537
+ "tool": "autotask_organizationalLevelAssociation_query",
5538
+ "purpose": "Query OrganizationalLevelAssociation records with a JSON filter.",
5539
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
5540
+ "backingOperation": "organizational_level_associations.query",
5541
+ "effect": "read",
5542
+ "dryRunFirst": false,
5543
+ "confirm": false,
5544
+ "requiredArgs": [],
5545
+ "tier": "advanced",
5546
+ "reachable": true,
5547
+ "reach": "dedicated tool",
5548
+ "reachReason": null,
5549
+ "boundedAlternative": null
5550
+ },
5551
+ {
5552
+ "operation": "organizational_level_associations.update",
5553
+ "core": false,
5554
+ "tool": "autotask_organizationalLevelAssociation_update",
5555
+ "purpose": "Update an organizational level association.",
5556
+ "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
5557
+ "backingOperation": "organizational_level_associations.update",
5558
+ "effect": "write",
5559
+ "dryRunFirst": true,
5560
+ "confirm": false,
5561
+ "requiredArgs": [
5562
+ "id",
5563
+ "data"
5564
+ ],
5565
+ "tier": "advanced",
5566
+ "reachable": true,
5567
+ "reach": "dedicated tool",
5568
+ "reachReason": null,
5569
+ "boundedAlternative": null
5570
+ },
5571
+ {
5572
+ "operation": "organizational_level1s.count",
5573
+ "core": false,
5574
+ "tool": "autotask_organizationalLevel1_count",
5575
+ "purpose": "Count organizational level 1 records matching a JSON filter.",
5576
+ "preferredWhen": null,
5577
+ "backingOperation": "organizational_level1s.count",
5578
+ "effect": "read",
5579
+ "dryRunFirst": false,
5580
+ "confirm": false,
5581
+ "requiredArgs": [],
5582
+ "tier": "advanced",
5583
+ "reachable": true,
5584
+ "reach": "dedicated tool",
5585
+ "reachReason": null,
5586
+ "boundedAlternative": null
5587
+ },
5588
+ {
5589
+ "operation": "organizational_level1s.create",
5590
+ "core": false,
5591
+ "tool": "autotask_organizationalLevel1_create",
5592
+ "purpose": "Create an organizational level 1.",
5593
+ "preferredWhen": "Only for a record that does not exist yet; prefer update for an id you already have.",
5594
+ "backingOperation": "organizational_level1s.create",
5595
+ "effect": "write",
5596
+ "dryRunFirst": true,
5597
+ "confirm": false,
5598
+ "requiredArgs": [
5599
+ "data"
5600
+ ],
5601
+ "tier": "advanced",
5602
+ "reachable": true,
5603
+ "reach": "dedicated tool",
5604
+ "reachReason": null,
5605
+ "boundedAlternative": null
5606
+ },
5607
+ {
5608
+ "operation": "organizational_level1s.get",
5609
+ "core": false,
5610
+ "tool": "autotask_organizationalLevel1_get",
5611
+ "purpose": "Get one OrganizationalLevel1 by id.",
5612
+ "preferredWhen": "Preferred when the numeric id is already known.",
5613
+ "backingOperation": "organizational_level1s.get",
5614
+ "effect": "read",
5615
+ "dryRunFirst": false,
5616
+ "confirm": false,
5617
+ "requiredArgs": [
5618
+ "id"
5619
+ ],
5620
+ "tier": "advanced",
5621
+ "reachable": true,
5622
+ "reach": "dedicated tool",
5623
+ "reachReason": null,
5624
+ "boundedAlternative": null
5625
+ },
5626
+ {
5627
+ "operation": "organizational_level1s.getEntityInfo",
5628
+ "core": false,
5629
+ "tool": null,
5630
+ "purpose": "Get the OrganizationalLevel1 capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
5631
+ "preferredWhen": null,
5632
+ "backingOperation": "organizational_level1s.getEntityInfo",
5633
+ "effect": "read",
5634
+ "dryRunFirst": false,
5635
+ "confirm": false,
5636
+ "requiredArgs": [],
5637
+ "tier": "advanced",
5638
+ "reachable": true,
5639
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5640
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5641
+ "boundedAlternative": null
5642
+ },
5643
+ {
5644
+ "operation": "organizational_level1s.getFieldInfo",
5645
+ "core": false,
5646
+ "tool": null,
5647
+ "purpose": "Get the OrganizationalLevel1 field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
5648
+ "preferredWhen": null,
5649
+ "backingOperation": "organizational_level1s.getFieldInfo",
5650
+ "effect": "read",
5651
+ "dryRunFirst": false,
5652
+ "confirm": false,
5653
+ "requiredArgs": [],
5654
+ "tier": "advanced",
5655
+ "reachable": true,
5656
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5657
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5658
+ "boundedAlternative": null
5659
+ },
5660
+ {
5661
+ "operation": "organizational_level1s.getUdfInfo",
5662
+ "core": false,
5663
+ "tool": null,
5664
+ "purpose": "Get the OrganizationalLevel1 user-defined-field catalog.",
5665
+ "preferredWhen": null,
5666
+ "backingOperation": "organizational_level1s.getUdfInfo",
5667
+ "effect": "read",
5668
+ "dryRunFirst": false,
5669
+ "confirm": false,
5670
+ "requiredArgs": [],
5671
+ "tier": "advanced",
5672
+ "reachable": true,
5673
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5674
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5675
+ "boundedAlternative": null
5676
+ },
5677
+ {
5678
+ "operation": "organizational_level1s.query",
5679
+ "core": false,
5680
+ "tool": "autotask_organizationalLevel1_query",
5681
+ "purpose": "Query OrganizationalLevel1 records with a JSON filter.",
5682
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
5683
+ "backingOperation": "organizational_level1s.query",
5684
+ "effect": "read",
5685
+ "dryRunFirst": false,
5686
+ "confirm": false,
5687
+ "requiredArgs": [],
5688
+ "tier": "advanced",
5689
+ "reachable": true,
5690
+ "reach": "dedicated tool",
5691
+ "reachReason": null,
5692
+ "boundedAlternative": null
5693
+ },
5694
+ {
5695
+ "operation": "organizational_level1s.update",
5696
+ "core": false,
5697
+ "tool": "autotask_organizationalLevel1_update",
5698
+ "purpose": "Update an organizational level 1.",
5699
+ "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
5700
+ "backingOperation": "organizational_level1s.update",
5701
+ "effect": "write",
5702
+ "dryRunFirst": true,
5703
+ "confirm": false,
5704
+ "requiredArgs": [
5705
+ "id",
5706
+ "data"
5707
+ ],
5708
+ "tier": "advanced",
5709
+ "reachable": true,
5710
+ "reach": "dedicated tool",
5711
+ "reachReason": null,
5712
+ "boundedAlternative": null
5713
+ },
5714
+ {
5715
+ "operation": "organizational_level2s.count",
5716
+ "core": false,
5717
+ "tool": "autotask_organizationalLevel2_count",
5718
+ "purpose": "Count organizational level 2 records matching a JSON filter.",
5719
+ "preferredWhen": null,
5720
+ "backingOperation": "organizational_level2s.count",
5721
+ "effect": "read",
5722
+ "dryRunFirst": false,
5723
+ "confirm": false,
5724
+ "requiredArgs": [],
5725
+ "tier": "advanced",
5726
+ "reachable": true,
5727
+ "reach": "dedicated tool",
5728
+ "reachReason": null,
5729
+ "boundedAlternative": null
5730
+ },
5731
+ {
5732
+ "operation": "organizational_level2s.create",
5733
+ "core": false,
5734
+ "tool": "autotask_organizationalLevel2_create",
5735
+ "purpose": "Create an organizational level 2.",
5736
+ "preferredWhen": "Only for a record that does not exist yet; prefer update for an id you already have.",
5737
+ "backingOperation": "organizational_level2s.create",
5738
+ "effect": "write",
5739
+ "dryRunFirst": true,
5740
+ "confirm": false,
5741
+ "requiredArgs": [
5742
+ "data"
5743
+ ],
5744
+ "tier": "advanced",
5745
+ "reachable": true,
5746
+ "reach": "dedicated tool",
5747
+ "reachReason": null,
5748
+ "boundedAlternative": null
5749
+ },
5750
+ {
5751
+ "operation": "organizational_level2s.get",
5752
+ "core": false,
5753
+ "tool": "autotask_organizationalLevel2_get",
5754
+ "purpose": "Get one OrganizationalLevel2 by id.",
5755
+ "preferredWhen": "Preferred when the numeric id is already known.",
5756
+ "backingOperation": "organizational_level2s.get",
5757
+ "effect": "read",
5758
+ "dryRunFirst": false,
5759
+ "confirm": false,
5760
+ "requiredArgs": [
5761
+ "id"
5762
+ ],
5763
+ "tier": "advanced",
5764
+ "reachable": true,
5765
+ "reach": "dedicated tool",
5766
+ "reachReason": null,
5767
+ "boundedAlternative": null
5768
+ },
5769
+ {
5770
+ "operation": "organizational_level2s.getEntityInfo",
5771
+ "core": false,
5772
+ "tool": null,
5773
+ "purpose": "Get the OrganizationalLevel2 capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
5774
+ "preferredWhen": null,
5775
+ "backingOperation": "organizational_level2s.getEntityInfo",
5776
+ "effect": "read",
5777
+ "dryRunFirst": false,
5778
+ "confirm": false,
5779
+ "requiredArgs": [],
5780
+ "tier": "advanced",
5781
+ "reachable": true,
5782
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5783
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5784
+ "boundedAlternative": null
5785
+ },
5786
+ {
5787
+ "operation": "organizational_level2s.getFieldInfo",
5788
+ "core": false,
5789
+ "tool": null,
5790
+ "purpose": "Get the OrganizationalLevel2 field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
5791
+ "preferredWhen": null,
5792
+ "backingOperation": "organizational_level2s.getFieldInfo",
5793
+ "effect": "read",
5794
+ "dryRunFirst": false,
5795
+ "confirm": false,
5796
+ "requiredArgs": [],
5797
+ "tier": "advanced",
5798
+ "reachable": true,
5799
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5800
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5801
+ "boundedAlternative": null
5802
+ },
5803
+ {
5804
+ "operation": "organizational_level2s.getUdfInfo",
5805
+ "core": false,
5806
+ "tool": null,
5807
+ "purpose": "Get the OrganizationalLevel2 user-defined-field catalog.",
5808
+ "preferredWhen": null,
5809
+ "backingOperation": "organizational_level2s.getUdfInfo",
5201
5810
  "effect": "read",
5202
5811
  "dryRunFirst": false,
5203
5812
  "confirm": false,
5204
- "requiredArgs": [
5205
- "identifier"
5206
- ],
5207
- "tier": "extended",
5813
+ "requiredArgs": [],
5814
+ "tier": "advanced",
5208
5815
  "reachable": true,
5209
- "reach": "dedicated tool",
5210
- "reachReason": null,
5816
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
5817
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
5211
5818
  "boundedAlternative": null
5212
5819
  },
5213
5820
  {
5214
- "operation": "opportunity_categories.search",
5821
+ "operation": "organizational_level2s.query",
5215
5822
  "core": false,
5216
- "tool": "autotask_opportunityCategories_search",
5217
- "purpose": "Search opportunity category records by text (contains on the searchable fields).",
5218
- "preferredWhen": null,
5219
- "backingOperation": "opportunity_categories.search",
5823
+ "tool": "autotask_organizationalLevel2_query",
5824
+ "purpose": "Query OrganizationalLevel2 records with a JSON filter.",
5825
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
5826
+ "backingOperation": "organizational_level2s.query",
5220
5827
  "effect": "read",
5221
5828
  "dryRunFirst": false,
5222
5829
  "confirm": false,
5223
- "requiredArgs": [
5224
- "query"
5225
- ],
5226
- "tier": "extended",
5830
+ "requiredArgs": [],
5831
+ "tier": "advanced",
5227
5832
  "reachable": true,
5228
5833
  "reach": "dedicated tool",
5229
5834
  "reachReason": null,
5230
5835
  "boundedAlternative": null
5231
5836
  },
5232
5837
  {
5233
- "operation": "opportunity_categories.update",
5838
+ "operation": "organizational_level2s.update",
5234
5839
  "core": false,
5235
- "tool": "autotask_opportunityCategories_update",
5236
- "purpose": "Update an opportunity category.",
5840
+ "tool": "autotask_organizationalLevel2_update",
5841
+ "purpose": "Update an organizational level 2.",
5237
5842
  "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
5238
- "backingOperation": "opportunity_categories.update",
5843
+ "backingOperation": "organizational_level2s.update",
5239
5844
  "effect": "write",
5240
5845
  "dryRunFirst": true,
5241
5846
  "confirm": false,
@@ -5243,7 +5848,7 @@
5243
5848
  "id",
5244
5849
  "data"
5245
5850
  ],
5246
- "tier": "extended",
5851
+ "tier": "advanced",
5247
5852
  "reachable": true,
5248
5853
  "reach": "dedicated tool",
5249
5854
  "reachReason": null,
@@ -7528,6 +8133,130 @@
7528
8133
  "reachReason": null,
7529
8134
  "boundedAlternative": null
7530
8135
  },
8136
+ {
8137
+ "operation": "sales_orders.count",
8138
+ "core": false,
8139
+ "tool": "autotask_salesOrder_count",
8140
+ "purpose": "Count sales order records matching a JSON filter.",
8141
+ "preferredWhen": null,
8142
+ "backingOperation": "sales_orders.count",
8143
+ "effect": "read",
8144
+ "dryRunFirst": false,
8145
+ "confirm": false,
8146
+ "requiredArgs": [],
8147
+ "tier": "extended",
8148
+ "reachable": true,
8149
+ "reach": "dedicated tool",
8150
+ "reachReason": null,
8151
+ "boundedAlternative": null
8152
+ },
8153
+ {
8154
+ "operation": "sales_orders.get",
8155
+ "core": false,
8156
+ "tool": "autotask_salesOrder_get",
8157
+ "purpose": "Get one SalesOrder by id.",
8158
+ "preferredWhen": "Preferred when the numeric id is already known.",
8159
+ "backingOperation": "sales_orders.get",
8160
+ "effect": "read",
8161
+ "dryRunFirst": false,
8162
+ "confirm": false,
8163
+ "requiredArgs": [
8164
+ "id"
8165
+ ],
8166
+ "tier": "extended",
8167
+ "reachable": true,
8168
+ "reach": "dedicated tool",
8169
+ "reachReason": null,
8170
+ "boundedAlternative": null
8171
+ },
8172
+ {
8173
+ "operation": "sales_orders.getEntityInfo",
8174
+ "core": false,
8175
+ "tool": null,
8176
+ "purpose": "Get the SalesOrder capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
8177
+ "preferredWhen": null,
8178
+ "backingOperation": "sales_orders.getEntityInfo",
8179
+ "effect": "read",
8180
+ "dryRunFirst": false,
8181
+ "confirm": false,
8182
+ "requiredArgs": [],
8183
+ "tier": "extended",
8184
+ "reachable": true,
8185
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
8186
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
8187
+ "boundedAlternative": null
8188
+ },
8189
+ {
8190
+ "operation": "sales_orders.getFieldInfo",
8191
+ "core": false,
8192
+ "tool": null,
8193
+ "purpose": "Get the SalesOrder field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
8194
+ "preferredWhen": null,
8195
+ "backingOperation": "sales_orders.getFieldInfo",
8196
+ "effect": "read",
8197
+ "dryRunFirst": false,
8198
+ "confirm": false,
8199
+ "requiredArgs": [],
8200
+ "tier": "extended",
8201
+ "reachable": true,
8202
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
8203
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
8204
+ "boundedAlternative": null
8205
+ },
8206
+ {
8207
+ "operation": "sales_orders.getUdfInfo",
8208
+ "core": false,
8209
+ "tool": null,
8210
+ "purpose": "Get the SalesOrder user-defined-field catalog.",
8211
+ "preferredWhen": null,
8212
+ "backingOperation": "sales_orders.getUdfInfo",
8213
+ "effect": "read",
8214
+ "dryRunFirst": false,
8215
+ "confirm": false,
8216
+ "requiredArgs": [],
8217
+ "tier": "extended",
8218
+ "reachable": true,
8219
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
8220
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
8221
+ "boundedAlternative": null
8222
+ },
8223
+ {
8224
+ "operation": "sales_orders.query",
8225
+ "core": false,
8226
+ "tool": "autotask_salesOrder_query",
8227
+ "purpose": "Query SalesOrder records with a JSON filter.",
8228
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
8229
+ "backingOperation": "sales_orders.query",
8230
+ "effect": "read",
8231
+ "dryRunFirst": false,
8232
+ "confirm": false,
8233
+ "requiredArgs": [],
8234
+ "tier": "extended",
8235
+ "reachable": true,
8236
+ "reach": "dedicated tool",
8237
+ "reachReason": null,
8238
+ "boundedAlternative": null
8239
+ },
8240
+ {
8241
+ "operation": "sales_orders.update",
8242
+ "core": false,
8243
+ "tool": "autotask_salesOrder_update",
8244
+ "purpose": "Update a sales order.",
8245
+ "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
8246
+ "backingOperation": "sales_orders.update",
8247
+ "effect": "write",
8248
+ "dryRunFirst": true,
8249
+ "confirm": false,
8250
+ "requiredArgs": [
8251
+ "id",
8252
+ "data"
8253
+ ],
8254
+ "tier": "extended",
8255
+ "reachable": true,
8256
+ "reach": "dedicated tool",
8257
+ "reachReason": null,
8258
+ "boundedAlternative": null
8259
+ },
7531
8260
  {
7532
8261
  "operation": "service_call_task_resources.count",
7533
8262
  "core": false,
@@ -9725,6 +10454,149 @@
9725
10454
  "reachReason": null,
9726
10455
  "boundedAlternative": null
9727
10456
  },
10457
+ {
10458
+ "operation": "tax_regions.count",
10459
+ "core": false,
10460
+ "tool": "autotask_taxRegion_count",
10461
+ "purpose": "Count tax region records matching a JSON filter.",
10462
+ "preferredWhen": null,
10463
+ "backingOperation": "tax_regions.count",
10464
+ "effect": "read",
10465
+ "dryRunFirst": false,
10466
+ "confirm": false,
10467
+ "requiredArgs": [],
10468
+ "tier": "advanced",
10469
+ "reachable": true,
10470
+ "reach": "dedicated tool",
10471
+ "reachReason": null,
10472
+ "boundedAlternative": null
10473
+ },
10474
+ {
10475
+ "operation": "tax_regions.create",
10476
+ "core": false,
10477
+ "tool": "autotask_taxRegion_create",
10478
+ "purpose": "Create a tax region.",
10479
+ "preferredWhen": "Only for a record that does not exist yet; prefer update for an id you already have.",
10480
+ "backingOperation": "tax_regions.create",
10481
+ "effect": "write",
10482
+ "dryRunFirst": true,
10483
+ "confirm": false,
10484
+ "requiredArgs": [
10485
+ "data"
10486
+ ],
10487
+ "tier": "advanced",
10488
+ "reachable": true,
10489
+ "reach": "dedicated tool",
10490
+ "reachReason": null,
10491
+ "boundedAlternative": null
10492
+ },
10493
+ {
10494
+ "operation": "tax_regions.get",
10495
+ "core": false,
10496
+ "tool": "autotask_taxRegion_get",
10497
+ "purpose": "Get one TaxRegion by id.",
10498
+ "preferredWhen": "Preferred when the numeric id is already known.",
10499
+ "backingOperation": "tax_regions.get",
10500
+ "effect": "read",
10501
+ "dryRunFirst": false,
10502
+ "confirm": false,
10503
+ "requiredArgs": [
10504
+ "id"
10505
+ ],
10506
+ "tier": "advanced",
10507
+ "reachable": true,
10508
+ "reach": "dedicated tool",
10509
+ "reachReason": null,
10510
+ "boundedAlternative": null
10511
+ },
10512
+ {
10513
+ "operation": "tax_regions.getEntityInfo",
10514
+ "core": false,
10515
+ "tool": null,
10516
+ "purpose": "Get the TaxRegion capability metadata (canCreate/canUpdate/hasUserDefinedFields/...).",
10517
+ "preferredWhen": null,
10518
+ "backingOperation": "tax_regions.getEntityInfo",
10519
+ "effect": "read",
10520
+ "dryRunFirst": false,
10521
+ "confirm": false,
10522
+ "requiredArgs": [],
10523
+ "tier": "advanced",
10524
+ "reachable": true,
10525
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
10526
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
10527
+ "boundedAlternative": null
10528
+ },
10529
+ {
10530
+ "operation": "tax_regions.getFieldInfo",
10531
+ "core": false,
10532
+ "tool": null,
10533
+ "purpose": "Get the TaxRegion field catalog (types, picklists, required, maxLength) — the full raw field dump (the largest read of the info trio; compact discovery: operations.fieldCatalog).",
10534
+ "preferredWhen": null,
10535
+ "backingOperation": "tax_regions.getFieldInfo",
10536
+ "effect": "read",
10537
+ "dryRunFirst": false,
10538
+ "confirm": false,
10539
+ "requiredArgs": [],
10540
+ "tier": "advanced",
10541
+ "reachable": true,
10542
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
10543
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
10544
+ "boundedAlternative": null
10545
+ },
10546
+ {
10547
+ "operation": "tax_regions.getUdfInfo",
10548
+ "core": false,
10549
+ "tool": null,
10550
+ "purpose": "Get the TaxRegion user-defined-field catalog.",
10551
+ "preferredWhen": null,
10552
+ "backingOperation": "tax_regions.getUdfInfo",
10553
+ "effect": "read",
10554
+ "dryRunFirst": false,
10555
+ "confirm": false,
10556
+ "requiredArgs": [],
10557
+ "tier": "advanced",
10558
+ "reachable": true,
10559
+ "reach": "autotask_read (exact operation name; effect=read — read-only; zero mutating requests)",
10560
+ "reachReason": "no dedicated tool — the op is still discoverable and invocable by exact name",
10561
+ "boundedAlternative": null
10562
+ },
10563
+ {
10564
+ "operation": "tax_regions.query",
10565
+ "core": false,
10566
+ "tool": "autotask_taxRegion_query",
10567
+ "purpose": "Query TaxRegion records with a JSON filter.",
10568
+ "preferredWhen": "Default for filtered reads (the bounded query op). queryAll is the unbounded raw walk — only when you need the ENTIRE set and accept a large payload; default to the bounded query op. Prefer an includeFields subset over the full model (field names via operations.fieldCatalog). latest: N is the latest-N rows (id-descending) when the newest rows are the goal (the vendor has no sort — count-anchored, docs/API.md §4). Prefer a fieldsPreset for common narrow reads (v1: \"billing_join\" on billing_items.query) over a hand-listed includeFields; noteChars: N caps the untrusted-class free-text fields of the resource (notes/descriptions/UDF prose) to N chars each with the explicit … [+N chars truncated] marker (opt-in; the raw result when absent).",
10569
+ "backingOperation": "tax_regions.query",
10570
+ "effect": "read",
10571
+ "dryRunFirst": false,
10572
+ "confirm": false,
10573
+ "requiredArgs": [],
10574
+ "tier": "advanced",
10575
+ "reachable": true,
10576
+ "reach": "dedicated tool",
10577
+ "reachReason": null,
10578
+ "boundedAlternative": null
10579
+ },
10580
+ {
10581
+ "operation": "tax_regions.update",
10582
+ "core": false,
10583
+ "tool": "autotask_taxRegion_update",
10584
+ "purpose": "Update a tax region.",
10585
+ "preferredWhen": "Preferred over create or delete when the record exists and only some fields change.",
10586
+ "backingOperation": "tax_regions.update",
10587
+ "effect": "write",
10588
+ "dryRunFirst": true,
10589
+ "confirm": false,
10590
+ "requiredArgs": [
10591
+ "id",
10592
+ "data"
10593
+ ],
10594
+ "tier": "advanced",
10595
+ "reachable": true,
10596
+ "reach": "dedicated tool",
10597
+ "reachReason": null,
10598
+ "boundedAlternative": null
10599
+ },
9728
10600
  {
9729
10601
  "operation": "threshold_information.get",
9730
10602
  "core": true,
@@ -10535,6 +11407,25 @@
10535
11407
  "reachReason": null,
10536
11408
  "boundedAlternative": null
10537
11409
  },
11410
+ {
11411
+ "operation": "time_entries.approve",
11412
+ "core": false,
11413
+ "tool": "autotask_timeEntry_approve",
11414
+ "purpose": "Approve a time entry (the REST-only approval path): create the BillingItemApprovalLevels record, apply the vendor-documented follow-up update of BillingApprovalDateTime + BillingApprovalResourceID, then read the entry back and report whether the vendor accepted it.",
11415
+ "preferredWhen": "Approving (or adding the next approval level to) a time entry. This is the only approval channel the REST API exposes — there is no TimeEntries/Approve path. When the follow-up update throws, the approval level record HAS been created on the vendor (there is no rollback and no delete): reconcile by re-reading the entry's billingApprovalLevelMostRecent or querying billing_item_approval_levels by timeEntryID.",
11416
+ "backingOperation": "time_entries.approve",
11417
+ "effect": "write",
11418
+ "dryRunFirst": true,
11419
+ "confirm": false,
11420
+ "requiredArgs": [
11421
+ "id"
11422
+ ],
11423
+ "tier": "extended",
11424
+ "reachable": true,
11425
+ "reach": "dedicated tool",
11426
+ "reachReason": null,
11427
+ "boundedAlternative": null
11428
+ },
10538
11429
  {
10539
11430
  "operation": "time_entries.count",
10540
11431
  "core": false,
@@ -22506,11 +23397,11 @@
22506
23397
  }
22507
23398
  ],
22508
23399
  "counts": {
22509
- "registryOperations": 1225,
23400
+ "registryOperations": 1275,
22510
23401
  "coreOperations": 10,
22511
- "catalogRows": 1225,
22512
- "withTool": 859,
22513
- "readModeOnly": 366,
23402
+ "catalogRows": 1275,
23403
+ "withTool": 891,
23404
+ "readModeOnly": 384,
22514
23405
  "neverExposed": 0,
22515
23406
  "metaTools": 5
22516
23407
  }