node-autotask 0.39.4 → 0.41.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 +6 -2
- package/CHANGELOG.md +33 -0
- package/MCP_TOOL_CATALOG.json +10 -32
- package/MCP_TOOL_MANIFEST.md +12 -13
- package/N8N_MCP_MANIFEST.json +5 -44
- package/N8N_MCP_MANIFEST.md +7 -8
- package/README.md +29 -37
- package/capabilities.json +1346 -1535
- package/dist/base-CVx2VMSj.d.cts +103 -0
- package/dist/base-CVx2VMSj.d.ts +103 -0
- package/dist/capabilities.cjs +2 -2
- package/dist/capabilities.js +1 -1
- package/dist/{chunk-SGKGNJEI.cjs → chunk-DKAD7MOV.cjs} +771 -1835
- package/dist/{chunk-DJCRQLQE.cjs → chunk-DXEBPK55.cjs} +287 -292
- package/dist/{chunk-GHRB46YN.js → chunk-LR6FDJI3.js} +614 -1678
- package/dist/{chunk-VR6RYXTD.cjs → chunk-MJ6J74F3.cjs} +1345 -1534
- package/dist/{chunk-JBQ55HYG.js → chunk-P5655PGY.js} +2 -2
- package/dist/{chunk-DBLXPY4B.js → chunk-TCND5PFF.js} +4 -9
- package/dist/{chunk-H4S4KSXX.cjs → chunk-YAHFPOQF.cjs} +143 -143
- package/dist/{chunk-GDSCYY2G.js → chunk-ZVSSAULC.js} +1345 -1534
- package/dist/{index-DkZVRMeW.d.ts → index-CqO1HNHl.d.cts} +125 -851
- package/dist/{index-DkZVRMeW.d.cts → index-CqO1HNHl.d.ts} +125 -851
- package/dist/index.cjs +23 -51
- package/dist/index.d.cts +103 -102
- package/dist/index.d.ts +103 -102
- package/dist/index.js +19 -47
- package/dist/operations/index.cjs +178 -178
- package/dist/operations/index.d.cts +5 -4
- package/dist/operations/index.d.ts +5 -4
- package/dist/operations/index.js +3 -3
- package/dist/pool.cjs +17 -60
- package/dist/pool.d.cts +5 -13
- package/dist/pool.d.ts +5 -13
- package/dist/pool.js +13 -56
- 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/types/index.d.cts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/docs/API.md +138 -340
- package/docs/N8N-ADAPTER.md +7 -7
- package/examples/mcp-server-http.ts +18 -18
- package/package.json +1 -1
package/docs/N8N-ADAPTER.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**Status:** v0.1.0 (the 121-entity MVP set). Generated tables are marked
|
|
4
4
|
`GENERATED` and regenerated by `npm run docs:render` — two JSONs in
|
|
5
|
-
(
|
|
5
|
+
(`scripts/n8n-mapping.json` × `capabilities.json`, plus the plan × the
|
|
6
6
|
vendored `api-docs.json` for the gap table), markdown table out. Do not
|
|
7
7
|
hand-type the generated regions.
|
|
8
8
|
|
|
@@ -30,7 +30,7 @@ Autotask semantic is an SDK call.
|
|
|
30
30
|
## 2. Operation mapping — node resource → SDK operations
|
|
31
31
|
|
|
32
32
|
<!-- BEGIN GENERATED:n8n-op-mapping -->
|
|
33
|
-
Two sources in, markdown table out: the node repo (the ops column is re-derived from the `name: 'operation'` property options of each `resources/<dir>` dir — style A const or inline options; values of any other dropdown property, e.g. the timeEntries dateRange presets, are filter options and never ops) × `capabilities.json` (SDK operations per resource key, generated registry).
|
|
33
|
+
Two sources in, markdown table out: the node repo (the ops column is re-derived from the `name: 'operation'` property options of each `resources/<dir>` dir — style A const or inline options; values of any other dropdown property, e.g. the timeEntries dateRange presets, are filter options and never ops) × `capabilities.json` (SDK operations per resource key, generated registry). `scripts/n8n-mapping.json` supplies the row set (node dir → apiEntity), the parent-scoped flag and the curated special ops. Standard node ops map to the SDK primitive of the same name (`getMany` → `queryAll`, the unbounded raw walk — the bounded MCP read is the `query` op, routed by `invoke` to `queryBounded`). A node special op maps to the SDK operation of the same name on the same resource when the registry has it; `—` = the node op has no SDK operation of its own (handled in the adjacent sections).
|
|
34
34
|
|
|
35
35
|
| node dir | apiEntity | parent-scoped | node ops (opsImplemented) | node special ops | SDK methods (from the registry) |
|
|
36
36
|
|----------|-----------|---------------|---------------------------|------------------|----------------------------------|
|
|
@@ -41,7 +41,7 @@ Two sources in, markdown table out: the node repo (the ops column is re-derived
|
|
|
41
41
|
| `checklistLibraries` | ChecklistLibrary | no | create, update, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
42
42
|
| `checklistLibraryChecklistItems` | ChecklistLibraryChecklistItem | yes | create, update, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
43
43
|
| `classificationIcons` | ClassificationIcon | no | get, getMany, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search |
|
|
44
|
-
| `companies` | Company | no | create, update, get, getMany, count, searchByIdentity, searchByDomain | searchByDomain → `companies.searchByDomain`; searchByIdentity → `companies.searchByIdentity` | count, create, fullProfile, get, getContext, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, searchByDomain, searchByIdentity, unbilledWork, update, upsertByName |
|
|
44
|
+
| `companies` | Company | no | create, update, get, getMany, count, searchByIdentity, searchByDomain | searchByDomain → `companies.searchByDomain`; searchByIdentity → `companies.searchByIdentity` | count, create, fullProfile, get, getContext, getEntityInfo, getFieldInfo, getUdfInfo, prepareCrmWrite, query, resolve, search, searchByDomain, searchByIdentity, unbilledWork, update, upsertByName |
|
|
45
45
|
| `companyAlerts` | CompanyAlert | yes | create, update, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
46
46
|
| `companyLocations` | CompanyLocation | yes | create, get, getMany, update, delete, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
47
47
|
| `companyNotes` | CompanyNote | yes | create, update, get, getMany, count | — | count, create, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
@@ -82,7 +82,7 @@ Two sources in, markdown table out: the node repo (the ops column is re-derived
|
|
|
82
82
|
| `contractServiceUnits` | ContractServiceUnit | yes | get, getMany, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
83
83
|
| `contractServices` | ContractService | yes | create, update, get, getMany, count, createIfNotExists | createIfNotExists → `contract_services.createIfNotExists` | count, create, createIfNotExists, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
84
84
|
| `contractTicketPurchases` | ContractTicketPurchases | yes | create, update, get, getMany, count | — | count, create, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
85
|
-
| `contracts` | Contract | no | create, update, get, getMany, count, createIfNotExists | createIfNotExists → `contracts.createIfNotExists` | count, create, createIfNotExists, get, getEntityInfo, getFieldInfo, getUdfInfo, profitability, query, resolve, search, update |
|
|
85
|
+
| `contracts` | Contract | no | create, update, get, getMany, count, createIfNotExists | createIfNotExists → `contracts.createIfNotExists` | count, create, createIfNotExists, get, getEntityInfo, getFieldInfo, getUdfInfo, lineOfBusiness, profitability, query, resolve, search, update |
|
|
86
86
|
| `countries` | Country | no | get, getMany, update, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
87
87
|
| `departments` | Department | no | count, create, get, getMany, update | — | count, create, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
88
88
|
| `domainRegistrar` | DomainRegistrar | no | create, update, get, getMany, count | — | count, create, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
@@ -141,7 +141,7 @@ Two sources in, markdown table out: the node repo (the ops column is re-derived
|
|
|
141
141
|
| `ticketCategories` | TicketCategory | no | get, getMany, update, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
142
142
|
| `ticketCategoryFieldDefaults` | TicketCategoryFieldDefault | yes | get, getMany, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
143
143
|
| `ticketChangeRequestApprovals` | TicketChangeRequestApproval | yes | create, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
144
|
-
| `ticketCharges` | TicketCharge | yes | create, createIfNotExists, update, delete, get, getMany, count | createIfNotExists → `ticket_charges.createIfNotExists` | count, create, createIfNotExists, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
144
|
+
| `ticketCharges` | TicketCharge | yes | create, createIfNotExists, update, delete, get, getMany, count | createIfNotExists → `ticket_charges.createIfNotExists` | count, create, createIfNotExists, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, moveToTicket, query, resolve, search, update |
|
|
145
145
|
| `ticketChecklistItems` | TicketChecklistItem | yes | create, update, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
146
146
|
| `ticketChecklistLibraries` | TicketChecklistLibrary | yes | create | — | attachToDocument, create, getEntityInfo, getFieldInfo, getUdfInfo, resolve |
|
|
147
147
|
| `ticketHistories` | TicketHistory | no | get, getMany, count | — | count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
@@ -150,8 +150,8 @@ Two sources in, markdown table out: the node repo (the ops column is re-derived
|
|
|
150
150
|
| `ticketNotes` | TicketNote | yes | create, update, get, getMany, count | — | count, create, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, update |
|
|
151
151
|
| `ticketSecondaryResources` | TicketSecondaryResource | yes | create, delete, get, getMany, count | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
152
152
|
| `ticketWebhooks` | TicketWebhook | yes | get, getMany, delete | — | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, search, update |
|
|
153
|
-
| `tickets` | Ticket | no | create, get, getMany, slaHealthCheck, summary, timeline, update, count | slaHealthCheck → `tickets.slaHealthCheck`; summary → `tickets.summary`; timeline → `tickets.timeline` | changeStatus, count, create, findByTicketNumber, fullContext, get, getContext, getEntityInfo, getFieldInfo, getUdfInfo, openWithNoteAndAssign, query, resolve, search, slaHealthCheck, summary, timeline, update |
|
|
154
|
-
| `timeEntries` | TimeEntry | no | create, update, get, getMany, getPosted, getUnposted, delete, count, createIfNotExists | createIfNotExists → `time_entries.createIfNotExists`; customRange → `time_entries.customRange`; getPosted → `time_entries.getPosted`; getUnposted → `time_entries.getUnposted`; last14 → `time_entries.last14`; last24h → `time_entries.last24h`; last30 → `time_entries.last30`; last7 → `time_entries.last7`; last90 → `time_entries.last90`; lastFullFortnight → `time_entries.lastFullFortnight`; lastFullMonth → `time_entries.lastFullMonth`; lastFullQuarter → `time_entries.lastFullQuarter`; lastFullWeek → `time_entries.lastFullWeek`; today → `time_entries.today`; yesterday → `time_entries.yesterday` | count, create, createForResource, createIfNotExists, customRange, dateWorkedWindow, delete, get, getEntityInfo, getFieldInfo, getPosted, getUdfInfo, getUnposted, last14, last24h, last30, last7, last90, lastFullFortnight, lastFullMonth, lastFullQuarter, lastFullWeek, postedWithin, query, resolve, today, update, yesterday |
|
|
153
|
+
| `tickets` | Ticket | no | create, get, getMany, slaHealthCheck, summary, timeline, update, count | slaHealthCheck → `tickets.slaHealthCheck`; summary → `tickets.summary`; timeline → `tickets.timeline` | changeStatus, count, create, findByTicketNumber, forResource, fullContext, get, getContext, getEntityInfo, getFieldInfo, getUdfInfo, lineOfBusiness, openWithNoteAndAssign, query, resolve, search, slaHealthCheck, statusSemantics, summary, timeline, update |
|
|
154
|
+
| `timeEntries` | TimeEntry | no | create, update, get, getMany, getPosted, getUnposted, delete, count, createIfNotExists | createIfNotExists → `time_entries.createIfNotExists`; customRange → `time_entries.customRange`; getPosted → `time_entries.getPosted`; getUnposted → `time_entries.getUnposted`; last14 → `time_entries.last14`; last24h → `time_entries.last24h`; last30 → `time_entries.last30`; last7 → `time_entries.last7`; last90 → `time_entries.last90`; lastFullFortnight → `time_entries.lastFullFortnight`; lastFullMonth → `time_entries.lastFullMonth`; lastFullQuarter → `time_entries.lastFullQuarter`; lastFullWeek → `time_entries.lastFullWeek`; today → `time_entries.today`; yesterday → `time_entries.yesterday` | approve, count, create, createForResource, createIfNotExists, customRange, dateWorkedWindow, delete, get, getEntityInfo, getFieldInfo, getPosted, getUdfInfo, getUnposted, last14, last24h, last30, last7, last90, lastFullFortnight, lastFullMonth, lastFullQuarter, lastFullWeek, moveToTicket, postedWithin, query, resolve, today, update, yesterday |
|
|
155
155
|
| `timeEntryAttachments` | TimeEntryAttachment | yes | create, getMany, count, download, delete | download → `time_entry_attachments.download` | count, create, delete, download, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve |
|
|
156
156
|
| `timeOffRequests` | TimeOffRequest | no | get, getMany, count, approve, reject | approve → `time_off_requests.approve`; reject → `time_off_requests.reject` | approve, count, get, getEntityInfo, getFieldInfo, getUdfInfo, query, reject, resolve |
|
|
157
157
|
| `(none — NOT IMPLEMENTED in node)` | InventoryProduct (StockedItemsAdd/Remove/Transfer pseudo-entities) | yes | | stockedItemsAdd → `inventory_products.stockedItemsAdd`; stockedItemsRemove → `inventory_products.stockedItemsRemove`; stockedItemsTransfer → `inventory_products.stockedItemsTransfer` | count, create, delete, get, getEntityInfo, getFieldInfo, getUdfInfo, query, resolve, stockedItemsAdd, stockedItemsRemove, stockedItemsTransfer, update |
|
|
@@ -82,7 +82,7 @@ import { pipeline } from 'node:stream/promises';
|
|
|
82
82
|
import type { ReadableStream as NodeReadableStream } from 'node:stream/web';
|
|
83
83
|
import { createMcpHandler, McpServer } from '@modelcontextprotocol/server';
|
|
84
84
|
import type { McpServerFactory } from '@modelcontextprotocol/server';
|
|
85
|
-
import { AutotaskClient, type ZoneName } from 'node-autotask';
|
|
85
|
+
import { AutotaskClient, type AutotaskConfig, type ZoneName } from 'node-autotask';
|
|
86
86
|
import { createClientPool, type ClientPool } from 'node-autotask/pool';
|
|
87
87
|
import { MCP_SERVER_OPTIONS, registerCoreTools, SERVER_INFO, effectForOperation } from './mcp-register.js';
|
|
88
88
|
import { createStderrAuditSink } from './mcp-audit.js';
|
|
@@ -142,21 +142,21 @@ const client = GATEWAY || DRY
|
|
|
142
142
|
* is shared between its requests, never across tenants), the user-visible
|
|
143
143
|
* warning sink, and the shared audit sink.
|
|
144
144
|
*/
|
|
145
|
-
const pool: ClientPool | undefined = GATEWAY
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
145
|
+
const pool: ClientPool | undefined = GATEWAY ? createClientPool() : undefined;
|
|
146
|
+
|
|
147
|
+
/** The pooled client's config: the tenant's credentials over the shared gateway settings. */
|
|
148
|
+
function pooledConfig(creds: Parameters<typeof gatewayConfig>[0]): AutotaskConfig {
|
|
149
|
+
return {
|
|
150
|
+
// Issue #4: the SAME env overrides apply to every pooled client — spread
|
|
151
|
+
// first, so the per-request tenant config and the pooled read cache
|
|
152
|
+
// (explicit) always win over the env (explicit > env > profile).
|
|
153
|
+
...withEnvOverrides(),
|
|
154
|
+
...gatewayConfig(creds),
|
|
155
|
+
cache: { ttlMs: GATEWAY_CACHE_TTL_MS },
|
|
156
|
+
logger: { warn: (m: string) => console.error(m) },
|
|
157
|
+
onAudit: createStderrAuditSink({ resolveEffect: effectForOperation }),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
160
|
|
|
161
161
|
/** The pooled client for one gateway request (null = DRY surface). */
|
|
162
162
|
function gatewayClientFor(request: Request | undefined): { client: AutotaskClient | null; dry: boolean } {
|
|
@@ -165,7 +165,7 @@ function gatewayClientFor(request: Request | undefined): { client: AutotaskClien
|
|
|
165
165
|
// re-parse (the same pure function) only selects the pooled client.
|
|
166
166
|
const parsed = extractGatewayCredentials(request.headers);
|
|
167
167
|
if ('status' in parsed) return { client: null, dry: true };
|
|
168
|
-
return { client: pool.get(
|
|
168
|
+
return { client: pool.get(pooledConfig(parsed)), dry: false };
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
/** One `McpServer` per HTTP request; the tool surface is global (same as stdio). */
|
|
@@ -208,7 +208,7 @@ async function fetchHandler(request: Request): Promise<Response> {
|
|
|
208
208
|
headers: { 'content-type': 'text/plain; charset=utf-8' },
|
|
209
209
|
});
|
|
210
210
|
}
|
|
211
|
-
const gwClient = pool.get(
|
|
211
|
+
const gwClient = pool.get(pooledConfig(parsed));
|
|
212
212
|
// Bounded warm-up: the tenant's probe is awaited for AT MOST
|
|
213
213
|
// GATEWAY_WARMUP_BUDGET_MS (fixed), then the request proceeds without
|
|
214
214
|
// it — a cold cache on a large tenant cannot push the call past the
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-autotask",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"description": "Fully-typed TypeScript SDK for the Autotask (Datto) PSA REST API. Zero runtime dependencies. Built for building MCP servers and integrations.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|