@assetlab/mcp-server 1.14.1 → 1.16.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/dist/tools-write.js +102 -11
- package/dist/tools-write.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +15 -2
- package/dist/tools.js.map +1 -1
- package/package.json +1 -1
package/dist/tools-write.js
CHANGED
|
@@ -32,12 +32,12 @@ export function registerWriteTools(server, client) {
|
|
|
32
32
|
// ============================================================
|
|
33
33
|
// 1. Work Orders (scope: work_orders)
|
|
34
34
|
// ============================================================
|
|
35
|
-
server.tool('create_work_order', 'Create a new work order. Requires work_orders:write scope.
|
|
35
|
+
server.tool('create_work_order', 'Create a new work order. Requires work_orders:write scope. REQUIRED fields: title, site_id, building_id, AND at least one association (asset_id OR location_id). A work order with no asset/location association is not valid — ask the user which one applies before calling. RECOMMENDED: work_category_id (look up via list_work_categories; omit only if no reasonable match exists). Location hierarchy: always resolve top-down by calling list_sites first, then list_buildings filtered by site_id, then list_locations filtered by building_id.', {
|
|
36
36
|
title: z.string().min(1).max(500).describe('Work order title (required)'),
|
|
37
37
|
description: z.string().optional().describe('Detailed description'),
|
|
38
38
|
priority: z.enum(['LOW', 'MEDIUM', 'HIGH', 'URGENT']).optional().describe('Priority level'),
|
|
39
39
|
status: z.enum(['NEW', 'IN_PROGRESS', 'ON_HOLD', 'REJECTED', 'COMPLETED', 'CANCELLED']).optional().describe('Status'),
|
|
40
|
-
type: z.enum(['PM', '
|
|
40
|
+
type: z.enum(['PM', 'REACTIVE']).optional().describe('Work order type'),
|
|
41
41
|
site_id: z.string().uuid().optional().describe('Site ID — resolve first via list_sites'),
|
|
42
42
|
building_id: z.string().uuid().optional().describe('Building ID — resolve second via list_buildings filtered by site_id'),
|
|
43
43
|
location_id: z.string().uuid().optional().describe('Location ID — resolve last via list_locations filtered by building_id'),
|
|
@@ -50,6 +50,8 @@ export function registerWriteTools(server, client) {
|
|
|
50
50
|
assigned_to: z.string().optional().describe('Assigned user ID (mapped to assignees array)'),
|
|
51
51
|
assignees: z.array(z.string()).optional().describe('Array of assigned user IDs (alternative to assigned_to for multiple assignees)'),
|
|
52
52
|
image_url: z.string().max(2000).optional().describe('Image URL (upload via create_upload_url with bucket "attachments", then set this to the public_url)'),
|
|
53
|
+
meter_reading: z.number().min(0).optional().describe('Meter/odometer reading at time of service'),
|
|
54
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
53
55
|
}, async (params) => {
|
|
54
56
|
try {
|
|
55
57
|
const result = await client.create('work-orders', buildBody(params));
|
|
@@ -65,7 +67,7 @@ export function registerWriteTools(server, client) {
|
|
|
65
67
|
description: z.string().optional().describe('Detailed description'),
|
|
66
68
|
priority: z.enum(['LOW', 'MEDIUM', 'HIGH', 'URGENT']).optional().describe('Priority level'),
|
|
67
69
|
status: z.enum(['NEW', 'IN_PROGRESS', 'ON_HOLD', 'REJECTED', 'COMPLETED', 'CANCELLED']).optional().describe('Status'),
|
|
68
|
-
type: z.enum(['PM', '
|
|
70
|
+
type: z.enum(['PM', 'REACTIVE']).optional().describe('Work order type'),
|
|
69
71
|
site_id: z.string().uuid().optional().describe('Site ID — resolve first via list_sites'),
|
|
70
72
|
building_id: z.string().uuid().optional().describe('Building ID — resolve second via list_buildings filtered by site_id'),
|
|
71
73
|
location_id: z.string().uuid().optional().describe('Location ID — resolve last via list_locations filtered by building_id'),
|
|
@@ -78,6 +80,8 @@ export function registerWriteTools(server, client) {
|
|
|
78
80
|
assigned_to: z.string().optional().describe('Assigned user ID (mapped to assignees array)'),
|
|
79
81
|
assignees: z.array(z.string()).optional().describe('Array of assigned user IDs (alternative to assigned_to for multiple assignees)'),
|
|
80
82
|
image_url: z.string().max(2000).optional().describe('Image URL (upload via create_upload_url with bucket "attachments", then set this to the public_url)'),
|
|
83
|
+
meter_reading: z.number().min(0).optional().describe('Meter/odometer reading at time of service'),
|
|
84
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
81
85
|
}, async ({ id, ...rest }) => {
|
|
82
86
|
try {
|
|
83
87
|
const result = await client.update('work-orders', id, buildBody(rest));
|
|
@@ -134,6 +138,8 @@ export function registerWriteTools(server, client) {
|
|
|
134
138
|
environmental_impact: z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe('Environmental impact level (LOW, MEDIUM, HIGH, CRITICAL)'),
|
|
135
139
|
regulatory_impact: z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe('Regulatory impact level (LOW, MEDIUM, HIGH, CRITICAL)'),
|
|
136
140
|
reputation_impact: z.enum(['LOW', 'MEDIUM', 'HIGH', 'CRITICAL']).optional().describe('Reputation impact level (LOW, MEDIUM, HIGH, CRITICAL)'),
|
|
141
|
+
current_meter_reading: z.number().min(0).optional().describe('Current meter/odometer reading'),
|
|
142
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
137
143
|
}, async (params) => {
|
|
138
144
|
try {
|
|
139
145
|
const result = await client.create('assets', buildBody(params));
|
|
@@ -166,6 +172,8 @@ export function registerWriteTools(server, client) {
|
|
|
166
172
|
system_id: z.string().uuid().optional().describe('System ID — resolve last via list_systems filtered by system_group_id'),
|
|
167
173
|
image_url: z.string().max(2000).optional().describe('Image URL'),
|
|
168
174
|
last_maintenance_date: z.string().optional().describe('Last maintenance date (ISO 8601)'),
|
|
175
|
+
current_meter_reading: z.number().min(0).optional().describe('Current meter/odometer reading'),
|
|
176
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
169
177
|
quantity: z.number().min(0).optional().describe('Quantity'),
|
|
170
178
|
unit_of_measure: z.string().max(100).optional().describe('Unit of measure'),
|
|
171
179
|
unit_replacement_value: z.number().min(0).optional().describe('Unit replacement value'),
|
|
@@ -485,6 +493,9 @@ export function registerWriteTools(server, client) {
|
|
|
485
493
|
status: z.enum(['active', 'inactive']).optional().describe('Schedule status'),
|
|
486
494
|
auto_generate_wo: z.boolean().optional().describe('Auto-generate work orders'),
|
|
487
495
|
floating: z.boolean().optional().describe('Floating schedule (due date based on completion)'),
|
|
496
|
+
meter_based: z.boolean().optional().describe('Whether this PM triggers at meter intervals (e.g. every 5000 km)'),
|
|
497
|
+
meter_interval: z.number().min(0).optional().describe('Meter interval — trigger every N units'),
|
|
498
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
488
499
|
start_date: z.string().optional().describe('Start date (ISO 8601)'),
|
|
489
500
|
asset_ids: z.array(z.string().uuid()).optional().describe('Array of asset IDs'),
|
|
490
501
|
system_ids: z.array(z.string().uuid()).optional().describe('Array of system IDs'),
|
|
@@ -524,6 +535,9 @@ export function registerWriteTools(server, client) {
|
|
|
524
535
|
status: z.enum(['active', 'inactive']).optional().describe('Schedule status'),
|
|
525
536
|
auto_generate_wo: z.boolean().optional().describe('Auto-generate work orders'),
|
|
526
537
|
floating: z.boolean().optional().describe('Floating schedule (due date based on completion)'),
|
|
538
|
+
meter_based: z.boolean().optional().describe('Whether this PM triggers at meter intervals'),
|
|
539
|
+
meter_interval: z.number().min(0).optional().describe('Meter interval — trigger every N units'),
|
|
540
|
+
meter_unit: z.string().max(50).optional().describe('Meter unit (km, miles, hours, cycles)'),
|
|
527
541
|
start_date: z.string().optional().describe('Start date (ISO 8601)'),
|
|
528
542
|
asset_ids: z.array(z.string().uuid()).optional().describe('Array of asset IDs'),
|
|
529
543
|
system_ids: z.array(z.string().uuid()).optional().describe('Array of system IDs'),
|
|
@@ -552,6 +566,75 @@ export function registerWriteTools(server, client) {
|
|
|
552
566
|
}
|
|
553
567
|
});
|
|
554
568
|
// ============================================================
|
|
569
|
+
// 8b. PM Templates (scope: pm_templates)
|
|
570
|
+
// ============================================================
|
|
571
|
+
server.tool('create_pm_template', 'Create a new PM template. Templates are reusable PM definitions (not linked to a site/asset) that can seed new PM schedules. Requires pm_templates:write scope.', {
|
|
572
|
+
title: z.string().min(1).max(500).describe('PM template title (required, unique per tenant)'),
|
|
573
|
+
description: z.string().optional().describe('Description'),
|
|
574
|
+
frequency: z.enum(['DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY', 'SEMI_ANNUAL', 'ANNUAL', 'FIVE_YEARLY', 'CUSTOM']).optional().describe('Suggested maintenance frequency'),
|
|
575
|
+
custom_interval_weeks: z.number().int().min(1).optional().describe('Custom interval in weeks (when frequency is CUSTOM)'),
|
|
576
|
+
work_category: z.string().max(200).optional().describe('Work category label (free text)'),
|
|
577
|
+
work_category_id: z.string().uuid().optional().describe('Work category ID — resolve via list_work_categories'),
|
|
578
|
+
estimated_hours: z.number().min(0).optional().describe('Estimated hours'),
|
|
579
|
+
estimated_cost: z.number().min(0).optional().describe('Estimated cost'),
|
|
580
|
+
safety_requirements: z.string().optional().describe('Safety requirements'),
|
|
581
|
+
tasks: z.array(z.object({
|
|
582
|
+
id: z.string().describe('Unique task ID (use a random string)'),
|
|
583
|
+
description: z.string().describe('Task description'),
|
|
584
|
+
completed: z.boolean().describe('Whether the task is completed'),
|
|
585
|
+
})).optional().describe('Checklist of tasks baked into this template'),
|
|
586
|
+
resources: z.array(z.record(z.unknown())).optional().describe('Resource references (parts, tools, documents)'),
|
|
587
|
+
documents: z.array(z.record(z.unknown())).optional().describe('Document references'),
|
|
588
|
+
asset_ids: z.array(z.string().uuid()).optional().describe('Default asset IDs to seed on derived schedules'),
|
|
589
|
+
location_ids: z.array(z.string().uuid()).optional().describe('Default location IDs to seed on derived schedules'),
|
|
590
|
+
}, async (params) => {
|
|
591
|
+
try {
|
|
592
|
+
const result = await client.create('pm-templates', buildBody(params));
|
|
593
|
+
return formatResult(result);
|
|
594
|
+
}
|
|
595
|
+
catch (err) {
|
|
596
|
+
return formatError(err);
|
|
597
|
+
}
|
|
598
|
+
});
|
|
599
|
+
server.tool('update_pm_template', 'Update an existing PM template by ID. Requires pm_templates:write scope.', {
|
|
600
|
+
id: z.string().uuid().describe('PM template ID'),
|
|
601
|
+
title: z.string().min(1).max(500).optional().describe('PM template title'),
|
|
602
|
+
description: z.string().optional().describe('Description'),
|
|
603
|
+
frequency: z.enum(['DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY', 'SEMI_ANNUAL', 'ANNUAL', 'FIVE_YEARLY', 'CUSTOM']).optional().describe('Suggested maintenance frequency'),
|
|
604
|
+
custom_interval_weeks: z.number().int().min(1).optional().describe('Custom interval in weeks (when frequency is CUSTOM)'),
|
|
605
|
+
work_category: z.string().max(200).optional().describe('Work category label (free text)'),
|
|
606
|
+
work_category_id: z.string().uuid().optional().describe('Work category ID'),
|
|
607
|
+
estimated_hours: z.number().min(0).optional().describe('Estimated hours'),
|
|
608
|
+
estimated_cost: z.number().min(0).optional().describe('Estimated cost'),
|
|
609
|
+
safety_requirements: z.string().optional().describe('Safety requirements'),
|
|
610
|
+
tasks: z.array(z.object({
|
|
611
|
+
id: z.string().describe('Unique task ID'),
|
|
612
|
+
description: z.string().describe('Task description'),
|
|
613
|
+
completed: z.boolean().describe('Whether the task is completed'),
|
|
614
|
+
})).optional().describe('Checklist of tasks baked into this template'),
|
|
615
|
+
resources: z.array(z.record(z.unknown())).optional().describe('Resource references'),
|
|
616
|
+
documents: z.array(z.record(z.unknown())).optional().describe('Document references'),
|
|
617
|
+
asset_ids: z.array(z.string().uuid()).optional().describe('Default asset IDs'),
|
|
618
|
+
location_ids: z.array(z.string().uuid()).optional().describe('Default location IDs'),
|
|
619
|
+
}, async ({ id, ...rest }) => {
|
|
620
|
+
try {
|
|
621
|
+
const result = await client.update('pm-templates', id, buildBody(rest));
|
|
622
|
+
return formatResult(result);
|
|
623
|
+
}
|
|
624
|
+
catch (err) {
|
|
625
|
+
return formatError(err);
|
|
626
|
+
}
|
|
627
|
+
});
|
|
628
|
+
server.tool('delete_pm_template', 'Delete a PM template by ID. Requires pm_templates:write scope.', { id: z.string().uuid().describe('PM template ID') }, async ({ id }) => {
|
|
629
|
+
try {
|
|
630
|
+
const result = await client.remove('pm-templates', id);
|
|
631
|
+
return formatResult(result);
|
|
632
|
+
}
|
|
633
|
+
catch (err) {
|
|
634
|
+
return formatError(err);
|
|
635
|
+
}
|
|
636
|
+
});
|
|
637
|
+
// ============================================================
|
|
555
638
|
// 9. Projects (scope: projects)
|
|
556
639
|
// ============================================================
|
|
557
640
|
server.tool('create_project', 'Create a new project. Requires projects:write scope.', {
|
|
@@ -1992,10 +2075,14 @@ export function registerWriteTools(server, client) {
|
|
|
1992
2075
|
// ============================================================
|
|
1993
2076
|
// 36. Custom Field Values (scope: custom_fields)
|
|
1994
2077
|
// ============================================================
|
|
1995
|
-
server.tool('create_custom_field_value', 'Create a
|
|
1996
|
-
entity_id: z.string().uuid().describe('Entity ID (required)'),
|
|
1997
|
-
field_definition_id: z.string().uuid().describe('Custom field definition ID (required)'),
|
|
1998
|
-
|
|
2078
|
+
server.tool('create_custom_field_value', 'Create (upsert) a custom field value for an entity. The table stores values in typed columns — prefer setting the one that matches the field definition\'s field_type: value_text (text/select), value_number (number), value_date (date, ISO YYYY-MM-DD), value_boolean (boolean). Alternatively pass a single `value` string and the server will dispatch it to the right column based on field_type. Writes upsert on (entity_id, field_definition_id) so replaying a batch is idempotent. Requires custom_fields:write scope.', {
|
|
2079
|
+
entity_id: z.string().uuid().describe('Entity ID — e.g. asset.id, work_order.id (required)'),
|
|
2080
|
+
field_definition_id: z.string().uuid().describe('Custom field definition ID — resolve via list_custom_field_definitions (required)'),
|
|
2081
|
+
value_text: z.string().max(5000).nullable().optional().describe('Text value (use for field_type=text or select)'),
|
|
2082
|
+
value_number: z.number().nullable().optional().describe('Numeric value (use for field_type=number)'),
|
|
2083
|
+
value_date: z.string().nullable().optional().describe('Date value, ISO YYYY-MM-DD (use for field_type=date)'),
|
|
2084
|
+
value_boolean: z.boolean().nullable().optional().describe('Boolean value (use for field_type=boolean)'),
|
|
2085
|
+
value: z.string().max(5000).optional().describe('Legacy single-value shim — server dispatches to the correct typed column based on the field definition\'s field_type. Ignored if any value_* typed column is set.'),
|
|
1999
2086
|
}, async (params) => {
|
|
2000
2087
|
try {
|
|
2001
2088
|
const result = await client.create('custom-field-values', buildBody(params));
|
|
@@ -2005,11 +2092,15 @@ export function registerWriteTools(server, client) {
|
|
|
2005
2092
|
return formatError(err);
|
|
2006
2093
|
}
|
|
2007
2094
|
});
|
|
2008
|
-
server.tool('update_custom_field_value', 'Update an existing custom field value by ID. Requires custom_fields:write scope.', {
|
|
2095
|
+
server.tool('update_custom_field_value', 'Update an existing custom field value by ID. Set whichever typed column matches the definition\'s field_type (value_text / value_number / value_date / value_boolean), or pass a single `value` and the server will dispatch it. Requires custom_fields:write scope.', {
|
|
2009
2096
|
id: z.string().uuid().describe('Custom field value ID'),
|
|
2010
2097
|
entity_id: z.string().uuid().optional().describe('Entity ID'),
|
|
2011
|
-
field_definition_id: z.string().uuid().optional().describe('Custom field definition ID'),
|
|
2012
|
-
|
|
2098
|
+
field_definition_id: z.string().uuid().optional().describe('Custom field definition ID — required when using the `value` fallback if you want to avoid the server fetching it'),
|
|
2099
|
+
value_text: z.string().max(5000).nullable().optional().describe('Text value'),
|
|
2100
|
+
value_number: z.number().nullable().optional().describe('Numeric value'),
|
|
2101
|
+
value_date: z.string().nullable().optional().describe('Date value, ISO YYYY-MM-DD'),
|
|
2102
|
+
value_boolean: z.boolean().nullable().optional().describe('Boolean value'),
|
|
2103
|
+
value: z.string().max(5000).optional().describe('Legacy single-value shim — server dispatches based on field_type'),
|
|
2013
2104
|
}, async ({ id, ...rest }) => {
|
|
2014
2105
|
try {
|
|
2015
2106
|
const result = await client.update('custom-field-values', id, buildBody(rest));
|
|
@@ -2886,7 +2977,7 @@ export function registerWriteTools(server, client) {
|
|
|
2886
2977
|
const BULK_RESOURCES = [
|
|
2887
2978
|
'assets', 'work-orders', 'work-requests', 'vendors', 'sites',
|
|
2888
2979
|
'buildings', 'locations', 'systems', 'system-groups', 'system-classes',
|
|
2889
|
-
'pm-schedules', 'projects',
|
|
2980
|
+
'pm-schedules', 'pm-templates', 'projects',
|
|
2890
2981
|
'contracts', 'invoices', 'purchase-orders', 'expenses', 'budgets',
|
|
2891
2982
|
'asset-types', 'asset-type-groups', 'asset-statuses', 'work-categories', 'manufacturers',
|
|
2892
2983
|
'building-types', 'location-types', 'cost-categories',
|