@wilnertech/halopsa-mcp-server 1.0.2 → 1.2.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/.env.example +18 -18
- package/LICENSE +21 -21
- package/README.md +290 -205
- package/dist/api/client.d.ts +7 -2
- package/dist/api/client.d.ts.map +1 -1
- package/dist/api/client.js +35 -8
- package/dist/api/client.js.map +1 -1
- package/dist/cache/memory-cache.d.ts +7 -0
- package/dist/cache/memory-cache.d.ts.map +1 -1
- package/dist/cache/memory-cache.js +7 -0
- package/dist/cache/memory-cache.js.map +1 -1
- package/dist/cache/prewarm.d.ts +3 -1
- package/dist/cache/prewarm.d.ts.map +1 -1
- package/dist/cache/prewarm.js +17 -1
- package/dist/cache/prewarm.js.map +1 -1
- package/dist/schemas/common.d.ts +30 -99
- package/dist/schemas/common.d.ts.map +1 -1
- package/dist/schemas/common.js +2 -2
- package/dist/schemas/common.js.map +1 -1
- package/dist/tools/assets.d.ts +87 -297
- package/dist/tools/assets.d.ts.map +1 -1
- package/dist/tools/assets.js +7 -3
- package/dist/tools/assets.js.map +1 -1
- package/dist/tools/batch-operations.d.ts +49 -81
- package/dist/tools/batch-operations.d.ts.map +1 -1
- package/dist/tools/batch-operations.js +62 -0
- package/dist/tools/batch-operations.js.map +1 -1
- package/dist/tools/clients.d.ts +24 -92
- package/dist/tools/clients.d.ts.map +1 -1
- package/dist/tools/reference-data.d.ts +44 -72
- package/dist/tools/reference-data.d.ts.map +1 -1
- package/dist/tools/reference-data.js +27 -0
- package/dist/tools/reference-data.js.map +1 -1
- package/dist/tools/registrations.d.ts +7 -1
- package/dist/tools/registrations.d.ts.map +1 -1
- package/dist/tools/registrations.js +43 -7
- package/dist/tools/registrations.js.map +1 -1
- package/dist/tools/registry.d.ts +12 -5
- package/dist/tools/registry.d.ts.map +1 -1
- package/dist/tools/registry.js +26 -2
- package/dist/tools/registry.js.map +1 -1
- package/dist/tools/sites.d.ts +28 -111
- package/dist/tools/sites.d.ts.map +1 -1
- package/dist/tools/sites.js +4 -2
- package/dist/tools/sites.js.map +1 -1
- package/dist/tools/ticket-actions.d.ts +50 -0
- package/dist/tools/ticket-actions.d.ts.map +1 -0
- package/dist/tools/ticket-actions.js +224 -0
- package/dist/tools/ticket-actions.js.map +1 -0
- package/dist/tools/ticket-custom-fields.d.ts +33 -0
- package/dist/tools/ticket-custom-fields.d.ts.map +1 -0
- package/dist/tools/ticket-custom-fields.js +155 -0
- package/dist/tools/ticket-custom-fields.js.map +1 -0
- package/dist/tools/ticket-reference-data.d.ts +88 -0
- package/dist/tools/ticket-reference-data.d.ts.map +1 -0
- package/dist/tools/ticket-reference-data.js +185 -0
- package/dist/tools/ticket-reference-data.js.map +1 -0
- package/dist/tools/tickets.d.ts +190 -0
- package/dist/tools/tickets.d.ts.map +1 -0
- package/dist/tools/tickets.js +592 -0
- package/dist/tools/tickets.js.map +1 -0
- package/dist/tools/users.d.ts +55 -193
- package/dist/tools/users.d.ts.map +1 -1
- package/dist/tools/users.js +7 -3
- package/dist/tools/users.js.map +1 -1
- package/dist/types/tickets.d.ts +193 -0
- package/dist/types/tickets.d.ts.map +1 -0
- package/dist/types/tickets.js +14 -0
- package/dist/types/tickets.js.map +1 -0
- package/dist/utils/formatter.d.ts +34 -1
- package/dist/utils/formatter.d.ts.map +1 -1
- package/dist/utils/formatter.js +203 -6
- package/dist/utils/formatter.js.map +1 -1
- package/package.json +68 -61
- package/dist/utils/zod-to-schema.d.ts +0 -29
- package/dist/utils/zod-to-schema.d.ts.map +0 -1
- package/dist/utils/zod-to-schema.js +0 -182
- package/dist/utils/zod-to-schema.js.map +0 -1
|
@@ -8,11 +8,44 @@ export interface FormatOptions {
|
|
|
8
8
|
omit_empty?: boolean;
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Recursively walk `payload` (objects + arrays) and replace the VALUE of any
|
|
12
|
+
* key matching CREDENTIAL_KEY_RE with the string '[REDACTED]'.
|
|
13
|
+
*
|
|
14
|
+
* The function is IMMUTABLE — it deep-clones before mutating so the original
|
|
15
|
+
* object passed by the caller is never modified.
|
|
16
|
+
*/
|
|
17
|
+
export declare function scrubCredentials(payload: unknown): unknown;
|
|
18
|
+
/**
|
|
19
|
+
* Format a response object based on options.
|
|
20
|
+
*
|
|
21
|
+
* Credential scrubbing: `scrubCredentials()` is applied to `data` BEFORE
|
|
22
|
+
* serialization so that fields like `new_password`, `api_key`, `secret`,
|
|
23
|
+
* `token`, and `client_secret` are replaced with '[REDACTED]' in every tool
|
|
24
|
+
* response automatically. The response signature is unchanged (string).
|
|
25
|
+
*
|
|
12
26
|
* @param data - The data to format (single object or array)
|
|
13
27
|
* @param options - Formatting options
|
|
14
28
|
* @param meta - Optional metadata (pagination, counts)
|
|
15
29
|
* @returns JSON string formatted according to options
|
|
16
30
|
*/
|
|
17
31
|
export declare function formatResponse<T>(data: T | T[], options?: FormatOptions, meta?: Record<string, unknown>): string;
|
|
32
|
+
export type WriteResponseEntityType = 'ticket' | 'asset' | 'user' | 'site' | 'action';
|
|
33
|
+
/**
|
|
34
|
+
* Strip a write-endpoint response (create/update) to a compact shape.
|
|
35
|
+
*
|
|
36
|
+
* - When `format === 'detailed'`, returns the input unchanged (passthrough).
|
|
37
|
+
* - When `format === 'compact'` (or unset/other), applies:
|
|
38
|
+
* 1. Integration-key scrubbing (pagerduty*, orion*, ai_*, etc.)
|
|
39
|
+
* 2. Entity-type–specific top-level key removal (nested objects whose
|
|
40
|
+
* important data is already in flat _id / _name siblings)
|
|
41
|
+
* 3. `customfields[].fieldinfo` removal (keeps `{id, name?, value}`)
|
|
42
|
+
*
|
|
43
|
+
* Credential scrubbing is intentionally NOT performed here — it is applied
|
|
44
|
+
* downstream by `formatResponse()` which must always run AFTER this call.
|
|
45
|
+
*
|
|
46
|
+
* @param payload - Raw API response object (or array — normalized to single object upstream)
|
|
47
|
+
* @param format - FormatOptions.format value from the caller's args; defaults to 'compact'
|
|
48
|
+
* @param entity - Which entity type to apply the strip rules for
|
|
49
|
+
*/
|
|
50
|
+
export declare function stripWriteResponse(payload: unknown, format: string | undefined, entity: WriteResponseEntityType): unknown;
|
|
18
51
|
//# sourceMappingURL=formatter.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;
|
|
1
|
+
{"version":3,"file":"formatter.d.ts","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,UAAU,CAAC;IAC7C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAeD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAoB1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAC9B,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,EACb,OAAO,GAAE,aAAkB,EAC3B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,MAAM,CA6CR;AA0QD,MAAM,MAAM,uBAAuB,GAC/B,QAAQ,GACR,OAAO,GACP,MAAM,GACN,MAAM,GACN,QAAQ,CAAC;AAEb;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,MAAM,EAAE,uBAAuB,GAC9B,OAAO,CAwCT"}
|
package/dist/utils/formatter.js
CHANGED
|
@@ -3,7 +3,51 @@
|
|
|
3
3
|
* Provides compact, standard, and detailed output modes for HaloPSA responses
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* Regex that matches credential-bearing key names (case-insensitive).
|
|
7
|
+
*
|
|
8
|
+
* Covered patterns:
|
|
9
|
+
* password, new_password
|
|
10
|
+
* api_key, apikey, api-key
|
|
11
|
+
* secret
|
|
12
|
+
* token, access_token
|
|
13
|
+
* client_secret
|
|
14
|
+
*/
|
|
15
|
+
const CREDENTIAL_KEY_RE = /^(new_)?password$|api[_-]?key$|secret$|(access_)?token$|client_secret$/i;
|
|
16
|
+
/**
|
|
17
|
+
* Recursively walk `payload` (objects + arrays) and replace the VALUE of any
|
|
18
|
+
* key matching CREDENTIAL_KEY_RE with the string '[REDACTED]'.
|
|
19
|
+
*
|
|
20
|
+
* The function is IMMUTABLE — it deep-clones before mutating so the original
|
|
21
|
+
* object passed by the caller is never modified.
|
|
22
|
+
*/
|
|
23
|
+
export function scrubCredentials(payload) {
|
|
24
|
+
if (Array.isArray(payload)) {
|
|
25
|
+
return payload.map((item) => scrubCredentials(item));
|
|
26
|
+
}
|
|
27
|
+
if (payload !== null && typeof payload === 'object') {
|
|
28
|
+
const source = payload;
|
|
29
|
+
const result = {};
|
|
30
|
+
for (const key of Object.keys(source)) {
|
|
31
|
+
if (CREDENTIAL_KEY_RE.test(key)) {
|
|
32
|
+
result[key] = '[REDACTED]';
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
result[key] = scrubCredentials(source[key]);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
// Primitives (string, number, boolean, null, undefined) — return as-is
|
|
41
|
+
return payload;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Format a response object based on options.
|
|
45
|
+
*
|
|
46
|
+
* Credential scrubbing: `scrubCredentials()` is applied to `data` BEFORE
|
|
47
|
+
* serialization so that fields like `new_password`, `api_key`, `secret`,
|
|
48
|
+
* `token`, and `client_secret` are replaced with '[REDACTED]' in every tool
|
|
49
|
+
* response automatically. The response signature is unchanged (string).
|
|
50
|
+
*
|
|
7
51
|
* @param data - The data to format (single object or array)
|
|
8
52
|
* @param options - Formatting options
|
|
9
53
|
* @param meta - Optional metadata (pagination, counts)
|
|
@@ -11,20 +55,22 @@
|
|
|
11
55
|
*/
|
|
12
56
|
export function formatResponse(data, options = {}, meta) {
|
|
13
57
|
const { format = 'standard', fields, omit_empty = false, } = options;
|
|
58
|
+
// Scrub credential fields before any further processing
|
|
59
|
+
const safeData = scrubCredentials(data);
|
|
14
60
|
// Process data
|
|
15
61
|
let processedData;
|
|
16
|
-
if (Array.isArray(
|
|
17
|
-
processedData =
|
|
62
|
+
if (Array.isArray(safeData)) {
|
|
63
|
+
processedData = safeData.map((item) => processItem(item, fields, omit_empty, format));
|
|
18
64
|
}
|
|
19
65
|
else {
|
|
20
|
-
processedData = processItem(
|
|
66
|
+
processedData = processItem(safeData, fields, omit_empty, format);
|
|
21
67
|
}
|
|
22
68
|
// Build result object
|
|
23
|
-
const result = Array.isArray(
|
|
69
|
+
const result = Array.isArray(safeData)
|
|
24
70
|
? { data: processedData }
|
|
25
71
|
: processedData;
|
|
26
72
|
// Add metadata if provided and data is array
|
|
27
|
-
if (meta && Array.isArray(
|
|
73
|
+
if (meta && Array.isArray(safeData)) {
|
|
28
74
|
result.meta = meta;
|
|
29
75
|
}
|
|
30
76
|
// Return with appropriate formatting
|
|
@@ -175,4 +221,155 @@ function setNestedValue(obj, parts, value) {
|
|
|
175
221
|
}
|
|
176
222
|
current[parts[parts.length - 1]] = value;
|
|
177
223
|
}
|
|
224
|
+
// =============================================================================
|
|
225
|
+
// Write-response stripping (compact mode)
|
|
226
|
+
// =============================================================================
|
|
227
|
+
/**
|
|
228
|
+
* Keys stripped from EVERY level of a compact write response.
|
|
229
|
+
* These are integration-scaffolding fields (third-party system IDs,
|
|
230
|
+
* workflow-audit internals, RMM connectors) that 99% of callers never need.
|
|
231
|
+
* The "detailed" format returns them untouched.
|
|
232
|
+
*/
|
|
233
|
+
const INTEGRATION_KEY_RE = /^(_.*|pagerduty.*|splunkoncall.*|splunkoncall_id|splunkoncallurl|splunkoncallstatus|orion.*|ai_.*|auvik_.*|automate_id|device_automate_id|connectwise_.*|autotask_.*|freshdesk_.*|ninja.*|meraki.*|servicenow.*|atera_alert_id|scomalertstate|datto_alert_state|pagerdutyeragent|gfialerttype|useworkinghours.*|statusnochangehours.*|statusemail.*|nochangetemplate|messsent|auditstatus|auditunum|auditdate|azure_tenant.*|passportal_id|liongardid|kashflowid|snelstart_id|xeroid|syncroid|ateraid|connectwiseid|autotaskid|device42id|servicenowid|ncentral_details_id|dattocommerce_tenantid|kasea.*)$/i;
|
|
234
|
+
/**
|
|
235
|
+
* Top-level keys to STRIP entirely from a compact ticket write response.
|
|
236
|
+
* These are heavy nested objects whose important data is already
|
|
237
|
+
* denormalized into the flat _id / _name siblings.
|
|
238
|
+
*/
|
|
239
|
+
const TICKET_STRIP_TOP_KEYS = new Set([
|
|
240
|
+
'tickettype', // keep tickettype_id + tickettype_name (flat)
|
|
241
|
+
'user', // keep user_id + user_name (flat); contains user.site.client.quickbooks_details
|
|
242
|
+
'client', // keep client_id + client_name (flat)
|
|
243
|
+
'priority', // keep priority_id (flat)
|
|
244
|
+
'popup_notes',
|
|
245
|
+
'external_links',
|
|
246
|
+
'outcomes',
|
|
247
|
+
'delivery_address',
|
|
248
|
+
'billing_address',
|
|
249
|
+
'contact_address',
|
|
250
|
+
]);
|
|
251
|
+
/**
|
|
252
|
+
* Top-level keys to STRIP from a compact asset write response.
|
|
253
|
+
* Assets have similar integration scaffolding plus nested type/client objects.
|
|
254
|
+
*/
|
|
255
|
+
const ASSET_STRIP_TOP_KEYS = new Set([
|
|
256
|
+
'assettype', // keep assettype_id (flat)
|
|
257
|
+
'client', // keep client_id + client_name (flat)
|
|
258
|
+
'site', // keep site_id + site_name (flat)
|
|
259
|
+
'linked_tickets',
|
|
260
|
+
'linked_assets',
|
|
261
|
+
]);
|
|
262
|
+
/**
|
|
263
|
+
* Top-level keys to STRIP from a compact user write response.
|
|
264
|
+
*/
|
|
265
|
+
const USER_STRIP_TOP_KEYS = new Set([
|
|
266
|
+
'client', // keep client_id (flat)
|
|
267
|
+
'site', // keep site_id (flat)
|
|
268
|
+
'agent',
|
|
269
|
+
'linked_tickets',
|
|
270
|
+
]);
|
|
271
|
+
/**
|
|
272
|
+
* Top-level keys to STRIP from a compact site write response.
|
|
273
|
+
*/
|
|
274
|
+
const SITE_STRIP_TOP_KEYS = new Set([
|
|
275
|
+
'client', // keep client_id (flat)
|
|
276
|
+
'users',
|
|
277
|
+
'linked_tickets',
|
|
278
|
+
]);
|
|
279
|
+
/**
|
|
280
|
+
* Top-level keys to STRIP from a compact ticket-action write response.
|
|
281
|
+
*/
|
|
282
|
+
const ACTION_STRIP_TOP_KEYS = new Set([
|
|
283
|
+
'ticket', // keep ticket_id (flat)
|
|
284
|
+
'agent',
|
|
285
|
+
'attachments',
|
|
286
|
+
]);
|
|
287
|
+
/**
|
|
288
|
+
* Recursively walk a plain object/array and remove any key whose name matches
|
|
289
|
+
* INTEGRATION_KEY_RE. Operates on a clone — does not mutate `input`.
|
|
290
|
+
*/
|
|
291
|
+
function stripIntegrationKeys(input) {
|
|
292
|
+
if (Array.isArray(input)) {
|
|
293
|
+
return input.map(stripIntegrationKeys);
|
|
294
|
+
}
|
|
295
|
+
if (input !== null && typeof input === 'object') {
|
|
296
|
+
const src = input;
|
|
297
|
+
const out = {};
|
|
298
|
+
for (const key of Object.keys(src)) {
|
|
299
|
+
if (!INTEGRATION_KEY_RE.test(key)) {
|
|
300
|
+
out[key] = stripIntegrationKeys(src[key]);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return out;
|
|
304
|
+
}
|
|
305
|
+
return input;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Strip the `fieldinfo` sub-object from each element of a customfields array,
|
|
309
|
+
* keeping only `{ id, name?, value }`.
|
|
310
|
+
*/
|
|
311
|
+
function stripCustomFieldInfo(cfs) {
|
|
312
|
+
if (!Array.isArray(cfs))
|
|
313
|
+
return cfs;
|
|
314
|
+
return cfs.map((cf) => {
|
|
315
|
+
if (cf === null || typeof cf !== 'object')
|
|
316
|
+
return cf;
|
|
317
|
+
const { id, name, value } = cf;
|
|
318
|
+
const slim = { id, value };
|
|
319
|
+
if (name !== undefined)
|
|
320
|
+
slim.name = name;
|
|
321
|
+
return slim;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Strip a write-endpoint response (create/update) to a compact shape.
|
|
326
|
+
*
|
|
327
|
+
* - When `format === 'detailed'`, returns the input unchanged (passthrough).
|
|
328
|
+
* - When `format === 'compact'` (or unset/other), applies:
|
|
329
|
+
* 1. Integration-key scrubbing (pagerduty*, orion*, ai_*, etc.)
|
|
330
|
+
* 2. Entity-type–specific top-level key removal (nested objects whose
|
|
331
|
+
* important data is already in flat _id / _name siblings)
|
|
332
|
+
* 3. `customfields[].fieldinfo` removal (keeps `{id, name?, value}`)
|
|
333
|
+
*
|
|
334
|
+
* Credential scrubbing is intentionally NOT performed here — it is applied
|
|
335
|
+
* downstream by `formatResponse()` which must always run AFTER this call.
|
|
336
|
+
*
|
|
337
|
+
* @param payload - Raw API response object (or array — normalized to single object upstream)
|
|
338
|
+
* @param format - FormatOptions.format value from the caller's args; defaults to 'compact'
|
|
339
|
+
* @param entity - Which entity type to apply the strip rules for
|
|
340
|
+
*/
|
|
341
|
+
export function stripWriteResponse(payload, format, entity) {
|
|
342
|
+
// Detailed format: return untouched so callers always get the full payload.
|
|
343
|
+
if (format === 'detailed') {
|
|
344
|
+
return payload;
|
|
345
|
+
}
|
|
346
|
+
if (payload === null || typeof payload !== 'object') {
|
|
347
|
+
return payload;
|
|
348
|
+
}
|
|
349
|
+
// Step 1: Strip integration-scaffolding keys at every level.
|
|
350
|
+
const afterIntegration = stripIntegrationKeys(payload);
|
|
351
|
+
// Step 2: Strip entity-specific top-level keys (heavy nested objects).
|
|
352
|
+
const stripKeys = entity === 'ticket' ? TICKET_STRIP_TOP_KEYS
|
|
353
|
+
: entity === 'asset' ? ASSET_STRIP_TOP_KEYS
|
|
354
|
+
: entity === 'user' ? USER_STRIP_TOP_KEYS
|
|
355
|
+
: entity === 'site' ? SITE_STRIP_TOP_KEYS
|
|
356
|
+
: ACTION_STRIP_TOP_KEYS;
|
|
357
|
+
const afterTopStrip = {};
|
|
358
|
+
for (const [key, val] of Object.entries(afterIntegration)) {
|
|
359
|
+
if (!stripKeys.has(key)) {
|
|
360
|
+
afterTopStrip[key] = val;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// Step 3: Strip fieldinfo from customfields[] (ticket) or fields[] (asset).
|
|
364
|
+
if (entity === 'ticket' && Array.isArray(afterTopStrip['customfields'])) {
|
|
365
|
+
afterTopStrip['customfields'] = stripCustomFieldInfo(afterTopStrip['customfields']);
|
|
366
|
+
}
|
|
367
|
+
if (entity === 'asset' && Array.isArray(afterTopStrip['fields'])) {
|
|
368
|
+
afterTopStrip['fields'] = stripCustomFieldInfo(afterTopStrip['fields']);
|
|
369
|
+
}
|
|
370
|
+
if (entity === 'user' && Array.isArray(afterTopStrip['user_customfields'])) {
|
|
371
|
+
afterTopStrip['user_customfields'] = stripCustomFieldInfo(afterTopStrip['user_customfields']);
|
|
372
|
+
}
|
|
373
|
+
return afterTopStrip;
|
|
374
|
+
}
|
|
178
375
|
//# sourceMappingURL=formatter.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAa,EACb,UAAyB,EAAE,EAC3B,IAA8B;IAE9B,MAAM,EACJ,MAAM,GAAG,UAAU,EACnB,MAAM,EACN,UAAU,GAAG,KAAK,GACnB,GAAG,OAAO,CAAC;IAEZ,eAAe;IACf,IAAI,aAAsB,CAAC;IAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"formatter.js","sourceRoot":"","sources":["../../src/utils/formatter.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,61 +1,68 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@wilnertech/halopsa-mcp-server",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "Model Context Protocol server for HaloPSA API integration with asset, user, and site management",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"bin": {
|
|
8
|
-
"halopsa-mcp-server": "dist/index.js"
|
|
9
|
-
},
|
|
10
|
-
"files": [
|
|
11
|
-
"dist",
|
|
12
|
-
"README.md",
|
|
13
|
-
"LICENSE",
|
|
14
|
-
".env.example"
|
|
15
|
-
],
|
|
16
|
-
"scripts": {
|
|
17
|
-
"build": "tsc",
|
|
18
|
-
"dev": "tsc --watch",
|
|
19
|
-
"start": "node dist/index.js",
|
|
20
|
-
"test
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
"
|
|
47
|
-
|
|
48
|
-
"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
"
|
|
60
|
-
}
|
|
61
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@wilnertech/halopsa-mcp-server",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Model Context Protocol server for HaloPSA API integration with asset, user, and site management",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"halopsa-mcp-server": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
"LICENSE",
|
|
14
|
+
".env.example"
|
|
15
|
+
],
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"dev": "tsc --watch",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
21
|
+
"test:smoke": "node tests/smoke-crud.mjs",
|
|
22
|
+
"test:smoke:local": "node --env-file=.env tests/smoke-crud.mjs",
|
|
23
|
+
"start:local": "node --env-file=.env dist/index.js",
|
|
24
|
+
"typecheck": "tsc --noEmit",
|
|
25
|
+
"lint": "eslint src",
|
|
26
|
+
"format": "prettier --write \"src/**/*.ts\"",
|
|
27
|
+
"prepublishOnly": "npm run build"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
31
|
+
"axios": "^1.7.9",
|
|
32
|
+
"zod": "^4.3.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@types/jest": "^30.0.0",
|
|
36
|
+
"@types/node": "^22.10.5",
|
|
37
|
+
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
|
38
|
+
"@typescript-eslint/parser": "^8.20.0",
|
|
39
|
+
"eslint": "^9.18.0",
|
|
40
|
+
"jest": "^30.3.0",
|
|
41
|
+
"prettier": "^3.4.2",
|
|
42
|
+
"ts-jest": "^29.2.5",
|
|
43
|
+
"typescript": "^5.7.3"
|
|
44
|
+
},
|
|
45
|
+
"engines": {
|
|
46
|
+
"node": ">=18.0.0"
|
|
47
|
+
},
|
|
48
|
+
"keywords": [
|
|
49
|
+
"mcp",
|
|
50
|
+
"halopsa",
|
|
51
|
+
"api",
|
|
52
|
+
"psa",
|
|
53
|
+
"claude"
|
|
54
|
+
],
|
|
55
|
+
"author": "Yisroel Wilner",
|
|
56
|
+
"license": "MIT",
|
|
57
|
+
"repository": {
|
|
58
|
+
"type": "git",
|
|
59
|
+
"url": "https://github.com/SuperGaco/halopsa-mcp-server.git"
|
|
60
|
+
},
|
|
61
|
+
"homepage": "https://github.com/SuperGaco/halopsa-mcp-server#readme",
|
|
62
|
+
"bugs": {
|
|
63
|
+
"url": "https://github.com/SuperGaco/halopsa-mcp-server/issues"
|
|
64
|
+
},
|
|
65
|
+
"publishConfig": {
|
|
66
|
+
"access": "public"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts Zod schemas to MCP-compatible JSON Schema objects.
|
|
3
|
-
*
|
|
4
|
-
* The MCP SDK expects inputSchema as:
|
|
5
|
-
* { type: 'object', properties: Record<string, unknown>, required?: string[] }
|
|
6
|
-
*
|
|
7
|
-
* This utility traverses Zod's internal _def structure to produce that shape,
|
|
8
|
-
* handling the types used across ITGlue MCP tool schemas: string, number,
|
|
9
|
-
* boolean, array, object, enum, literal, optional, default, and effects
|
|
10
|
-
* (z.coerce). Descriptions and numeric min/max checks are preserved.
|
|
11
|
-
*/
|
|
12
|
-
import { z } from 'zod';
|
|
13
|
-
/**
|
|
14
|
-
* MCP-compatible JSON Schema for a tool's inputSchema.
|
|
15
|
-
*/
|
|
16
|
-
interface McpInputSchema {
|
|
17
|
-
type: 'object';
|
|
18
|
-
properties: Record<string, unknown>;
|
|
19
|
-
required?: string[];
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Convert a top-level Zod object schema to an MCP-compatible inputSchema.
|
|
23
|
-
*
|
|
24
|
-
* The input is expected to be a z.ZodObject (possibly wrapped in optional/effects).
|
|
25
|
-
* Returns { type: 'object', properties: {...}, required?: [...] }.
|
|
26
|
-
*/
|
|
27
|
-
export declare function zodToJsonSchema(schema: z.ZodType): McpInputSchema;
|
|
28
|
-
export {};
|
|
29
|
-
//# sourceMappingURL=zod-to-schema.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"zod-to-schema.d.ts","sourceRoot":"","sources":["../../src/utils/zod-to-schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;GAEG;AACH,UAAU,cAAc;IACtB,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAkLD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,cAAc,CASjE"}
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Converts Zod schemas to MCP-compatible JSON Schema objects.
|
|
3
|
-
*
|
|
4
|
-
* The MCP SDK expects inputSchema as:
|
|
5
|
-
* { type: 'object', properties: Record<string, unknown>, required?: string[] }
|
|
6
|
-
*
|
|
7
|
-
* This utility traverses Zod's internal _def structure to produce that shape,
|
|
8
|
-
* handling the types used across ITGlue MCP tool schemas: string, number,
|
|
9
|
-
* boolean, array, object, enum, literal, optional, default, and effects
|
|
10
|
-
* (z.coerce). Descriptions and numeric min/max checks are preserved.
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* Convert a single Zod type to a JSON Schema property descriptor.
|
|
14
|
-
* Handles wrapper types (optional, default, effects/coerce, nullable)
|
|
15
|
-
* by recursing into their inner types.
|
|
16
|
-
*/
|
|
17
|
-
function zodTypeToJsonSchema(schema) {
|
|
18
|
-
const def = schema._def;
|
|
19
|
-
const typeName = def.typeName;
|
|
20
|
-
const result = {};
|
|
21
|
-
// Preserve .describe() text
|
|
22
|
-
if (typeof def.description === 'string') {
|
|
23
|
-
result.description = def.description;
|
|
24
|
-
}
|
|
25
|
-
switch (typeName) {
|
|
26
|
-
case 'ZodString': {
|
|
27
|
-
result.type = 'string';
|
|
28
|
-
break;
|
|
29
|
-
}
|
|
30
|
-
case 'ZodNumber': {
|
|
31
|
-
result.type = 'number';
|
|
32
|
-
// Propagate min/max constraints from .min()/.max() checks
|
|
33
|
-
const checks = def.checks;
|
|
34
|
-
if (checks) {
|
|
35
|
-
for (const check of checks) {
|
|
36
|
-
if (check.kind === 'min') {
|
|
37
|
-
result.minimum = check.value;
|
|
38
|
-
}
|
|
39
|
-
else if (check.kind === 'max') {
|
|
40
|
-
result.maximum = check.value;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
case 'ZodBoolean': {
|
|
47
|
-
result.type = 'boolean';
|
|
48
|
-
break;
|
|
49
|
-
}
|
|
50
|
-
case 'ZodEnum': {
|
|
51
|
-
result.type = 'string';
|
|
52
|
-
result.enum = def.values;
|
|
53
|
-
break;
|
|
54
|
-
}
|
|
55
|
-
case 'ZodLiteral': {
|
|
56
|
-
const value = def.value;
|
|
57
|
-
if (typeof value === 'string') {
|
|
58
|
-
result.type = 'string';
|
|
59
|
-
}
|
|
60
|
-
else if (typeof value === 'number') {
|
|
61
|
-
result.type = 'number';
|
|
62
|
-
}
|
|
63
|
-
else if (typeof value === 'boolean') {
|
|
64
|
-
result.type = 'boolean';
|
|
65
|
-
}
|
|
66
|
-
result.const = value;
|
|
67
|
-
break;
|
|
68
|
-
}
|
|
69
|
-
case 'ZodArray': {
|
|
70
|
-
result.type = 'array';
|
|
71
|
-
const itemSchema = def.type;
|
|
72
|
-
result.items = zodTypeToJsonSchema(itemSchema);
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case 'ZodObject': {
|
|
76
|
-
result.type = 'object';
|
|
77
|
-
const shape = schema._def.shape();
|
|
78
|
-
const properties = {};
|
|
79
|
-
const required = [];
|
|
80
|
-
for (const [key, fieldSchema] of Object.entries(shape)) {
|
|
81
|
-
properties[key] = zodTypeToJsonSchema(fieldSchema);
|
|
82
|
-
if (!isOptionalType(fieldSchema)) {
|
|
83
|
-
required.push(key);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
result.properties = properties;
|
|
87
|
-
if (required.length > 0) {
|
|
88
|
-
result.required = required;
|
|
89
|
-
}
|
|
90
|
-
break;
|
|
91
|
-
}
|
|
92
|
-
// Wrapper types: unwrap and recurse
|
|
93
|
-
case 'ZodOptional': {
|
|
94
|
-
const innerOptional = def.innerType;
|
|
95
|
-
const inner = zodTypeToJsonSchema(innerOptional);
|
|
96
|
-
// Merge description from the optional wrapper if present, inner takes precedence
|
|
97
|
-
if (result.description && !inner.description) {
|
|
98
|
-
inner.description = result.description;
|
|
99
|
-
}
|
|
100
|
-
return inner;
|
|
101
|
-
}
|
|
102
|
-
case 'ZodDefault': {
|
|
103
|
-
const innerDefault = def.innerType;
|
|
104
|
-
const inner = zodTypeToJsonSchema(innerDefault);
|
|
105
|
-
if (result.description && !inner.description) {
|
|
106
|
-
inner.description = result.description;
|
|
107
|
-
}
|
|
108
|
-
return inner;
|
|
109
|
-
}
|
|
110
|
-
case 'ZodNullable': {
|
|
111
|
-
const innerNullable = def.innerType;
|
|
112
|
-
const inner = zodTypeToJsonSchema(innerNullable);
|
|
113
|
-
if (result.description && !inner.description) {
|
|
114
|
-
inner.description = result.description;
|
|
115
|
-
}
|
|
116
|
-
return inner;
|
|
117
|
-
}
|
|
118
|
-
case 'ZodEffects': {
|
|
119
|
-
// z.coerce.number(), z.coerce.string(), z.preprocess(), z.transform()
|
|
120
|
-
const innerEffects = def.schema;
|
|
121
|
-
const inner = zodTypeToJsonSchema(innerEffects);
|
|
122
|
-
if (result.description && !inner.description) {
|
|
123
|
-
inner.description = result.description;
|
|
124
|
-
}
|
|
125
|
-
return inner;
|
|
126
|
-
}
|
|
127
|
-
case 'ZodAny': {
|
|
128
|
-
// z.any() — no type constraint, description carries the semantics
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
case 'ZodRecord': {
|
|
132
|
-
// z.record() — open-ended object
|
|
133
|
-
result.type = 'object';
|
|
134
|
-
break;
|
|
135
|
-
}
|
|
136
|
-
default: {
|
|
137
|
-
// Fallback for unknown types - warn and treat as opaque object
|
|
138
|
-
console.warn(`zod-to-schema: unhandled Zod type "${typeName}" — falling back to { type: "object" }`);
|
|
139
|
-
result.type = 'object';
|
|
140
|
-
break;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Check whether a Zod type represents an optional field.
|
|
147
|
-
* Optional, default, and nullable wrappers all make a field non-required.
|
|
148
|
-
*/
|
|
149
|
-
function isOptionalType(schema) {
|
|
150
|
-
const def = schema._def;
|
|
151
|
-
const typeName = def.typeName;
|
|
152
|
-
if (typeName === 'ZodOptional' || typeName === 'ZodDefault') {
|
|
153
|
-
return true;
|
|
154
|
-
}
|
|
155
|
-
// ZodNullable wrapping an optional
|
|
156
|
-
if (typeName === 'ZodNullable') {
|
|
157
|
-
const inner = def.innerType;
|
|
158
|
-
return isOptionalType(inner);
|
|
159
|
-
}
|
|
160
|
-
// ZodEffects wrapping an optional (e.g., z.coerce.number().optional() piped through transform)
|
|
161
|
-
if (typeName === 'ZodEffects') {
|
|
162
|
-
const inner = def.schema;
|
|
163
|
-
return isOptionalType(inner);
|
|
164
|
-
}
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* Convert a top-level Zod object schema to an MCP-compatible inputSchema.
|
|
169
|
-
*
|
|
170
|
-
* The input is expected to be a z.ZodObject (possibly wrapped in optional/effects).
|
|
171
|
-
* Returns { type: 'object', properties: {...}, required?: [...] }.
|
|
172
|
-
*/
|
|
173
|
-
export function zodToJsonSchema(schema) {
|
|
174
|
-
const converted = zodTypeToJsonSchema(schema);
|
|
175
|
-
// The top-level must always be type: 'object'
|
|
176
|
-
return {
|
|
177
|
-
type: 'object',
|
|
178
|
-
properties: converted.properties || {},
|
|
179
|
-
...(converted.required ? { required: converted.required } : {}),
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
//# sourceMappingURL=zod-to-schema.js.map
|