@assetlab/mcp-server 2.2.0 โ 2.3.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/README.md +218 -150
- package/dist/tools-write.js +131 -0
- package/dist/tools-write.js.map +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +38 -0
- package/dist/tools.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,174 +1,242 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AssetLab MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@assetlab/mcp-server)
|
|
4
|
+
[](https://www.npmjs.com/package/@assetlab/mcp-server)
|
|
5
|
+
[](https://www.npmjs.com/package/@assetlab/mcp-server)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
4
7
|
|
|
5
|
-
|
|
8
|
+
**Talk to your assets.** Connect Claude, ChatGPT, or any MCP-compatible client to your
|
|
9
|
+
[AssetLab](https://assetlab.ca) account through the
|
|
10
|
+
[Model Context Protocol](https://modelcontextprotocol.io) - ask about work orders, PM
|
|
11
|
+
schedules, capital plans, and infrastructure networks in plain language, and create or
|
|
12
|
+
update records hands-free.
|
|
6
13
|
|
|
7
|
-
|
|
14
|
+
> ๐งฐ **428 tools** across **100+ resources** ยท ๐ scoped, tenant-bound, audited ยท
|
|
15
|
+
> โ๏ธ read *and* write ยท ๐ hosted or local
|
|
8
16
|
|
|
9
|
-
|
|
17
|
+
---
|
|
10
18
|
|
|
11
|
-
##
|
|
19
|
+
## ๐ Quick start
|
|
12
20
|
|
|
13
|
-
### Claude.ai
|
|
21
|
+
### Claude.ai (hosted - easiest)
|
|
14
22
|
|
|
15
23
|
1. Create an API key in **AssetLab โ Settings โ API Keys**
|
|
16
|
-
2. In Claude.ai
|
|
24
|
+
2. In Claude.ai: **Settings โ Connectors โ Add connector**
|
|
17
25
|
3. Paste the connector URL: `https://mcp.assetlab.ca`
|
|
18
26
|
4. When prompted for auth, paste your API key (`al_live_...`)
|
|
19
27
|
|
|
20
28
|
### ChatGPT
|
|
21
29
|
|
|
22
30
|
1. Create an API key in **AssetLab โ Settings โ API Keys**
|
|
23
|
-
2. In ChatGPT
|
|
24
|
-
3.
|
|
25
|
-
4. Set authentication to **OAuth**
|
|
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
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
|
87
|
-
|
|
88
|
-
|
|
|
89
|
-
|
|
|
90
|
-
|
|
|
91
|
-
| Asset
|
|
92
|
-
|
|
|
93
|
-
|
|
|
94
|
-
|
|
|
95
|
-
|
|
|
96
|
-
|
|
|
97
|
-
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
|
108
|
-
| Work
|
|
109
|
-
| Work
|
|
110
|
-
|
|
|
111
|
-
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
|
119
|
-
|
|
120
|
-
|
|
|
121
|
-
|
|
|
122
|
-
|
|
|
123
|
-
|
|
|
124
|
-
|
|
|
125
|
-
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
|
149
|
-
|
|
150
|
-
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
31
|
+
2. In ChatGPT: **Settings โ Apps & Connectors โ Add new connector**
|
|
32
|
+
3. Name it (e.g. `AssetLab`) and enter the server URL: `https://mcp.assetlab.ca`
|
|
33
|
+
4. Set authentication to **OAuth** and click **Create** - the OAuth endpoints are
|
|
34
|
+
auto-discovered
|
|
35
|
+
5. On the AssetLab authorization page, paste your API key (`al_live_...`)
|
|
36
|
+
|
|
37
|
+
### Claude Desktop / Claude Code (local, stdio)
|
|
38
|
+
|
|
39
|
+
This package runs as a local MCP server over stdio - nothing is exposed on the network.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"assetlab": {
|
|
45
|
+
"command": "npx",
|
|
46
|
+
"args": ["-y", "@assetlab/mcp-server"],
|
|
47
|
+
"env": {
|
|
48
|
+
"ASSETLAB_API_KEY": "al_live_...",
|
|
49
|
+
"ASSETLAB_API_URL": "https://<your-project>.supabase.co/functions/v1/api-gateway"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Your AssetLab administrator can provide the API URL for your organization.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## ๐ฌ What can you ask?
|
|
61
|
+
|
|
62
|
+
| You say | It does |
|
|
63
|
+
|---|---|
|
|
64
|
+
| *"Show me all overdue work orders"* | Lists them, sorted, with links back to AssetLab |
|
|
65
|
+
| *"Create a work order for the broken pump in Building 3"* | Looks up the building and asset, then creates it |
|
|
66
|
+
| *"Which projects are at risk or delayed?"* | Scans project status and risks |
|
|
67
|
+
| *"What's the total cost history for Asset X?"* | Aggregates every cost record |
|
|
68
|
+
| *"List watermains over 500 mm in poor condition"* | Filters infrastructure features by diameter and condition |
|
|
69
|
+
| *"Add a crack-sealing event to the sidewalk strategy at $4 per square metre"* | Maintains your lifecycle strategies ๐ |
|
|
70
|
+
| *"What PM schedules are due this month?"* | Checks every schedule's next due date |
|
|
71
|
+
| *"Update the priority on WO-1234 to urgent"* | Edits the record (with your write scope) |
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## ๐ What's new in 2.3
|
|
76
|
+
|
|
77
|
+
**Infrastructure lifecycle events.** Read and maintain lifecycle strategies - the
|
|
78
|
+
condition-triggered interventions ("crack sealing at condition 80-90 adds two years")
|
|
79
|
+
that bend renewal forecasts across the planner, the map, and corridor bundling. Five new
|
|
80
|
+
tools under the `infrastructure_lifecycle_events` scope.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## ๐งฐ Tool catalog
|
|
85
|
+
|
|
86
|
+
Tools follow one naming pattern throughout: `list_*` / `get_*` to read, `create_*` /
|
|
87
|
+
`update_*` / `delete_*` to write. **Read** below means list/get; **Write** means
|
|
88
|
+
create/update/delete (availability varies slightly per resource - the tool descriptions
|
|
89
|
+
are the authority).
|
|
90
|
+
|
|
91
|
+
<details>
|
|
92
|
+
<summary><b>๐ญ Assets & maintenance records</b> (16 resources)</summary>
|
|
93
|
+
|
|
94
|
+
| Resource | Read | Write |
|
|
95
|
+
|---|:-:|:-:|
|
|
96
|
+
| Assets | โ | โ |
|
|
97
|
+
| Asset comments ยท costs ยท documents ยท parts | โ | โ |
|
|
98
|
+
| Asset placements (floorplan pins) | โ | โ |
|
|
99
|
+
| Asset replacement plans | โ | โ |
|
|
100
|
+
| Asset condition assessments | โ | โ |
|
|
101
|
+
| Asset risk history | โ | - |
|
|
102
|
+
| Asset statuses ยท types ยท type groups | โ | โ |
|
|
103
|
+
| Attachments (+ `upload_file`, `create_upload_url`) | โ | โ |
|
|
104
|
+
| Manufacturers | โ | โ |
|
|
105
|
+
| Parts ยท part categories | โ | โ |
|
|
106
|
+
|
|
107
|
+
</details>
|
|
108
|
+
|
|
109
|
+
<details>
|
|
110
|
+
<summary><b>๐ ๏ธ Work management</b> (7 resources)</summary>
|
|
111
|
+
|
|
112
|
+
| Resource | Read | Write |
|
|
113
|
+
|---|:-:|:-:|
|
|
114
|
+
| Work orders | โ | โ |
|
|
115
|
+
| Work order comments ยท schedules | โ | โ |
|
|
116
|
+
| Work requests | โ | โ |
|
|
117
|
+
| Work categories | โ | โ |
|
|
118
|
+
| PM schedules | โ | โ |
|
|
119
|
+
| PM templates | โ | โ |
|
|
120
|
+
|
|
121
|
+
</details>
|
|
122
|
+
|
|
123
|
+
<details>
|
|
124
|
+
<summary><b>๐ Sites, buildings & systems</b> (11 resources)</summary>
|
|
125
|
+
|
|
126
|
+
| Resource | Read | Write |
|
|
127
|
+
|---|:-:|:-:|
|
|
128
|
+
| Sites | โ | โ |
|
|
129
|
+
| Site FCI history | โ | - |
|
|
130
|
+
| Buildings ยท building types | โ | โ |
|
|
131
|
+
| Locations ยท location types | โ | โ |
|
|
132
|
+
| Systems ยท system classes ยท system groups | โ | โ |
|
|
133
|
+
| Floorplans ยท floorplan regions | โ | โ |
|
|
134
|
+
|
|
135
|
+
</details>
|
|
136
|
+
|
|
137
|
+
<details>
|
|
138
|
+
<summary><b>๐ฃ๏ธ Infrastructure (linear assets)</b> (11 resources)</summary>
|
|
139
|
+
|
|
140
|
+
| Resource | Read | Write |
|
|
141
|
+
|---|:-:|:-:|
|
|
142
|
+
| Feature classes | โ | โ |
|
|
143
|
+
| Networks | โ | โ |
|
|
144
|
+
| Features (segments & nodes, GeoJSON geometry) | โ | โ |
|
|
145
|
+
| Feature inspections | โ | โ |
|
|
146
|
+
| Lifecycle events (strategies) ๐ | โ | โ |
|
|
147
|
+
| Zones | โ | โ |
|
|
148
|
+
| Feature comments ยท costs ยท documents ยท parts | โ | โ |
|
|
149
|
+
| Feature risk history | โ | - |
|
|
150
|
+
|
|
151
|
+
</details>
|
|
152
|
+
|
|
153
|
+
<details>
|
|
154
|
+
<summary><b>๐ Projects & capital planning</b> (20+ resources)</summary>
|
|
155
|
+
|
|
156
|
+
| Resource | Read | Write |
|
|
157
|
+
|---|:-:|:-:|
|
|
158
|
+
| Projects | โ | โ |
|
|
159
|
+
| Tasks ยท task dependencies ยท milestones | โ | โ |
|
|
160
|
+
| Phases ยท phase categories | โ | โ |
|
|
161
|
+
| Budget items ยท time entries ยท cost snapshots | โ | โ |
|
|
162
|
+
| Comments ยท updates ยท risks ยท team members | โ | โ |
|
|
163
|
+
| Documents ยท document folder templates | โ | โ |
|
|
164
|
+
| Project links (assets, buildings, sites, locations, systems, infrastructure) | โ | โ |
|
|
165
|
+
| Service areas (+ site and system-class links) | โ | โ |
|
|
166
|
+
|
|
167
|
+
</details>
|
|
168
|
+
|
|
169
|
+
<details>
|
|
170
|
+
<summary><b>๐ฐ Finance & vendors</b> (10 resources)</summary>
|
|
171
|
+
|
|
172
|
+
| Resource | Read | Write |
|
|
173
|
+
|---|:-:|:-:|
|
|
174
|
+
| Budgets | โ | โ |
|
|
175
|
+
| Expenses ยท invoices ยท purchase orders | โ | โ |
|
|
176
|
+
| Change orders | โ | โ |
|
|
177
|
+
| Cost categories | โ | โ |
|
|
178
|
+
| Contracts ยท contract sites ยท contract documents | โ | โ |
|
|
179
|
+
| Vendors ยท vendor site assignments | โ | โ |
|
|
180
|
+
|
|
181
|
+
</details>
|
|
182
|
+
|
|
183
|
+
<details>
|
|
184
|
+
<summary><b>โ
Compliance, forms & level of service</b> (9 resources)</summary>
|
|
185
|
+
|
|
186
|
+
| Resource | Read | Write |
|
|
187
|
+
|---|:-:|:-:|
|
|
188
|
+
| Compliance items ยท records | โ | โ |
|
|
189
|
+
| Form templates ยท template items | โ | โ |
|
|
190
|
+
| Form responses | โ | โ |
|
|
191
|
+
| Form response answers | โ | - |
|
|
192
|
+
| LoS measures ยท measurements | โ | โ |
|
|
193
|
+
| LoS targets history | โ | - |
|
|
194
|
+
|
|
195
|
+
</details>
|
|
196
|
+
|
|
197
|
+
<details>
|
|
198
|
+
<summary><b>โ๏ธ Admin & analytics</b> (6 resources)</summary>
|
|
199
|
+
|
|
200
|
+
| Resource | Read | Write |
|
|
201
|
+
|---|:-:|:-:|
|
|
202
|
+
| Users | โ | - |
|
|
203
|
+
| Custom field definitions ยท values | โ | โ |
|
|
204
|
+
| Dashboard summary ยท snapshots | โ | - |
|
|
205
|
+
| Bulk operations (`bulk_create`, `bulk_update`) | - | โ |
|
|
206
|
+
|
|
207
|
+
</details>
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## ๐ Scopes
|
|
212
|
+
|
|
213
|
+
API keys use scopes to control exactly what your assistant can touch. Configure
|
|
214
|
+
per-resource read and write access in **Settings โ API Keys** - scopes are grouped by
|
|
215
|
+
category (Operations, Facilities, Projects, Finance, Infrastructure, ...) with
|
|
216
|
+
bulk-toggle controls.
|
|
155
217
|
|
|
156
218
|
| Scope pattern | Access |
|
|
157
|
-
|
|
219
|
+
|---|---|
|
|
158
220
|
| `resource:read` | List and get records (e.g. `assets:read`, `work_orders:read`) |
|
|
159
|
-
| `resource:write` | Create, update, and delete records (e.g. `assets:write
|
|
221
|
+
| `resource:write` | Create, update, and delete records (e.g. `assets:write`) |
|
|
160
222
|
| `*:*` | Full access to all resources |
|
|
161
223
|
|
|
162
|
-
|
|
224
|
+
---
|
|
163
225
|
|
|
164
|
-
## Security
|
|
226
|
+
## ๐ก๏ธ Security
|
|
165
227
|
|
|
166
|
-
-
|
|
167
|
-
|
|
168
|
-
-
|
|
169
|
-
|
|
170
|
-
-
|
|
228
|
+
- ๐ **OAuth 2.0 + PKCE** through `mcp.assetlab.ca`; your API key is encrypted in
|
|
229
|
+
transit and never stored by the MCP server
|
|
230
|
+
- ๐ข **Tenant-bound** - every key is scoped to your organization only, and the server
|
|
231
|
+
ignores any attempt to address another tenant
|
|
232
|
+
- ๐ **Audited** - all data access is logged in AssetLab's audit log
|
|
233
|
+
- ๐งฏ **Revocable** - revoke a key any time in **Settings โ API Keys**; it dies instantly
|
|
234
|
+
- โ **Read-only by default** - write operations require explicit write scopes
|
|
171
235
|
|
|
172
|
-
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## ๐ Support
|
|
173
239
|
|
|
174
240
|
Questions or issues? Email [support@assetlab.ca](mailto:support@assetlab.ca).
|
|
241
|
+
|
|
242
|
+
Docs: [assetlab.ca](https://assetlab.ca) โ **Docs โ AI & MCP**
|
package/dist/tools-write.js
CHANGED
|
@@ -4696,6 +4696,137 @@ export function registerWriteTools(server, client) {
|
|
|
4696
4696
|
}
|
|
4697
4697
|
});
|
|
4698
4698
|
// ============================================================
|
|
4699
|
+
// Infrastructure Lifecycle Events (scope: infrastructure_lifecycle_events)
|
|
4700
|
+
// ============================================================
|
|
4701
|
+
const lifecycleEventScope = {
|
|
4702
|
+
feature_class: z
|
|
4703
|
+
.string()
|
|
4704
|
+
.regex(/^[a-z][a-z0-9_]{0,49}$/)
|
|
4705
|
+
.optional()
|
|
4706
|
+
.describe('Feature class code the strategy scope applies to (omit for a material-wide scope; at least one of feature_class/material is required)'),
|
|
4707
|
+
material: z
|
|
4708
|
+
.string()
|
|
4709
|
+
.max(200)
|
|
4710
|
+
.optional()
|
|
4711
|
+
.describe('Material the scope applies to, exactly as features carry it (e.g. "PVC")'),
|
|
4712
|
+
diameter_min_mm: z
|
|
4713
|
+
.number()
|
|
4714
|
+
.positive()
|
|
4715
|
+
.optional()
|
|
4716
|
+
.describe('Lower bound of a diameter band (requires material); bands ladder like rates'),
|
|
4717
|
+
};
|
|
4718
|
+
const lifecycleEventFields = {
|
|
4719
|
+
event_class: z
|
|
4720
|
+
.enum(['preventive', 'rehabilitation'])
|
|
4721
|
+
.describe('Event type โ preventative maintenance or rehabilitation'),
|
|
4722
|
+
trigger_condition_max: z
|
|
4723
|
+
.number()
|
|
4724
|
+
.int()
|
|
4725
|
+
.min(1)
|
|
4726
|
+
.max(99)
|
|
4727
|
+
.describe('Upper bound of the trigger window โ the event fires when projected condition falls to this'),
|
|
4728
|
+
trigger_condition_min: z
|
|
4729
|
+
.number()
|
|
4730
|
+
.int()
|
|
4731
|
+
.min(0)
|
|
4732
|
+
.max(98)
|
|
4733
|
+
.optional()
|
|
4734
|
+
.describe('Lower bound of the trigger window (default 0); a feature already below it has missed the event'),
|
|
4735
|
+
impact_method: z
|
|
4736
|
+
.enum(['add_years', 'reset_condition'])
|
|
4737
|
+
.describe('Effect: add years of life, or reset condition to a value'),
|
|
4738
|
+
impact_add_years: z
|
|
4739
|
+
.number()
|
|
4740
|
+
.positive()
|
|
4741
|
+
.max(100)
|
|
4742
|
+
.optional()
|
|
4743
|
+
.describe('Years added (required when impact_method is add_years)'),
|
|
4744
|
+
impact_reset_to: z
|
|
4745
|
+
.number()
|
|
4746
|
+
.int()
|
|
4747
|
+
.min(1)
|
|
4748
|
+
.max(100)
|
|
4749
|
+
.optional()
|
|
4750
|
+
.describe('Condition after the event (required when impact_method is reset_condition)'),
|
|
4751
|
+
cost_method: z
|
|
4752
|
+
.enum(['per_unit', 'fixed'])
|
|
4753
|
+
.optional()
|
|
4754
|
+
.describe("Costing: per unit (uses the feature's measured quantity and unit) or a fixed amount (default per_unit)"),
|
|
4755
|
+
unit_cost: z
|
|
4756
|
+
.number()
|
|
4757
|
+
.min(0)
|
|
4758
|
+
.optional()
|
|
4759
|
+
.describe('Cost per unit (current dollars, never indexed)'),
|
|
4760
|
+
fixed_cost: z.number().min(0).optional().describe('Fixed cost (current dollars)'),
|
|
4761
|
+
cost_source: z
|
|
4762
|
+
.string()
|
|
4763
|
+
.max(200)
|
|
4764
|
+
.optional()
|
|
4765
|
+
.describe('Provenance of the cost ("Engineering 2026", a tender reference)'),
|
|
4766
|
+
max_applications: z
|
|
4767
|
+
.number()
|
|
4768
|
+
.int()
|
|
4769
|
+
.min(1)
|
|
4770
|
+
.max(10)
|
|
4771
|
+
.optional()
|
|
4772
|
+
.describe("How many times the event may fire over a feature's life (default 1)"),
|
|
4773
|
+
min_years_between: z
|
|
4774
|
+
.number()
|
|
4775
|
+
.min(1)
|
|
4776
|
+
.max(100)
|
|
4777
|
+
.optional()
|
|
4778
|
+
.describe('Minimum years between firings of a recurring event (default 1)'),
|
|
4779
|
+
sort_order: z.number().int().min(0).optional().describe('Evaluation order within the strategy'),
|
|
4780
|
+
};
|
|
4781
|
+
server.tool('create_infrastructure_lifecycle_event', 'Create a lifecycle strategy event. Events attach to a SCOPE (feature_class code, material, optional diameter band) โ never to individual features; every feature resolves the most specific matching scope, like replacement rates. Replacement is NOT an event (it is priced by the rates and scheduled by the renewal forecast) โ model the interventions BEFORE replacement: crack sealing, relining, resurfacing. List existing events first to reuse a scope. Requires infrastructure_lifecycle_events:write scope.', {
|
|
4782
|
+
name: z.string().max(200).describe('Event name (required, e.g. "Crack Sealing")'),
|
|
4783
|
+
...lifecycleEventScope,
|
|
4784
|
+
...lifecycleEventFields,
|
|
4785
|
+
}, async (params) => {
|
|
4786
|
+
try {
|
|
4787
|
+
const result = await client.create('infrastructure-lifecycle-events', buildBody(params));
|
|
4788
|
+
return formatResult(result);
|
|
4789
|
+
}
|
|
4790
|
+
catch (err) {
|
|
4791
|
+
return formatError(err);
|
|
4792
|
+
}
|
|
4793
|
+
});
|
|
4794
|
+
server.tool('update_infrastructure_lifecycle_event', 'Update a lifecycle strategy event by ID. Editing re-confirms the cost (cost_reviewed_on is server-set). Set is_active false to disable an event without deleting it โ projections recompute immediately. Requires infrastructure_lifecycle_events:write scope.', {
|
|
4795
|
+
id: z.string().uuid().describe('Lifecycle event ID'),
|
|
4796
|
+
name: z.string().max(200).optional().describe('Event name'),
|
|
4797
|
+
is_active: z.boolean().optional().describe('Disable/enable the event'),
|
|
4798
|
+
event_class: lifecycleEventFields.event_class.optional(),
|
|
4799
|
+
trigger_condition_max: lifecycleEventFields.trigger_condition_max.optional(),
|
|
4800
|
+
trigger_condition_min: lifecycleEventFields.trigger_condition_min,
|
|
4801
|
+
impact_method: lifecycleEventFields.impact_method.optional(),
|
|
4802
|
+
impact_add_years: lifecycleEventFields.impact_add_years,
|
|
4803
|
+
impact_reset_to: lifecycleEventFields.impact_reset_to,
|
|
4804
|
+
cost_method: lifecycleEventFields.cost_method,
|
|
4805
|
+
unit_cost: lifecycleEventFields.unit_cost,
|
|
4806
|
+
fixed_cost: lifecycleEventFields.fixed_cost,
|
|
4807
|
+
cost_source: lifecycleEventFields.cost_source,
|
|
4808
|
+
max_applications: lifecycleEventFields.max_applications,
|
|
4809
|
+
min_years_between: lifecycleEventFields.min_years_between,
|
|
4810
|
+
sort_order: lifecycleEventFields.sort_order,
|
|
4811
|
+
}, async ({ id, ...rest }) => {
|
|
4812
|
+
try {
|
|
4813
|
+
const result = await client.update('infrastructure-lifecycle-events', id, buildBody(rest));
|
|
4814
|
+
return formatResult(result);
|
|
4815
|
+
}
|
|
4816
|
+
catch (err) {
|
|
4817
|
+
return formatError(err);
|
|
4818
|
+
}
|
|
4819
|
+
});
|
|
4820
|
+
server.tool('delete_infrastructure_lifecycle_event', 'Delete a lifecycle strategy event by ID. Projections recompute immediately; consider update with is_active=false to disable instead. Requires infrastructure_lifecycle_events:write scope.', { id: z.string().uuid().describe('Lifecycle event ID') }, async ({ id }) => {
|
|
4821
|
+
try {
|
|
4822
|
+
const result = await client.remove('infrastructure-lifecycle-events', id);
|
|
4823
|
+
return formatResult(result);
|
|
4824
|
+
}
|
|
4825
|
+
catch (err) {
|
|
4826
|
+
return formatError(err);
|
|
4827
|
+
}
|
|
4828
|
+
});
|
|
4829
|
+
// ============================================================
|
|
4699
4830
|
// Infrastructure Networks (scope: infrastructure_networks)
|
|
4700
4831
|
// ============================================================
|
|
4701
4832
|
server.tool('create_infrastructure_network', 'Create an infrastructure network โ a named grouping of features bound to one feature class. Requires infrastructure_networks:write scope.', {
|