@burdenoff/mcp-libs 2026.626.1 → 2026.627.2

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 (61) hide show
  1. package/dist/modules/assethandler/index.cjs +1601 -0
  2. package/dist/modules/assethandler/index.cjs.map +1 -0
  3. package/dist/modules/assethandler/index.d.cts +8 -0
  4. package/dist/modules/assethandler/index.d.ts +8 -0
  5. package/dist/modules/assethandler/index.js +1540 -0
  6. package/dist/modules/assethandler/index.js.map +1 -0
  7. package/dist/modules/crewfoundry/index.cjs +1598 -0
  8. package/dist/modules/crewfoundry/index.cjs.map +1 -0
  9. package/dist/modules/crewfoundry/index.d.cts +8 -0
  10. package/dist/modules/crewfoundry/index.d.ts +8 -0
  11. package/dist/modules/crewfoundry/index.js +1537 -0
  12. package/dist/modules/crewfoundry/index.js.map +1 -0
  13. package/dist/modules/eventfullymanaged/index.cjs +3364 -0
  14. package/dist/modules/eventfullymanaged/index.cjs.map +1 -0
  15. package/dist/modules/eventfullymanaged/index.d.cts +8 -0
  16. package/dist/modules/eventfullymanaged/index.d.ts +8 -0
  17. package/dist/modules/eventfullymanaged/index.js +3303 -0
  18. package/dist/modules/eventfullymanaged/index.js.map +1 -0
  19. package/dist/modules/ggnomad/index.cjs +1068 -0
  20. package/dist/modules/ggnomad/index.cjs.map +1 -0
  21. package/dist/modules/ggnomad/index.d.cts +8 -0
  22. package/dist/modules/ggnomad/index.d.ts +8 -0
  23. package/dist/modules/ggnomad/index.js +1007 -0
  24. package/dist/modules/ggnomad/index.js.map +1 -0
  25. package/dist/modules/headshotmarketing/index.cjs +5031 -0
  26. package/dist/modules/headshotmarketing/index.cjs.map +1 -0
  27. package/dist/modules/headshotmarketing/index.d.cts +8 -0
  28. package/dist/modules/headshotmarketing/index.d.ts +8 -0
  29. package/dist/modules/headshotmarketing/index.js +4970 -0
  30. package/dist/modules/headshotmarketing/index.js.map +1 -0
  31. package/dist/modules/housingvista/index.cjs +1092 -0
  32. package/dist/modules/housingvista/index.cjs.map +1 -0
  33. package/dist/modules/housingvista/index.d.cts +8 -0
  34. package/dist/modules/housingvista/index.d.ts +8 -0
  35. package/dist/modules/housingvista/index.js +1031 -0
  36. package/dist/modules/housingvista/index.js.map +1 -0
  37. package/dist/modules/movethewheels/index.cjs +3915 -0
  38. package/dist/modules/movethewheels/index.cjs.map +1 -0
  39. package/dist/modules/movethewheels/index.d.cts +8 -0
  40. package/dist/modules/movethewheels/index.d.ts +8 -0
  41. package/dist/modules/movethewheels/index.js +3854 -0
  42. package/dist/modules/movethewheels/index.js.map +1 -0
  43. package/dist/modules/planmagnet/index.cjs +6171 -0
  44. package/dist/modules/planmagnet/index.cjs.map +1 -0
  45. package/dist/modules/planmagnet/index.d.cts +8 -0
  46. package/dist/modules/planmagnet/index.d.ts +8 -0
  47. package/dist/modules/planmagnet/index.js +6110 -0
  48. package/dist/modules/planmagnet/index.js.map +1 -0
  49. package/dist/modules/proserviceworld/index.cjs +1404 -0
  50. package/dist/modules/proserviceworld/index.cjs.map +1 -0
  51. package/dist/modules/proserviceworld/index.d.cts +8 -0
  52. package/dist/modules/proserviceworld/index.d.ts +8 -0
  53. package/dist/modules/proserviceworld/index.js +1343 -0
  54. package/dist/modules/proserviceworld/index.js.map +1 -0
  55. package/dist/modules/timecampus/index.cjs +6482 -0
  56. package/dist/modules/timecampus/index.cjs.map +1 -0
  57. package/dist/modules/timecampus/index.d.cts +8 -0
  58. package/dist/modules/timecampus/index.d.ts +8 -0
  59. package/dist/modules/timecampus/index.js +6421 -0
  60. package/dist/modules/timecampus/index.js.map +1 -0
  61. package/package.json +1 -1
@@ -0,0 +1,1540 @@
1
+ import { mcpToolName, errorResult, jsonResult, mcpResourceUri, mcpPromptName } from '../../chunk-H2OYWLOA.js';
2
+ import { z } from 'zod';
3
+
4
+ // src/modules/assethandler/operations.ts
5
+ var ASSET_FIELDS = `
6
+ id assetNumber name description category serialNumber status condition
7
+ locationName assignedTo tags customAttributes workspaceId createdAt updatedAt
8
+ `;
9
+ var SOFTWARE_ASSET_FIELDS = `
10
+ id name vendor version licenseType seatsPurchased seatsUsed compliancePercent
11
+ workspaceId createdAt updatedAt
12
+ `;
13
+ var CONFIGURATION_ITEM_FIELDS = `
14
+ id ciNumber ciType name status environment owner attributes workspaceId
15
+ createdAt updatedAt
16
+ `;
17
+ var DISCOVERY_JOB_FIELDS = `
18
+ id name source status assetsDiscovered createdBy errorSummary startedAt
19
+ completedAt workspaceId createdAt updatedAt
20
+ `;
21
+ var INCIDENT_FIELDS = `
22
+ id title description category priority status reportedBy reportedAt resolvedAt
23
+ slaBreached assignedTo workspaceId
24
+ `;
25
+ var PROBLEM_FIELDS = `
26
+ id title description category priority status rootCause workaround
27
+ relatedIncidents assignedTo workspaceId createdAt updatedAt
28
+ `;
29
+ var CHANGE_REQUEST_FIELDS = `
30
+ id title description type status risk requestedBy assignedTo affectedAssets
31
+ approvals scheduledStart scheduledEnd workspaceId createdAt updatedAt
32
+ `;
33
+ var WORK_ORDER_FIELDS = `
34
+ id title description type status priority assetId assignedTo workspaceId
35
+ createdAt updatedAt
36
+ `;
37
+ var MAINTENANCE_RECORD_FIELDS = `
38
+ id assetId title description type status priority estimatedCost actualCost
39
+ checklist scheduledAt completedAt workspaceId createdAt updatedAt
40
+ `;
41
+ var KNOWLEDGE_ARTICLE_FIELDS = `
42
+ id title slug summary content status tags relatedAssetId relatedIncidentId
43
+ views createdBy updatedBy publishedAt workspaceId createdAt updatedAt
44
+ `;
45
+ var BUDGET_FIELDS = `
46
+ id name category department period allocated spent remaining status
47
+ workspaceId createdAt updatedAt
48
+ `;
49
+ var TRANSACTION_FIELDS = `
50
+ id type category description amount currency vendor department status
51
+ occurredAt workspaceId
52
+ `;
53
+ var INVOICE_FIELDS = `
54
+ id number vendor amount currency status issueDate dueDate items relatedPO
55
+ workspaceId createdAt updatedAt
56
+ `;
57
+ var COMPLIANCE_FRAMEWORK_FIELDS = `
58
+ id name version status score totalControls passedControls failedControls
59
+ lastAssessment nextAssessment workspaceId createdAt updatedAt
60
+ `;
61
+ var SECURITY_POLICY_FIELDS = `
62
+ id name version status category description owner applicableTo effectiveDate
63
+ reviewDate workspaceId createdAt updatedAt
64
+ `;
65
+ var SECURITY_EVENT_FIELDS = `
66
+ id title description eventType severity source resolved ipAddress userId
67
+ occurredAt workspaceId createdAt
68
+ `;
69
+ var ESG_METRIC_FIELDS = `
70
+ id category metricKey metricName value unit target trend periodStart periodEnd
71
+ updatedBy workspaceId createdAt updatedAt
72
+ `;
73
+ var DIGITAL_TWIN_FIELDS = `
74
+ id assetId fidelityLevel modelRef geometryRef properties workspaceId
75
+ createdAt updatedAt
76
+ `;
77
+ var IOT_DEVICE_FIELDS = `
78
+ id deviceId name type protocol status metadata assetId workspaceId
79
+ createdAt updatedAt
80
+ `;
81
+ var AI_PREDICTION_FIELDS = `
82
+ id assetId predictionType modelVersion score confidence recommendation status
83
+ features generatedAt workspaceId createdAt
84
+ `;
85
+ var PROVENANCE_RECORD_FIELDS = `
86
+ id assetId chainNetwork hash txHash blockNumber attestedBy attestedAt metadata
87
+ workspaceId createdAt
88
+ `;
89
+ var GET_ASSET = `
90
+ query AssetHandlerGetAsset($id: ID!) {
91
+ asset(id: $id) {
92
+ ${ASSET_FIELDS}
93
+ }
94
+ }
95
+ `;
96
+ var LIST_ASSETS = `
97
+ query AssetHandlerListAssets($pagination: AssetHandlerPaginationInput) {
98
+ assets(pagination: $pagination) {
99
+ ${ASSET_FIELDS}
100
+ }
101
+ }
102
+ `;
103
+ var CREATE_ASSET = `
104
+ mutation AssetHandlerCreateAsset($input: CreateAssetInput!) {
105
+ createAsset(input: $input) {
106
+ ${ASSET_FIELDS}
107
+ }
108
+ }
109
+ `;
110
+ var LIST_SOFTWARE_ASSETS = `
111
+ query AssetHandlerListSoftwareAssets($pagination: AssetHandlerPaginationInput) {
112
+ softwareAssets(pagination: $pagination) {
113
+ ${SOFTWARE_ASSET_FIELDS}
114
+ }
115
+ }
116
+ `;
117
+ var UPSERT_SOFTWARE_ASSET = `
118
+ mutation AssetHandlerUpsertSoftwareAsset($input: UpsertSoftwareAssetInput!) {
119
+ upsertSoftwareAsset(input: $input) {
120
+ ${SOFTWARE_ASSET_FIELDS}
121
+ }
122
+ }
123
+ `;
124
+ var LIST_CONFIGURATION_ITEMS = `
125
+ query AssetHandlerListConfigurationItems($pagination: AssetHandlerPaginationInput) {
126
+ configurationItems(pagination: $pagination) {
127
+ ${CONFIGURATION_ITEM_FIELDS}
128
+ }
129
+ }
130
+ `;
131
+ var UPSERT_CONFIGURATION_ITEM = `
132
+ mutation AssetHandlerUpsertConfigurationItem($input: UpsertConfigurationItemInput!) {
133
+ upsertConfigurationItem(input: $input) {
134
+ ${CONFIGURATION_ITEM_FIELDS}
135
+ }
136
+ }
137
+ `;
138
+ var LIST_DISCOVERY_JOBS = `
139
+ query AssetHandlerListDiscoveryJobs($pagination: AssetHandlerPaginationInput) {
140
+ discoveryJobs(pagination: $pagination) {
141
+ ${DISCOVERY_JOB_FIELDS}
142
+ }
143
+ }
144
+ `;
145
+ var START_DISCOVERY_JOB = `
146
+ mutation AssetHandlerStartDiscoveryJob($input: StartDiscoveryJobInput!) {
147
+ startDiscoveryJob(input: $input) {
148
+ ${DISCOVERY_JOB_FIELDS}
149
+ }
150
+ }
151
+ `;
152
+ var LIST_INCIDENTS = `
153
+ query AssetHandlerListIncidents($pagination: AssetHandlerPaginationInput) {
154
+ incidents(pagination: $pagination) {
155
+ ${INCIDENT_FIELDS}
156
+ }
157
+ }
158
+ `;
159
+ var CREATE_INCIDENT = `
160
+ mutation AssetHandlerCreateIncident($input: CreateIncidentInput!) {
161
+ createIncident(input: $input) {
162
+ ${INCIDENT_FIELDS}
163
+ }
164
+ }
165
+ `;
166
+ var LIST_PROBLEMS = `
167
+ query AssetHandlerListProblems($pagination: AssetHandlerPaginationInput) {
168
+ problems(pagination: $pagination) {
169
+ ${PROBLEM_FIELDS}
170
+ }
171
+ }
172
+ `;
173
+ var LIST_CHANGE_REQUESTS = `
174
+ query AssetHandlerListChangeRequests($pagination: AssetHandlerPaginationInput) {
175
+ changeRequests(pagination: $pagination) {
176
+ ${CHANGE_REQUEST_FIELDS}
177
+ }
178
+ }
179
+ `;
180
+ var LIST_WORK_ORDERS = `
181
+ query AssetHandlerListWorkOrders($pagination: AssetHandlerPaginationInput) {
182
+ workOrders(pagination: $pagination) {
183
+ ${WORK_ORDER_FIELDS}
184
+ }
185
+ }
186
+ `;
187
+ var CREATE_WORK_ORDER = `
188
+ mutation AssetHandlerCreateWorkOrder($input: CreateWorkOrderInput!) {
189
+ createWorkOrder(input: $input) {
190
+ ${WORK_ORDER_FIELDS}
191
+ }
192
+ }
193
+ `;
194
+ var LIST_MAINTENANCE_RECORDS = `
195
+ query AssetHandlerListMaintenanceRecords($pagination: AssetHandlerPaginationInput) {
196
+ maintenanceRecords(pagination: $pagination) {
197
+ ${MAINTENANCE_RECORD_FIELDS}
198
+ }
199
+ }
200
+ `;
201
+ var LIST_KNOWLEDGE_ARTICLES = `
202
+ query AssetHandlerListKnowledgeArticles($pagination: AssetHandlerPaginationInput) {
203
+ knowledgeArticles(pagination: $pagination) {
204
+ ${KNOWLEDGE_ARTICLE_FIELDS}
205
+ }
206
+ }
207
+ `;
208
+ var CREATE_KNOWLEDGE_ARTICLE = `
209
+ mutation AssetHandlerCreateKnowledgeArticle($input: CreateKnowledgeArticleInput!) {
210
+ createKnowledgeArticle(input: $input) {
211
+ ${KNOWLEDGE_ARTICLE_FIELDS}
212
+ }
213
+ }
214
+ `;
215
+ var LIST_BUDGETS = `
216
+ query AssetHandlerListBudgets($pagination: AssetHandlerPaginationInput) {
217
+ budgets(pagination: $pagination) {
218
+ ${BUDGET_FIELDS}
219
+ }
220
+ }
221
+ `;
222
+ var LIST_TRANSACTIONS = `
223
+ query AssetHandlerListTransactions($pagination: AssetHandlerPaginationInput) {
224
+ transactions(pagination: $pagination) {
225
+ ${TRANSACTION_FIELDS}
226
+ }
227
+ }
228
+ `;
229
+ var CREATE_TRANSACTION = `
230
+ mutation AssetHandlerCreateTransaction($input: CreateTransactionInput!) {
231
+ createTransaction(input: $input) {
232
+ ${TRANSACTION_FIELDS}
233
+ }
234
+ }
235
+ `;
236
+ var LIST_INVOICES = `
237
+ query AssetHandlerListInvoices($pagination: AssetHandlerPaginationInput) {
238
+ invoices(pagination: $pagination) {
239
+ ${INVOICE_FIELDS}
240
+ }
241
+ }
242
+ `;
243
+ var LIST_COMPLIANCE_FRAMEWORKS = `
244
+ query AssetHandlerListComplianceFrameworks($pagination: AssetHandlerPaginationInput) {
245
+ complianceFrameworks(pagination: $pagination) {
246
+ ${COMPLIANCE_FRAMEWORK_FIELDS}
247
+ }
248
+ }
249
+ `;
250
+ var LIST_SECURITY_POLICIES = `
251
+ query AssetHandlerListSecurityPolicies($pagination: AssetHandlerPaginationInput) {
252
+ assetSecurityPolicies(pagination: $pagination) {
253
+ ${SECURITY_POLICY_FIELDS}
254
+ }
255
+ }
256
+ `;
257
+ var LIST_SECURITY_EVENTS = `
258
+ query AssetHandlerListSecurityEvents($pagination: AssetHandlerPaginationInput) {
259
+ securityEvents(pagination: $pagination) {
260
+ ${SECURITY_EVENT_FIELDS}
261
+ }
262
+ }
263
+ `;
264
+ var LIST_ESG_METRICS = `
265
+ query AssetHandlerListEsgMetrics($pagination: AssetHandlerPaginationInput) {
266
+ esgMetrics(pagination: $pagination) {
267
+ ${ESG_METRIC_FIELDS}
268
+ }
269
+ }
270
+ `;
271
+ var UPSERT_ESG_METRIC = `
272
+ mutation AssetHandlerUpsertEsgMetric($input: UpsertEsgMetricInput!) {
273
+ upsertEsgMetric(input: $input) {
274
+ ${ESG_METRIC_FIELDS}
275
+ }
276
+ }
277
+ `;
278
+ var LIST_DIGITAL_TWINS = `
279
+ query AssetHandlerListDigitalTwins($pagination: AssetHandlerPaginationInput) {
280
+ digitalTwins(pagination: $pagination) {
281
+ ${DIGITAL_TWIN_FIELDS}
282
+ }
283
+ }
284
+ `;
285
+ var CREATE_DIGITAL_TWIN = `
286
+ mutation AssetHandlerCreateDigitalTwin($input: CreateDigitalTwinInput!) {
287
+ createDigitalTwin(input: $input) {
288
+ ${DIGITAL_TWIN_FIELDS}
289
+ }
290
+ }
291
+ `;
292
+ var LIST_IOT_DEVICES = `
293
+ query AssetHandlerListIotDevices($pagination: AssetHandlerPaginationInput) {
294
+ iotDevices(pagination: $pagination) {
295
+ ${IOT_DEVICE_FIELDS}
296
+ }
297
+ }
298
+ `;
299
+ var REGISTER_IOT_DEVICE = `
300
+ mutation AssetHandlerRegisterIoTDevice($input: RegisterIoTDeviceInput!) {
301
+ registerIoTDevice(input: $input) {
302
+ ${IOT_DEVICE_FIELDS}
303
+ }
304
+ }
305
+ `;
306
+ var LIST_AI_PREDICTIONS = `
307
+ query AssetHandlerListAiPredictions($pagination: AssetHandlerPaginationInput) {
308
+ aiPredictions(pagination: $pagination) {
309
+ ${AI_PREDICTION_FIELDS}
310
+ }
311
+ }
312
+ `;
313
+ var REQUEST_AI_PREDICTION = `
314
+ mutation AssetHandlerRequestAIPrediction($input: RequestAIPredictionInput!) {
315
+ requestAIPrediction(input: $input) {
316
+ ${AI_PREDICTION_FIELDS}
317
+ }
318
+ }
319
+ `;
320
+ var LIST_PROVENANCE_RECORDS = `
321
+ query AssetHandlerListProvenanceRecords($pagination: AssetHandlerPaginationInput) {
322
+ provenanceRecords(pagination: $pagination) {
323
+ ${PROVENANCE_RECORD_FIELDS}
324
+ }
325
+ }
326
+ `;
327
+ var RECORD_PROVENANCE = `
328
+ mutation AssetHandlerRecordProvenance($input: RecordProvenanceInput!) {
329
+ recordProvenance(input: $input) {
330
+ ${PROVENANCE_RECORD_FIELDS}
331
+ }
332
+ }
333
+ `;
334
+ var DASHBOARD_OVERVIEW = `
335
+ query AssetHandlerDashboardOverview {
336
+ dashboardOverview {
337
+ totalAssets
338
+ totalTransactions
339
+ openIncidents
340
+ openWorkOrders
341
+ }
342
+ }
343
+ `;
344
+ var AssetConditionEnum = z.enum(["DAMAGED", "EXCELLENT", "FAIR", "GOOD", "POOR"]).describe("Physical condition of an asset");
345
+ var AssetStatusEnum = z.enum(["ACTIVE", "DISPOSED", "INACTIVE", "MAINTENANCE", "RETIRED"]).describe("Lifecycle status of an asset");
346
+ var PriorityEnum = z.enum(["CRITICAL", "HIGH", "LOW", "MEDIUM"]).describe("Priority of an incident or work order");
347
+ var KnowledgeArticleStatusEnum = z.enum(["ARCHIVED", "DRAFT", "PUBLISHED"]).describe("Publication status of a knowledge article");
348
+ var TransactionTypeEnum = z.enum(["DISPOSAL", "LEASE", "MAINTENANCE", "PURCHASE", "TRANSFER"]).describe("Category of an asset financial transaction");
349
+ var TransactionStatusEnum = z.enum(["APPROVED", "COMPLETED", "PENDING", "REJECTED"]).describe("Approval status of a transaction");
350
+ var WorkOrderTypeEnum = z.enum(["CORRECTIVE", "EMERGENCY", "PREDICTIVE", "PREVENTIVE"]).describe("Type of maintenance work order");
351
+ var WorkOrderStatusEnum = z.enum(["APPROVED", "CANCELLED", "COMPLETED", "DRAFT", "IN_PROGRESS", "SCHEDULED"]).describe("Lifecycle status of a work order");
352
+ var JsonObject = z.record(z.string(), z.unknown());
353
+ var PaginationArgs = {
354
+ limit: z.number().int().optional().describe("Page size (server-clamped to \u2264100)"),
355
+ cursor: z.string().optional().describe("Opaque cursor \u2014 the `id` returned from the previous page")
356
+ };
357
+ function buildPagination(limit, cursor) {
358
+ const pagination = {};
359
+ if (limit !== void 0) pagination.limit = limit;
360
+ if (cursor !== void 0) pagination.cursor = cursor;
361
+ return Object.keys(pagination).length > 0 ? pagination : void 0;
362
+ }
363
+
364
+ // src/modules/assethandler/tools/assets.ts
365
+ function registerAssetTools(server, ctx, track) {
366
+ server.registerTool(
367
+ track(mcpToolName(ctx.productName, "assets_get")),
368
+ {
369
+ title: "Get Asset",
370
+ description: "Fetch a single asset by ID from the bound workspace.",
371
+ inputSchema: { id: z.string().describe("Asset ID") }
372
+ },
373
+ async ({ id }) => {
374
+ try {
375
+ const data = await ctx.gql.workspace.request(GET_ASSET, { id });
376
+ if (!data.asset) return errorResult(`Asset ${id} not found`);
377
+ return jsonResult(data.asset);
378
+ } catch (error) {
379
+ ctx.logger.error("assethandler assets_get failed", { error: String(error) });
380
+ return errorResult(
381
+ `Failed to get asset: ${error instanceof Error ? error.message : String(error)}`
382
+ );
383
+ }
384
+ }
385
+ );
386
+ server.registerTool(
387
+ track(mcpToolName(ctx.productName, "assets_list")),
388
+ {
389
+ title: "List Assets",
390
+ description: "List assets in the bound workspace with cursor-based pagination ({ limit, cursor }).",
391
+ inputSchema: { ...PaginationArgs }
392
+ },
393
+ async ({ limit, cursor }) => {
394
+ try {
395
+ const data = await ctx.gql.workspace.request(LIST_ASSETS, { pagination: buildPagination(limit, cursor) });
396
+ return jsonResult(data.assets);
397
+ } catch (error) {
398
+ ctx.logger.error("assethandler assets_list failed", { error: String(error) });
399
+ return errorResult(
400
+ `Failed to list assets: ${error instanceof Error ? error.message : String(error)}`
401
+ );
402
+ }
403
+ }
404
+ );
405
+ server.registerTool(
406
+ track(mcpToolName(ctx.productName, "assets_create")),
407
+ {
408
+ title: "Create Asset",
409
+ description: "Register a new asset. `assetNumber`, `name`, and `category` are required; `condition`/`status` default server-side.",
410
+ inputSchema: {
411
+ assetNumber: z.string().min(1).describe("Unique asset/tag number"),
412
+ name: z.string().min(1).describe("Asset display name"),
413
+ category: z.string().min(1).describe("Asset category (free-form)"),
414
+ condition: AssetConditionEnum.optional().describe("Physical condition"),
415
+ status: AssetStatusEnum.optional().describe("Lifecycle status"),
416
+ description: z.string().optional().describe("Asset description"),
417
+ serialNumber: z.string().optional().describe("Manufacturer serial number"),
418
+ locationName: z.string().optional().describe("Physical location name"),
419
+ assignedTo: z.string().optional().describe("User/owner the asset is assigned to"),
420
+ tags: z.array(z.string()).optional().describe("Free-form tags"),
421
+ customAttributes: JsonObject.optional().describe("Arbitrary custom attribute JSON")
422
+ }
423
+ },
424
+ async ({
425
+ assetNumber,
426
+ name,
427
+ category,
428
+ condition,
429
+ status,
430
+ description,
431
+ serialNumber,
432
+ locationName,
433
+ assignedTo,
434
+ tags,
435
+ customAttributes
436
+ }) => {
437
+ try {
438
+ const input = { assetNumber, name, category };
439
+ if (condition !== void 0) input.condition = condition;
440
+ if (status !== void 0) input.status = status;
441
+ if (description !== void 0) input.description = description;
442
+ if (serialNumber !== void 0) input.serialNumber = serialNumber;
443
+ if (locationName !== void 0) input.locationName = locationName;
444
+ if (assignedTo !== void 0) input.assignedTo = assignedTo;
445
+ if (tags !== void 0) input.tags = tags;
446
+ if (customAttributes !== void 0) input.customAttributes = customAttributes;
447
+ const data = await ctx.gql.workspace.request(CREATE_ASSET, { input });
448
+ return jsonResult(data.createAsset);
449
+ } catch (error) {
450
+ ctx.logger.error("assethandler assets_create failed", { error: String(error) });
451
+ return errorResult(
452
+ `Failed to create asset: ${error instanceof Error ? error.message : String(error)}`
453
+ );
454
+ }
455
+ }
456
+ );
457
+ server.registerTool(
458
+ track(mcpToolName(ctx.productName, "software_list")),
459
+ {
460
+ title: "List Software Assets",
461
+ description: "List software-license assets with cursor-based pagination.",
462
+ inputSchema: { ...PaginationArgs }
463
+ },
464
+ async ({ limit, cursor }) => {
465
+ try {
466
+ const data = await ctx.gql.workspace.request(LIST_SOFTWARE_ASSETS, { pagination: buildPagination(limit, cursor) });
467
+ return jsonResult(data.softwareAssets);
468
+ } catch (error) {
469
+ ctx.logger.error("assethandler software_list failed", { error: String(error) });
470
+ return errorResult(
471
+ `Failed to list software assets: ${error instanceof Error ? error.message : String(error)}`
472
+ );
473
+ }
474
+ }
475
+ );
476
+ server.registerTool(
477
+ track(mcpToolName(ctx.productName, "software_upsert")),
478
+ {
479
+ title: "Upsert Software Asset",
480
+ description: "Create or update a software-license asset. Provide `id` to update an existing record; omit it to create.",
481
+ inputSchema: {
482
+ name: z.string().min(1).describe("Software product name"),
483
+ vendor: z.string().min(1).describe("Software vendor"),
484
+ version: z.string().min(1).describe("Version string"),
485
+ licenseType: z.string().min(1).describe("License type (e.g. perpetual, subscription)"),
486
+ id: z.string().optional().describe("Existing software-asset ID (omit to create)"),
487
+ seatsPurchased: z.number().int().optional().describe("Number of seats purchased"),
488
+ seatsUsed: z.number().int().optional().describe("Number of seats in use")
489
+ }
490
+ },
491
+ async ({ name, vendor, version, licenseType, id, seatsPurchased, seatsUsed }) => {
492
+ try {
493
+ const input = { name, vendor, version, licenseType };
494
+ if (id !== void 0) input.id = id;
495
+ if (seatsPurchased !== void 0) input.seatsPurchased = seatsPurchased;
496
+ if (seatsUsed !== void 0) input.seatsUsed = seatsUsed;
497
+ const data = await ctx.gql.workspace.request(UPSERT_SOFTWARE_ASSET, { input });
498
+ return jsonResult(data.upsertSoftwareAsset);
499
+ } catch (error) {
500
+ ctx.logger.error("assethandler software_upsert failed", { error: String(error) });
501
+ return errorResult(
502
+ `Failed to upsert software asset: ${error instanceof Error ? error.message : String(error)}`
503
+ );
504
+ }
505
+ }
506
+ );
507
+ server.registerTool(
508
+ track(mcpToolName(ctx.productName, "configuration_list")),
509
+ {
510
+ title: "List Configuration Items",
511
+ description: "List CMDB configuration items with cursor-based pagination.",
512
+ inputSchema: { ...PaginationArgs }
513
+ },
514
+ async ({ limit, cursor }) => {
515
+ try {
516
+ const data = await ctx.gql.workspace.request(LIST_CONFIGURATION_ITEMS, { pagination: buildPagination(limit, cursor) });
517
+ return jsonResult(data.configurationItems);
518
+ } catch (error) {
519
+ ctx.logger.error("assethandler configuration_list failed", { error: String(error) });
520
+ return errorResult(
521
+ `Failed to list configuration items: ${error instanceof Error ? error.message : String(error)}`
522
+ );
523
+ }
524
+ }
525
+ );
526
+ server.registerTool(
527
+ track(mcpToolName(ctx.productName, "configuration_upsert")),
528
+ {
529
+ title: "Upsert Configuration Item",
530
+ description: "Create or update a CMDB configuration item. Provide `id` to update an existing CI; omit it to create.",
531
+ inputSchema: {
532
+ ciNumber: z.string().min(1).describe("Unique CI number"),
533
+ ciType: z.string().min(1).describe("CI type (e.g. server, database, application)"),
534
+ name: z.string().min(1).describe("CI display name"),
535
+ status: z.string().min(1).describe("CI status (free-form)"),
536
+ id: z.string().optional().describe("Existing CI ID (omit to create)"),
537
+ environment: z.string().optional().describe("Environment (e.g. prod, staging)"),
538
+ owner: z.string().optional().describe("Owning user/team"),
539
+ attributes: JsonObject.optional().describe("Arbitrary CI attribute JSON")
540
+ }
541
+ },
542
+ async ({ ciNumber, ciType, name, status, id, environment, owner, attributes }) => {
543
+ try {
544
+ const input = { ciNumber, ciType, name, status };
545
+ if (id !== void 0) input.id = id;
546
+ if (environment !== void 0) input.environment = environment;
547
+ if (owner !== void 0) input.owner = owner;
548
+ if (attributes !== void 0) input.attributes = attributes;
549
+ const data = await ctx.gql.workspace.request(UPSERT_CONFIGURATION_ITEM, { input });
550
+ return jsonResult(data.upsertConfigurationItem);
551
+ } catch (error) {
552
+ ctx.logger.error("assethandler configuration_upsert failed", {
553
+ error: String(error)
554
+ });
555
+ return errorResult(
556
+ `Failed to upsert configuration item: ${error instanceof Error ? error.message : String(error)}`
557
+ );
558
+ }
559
+ }
560
+ );
561
+ server.registerTool(
562
+ track(mcpToolName(ctx.productName, "discovery_list")),
563
+ {
564
+ title: "List Discovery Jobs",
565
+ description: "List asset-discovery jobs with cursor-based pagination.",
566
+ inputSchema: { ...PaginationArgs }
567
+ },
568
+ async ({ limit, cursor }) => {
569
+ try {
570
+ const data = await ctx.gql.workspace.request(LIST_DISCOVERY_JOBS, { pagination: buildPagination(limit, cursor) });
571
+ return jsonResult(data.discoveryJobs);
572
+ } catch (error) {
573
+ ctx.logger.error("assethandler discovery_list failed", { error: String(error) });
574
+ return errorResult(
575
+ `Failed to list discovery jobs: ${error instanceof Error ? error.message : String(error)}`
576
+ );
577
+ }
578
+ }
579
+ );
580
+ server.registerTool(
581
+ track(mcpToolName(ctx.productName, "discovery_start")),
582
+ {
583
+ title: "Start Discovery Job",
584
+ description: "Kick off an asset-discovery job against a named source.",
585
+ inputSchema: {
586
+ name: z.string().min(1).describe("Discovery job name"),
587
+ source: z.string().min(1).describe("Discovery source (e.g. network range, cloud account)")
588
+ }
589
+ },
590
+ async ({ name, source }) => {
591
+ try {
592
+ const data = await ctx.gql.workspace.request(START_DISCOVERY_JOB, { input: { name, source } });
593
+ return jsonResult(data.startDiscoveryJob);
594
+ } catch (error) {
595
+ ctx.logger.error("assethandler discovery_start failed", { error: String(error) });
596
+ return errorResult(
597
+ `Failed to start discovery job: ${error instanceof Error ? error.message : String(error)}`
598
+ );
599
+ }
600
+ }
601
+ );
602
+ }
603
+ function registerServiceTools(server, ctx, track) {
604
+ server.registerTool(
605
+ track(mcpToolName(ctx.productName, "incidents_list")),
606
+ {
607
+ title: "List Incidents",
608
+ description: "List service incidents with cursor-based pagination.",
609
+ inputSchema: { ...PaginationArgs }
610
+ },
611
+ async ({ limit, cursor }) => {
612
+ try {
613
+ const data = await ctx.gql.workspace.request(LIST_INCIDENTS, { pagination: buildPagination(limit, cursor) });
614
+ return jsonResult(data.incidents);
615
+ } catch (error) {
616
+ ctx.logger.error("assethandler incidents_list failed", { error: String(error) });
617
+ return errorResult(
618
+ `Failed to list incidents: ${error instanceof Error ? error.message : String(error)}`
619
+ );
620
+ }
621
+ }
622
+ );
623
+ server.registerTool(
624
+ track(mcpToolName(ctx.productName, "incidents_create")),
625
+ {
626
+ title: "Create Incident",
627
+ description: "Open a new service incident. `title`, `description`, and `category` are required; optionally link an asset and set priority.",
628
+ inputSchema: {
629
+ title: z.string().min(1).describe("Incident title"),
630
+ description: z.string().min(1).describe("Incident description"),
631
+ category: z.string().min(1).describe("Incident category (free-form)"),
632
+ priority: PriorityEnum.optional().describe("Incident priority"),
633
+ assetId: z.string().optional().describe("Related asset ID"),
634
+ assignedTo: z.string().optional().describe("Assignee user ID")
635
+ }
636
+ },
637
+ async ({ title, description, category, priority, assetId, assignedTo }) => {
638
+ try {
639
+ const input = { title, description, category };
640
+ if (priority !== void 0) input.priority = priority;
641
+ if (assetId !== void 0) input.assetId = assetId;
642
+ if (assignedTo !== void 0) input.assignedTo = assignedTo;
643
+ const data = await ctx.gql.workspace.request(CREATE_INCIDENT, { input });
644
+ return jsonResult(data.createIncident);
645
+ } catch (error) {
646
+ ctx.logger.error("assethandler incidents_create failed", { error: String(error) });
647
+ return errorResult(
648
+ `Failed to create incident: ${error instanceof Error ? error.message : String(error)}`
649
+ );
650
+ }
651
+ }
652
+ );
653
+ server.registerTool(
654
+ track(mcpToolName(ctx.productName, "problems_list")),
655
+ {
656
+ title: "List Problems",
657
+ description: "List problem records (root-cause investigations) with cursor-based pagination.",
658
+ inputSchema: { ...PaginationArgs }
659
+ },
660
+ async ({ limit, cursor }) => {
661
+ try {
662
+ const data = await ctx.gql.workspace.request(LIST_PROBLEMS, { pagination: buildPagination(limit, cursor) });
663
+ return jsonResult(data.problems);
664
+ } catch (error) {
665
+ ctx.logger.error("assethandler problems_list failed", { error: String(error) });
666
+ return errorResult(
667
+ `Failed to list problems: ${error instanceof Error ? error.message : String(error)}`
668
+ );
669
+ }
670
+ }
671
+ );
672
+ server.registerTool(
673
+ track(mcpToolName(ctx.productName, "changes_list")),
674
+ {
675
+ title: "List Change Requests",
676
+ description: "List change requests with cursor-based pagination.",
677
+ inputSchema: { ...PaginationArgs }
678
+ },
679
+ async ({ limit, cursor }) => {
680
+ try {
681
+ const data = await ctx.gql.workspace.request(LIST_CHANGE_REQUESTS, { pagination: buildPagination(limit, cursor) });
682
+ return jsonResult(data.changeRequests);
683
+ } catch (error) {
684
+ ctx.logger.error("assethandler changes_list failed", { error: String(error) });
685
+ return errorResult(
686
+ `Failed to list change requests: ${error instanceof Error ? error.message : String(error)}`
687
+ );
688
+ }
689
+ }
690
+ );
691
+ server.registerTool(
692
+ track(mcpToolName(ctx.productName, "work_orders_list")),
693
+ {
694
+ title: "List Work Orders",
695
+ description: "List maintenance work orders with cursor-based pagination.",
696
+ inputSchema: { ...PaginationArgs }
697
+ },
698
+ async ({ limit, cursor }) => {
699
+ try {
700
+ const data = await ctx.gql.workspace.request(LIST_WORK_ORDERS, { pagination: buildPagination(limit, cursor) });
701
+ return jsonResult(data.workOrders);
702
+ } catch (error) {
703
+ ctx.logger.error("assethandler work_orders_list failed", { error: String(error) });
704
+ return errorResult(
705
+ `Failed to list work orders: ${error instanceof Error ? error.message : String(error)}`
706
+ );
707
+ }
708
+ }
709
+ );
710
+ server.registerTool(
711
+ track(mcpToolName(ctx.productName, "work_orders_create")),
712
+ {
713
+ title: "Create Work Order",
714
+ description: "Create a maintenance work order. `title` and `type` are required; optionally link an asset, assign it, and set priority/status.",
715
+ inputSchema: {
716
+ title: z.string().min(1).describe("Work order title"),
717
+ type: WorkOrderTypeEnum.describe("Work order type"),
718
+ description: z.string().optional().describe("Work order description"),
719
+ priority: PriorityEnum.optional().describe("Work order priority"),
720
+ status: WorkOrderStatusEnum.optional().describe("Initial status"),
721
+ assetId: z.string().optional().describe("Related asset ID"),
722
+ assignedTo: z.string().optional().describe("Assignee user ID")
723
+ }
724
+ },
725
+ async ({ title, type, description, priority, status, assetId, assignedTo }) => {
726
+ try {
727
+ const input = { title, type };
728
+ if (description !== void 0) input.description = description;
729
+ if (priority !== void 0) input.priority = priority;
730
+ if (status !== void 0) input.status = status;
731
+ if (assetId !== void 0) input.assetId = assetId;
732
+ if (assignedTo !== void 0) input.assignedTo = assignedTo;
733
+ const data = await ctx.gql.workspace.request(CREATE_WORK_ORDER, { input });
734
+ return jsonResult(data.createWorkOrder);
735
+ } catch (error) {
736
+ ctx.logger.error("assethandler work_orders_create failed", { error: String(error) });
737
+ return errorResult(
738
+ `Failed to create work order: ${error instanceof Error ? error.message : String(error)}`
739
+ );
740
+ }
741
+ }
742
+ );
743
+ server.registerTool(
744
+ track(mcpToolName(ctx.productName, "maintenance_list")),
745
+ {
746
+ title: "List Maintenance Records",
747
+ description: "List asset maintenance records with cursor-based pagination.",
748
+ inputSchema: { ...PaginationArgs }
749
+ },
750
+ async ({ limit, cursor }) => {
751
+ try {
752
+ const data = await ctx.gql.workspace.request(LIST_MAINTENANCE_RECORDS, { pagination: buildPagination(limit, cursor) });
753
+ return jsonResult(data.maintenanceRecords);
754
+ } catch (error) {
755
+ ctx.logger.error("assethandler maintenance_list failed", { error: String(error) });
756
+ return errorResult(
757
+ `Failed to list maintenance records: ${error instanceof Error ? error.message : String(error)}`
758
+ );
759
+ }
760
+ }
761
+ );
762
+ server.registerTool(
763
+ track(mcpToolName(ctx.productName, "knowledge_list")),
764
+ {
765
+ title: "List Knowledge Articles",
766
+ description: "List knowledge-base articles with cursor-based pagination.",
767
+ inputSchema: { ...PaginationArgs }
768
+ },
769
+ async ({ limit, cursor }) => {
770
+ try {
771
+ const data = await ctx.gql.workspace.request(LIST_KNOWLEDGE_ARTICLES, { pagination: buildPagination(limit, cursor) });
772
+ return jsonResult(data.knowledgeArticles);
773
+ } catch (error) {
774
+ ctx.logger.error("assethandler knowledge_list failed", { error: String(error) });
775
+ return errorResult(
776
+ `Failed to list knowledge articles: ${error instanceof Error ? error.message : String(error)}`
777
+ );
778
+ }
779
+ }
780
+ );
781
+ server.registerTool(
782
+ track(mcpToolName(ctx.productName, "knowledge_create")),
783
+ {
784
+ title: "Create Knowledge Article",
785
+ description: "Author a knowledge-base article. `title`, `slug`, and `content` are required; `slug` must be unique. Optionally link an asset/incident and set publication status.",
786
+ inputSchema: {
787
+ title: z.string().min(1).describe("Article title"),
788
+ slug: z.string().min(1).describe("URL slug, unique within the workspace"),
789
+ content: z.string().min(1).describe("Article body (markdown/plain)"),
790
+ summary: z.string().optional().describe("Short summary"),
791
+ status: KnowledgeArticleStatusEnum.optional().describe("Publication status"),
792
+ tags: z.array(z.string()).optional().describe("Free-form tags"),
793
+ relatedAssetId: z.string().optional().describe("Related asset ID"),
794
+ relatedIncidentId: z.string().optional().describe("Related incident ID")
795
+ }
796
+ },
797
+ async ({ title, slug, content, summary, status, tags, relatedAssetId, relatedIncidentId }) => {
798
+ try {
799
+ const input = { title, slug, content };
800
+ if (summary !== void 0) input.summary = summary;
801
+ if (status !== void 0) input.status = status;
802
+ if (tags !== void 0) input.tags = tags;
803
+ if (relatedAssetId !== void 0) input.relatedAssetId = relatedAssetId;
804
+ if (relatedIncidentId !== void 0) input.relatedIncidentId = relatedIncidentId;
805
+ const data = await ctx.gql.workspace.request(CREATE_KNOWLEDGE_ARTICLE, { input });
806
+ return jsonResult(data.createKnowledgeArticle);
807
+ } catch (error) {
808
+ ctx.logger.error("assethandler knowledge_create failed", { error: String(error) });
809
+ return errorResult(
810
+ `Failed to create knowledge article: ${error instanceof Error ? error.message : String(error)}`
811
+ );
812
+ }
813
+ }
814
+ );
815
+ }
816
+ function registerFinanceTools(server, ctx, track) {
817
+ server.registerTool(
818
+ track(mcpToolName(ctx.productName, "finance_budgets")),
819
+ {
820
+ title: "List Asset Budgets",
821
+ description: "List asset budgets with cursor-based pagination.",
822
+ inputSchema: { ...PaginationArgs }
823
+ },
824
+ async ({ limit, cursor }) => {
825
+ try {
826
+ const data = await ctx.gql.workspace.request(LIST_BUDGETS, { pagination: buildPagination(limit, cursor) });
827
+ return jsonResult(data.budgets);
828
+ } catch (error) {
829
+ ctx.logger.error("assethandler finance_budgets failed", { error: String(error) });
830
+ return errorResult(
831
+ `Failed to list budgets: ${error instanceof Error ? error.message : String(error)}`
832
+ );
833
+ }
834
+ }
835
+ );
836
+ server.registerTool(
837
+ track(mcpToolName(ctx.productName, "finance_transactions")),
838
+ {
839
+ title: "List Transactions",
840
+ description: "List asset financial transactions with cursor-based pagination.",
841
+ inputSchema: { ...PaginationArgs }
842
+ },
843
+ async ({ limit, cursor }) => {
844
+ try {
845
+ const data = await ctx.gql.workspace.request(LIST_TRANSACTIONS, { pagination: buildPagination(limit, cursor) });
846
+ return jsonResult(data.transactions);
847
+ } catch (error) {
848
+ ctx.logger.error("assethandler finance_transactions failed", { error: String(error) });
849
+ return errorResult(
850
+ `Failed to list transactions: ${error instanceof Error ? error.message : String(error)}`
851
+ );
852
+ }
853
+ }
854
+ );
855
+ server.registerTool(
856
+ track(mcpToolName(ctx.productName, "finance_create_transaction")),
857
+ {
858
+ title: "Create Transaction",
859
+ description: "Record an asset financial transaction. `amount`, `category`, `description`, and `type` are required.",
860
+ inputSchema: {
861
+ amount: z.number().describe("Transaction amount"),
862
+ category: z.string().min(1).describe("Transaction category (free-form)"),
863
+ description: z.string().min(1).describe("Transaction description"),
864
+ type: TransactionTypeEnum.describe("Transaction type"),
865
+ currency: z.string().optional().describe("ISO currency code (defaults server-side)"),
866
+ department: z.string().optional().describe("Owning department"),
867
+ status: TransactionStatusEnum.optional().describe("Approval status"),
868
+ vendor: z.string().optional().describe("Vendor name")
869
+ }
870
+ },
871
+ async ({ amount, category, description, type, currency, department, status, vendor }) => {
872
+ try {
873
+ const input = { amount, category, description, type };
874
+ if (currency !== void 0) input.currency = currency;
875
+ if (department !== void 0) input.department = department;
876
+ if (status !== void 0) input.status = status;
877
+ if (vendor !== void 0) input.vendor = vendor;
878
+ const data = await ctx.gql.workspace.request(CREATE_TRANSACTION, { input });
879
+ return jsonResult(data.createTransaction);
880
+ } catch (error) {
881
+ ctx.logger.error("assethandler finance_create_transaction failed", {
882
+ error: String(error)
883
+ });
884
+ return errorResult(
885
+ `Failed to create transaction: ${error instanceof Error ? error.message : String(error)}`
886
+ );
887
+ }
888
+ }
889
+ );
890
+ server.registerTool(
891
+ track(mcpToolName(ctx.productName, "finance_invoices")),
892
+ {
893
+ title: "List Invoices",
894
+ description: "List vendor invoices with cursor-based pagination.",
895
+ inputSchema: { ...PaginationArgs }
896
+ },
897
+ async ({ limit, cursor }) => {
898
+ try {
899
+ const data = await ctx.gql.workspace.request(LIST_INVOICES, { pagination: buildPagination(limit, cursor) });
900
+ return jsonResult(data.invoices);
901
+ } catch (error) {
902
+ ctx.logger.error("assethandler finance_invoices failed", { error: String(error) });
903
+ return errorResult(
904
+ `Failed to list invoices: ${error instanceof Error ? error.message : String(error)}`
905
+ );
906
+ }
907
+ }
908
+ );
909
+ }
910
+ function registerGovernanceTools(server, ctx, track) {
911
+ server.registerTool(
912
+ track(mcpToolName(ctx.productName, "compliance_frameworks")),
913
+ {
914
+ title: "List Compliance Frameworks",
915
+ description: "List compliance frameworks and their control scores with cursor-based pagination.",
916
+ inputSchema: { ...PaginationArgs }
917
+ },
918
+ async ({ limit, cursor }) => {
919
+ try {
920
+ const data = await ctx.gql.workspace.request(LIST_COMPLIANCE_FRAMEWORKS, { pagination: buildPagination(limit, cursor) });
921
+ return jsonResult(data.complianceFrameworks);
922
+ } catch (error) {
923
+ ctx.logger.error("assethandler compliance_frameworks failed", {
924
+ error: String(error)
925
+ });
926
+ return errorResult(
927
+ `Failed to list compliance frameworks: ${error instanceof Error ? error.message : String(error)}`
928
+ );
929
+ }
930
+ }
931
+ );
932
+ server.registerTool(
933
+ track(mcpToolName(ctx.productName, "security_policies")),
934
+ {
935
+ title: "List Security Policies",
936
+ description: "List asset-security policies with cursor-based pagination.",
937
+ inputSchema: { ...PaginationArgs }
938
+ },
939
+ async ({ limit, cursor }) => {
940
+ try {
941
+ const data = await ctx.gql.workspace.request(LIST_SECURITY_POLICIES, { pagination: buildPagination(limit, cursor) });
942
+ return jsonResult(data.assetSecurityPolicies);
943
+ } catch (error) {
944
+ ctx.logger.error("assethandler security_policies failed", { error: String(error) });
945
+ return errorResult(
946
+ `Failed to list security policies: ${error instanceof Error ? error.message : String(error)}`
947
+ );
948
+ }
949
+ }
950
+ );
951
+ server.registerTool(
952
+ track(mcpToolName(ctx.productName, "security_events")),
953
+ {
954
+ title: "List Security Events",
955
+ description: "List security events with cursor-based pagination.",
956
+ inputSchema: { ...PaginationArgs }
957
+ },
958
+ async ({ limit, cursor }) => {
959
+ try {
960
+ const data = await ctx.gql.workspace.request(LIST_SECURITY_EVENTS, { pagination: buildPagination(limit, cursor) });
961
+ return jsonResult(data.securityEvents);
962
+ } catch (error) {
963
+ ctx.logger.error("assethandler security_events failed", { error: String(error) });
964
+ return errorResult(
965
+ `Failed to list security events: ${error instanceof Error ? error.message : String(error)}`
966
+ );
967
+ }
968
+ }
969
+ );
970
+ server.registerTool(
971
+ track(mcpToolName(ctx.productName, "esg_list")),
972
+ {
973
+ title: "List ESG Metrics",
974
+ description: "List ESG (environmental/social/governance) metrics with cursor-based pagination.",
975
+ inputSchema: { ...PaginationArgs }
976
+ },
977
+ async ({ limit, cursor }) => {
978
+ try {
979
+ const data = await ctx.gql.workspace.request(LIST_ESG_METRICS, { pagination: buildPagination(limit, cursor) });
980
+ return jsonResult(data.esgMetrics);
981
+ } catch (error) {
982
+ ctx.logger.error("assethandler esg_list failed", { error: String(error) });
983
+ return errorResult(
984
+ `Failed to list ESG metrics: ${error instanceof Error ? error.message : String(error)}`
985
+ );
986
+ }
987
+ }
988
+ );
989
+ server.registerTool(
990
+ track(mcpToolName(ctx.productName, "esg_upsert")),
991
+ {
992
+ title: "Upsert ESG Metric",
993
+ description: "Record or update an ESG metric data point for a reporting period. `metricKey` + period identify the metric.",
994
+ inputSchema: {
995
+ category: z.string().min(1).describe("ESG category (Environmental/Social/Governance)"),
996
+ metricKey: z.string().min(1).describe("Stable metric key"),
997
+ metricName: z.string().min(1).describe("Human-readable metric name"),
998
+ value: z.number().describe("Measured value"),
999
+ unit: z.string().min(1).describe("Unit of measure"),
1000
+ periodStart: z.string().describe("Reporting-period start (ISO DateTime)"),
1001
+ periodEnd: z.string().describe("Reporting-period end (ISO DateTime)"),
1002
+ target: z.number().optional().describe("Target value"),
1003
+ trend: z.string().optional().describe("Trend indicator (e.g. up, down, flat)")
1004
+ }
1005
+ },
1006
+ async ({
1007
+ category,
1008
+ metricKey,
1009
+ metricName,
1010
+ value,
1011
+ unit,
1012
+ periodStart,
1013
+ periodEnd,
1014
+ target,
1015
+ trend
1016
+ }) => {
1017
+ try {
1018
+ const input = {
1019
+ category,
1020
+ metricKey,
1021
+ metricName,
1022
+ value,
1023
+ unit,
1024
+ periodStart,
1025
+ periodEnd
1026
+ };
1027
+ if (target !== void 0) input.target = target;
1028
+ if (trend !== void 0) input.trend = trend;
1029
+ const data = await ctx.gql.workspace.request(UPSERT_ESG_METRIC, { input });
1030
+ return jsonResult(data.upsertEsgMetric);
1031
+ } catch (error) {
1032
+ ctx.logger.error("assethandler esg_upsert failed", { error: String(error) });
1033
+ return errorResult(
1034
+ `Failed to upsert ESG metric: ${error instanceof Error ? error.message : String(error)}`
1035
+ );
1036
+ }
1037
+ }
1038
+ );
1039
+ }
1040
+ function registerInnovationTools(server, ctx, track) {
1041
+ server.registerTool(
1042
+ track(mcpToolName(ctx.productName, "digital_twins_list")),
1043
+ {
1044
+ title: "List Digital Twins",
1045
+ description: "List asset digital twins with cursor-based pagination.",
1046
+ inputSchema: { ...PaginationArgs }
1047
+ },
1048
+ async ({ limit, cursor }) => {
1049
+ try {
1050
+ const data = await ctx.gql.workspace.request(LIST_DIGITAL_TWINS, { pagination: buildPagination(limit, cursor) });
1051
+ return jsonResult(data.digitalTwins);
1052
+ } catch (error) {
1053
+ ctx.logger.error("assethandler digital_twins_list failed", { error: String(error) });
1054
+ return errorResult(
1055
+ `Failed to list digital twins: ${error instanceof Error ? error.message : String(error)}`
1056
+ );
1057
+ }
1058
+ }
1059
+ );
1060
+ server.registerTool(
1061
+ track(mcpToolName(ctx.productName, "digital_twins_create")),
1062
+ {
1063
+ title: "Create Digital Twin",
1064
+ description: "Create a digital twin for an asset. `assetId`, `fidelityLevel`, and `modelRef` are required.",
1065
+ inputSchema: {
1066
+ assetId: z.string().min(1).describe("Asset ID this twin models"),
1067
+ fidelityLevel: z.string().min(1).describe("Fidelity level (e.g. low, medium, high)"),
1068
+ modelRef: z.string().min(1).describe("Reference/URI of the 3D/simulation model"),
1069
+ geometryRef: z.string().optional().describe("Reference/URI of the geometry asset"),
1070
+ properties: JsonObject.optional().describe("Arbitrary twin property JSON")
1071
+ }
1072
+ },
1073
+ async ({ assetId, fidelityLevel, modelRef, geometryRef, properties }) => {
1074
+ try {
1075
+ const input = { assetId, fidelityLevel, modelRef };
1076
+ if (geometryRef !== void 0) input.geometryRef = geometryRef;
1077
+ if (properties !== void 0) input.properties = properties;
1078
+ const data = await ctx.gql.workspace.request(CREATE_DIGITAL_TWIN, { input });
1079
+ return jsonResult(data.createDigitalTwin);
1080
+ } catch (error) {
1081
+ ctx.logger.error("assethandler digital_twins_create failed", { error: String(error) });
1082
+ return errorResult(
1083
+ `Failed to create digital twin: ${error instanceof Error ? error.message : String(error)}`
1084
+ );
1085
+ }
1086
+ }
1087
+ );
1088
+ server.registerTool(
1089
+ track(mcpToolName(ctx.productName, "iot_list")),
1090
+ {
1091
+ title: "List IoT Devices",
1092
+ description: "List registered IoT devices with cursor-based pagination.",
1093
+ inputSchema: { ...PaginationArgs }
1094
+ },
1095
+ async ({ limit, cursor }) => {
1096
+ try {
1097
+ const data = await ctx.gql.workspace.request(LIST_IOT_DEVICES, { pagination: buildPagination(limit, cursor) });
1098
+ return jsonResult(data.iotDevices);
1099
+ } catch (error) {
1100
+ ctx.logger.error("assethandler iot_list failed", { error: String(error) });
1101
+ return errorResult(
1102
+ `Failed to list IoT devices: ${error instanceof Error ? error.message : String(error)}`
1103
+ );
1104
+ }
1105
+ }
1106
+ );
1107
+ server.registerTool(
1108
+ track(mcpToolName(ctx.productName, "iot_register")),
1109
+ {
1110
+ title: "Register IoT Device",
1111
+ description: "Register an IoT device. `deviceId`, `name`, `protocol`, and `type` are required; optionally link an asset.",
1112
+ inputSchema: {
1113
+ deviceId: z.string().min(1).describe("Stable device identifier"),
1114
+ name: z.string().min(1).describe("Device display name"),
1115
+ protocol: z.string().min(1).describe("Comms protocol (e.g. MQTT, CoAP, Modbus)"),
1116
+ type: z.string().min(1).describe("Device type (free-form)"),
1117
+ status: z.string().optional().describe("Initial status (free-form)"),
1118
+ assetId: z.string().optional().describe("Asset this device is attached to"),
1119
+ metadata: JsonObject.optional().describe("Arbitrary device metadata JSON")
1120
+ }
1121
+ },
1122
+ async ({ deviceId, name, protocol, type, status, assetId, metadata }) => {
1123
+ try {
1124
+ const input = { deviceId, name, protocol, type };
1125
+ if (status !== void 0) input.status = status;
1126
+ if (assetId !== void 0) input.assetId = assetId;
1127
+ if (metadata !== void 0) input.metadata = metadata;
1128
+ const data = await ctx.gql.workspace.request(REGISTER_IOT_DEVICE, { input });
1129
+ return jsonResult(data.registerIoTDevice);
1130
+ } catch (error) {
1131
+ ctx.logger.error("assethandler iot_register failed", { error: String(error) });
1132
+ return errorResult(
1133
+ `Failed to register IoT device: ${error instanceof Error ? error.message : String(error)}`
1134
+ );
1135
+ }
1136
+ }
1137
+ );
1138
+ server.registerTool(
1139
+ track(mcpToolName(ctx.productName, "predictions_list")),
1140
+ {
1141
+ title: "List AI Predictions",
1142
+ description: "List AI asset predictions with cursor-based pagination.",
1143
+ inputSchema: { ...PaginationArgs }
1144
+ },
1145
+ async ({ limit, cursor }) => {
1146
+ try {
1147
+ const data = await ctx.gql.workspace.request(LIST_AI_PREDICTIONS, { pagination: buildPagination(limit, cursor) });
1148
+ return jsonResult(data.aiPredictions);
1149
+ } catch (error) {
1150
+ ctx.logger.error("assethandler predictions_list failed", { error: String(error) });
1151
+ return errorResult(
1152
+ `Failed to list AI predictions: ${error instanceof Error ? error.message : String(error)}`
1153
+ );
1154
+ }
1155
+ }
1156
+ );
1157
+ server.registerTool(
1158
+ track(mcpToolName(ctx.productName, "predictions_request")),
1159
+ {
1160
+ title: "Request AI Prediction",
1161
+ description: "Request an AI prediction for an asset. `assetId` and `predictionType` are required; optionally supply a feature vector.",
1162
+ inputSchema: {
1163
+ assetId: z.string().min(1).describe("Asset ID to predict on"),
1164
+ predictionType: z.string().min(1).describe("Prediction type (e.g. failure, depreciation, utilization)"),
1165
+ featureVector: JsonObject.optional().describe("Optional feature-vector JSON")
1166
+ }
1167
+ },
1168
+ async ({ assetId, predictionType, featureVector }) => {
1169
+ try {
1170
+ const input = { assetId, predictionType };
1171
+ if (featureVector !== void 0) input.featureVector = featureVector;
1172
+ const data = await ctx.gql.workspace.request(REQUEST_AI_PREDICTION, { input });
1173
+ return jsonResult(data.requestAIPrediction);
1174
+ } catch (error) {
1175
+ ctx.logger.error("assethandler predictions_request failed", { error: String(error) });
1176
+ return errorResult(
1177
+ `Failed to request AI prediction: ${error instanceof Error ? error.message : String(error)}`
1178
+ );
1179
+ }
1180
+ }
1181
+ );
1182
+ server.registerTool(
1183
+ track(mcpToolName(ctx.productName, "provenance_list")),
1184
+ {
1185
+ title: "List Provenance Records",
1186
+ description: "List blockchain provenance-attestation records with cursor-based pagination.",
1187
+ inputSchema: { ...PaginationArgs }
1188
+ },
1189
+ async ({ limit, cursor }) => {
1190
+ try {
1191
+ const data = await ctx.gql.workspace.request(LIST_PROVENANCE_RECORDS, { pagination: buildPagination(limit, cursor) });
1192
+ return jsonResult(data.provenanceRecords);
1193
+ } catch (error) {
1194
+ ctx.logger.error("assethandler provenance_list failed", { error: String(error) });
1195
+ return errorResult(
1196
+ `Failed to list provenance records: ${error instanceof Error ? error.message : String(error)}`
1197
+ );
1198
+ }
1199
+ }
1200
+ );
1201
+ server.registerTool(
1202
+ track(mcpToolName(ctx.productName, "provenance_record")),
1203
+ {
1204
+ title: "Record Provenance",
1205
+ description: "Attest an asset provenance record on-chain. `assetId`, `chainNetwork`, and `hash` are required.",
1206
+ inputSchema: {
1207
+ assetId: z.string().min(1).describe("Asset ID being attested"),
1208
+ chainNetwork: z.string().min(1).describe("Chain network (e.g. ethereum, polygon)"),
1209
+ hash: z.string().min(1).describe("Attestation hash"),
1210
+ blockNumber: z.number().int().optional().describe("Block number"),
1211
+ txHash: z.string().optional().describe("Transaction hash"),
1212
+ metadata: JsonObject.optional().describe("Arbitrary attestation metadata JSON")
1213
+ }
1214
+ },
1215
+ async ({ assetId, chainNetwork, hash, blockNumber, txHash, metadata }) => {
1216
+ try {
1217
+ const input = { assetId, chainNetwork, hash };
1218
+ if (blockNumber !== void 0) input.blockNumber = blockNumber;
1219
+ if (txHash !== void 0) input.txHash = txHash;
1220
+ if (metadata !== void 0) input.metadata = metadata;
1221
+ const data = await ctx.gql.workspace.request(RECORD_PROVENANCE, { input });
1222
+ return jsonResult(data.recordProvenance);
1223
+ } catch (error) {
1224
+ ctx.logger.error("assethandler provenance_record failed", { error: String(error) });
1225
+ return errorResult(
1226
+ `Failed to record provenance: ${error instanceof Error ? error.message : String(error)}`
1227
+ );
1228
+ }
1229
+ }
1230
+ );
1231
+ }
1232
+
1233
+ // src/modules/assethandler/tools/analytics.ts
1234
+ function registerAnalyticsTools(server, ctx, track) {
1235
+ server.registerTool(
1236
+ track(mcpToolName(ctx.productName, "dashboard_overview")),
1237
+ {
1238
+ title: "AssetHandler Dashboard Overview",
1239
+ description: "Headline asset-management KPIs: total assets, total transactions, open incidents, and open work orders.",
1240
+ inputSchema: {}
1241
+ },
1242
+ async () => {
1243
+ try {
1244
+ const data = await ctx.gql.workspace.request(DASHBOARD_OVERVIEW, {});
1245
+ return jsonResult(data.dashboardOverview);
1246
+ } catch (error) {
1247
+ ctx.logger.error("assethandler dashboard_overview failed", { error: String(error) });
1248
+ return errorResult(
1249
+ `Failed to get dashboard overview: ${error instanceof Error ? error.message : String(error)}`
1250
+ );
1251
+ }
1252
+ }
1253
+ );
1254
+ }
1255
+
1256
+ // src/modules/assethandler/resources.ts
1257
+ function registerAssetHandlerResources(server, ctx, track) {
1258
+ const schemaUri = track(mcpResourceUri(ctx.productName, "schema"));
1259
+ const dashboardUri = track(mcpResourceUri(ctx.productName, "dashboard"));
1260
+ const assetsUri = track(mcpResourceUri(ctx.productName, "assets"));
1261
+ const incidentsUri = track(mcpResourceUri(ctx.productName, "incidents"));
1262
+ server.registerResource(
1263
+ "assethandler-schema",
1264
+ schemaUri,
1265
+ {
1266
+ title: "AssetHandler Domain Schema",
1267
+ description: "Overview of the AssetHandler enterprise-asset / ITSM / ITAM domain \u2014 entities, enums, and the per-entity tool surface.",
1268
+ mimeType: "text/plain"
1269
+ },
1270
+ async () => {
1271
+ ctx.logger.debug(`Resource ${schemaUri} requested`);
1272
+ const schema = `# AssetHandler Domain (Overview)
1273
+
1274
+ Enterprise asset management + IT service management (ITSM) + IT asset
1275
+ management (ITAM) platform.
1276
+
1277
+ ## Entities
1278
+ - Asset \u2014 the core asset register (category, condition, status, custom attributes)
1279
+ - SoftwareAsset \u2014 software-license assets (seats, compliance)
1280
+ - ConfigurationItem \u2014 CMDB configuration items
1281
+ - DiscoveryJob \u2014 automated asset-discovery runs
1282
+ - Incident / Problem / ChangeRequest \u2014 ITSM tickets
1283
+ - WorkOrder / MaintenanceRecord \u2014 maintenance management
1284
+ - KnowledgeArticle \u2014 knowledge base
1285
+ - AssetBudget / Transaction / Invoice \u2014 asset finance
1286
+ - ComplianceFramework / AssetSecurityPolicy / SecurityEvent \u2014 governance, risk & compliance
1287
+ - EsgMetric \u2014 ESG reporting
1288
+ - DigitalTwin / IoTDevice / AIPrediction / ProvenanceRecord \u2014 advanced (twins, IoT, AI, blockchain)
1289
+
1290
+ ## Enums (input-bearing)
1291
+ - AssetCondition: DAMAGED, EXCELLENT, FAIR, GOOD, POOR
1292
+ - AssetStatus: ACTIVE, DISPOSED, INACTIVE, MAINTENANCE, RETIRED
1293
+ - Priority: CRITICAL, HIGH, LOW, MEDIUM
1294
+ - KnowledgeArticleStatus: ARCHIVED, DRAFT, PUBLISHED
1295
+ - TransactionType: DISPOSAL, LEASE, MAINTENANCE, PURCHASE, TRANSFER
1296
+ - TransactionStatus: APPROVED, COMPLETED, PENDING, REJECTED
1297
+ - WorkOrderType: CORRECTIVE, EMERGENCY, PREDICTIVE, PREVENTIVE
1298
+ - WorkOrderStatus: APPROVED, CANCELLED, COMPLETED, DRAFT, IN_PROGRESS, SCHEDULED
1299
+
1300
+ ## Tool groups
1301
+ assets, service (ITSM), finance, governance, innovation, analytics.
1302
+ All run against the WORKSPACE gateway (workspace-scoped). List tools use
1303
+ cursor-based pagination ({ limit, cursor }). There is no public health probe.
1304
+ `;
1305
+ return {
1306
+ contents: [{ uri: schemaUri, text: schema, mimeType: "text/plain" }]
1307
+ };
1308
+ }
1309
+ );
1310
+ server.registerResource(
1311
+ "assethandler-dashboard",
1312
+ dashboardUri,
1313
+ {
1314
+ title: "AssetHandler Dashboard Overview",
1315
+ description: "Live headline KPIs (total assets, total transactions, open incidents, open work orders).",
1316
+ mimeType: "application/json"
1317
+ },
1318
+ async () => {
1319
+ ctx.logger.debug(`Resource ${dashboardUri} requested`);
1320
+ try {
1321
+ const data = await ctx.gql.workspace.request(
1322
+ DASHBOARD_OVERVIEW,
1323
+ {}
1324
+ );
1325
+ return {
1326
+ contents: [
1327
+ {
1328
+ uri: dashboardUri,
1329
+ text: JSON.stringify(data.dashboardOverview, null, 2),
1330
+ mimeType: "application/json"
1331
+ }
1332
+ ]
1333
+ };
1334
+ } catch (error) {
1335
+ return {
1336
+ contents: [
1337
+ {
1338
+ uri: dashboardUri,
1339
+ text: JSON.stringify({
1340
+ error: error instanceof Error ? error.message : String(error)
1341
+ }),
1342
+ mimeType: "application/json"
1343
+ }
1344
+ ]
1345
+ };
1346
+ }
1347
+ }
1348
+ );
1349
+ server.registerResource(
1350
+ "assethandler-assets",
1351
+ assetsUri,
1352
+ {
1353
+ title: "AssetHandler Asset Register",
1354
+ description: "The first 50 assets in the bound workspace.",
1355
+ mimeType: "application/json"
1356
+ },
1357
+ async () => {
1358
+ ctx.logger.debug(`Resource ${assetsUri} requested`);
1359
+ try {
1360
+ const data = await ctx.gql.workspace.request(LIST_ASSETS, {
1361
+ pagination: { limit: 50 }
1362
+ });
1363
+ return {
1364
+ contents: [
1365
+ {
1366
+ uri: assetsUri,
1367
+ text: JSON.stringify(data.assets, null, 2),
1368
+ mimeType: "application/json"
1369
+ }
1370
+ ]
1371
+ };
1372
+ } catch (error) {
1373
+ return {
1374
+ contents: [
1375
+ {
1376
+ uri: assetsUri,
1377
+ text: JSON.stringify({
1378
+ error: error instanceof Error ? error.message : String(error)
1379
+ }),
1380
+ mimeType: "application/json"
1381
+ }
1382
+ ]
1383
+ };
1384
+ }
1385
+ }
1386
+ );
1387
+ server.registerResource(
1388
+ "assethandler-incidents",
1389
+ incidentsUri,
1390
+ {
1391
+ title: "AssetHandler Incident Queue",
1392
+ description: "The first 50 service incidents in the bound workspace.",
1393
+ mimeType: "application/json"
1394
+ },
1395
+ async () => {
1396
+ ctx.logger.debug(`Resource ${incidentsUri} requested`);
1397
+ try {
1398
+ const data = await ctx.gql.workspace.request(LIST_INCIDENTS, {
1399
+ pagination: { limit: 50 }
1400
+ });
1401
+ return {
1402
+ contents: [
1403
+ {
1404
+ uri: incidentsUri,
1405
+ text: JSON.stringify(data.incidents, null, 2),
1406
+ mimeType: "application/json"
1407
+ }
1408
+ ]
1409
+ };
1410
+ } catch (error) {
1411
+ return {
1412
+ contents: [
1413
+ {
1414
+ uri: incidentsUri,
1415
+ text: JSON.stringify({
1416
+ error: error instanceof Error ? error.message : String(error)
1417
+ }),
1418
+ mimeType: "application/json"
1419
+ }
1420
+ ]
1421
+ };
1422
+ }
1423
+ }
1424
+ );
1425
+ }
1426
+ function registerAssetHandlerPrompts(server, ctx, track) {
1427
+ const p = ctx.productName;
1428
+ const onboardingName = track(mcpPromptName(p, "asset-onboarding"));
1429
+ const opsName = track(mcpPromptName(p, "itsm-ops"));
1430
+ server.registerPrompt(
1431
+ onboardingName,
1432
+ {
1433
+ title: "Asset Onboarding",
1434
+ description: "Guide for onboarding a new asset end to end: register the asset, attach a CMDB configuration item, optionally a digital twin / IoT device, and seed a maintenance/work-order baseline.",
1435
+ argsSchema: {
1436
+ name: z.string().optional().describe("Asset name"),
1437
+ category: z.string().optional().describe("Asset category")
1438
+ }
1439
+ },
1440
+ ({ name, category }) => {
1441
+ ctx.logger.debug(`Prompt ${onboardingName} called`, { name, category });
1442
+ const nameNote = name ? `Use the asset name "${name}".` : "Ask the user for the asset name.";
1443
+ const categoryNote = category ? `Use category "${category}".` : "Help the user pick a category.";
1444
+ return {
1445
+ messages: [
1446
+ {
1447
+ role: "user",
1448
+ content: {
1449
+ type: "text",
1450
+ text: `Help me onboard a new AssetHandler asset.
1451
+
1452
+ 1. **Register Asset**: Use ${p}_assets_create. ${nameNote} ${categoryNote} Provide a unique assetNumber; optionally set condition/status, serialNumber, locationName, assignedTo, tags, and customAttributes.
1453
+ 2. **CMDB**: Use ${p}_configuration_upsert to register a matching configuration item (ciNumber, ciType, status) if the asset is an IT CI.
1454
+ 3. **(Optional) Digital Twin**: Use ${p}_digital_twins_create with the new assetId, a fidelityLevel, and a modelRef.
1455
+ 4. **(Optional) IoT Device**: Use ${p}_iot_register to attach a sensor/device (deviceId, name, protocol, type) to the asset.
1456
+ 5. **Baseline Maintenance**: Use ${p}_work_orders_create (type=PREVENTIVE) to seed a preventive-maintenance work order.
1457
+ 6. **Verify**: Use ${p}_assets_get to confirm the asset, then ${p}_assets_list to see it in the register.
1458
+
1459
+ Show results at each step and confirm before creating downstream records.`
1460
+ }
1461
+ }
1462
+ ]
1463
+ };
1464
+ }
1465
+ );
1466
+ server.registerPrompt(
1467
+ opsName,
1468
+ {
1469
+ title: "ITSM Operations",
1470
+ description: "Daily IT service-management workflow: review KPIs, triage incidents, advance work orders, check problems/changes, and review compliance posture.",
1471
+ argsSchema: {
1472
+ focus: z.string().optional().describe("Optional area to focus on (incidents/maintenance/compliance)")
1473
+ }
1474
+ },
1475
+ ({ focus }) => {
1476
+ ctx.logger.debug(`Prompt ${opsName} called`, { focus });
1477
+ const focusNote = focus ? `Focus this run on: ${focus}.` : "Cover all areas below.";
1478
+ return {
1479
+ messages: [
1480
+ {
1481
+ role: "user",
1482
+ content: {
1483
+ type: "text",
1484
+ text: `Run daily AssetHandler ITSM operations. ${focusNote}
1485
+
1486
+ 1. **KPIs**: Use ${p}_dashboard_overview for headline numbers (assets, transactions, open incidents, open work orders).
1487
+ 2. **Incident Triage**: Use ${p}_incidents_list to find open incidents; open new ones with ${p}_incidents_create as needed.
1488
+ 3. **Problems & Changes**: Use ${p}_problems_list and ${p}_changes_list to review root-cause work and pending changes.
1489
+ 4. **Maintenance**: Use ${p}_work_orders_list and ${p}_maintenance_list to check the maintenance backlog; create work orders with ${p}_work_orders_create.
1490
+ 5. **Knowledge**: Use ${p}_knowledge_list; document recurring fixes with ${p}_knowledge_create.
1491
+ 6. **Governance**: Use ${p}_compliance_frameworks, ${p}_security_policies, and ${p}_security_events to review compliance/security posture.
1492
+
1493
+ Summarize what needs attention after each step.`
1494
+ }
1495
+ }
1496
+ ]
1497
+ };
1498
+ }
1499
+ );
1500
+ }
1501
+
1502
+ // src/modules/assethandler/index.ts
1503
+ var assethandlerModule = {
1504
+ id: "assethandler",
1505
+ version: "0.0.1",
1506
+ displayName: "AssetHandler",
1507
+ dependsOn: ["auth"],
1508
+ capabilities: { tools: {}, resources: {}, prompts: {} },
1509
+ register(server, ctx) {
1510
+ const tools = [];
1511
+ const resources = [];
1512
+ const prompts = [];
1513
+ const trackTool = (n) => {
1514
+ tools.push(n);
1515
+ return n;
1516
+ };
1517
+ const trackResource = (uri) => {
1518
+ resources.push(uri);
1519
+ return uri;
1520
+ };
1521
+ const trackPrompt = (n) => {
1522
+ prompts.push(n);
1523
+ return n;
1524
+ };
1525
+ registerAssetTools(server, ctx, trackTool);
1526
+ registerServiceTools(server, ctx, trackTool);
1527
+ registerFinanceTools(server, ctx, trackTool);
1528
+ registerGovernanceTools(server, ctx, trackTool);
1529
+ registerInnovationTools(server, ctx, trackTool);
1530
+ registerAnalyticsTools(server, ctx, trackTool);
1531
+ registerAssetHandlerResources(server, ctx, trackResource);
1532
+ registerAssetHandlerPrompts(server, ctx, trackPrompt);
1533
+ return { tools, resources, prompts };
1534
+ }
1535
+ };
1536
+ var assethandler_default = assethandlerModule;
1537
+
1538
+ export { assethandler_default as default };
1539
+ //# sourceMappingURL=index.js.map
1540
+ //# sourceMappingURL=index.js.map