@fruition/fcp-mcp-server 1.27.1 → 1.29.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 +27 -0
- package/dist/index.d.ts +432 -0
- package/dist/index.js +351 -2
- package/dist/skills-sync.d.ts +2 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,33 @@ MCP (Model Context Protocol) server that gives Claude Code direct access to the
|
|
|
16
16
|
| `fcp_add_progress_note` | Add progress notes to document work done |
|
|
17
17
|
| `fcp_get_claude_md` | Generate CLAUDE.md content for a launch |
|
|
18
18
|
|
|
19
|
+
### Tasker Freeze Management Tools
|
|
20
|
+
|
|
21
|
+
| Tool | Description |
|
|
22
|
+
|------|-------------|
|
|
23
|
+
| `fcp_list_freezes` | List active + scheduled auto-merge freezes and the available repos |
|
|
24
|
+
| `fcp_freeze_repo` | Schedule a freeze (by days or explicit window) to hold a repo's deploys |
|
|
25
|
+
| `fcp_update_freeze` | Edit an existing freeze's window or reason |
|
|
26
|
+
| `fcp_unfreeze` | Remove a freeze by id, or clear all freezes for a repo |
|
|
27
|
+
|
|
28
|
+
### Certificate Tools
|
|
29
|
+
|
|
30
|
+
| Tool | Description |
|
|
31
|
+
|------|-------------|
|
|
32
|
+
| `fcp_list_certificates` | Fleet TLS certs with status/expiry/cluster filters |
|
|
33
|
+
| `fcp_get_certificate` | Single certificate detail (issuer, SANs, expiry) |
|
|
34
|
+
| `fcp_scan_certificates` | Trigger a cert-monitor scan run |
|
|
35
|
+
|
|
36
|
+
### Tasker Job Control Tools
|
|
37
|
+
|
|
38
|
+
| Tool | Description |
|
|
39
|
+
|------|-------------|
|
|
40
|
+
| `fcp_spawn_task_job` | Spawn an automated code-change job for an Unroo task |
|
|
41
|
+
| `fcp_get_job_status` | Job status by job_id/task_id (or all + stats) |
|
|
42
|
+
| `fcp_list_jobs` | List the current Tasker job queue |
|
|
43
|
+
| `fcp_approve_job` | Approve merge for a job needing human sign-off |
|
|
44
|
+
| `fcp_override_merge_window` | Force-allow an auto-merge outside its deploy window (super_admin) |
|
|
45
|
+
|
|
19
46
|
### Unroo Task Management Tools
|
|
20
47
|
|
|
21
48
|
| Tool | Description |
|
package/dist/index.d.ts
CHANGED
|
@@ -7,4 +7,436 @@
|
|
|
7
7
|
* - Update checklist item status
|
|
8
8
|
* - Get project context for migrations
|
|
9
9
|
*/
|
|
10
|
+
interface Launch {
|
|
11
|
+
id: number;
|
|
12
|
+
name: string;
|
|
13
|
+
description: string | null;
|
|
14
|
+
platform: string;
|
|
15
|
+
launch_type: string;
|
|
16
|
+
status: string;
|
|
17
|
+
priority: string;
|
|
18
|
+
target_launch_date: string;
|
|
19
|
+
domain: string | null;
|
|
20
|
+
legacy_domain: string | null;
|
|
21
|
+
legacy_access_info: Record<string, any>;
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}
|
|
24
|
+
interface ChecklistItem {
|
|
25
|
+
id: number;
|
|
26
|
+
title: string;
|
|
27
|
+
description: string | null;
|
|
28
|
+
status: string;
|
|
29
|
+
category: string;
|
|
30
|
+
is_blocker: boolean;
|
|
31
|
+
claude_instructions: string | null;
|
|
32
|
+
[key: string]: any;
|
|
33
|
+
}
|
|
34
|
+
interface LaunchDetail {
|
|
35
|
+
launch: Launch;
|
|
36
|
+
checklist: ChecklistItem[];
|
|
37
|
+
[key: string]: any;
|
|
38
|
+
}
|
|
39
|
+
export declare class FCPClient {
|
|
40
|
+
private baseUrl;
|
|
41
|
+
private token;
|
|
42
|
+
private defaultTimeout;
|
|
43
|
+
constructor(baseUrl: string, token: string);
|
|
44
|
+
private fetch;
|
|
45
|
+
listLaunches(filters?: {
|
|
46
|
+
status?: string;
|
|
47
|
+
platform?: string;
|
|
48
|
+
upcoming?: number;
|
|
49
|
+
limit?: number;
|
|
50
|
+
}): Promise<{
|
|
51
|
+
launches: Launch[];
|
|
52
|
+
}>;
|
|
53
|
+
getLaunch(id: number): Promise<LaunchDetail>;
|
|
54
|
+
createChecklistItem(launchId: number, input: {
|
|
55
|
+
title: string;
|
|
56
|
+
category: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
role?: string;
|
|
59
|
+
environment?: string;
|
|
60
|
+
assigned_to_id?: number;
|
|
61
|
+
due_date?: string;
|
|
62
|
+
sort_order?: number;
|
|
63
|
+
depends_on_item_id?: number;
|
|
64
|
+
is_required?: boolean;
|
|
65
|
+
is_blocking?: boolean;
|
|
66
|
+
external_link?: string;
|
|
67
|
+
}): Promise<ChecklistItem>;
|
|
68
|
+
updateChecklistItem(launchId: number, itemId: number, updates: {
|
|
69
|
+
status?: string;
|
|
70
|
+
notes?: string;
|
|
71
|
+
title?: string;
|
|
72
|
+
description?: string | null;
|
|
73
|
+
category?: string;
|
|
74
|
+
role?: string;
|
|
75
|
+
environment?: string;
|
|
76
|
+
assigned_to_id?: number | null;
|
|
77
|
+
due_date?: string | null;
|
|
78
|
+
sort_order?: number;
|
|
79
|
+
depends_on_item_id?: number | null;
|
|
80
|
+
is_required?: boolean;
|
|
81
|
+
is_blocking?: boolean;
|
|
82
|
+
external_link?: string | null;
|
|
83
|
+
evidence_url?: string | null;
|
|
84
|
+
jira_ticket_key?: string | null;
|
|
85
|
+
completion_notes?: string | null;
|
|
86
|
+
}): Promise<ChecklistItem>;
|
|
87
|
+
deleteChecklistItem(launchId: number, itemId: number): Promise<{
|
|
88
|
+
success: boolean;
|
|
89
|
+
}>;
|
|
90
|
+
private buildQuery;
|
|
91
|
+
listAlerts(q?: {
|
|
92
|
+
status?: string;
|
|
93
|
+
source?: string;
|
|
94
|
+
severity?: string;
|
|
95
|
+
cluster?: string;
|
|
96
|
+
namespace?: string;
|
|
97
|
+
domain?: string;
|
|
98
|
+
websiteId?: number;
|
|
99
|
+
environment?: string;
|
|
100
|
+
from?: string;
|
|
101
|
+
to?: string;
|
|
102
|
+
page?: number;
|
|
103
|
+
limit?: number;
|
|
104
|
+
}): Promise<any>;
|
|
105
|
+
getAlert(id: number): Promise<any>;
|
|
106
|
+
createAlert(input: {
|
|
107
|
+
alertName: string;
|
|
108
|
+
severity?: string;
|
|
109
|
+
summary?: string;
|
|
110
|
+
cluster?: string;
|
|
111
|
+
namespace?: string;
|
|
112
|
+
domain?: string;
|
|
113
|
+
websiteId?: number;
|
|
114
|
+
}): Promise<any>;
|
|
115
|
+
updateAlert(id: number, updates: {
|
|
116
|
+
status?: string;
|
|
117
|
+
acknowledgedBy?: string;
|
|
118
|
+
silencedUntil?: string;
|
|
119
|
+
silencedBy?: string;
|
|
120
|
+
adminNotes?: string;
|
|
121
|
+
websiteId?: number;
|
|
122
|
+
unrooTaskId?: number;
|
|
123
|
+
}): Promise<any>;
|
|
124
|
+
getAlertStats(): Promise<any>;
|
|
125
|
+
listAlertRules(accountId?: number): Promise<any>;
|
|
126
|
+
getAlertRule(ruleId: number): Promise<any>;
|
|
127
|
+
createAlertRule(input: Record<string, any>): Promise<any>;
|
|
128
|
+
updateAlertRule(ruleId: number, updates: Record<string, any>): Promise<any>;
|
|
129
|
+
deleteAlertRule(ruleId: number): Promise<any>;
|
|
130
|
+
listOutages(q?: {
|
|
131
|
+
status?: string;
|
|
132
|
+
accountId?: number;
|
|
133
|
+
limit?: number;
|
|
134
|
+
}): Promise<any>;
|
|
135
|
+
getOutage(outageId: number): Promise<any>;
|
|
136
|
+
createOutage(input: Record<string, any>): Promise<any>;
|
|
137
|
+
updateOutage(outageId: number, updates: Record<string, any>): Promise<any>;
|
|
138
|
+
resolveOutage(outageId: number): Promise<any>;
|
|
139
|
+
bulkNotifyClients(input: {
|
|
140
|
+
outageIds: number[];
|
|
141
|
+
notificationType: string;
|
|
142
|
+
subject: string;
|
|
143
|
+
message: string;
|
|
144
|
+
channels?: string[];
|
|
145
|
+
sentBy?: string;
|
|
146
|
+
}): Promise<any>;
|
|
147
|
+
getBulkNotifyHistory(limit?: number): Promise<any>;
|
|
148
|
+
createLaunch(input: {
|
|
149
|
+
name: string;
|
|
150
|
+
platform: string;
|
|
151
|
+
launch_type: string;
|
|
152
|
+
target_launch_date: string;
|
|
153
|
+
website_id?: number;
|
|
154
|
+
account_id?: number;
|
|
155
|
+
description?: string;
|
|
156
|
+
soft_launch_date?: string;
|
|
157
|
+
kickoff_date?: string;
|
|
158
|
+
priority?: string;
|
|
159
|
+
jira_project_key?: string;
|
|
160
|
+
unroo_project_id?: number;
|
|
161
|
+
webops_lead_id?: number;
|
|
162
|
+
devops_lead_id?: number;
|
|
163
|
+
dev_lead_id?: number;
|
|
164
|
+
seo_lead_id?: number;
|
|
165
|
+
client_contact?: string;
|
|
166
|
+
client_contact_email?: string;
|
|
167
|
+
use_default_checklist?: boolean;
|
|
168
|
+
}): Promise<{
|
|
169
|
+
launch: Launch;
|
|
170
|
+
}>;
|
|
171
|
+
updateLaunch(id: number, updates: {
|
|
172
|
+
website_id?: number | null;
|
|
173
|
+
account_id?: number | null;
|
|
174
|
+
name?: string;
|
|
175
|
+
description?: string;
|
|
176
|
+
platform?: string;
|
|
177
|
+
launch_type?: string;
|
|
178
|
+
target_launch_date?: string;
|
|
179
|
+
soft_launch_date?: string | null;
|
|
180
|
+
actual_launch_date?: string | null;
|
|
181
|
+
kickoff_date?: string | null;
|
|
182
|
+
status?: string;
|
|
183
|
+
priority?: string;
|
|
184
|
+
jira_project_key?: string | null;
|
|
185
|
+
unroo_project_id?: number | null;
|
|
186
|
+
webops_lead_id?: number | null;
|
|
187
|
+
devops_lead_id?: number | null;
|
|
188
|
+
dev_lead_id?: number | null;
|
|
189
|
+
seo_lead_id?: number | null;
|
|
190
|
+
client_contact?: string | null;
|
|
191
|
+
client_contact_email?: string | null;
|
|
192
|
+
}): Promise<any>;
|
|
193
|
+
deleteLaunch(id: number): Promise<{
|
|
194
|
+
success: boolean;
|
|
195
|
+
}>;
|
|
196
|
+
getSuccessFactors(launchId: number, itemId: number): Promise<{
|
|
197
|
+
factors: any[];
|
|
198
|
+
}>;
|
|
199
|
+
validateChecklistItem(launchId: number, itemId: number): Promise<any>;
|
|
200
|
+
getClaudeMd(launchId: number): Promise<{
|
|
201
|
+
content: string;
|
|
202
|
+
}>;
|
|
203
|
+
addNote(launchId: number, content: string): Promise<any>;
|
|
204
|
+
listFileSyncConfigs(filters?: {
|
|
205
|
+
enabled?: boolean;
|
|
206
|
+
search?: string;
|
|
207
|
+
sync_direction?: string;
|
|
208
|
+
}): Promise<{
|
|
209
|
+
success: boolean;
|
|
210
|
+
data: any[];
|
|
211
|
+
count: number;
|
|
212
|
+
}>;
|
|
213
|
+
getFileSyncJobs(filters?: {
|
|
214
|
+
config_id?: number;
|
|
215
|
+
status?: string;
|
|
216
|
+
limit?: number;
|
|
217
|
+
}): Promise<{
|
|
218
|
+
success: boolean;
|
|
219
|
+
data: any[];
|
|
220
|
+
count: number;
|
|
221
|
+
}>;
|
|
222
|
+
startFileSync(input: {
|
|
223
|
+
config_id: number;
|
|
224
|
+
trigger_type?: string;
|
|
225
|
+
triggered_by?: string;
|
|
226
|
+
confirmation_token?: string;
|
|
227
|
+
}): Promise<{
|
|
228
|
+
success: boolean;
|
|
229
|
+
data: any;
|
|
230
|
+
message: string;
|
|
231
|
+
}>;
|
|
232
|
+
cancelFileSync(jobId: string): Promise<{
|
|
233
|
+
success: boolean;
|
|
234
|
+
message: string;
|
|
235
|
+
}>;
|
|
236
|
+
getFileSyncConfirmation(configId: number): Promise<{
|
|
237
|
+
success: boolean;
|
|
238
|
+
data: {
|
|
239
|
+
token: string;
|
|
240
|
+
config_id: number;
|
|
241
|
+
expires_at: string;
|
|
242
|
+
ttl_seconds: number;
|
|
243
|
+
warnings: string[];
|
|
244
|
+
};
|
|
245
|
+
}>;
|
|
246
|
+
triggerNucleiScan(websiteId: number, options?: {
|
|
247
|
+
url?: string;
|
|
248
|
+
severity?: string;
|
|
249
|
+
templates?: string;
|
|
250
|
+
}): Promise<any>;
|
|
251
|
+
getNucleiResults(websiteId: number, options?: {
|
|
252
|
+
scan_id?: string;
|
|
253
|
+
limit?: number;
|
|
254
|
+
status?: string;
|
|
255
|
+
}): Promise<any>;
|
|
256
|
+
scanSecurityHeaders(websiteId: number): Promise<any>;
|
|
257
|
+
getSecurityHeadersResults(websiteId: number, scanId?: string): Promise<any>;
|
|
258
|
+
listSites(filters?: {
|
|
259
|
+
account_id?: number;
|
|
260
|
+
cms?: string;
|
|
261
|
+
environment?: string;
|
|
262
|
+
fru_hosted?: boolean;
|
|
263
|
+
retired?: string;
|
|
264
|
+
limit?: number;
|
|
265
|
+
offset?: number;
|
|
266
|
+
}): Promise<any>;
|
|
267
|
+
searchSites(query: string, limit?: number): Promise<any>;
|
|
268
|
+
getSite(siteId: number): Promise<any>;
|
|
269
|
+
createSite(production: {
|
|
270
|
+
account_id: number;
|
|
271
|
+
domain: string;
|
|
272
|
+
cms: string;
|
|
273
|
+
url_full?: string;
|
|
274
|
+
git_provider?: string;
|
|
275
|
+
git_link?: string;
|
|
276
|
+
hosting_provider?: string;
|
|
277
|
+
fru_hosted?: boolean;
|
|
278
|
+
k8s_cluster?: string;
|
|
279
|
+
k8s_namespace?: string;
|
|
280
|
+
}, staging?: Array<{
|
|
281
|
+
domain: string;
|
|
282
|
+
k8s_namespace: string;
|
|
283
|
+
}>): Promise<any>;
|
|
284
|
+
updateSite(siteId: number, updates: Record<string, any>): Promise<any>;
|
|
285
|
+
deleteSite(siteId: number, options?: {
|
|
286
|
+
reason?: string;
|
|
287
|
+
forward_url?: string;
|
|
288
|
+
}): Promise<any>;
|
|
289
|
+
getLocalSetupGuide(siteId: number): Promise<any>;
|
|
290
|
+
listClients(filters?: {
|
|
291
|
+
q?: string;
|
|
292
|
+
webops_lead?: string;
|
|
293
|
+
contract_type?: string;
|
|
294
|
+
tier?: string;
|
|
295
|
+
marketing?: boolean;
|
|
296
|
+
status?: string;
|
|
297
|
+
limit?: number;
|
|
298
|
+
}): Promise<any>;
|
|
299
|
+
getClient(accountId: number): Promise<any>;
|
|
300
|
+
updateClientProfile(accountId: number, updates: Record<string, any>): Promise<any>;
|
|
301
|
+
shieldListDomains(filters?: {
|
|
302
|
+
status?: string;
|
|
303
|
+
account_id?: number;
|
|
304
|
+
}): Promise<any>;
|
|
305
|
+
shieldAddDomain(input: {
|
|
306
|
+
domain: string;
|
|
307
|
+
origin_type?: 'custom' | 's3';
|
|
308
|
+
origin_host?: string;
|
|
309
|
+
origin_port?: number;
|
|
310
|
+
origin_protocol?: string;
|
|
311
|
+
s3_bucket?: string;
|
|
312
|
+
s3_region?: string;
|
|
313
|
+
s3_origin_path?: string;
|
|
314
|
+
website_id?: number;
|
|
315
|
+
account_id?: number;
|
|
316
|
+
cache_profile?: string;
|
|
317
|
+
waf_profile?: string;
|
|
318
|
+
geo_block_countries?: string[];
|
|
319
|
+
bot_control_enabled?: boolean;
|
|
320
|
+
notes?: string;
|
|
321
|
+
}): Promise<any>;
|
|
322
|
+
shieldGetDomain(domainId: number): Promise<any>;
|
|
323
|
+
shieldUpdateDomain(domainId: number, updates: Record<string, any>): Promise<any>;
|
|
324
|
+
shieldRemoveDomain(domainId: number): Promise<any>;
|
|
325
|
+
shieldGetMetrics(): Promise<any>;
|
|
326
|
+
shieldVerifyDomain(domainId: number): Promise<any>;
|
|
327
|
+
private fetchText;
|
|
328
|
+
trustedIpListRanges(filters?: {
|
|
329
|
+
group?: string;
|
|
330
|
+
include_pending?: boolean;
|
|
331
|
+
include_expired?: boolean;
|
|
332
|
+
}): Promise<any>;
|
|
333
|
+
trustedIpAddRange(input: {
|
|
334
|
+
group_id: number;
|
|
335
|
+
cidr: string;
|
|
336
|
+
label?: string;
|
|
337
|
+
purpose?: string;
|
|
338
|
+
ticket_ref?: string;
|
|
339
|
+
expires_at?: string;
|
|
340
|
+
override_reason?: string;
|
|
341
|
+
}): Promise<any>;
|
|
342
|
+
trustedIpUpdateRange(id: number, updates: Record<string, unknown>): Promise<any>;
|
|
343
|
+
trustedIpRemoveRange(id: number): Promise<any>;
|
|
344
|
+
trustedIpExport(opts?: {
|
|
345
|
+
format?: string;
|
|
346
|
+
group?: string;
|
|
347
|
+
purpose?: string;
|
|
348
|
+
separator?: string;
|
|
349
|
+
}): Promise<string>;
|
|
350
|
+
listFreezes(): Promise<any>;
|
|
351
|
+
freezeRepo(input: {
|
|
352
|
+
repo: string;
|
|
353
|
+
reason: string;
|
|
354
|
+
days?: number;
|
|
355
|
+
starts_at?: string;
|
|
356
|
+
ends_at?: string;
|
|
357
|
+
}): Promise<any>;
|
|
358
|
+
updateFreeze(id: number, updates: Record<string, unknown>): Promise<any>;
|
|
359
|
+
unfreeze(input: {
|
|
360
|
+
id?: number;
|
|
361
|
+
repo?: string;
|
|
362
|
+
}): Promise<any>;
|
|
363
|
+
listCertificates(filters?: {
|
|
364
|
+
status?: string;
|
|
365
|
+
cluster?: string;
|
|
366
|
+
namespace?: string;
|
|
367
|
+
certType?: string;
|
|
368
|
+
expiringWithinDays?: number;
|
|
369
|
+
sortBy?: string;
|
|
370
|
+
sortDir?: string;
|
|
371
|
+
page?: number;
|
|
372
|
+
limit?: number;
|
|
373
|
+
}): Promise<any>;
|
|
374
|
+
getCertificate(certId: string | number): Promise<any>;
|
|
375
|
+
scanCertificates(input?: {
|
|
376
|
+
dryRun?: boolean;
|
|
377
|
+
}): Promise<any>;
|
|
378
|
+
spawnTaskJob(input: {
|
|
379
|
+
task_id: string;
|
|
380
|
+
task_title: string;
|
|
381
|
+
project_key: string;
|
|
382
|
+
task_description?: string;
|
|
383
|
+
labels?: string[];
|
|
384
|
+
}): Promise<any>;
|
|
385
|
+
getJobStatus(opts: {
|
|
386
|
+
job_id?: string;
|
|
387
|
+
task_id?: string;
|
|
388
|
+
}): Promise<any>;
|
|
389
|
+
listJobs(opts?: {
|
|
390
|
+
refresh?: boolean;
|
|
391
|
+
}): Promise<any>;
|
|
392
|
+
approveJob(id: string): Promise<any>;
|
|
393
|
+
overrideMergeWindow(id: string, input: {
|
|
394
|
+
action: 'set' | 'clear';
|
|
395
|
+
reason?: string;
|
|
396
|
+
ttl_minutes?: number;
|
|
397
|
+
}): Promise<any>;
|
|
398
|
+
backupListSites(): Promise<any>;
|
|
399
|
+
backupGetConfig(): Promise<any>;
|
|
400
|
+
backupListEligible(): Promise<any>;
|
|
401
|
+
backupEnable(siteId: number): Promise<any>;
|
|
402
|
+
backupTrigger(websiteId: number, triggerType?: string): Promise<any>;
|
|
403
|
+
backupCheckTrigger(websiteId: number): Promise<any>;
|
|
404
|
+
backupListBackups(siteId: string): Promise<any>;
|
|
405
|
+
backupGetStatus(options: {
|
|
406
|
+
backupId?: string;
|
|
407
|
+
websiteId?: number;
|
|
408
|
+
}): Promise<any>;
|
|
409
|
+
backupDownload(backupId: string): Promise<any>;
|
|
410
|
+
backupDownloadPrepared(input: {
|
|
411
|
+
siteId: string;
|
|
412
|
+
backupId: string;
|
|
413
|
+
downloadType: string;
|
|
414
|
+
format?: string;
|
|
415
|
+
sanitize?: boolean;
|
|
416
|
+
}): Promise<any>;
|
|
417
|
+
backupSanitizeStatus(jobId: string): Promise<any>;
|
|
418
|
+
backupListPairings(siteId?: number): Promise<any>;
|
|
419
|
+
backupUpdatePairing(siteId: number, pairingConfig: Record<string, any>): Promise<any>;
|
|
420
|
+
backupDeletePairing(siteId: number): Promise<any>;
|
|
421
|
+
kinstaBackupListSites(): Promise<any>;
|
|
422
|
+
kinstaBackupListBackups(siteId: string): Promise<any>;
|
|
423
|
+
kinstaBackupDownload(s3Key: string): Promise<any>;
|
|
424
|
+
cloneToStagingConfirm(productionSiteId: number, stagingSiteId: number): Promise<any>;
|
|
425
|
+
cloneToStaging(params: {
|
|
426
|
+
productionSiteId: number;
|
|
427
|
+
stagingSiteId: number;
|
|
428
|
+
includeFiles?: boolean;
|
|
429
|
+
includeDatabase?: boolean;
|
|
430
|
+
runSearchReplace?: boolean;
|
|
431
|
+
confirmationToken: string;
|
|
432
|
+
backupId?: string;
|
|
433
|
+
}): Promise<any>;
|
|
434
|
+
getCloneStatus(cloneId: string): Promise<any>;
|
|
435
|
+
listCloneOperations(params?: {
|
|
436
|
+
productionSiteId?: number;
|
|
437
|
+
stagingSiteId?: number;
|
|
438
|
+
limit?: number;
|
|
439
|
+
}): Promise<any>;
|
|
440
|
+
getDevEnvironmentInfo(siteId: number): Promise<any>;
|
|
441
|
+
}
|
|
10
442
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,8 @@ const TOOL_PERMISSIONS = {
|
|
|
98
98
|
fcp_trusted_ip_remove_range: 'super_admin',
|
|
99
99
|
fcp_backup_delete_pairing: 'super_admin',
|
|
100
100
|
fcp_filesync_cancel_sync: 'super_admin',
|
|
101
|
+
fcp_unfreeze: 'super_admin', // lifting a freeze releases a held deploy
|
|
102
|
+
fcp_override_merge_window: 'super_admin', // bypasses the deploy-window safety gate
|
|
101
103
|
// --- admin+: mutating ops with real-world side effects ---
|
|
102
104
|
fcp_create_launch: 'admin',
|
|
103
105
|
fcp_update_launch: 'admin',
|
|
@@ -108,6 +110,11 @@ const TOOL_PERMISSIONS = {
|
|
|
108
110
|
fcp_shield_update_domain: 'admin',
|
|
109
111
|
fcp_trusted_ip_add_range: 'admin',
|
|
110
112
|
fcp_trusted_ip_update_range: 'admin',
|
|
113
|
+
fcp_freeze_repo: 'admin',
|
|
114
|
+
fcp_update_freeze: 'admin',
|
|
115
|
+
fcp_scan_certificates: 'admin',
|
|
116
|
+
fcp_spawn_task_job: 'admin',
|
|
117
|
+
fcp_approve_job: 'admin',
|
|
111
118
|
fcp_backup_enable: 'admin',
|
|
112
119
|
fcp_backup_trigger: 'admin',
|
|
113
120
|
fcp_backup_check_trigger: 'admin',
|
|
@@ -157,6 +164,11 @@ const TOOL_PERMISSIONS = {
|
|
|
157
164
|
fcp_shield_get_metrics: 'viewer',
|
|
158
165
|
fcp_trusted_ip_list_ranges: 'viewer',
|
|
159
166
|
fcp_trusted_ip_export: 'viewer',
|
|
167
|
+
fcp_list_freezes: 'viewer',
|
|
168
|
+
fcp_list_certificates: 'viewer',
|
|
169
|
+
fcp_get_certificate: 'viewer',
|
|
170
|
+
fcp_list_jobs: 'viewer',
|
|
171
|
+
fcp_get_job_status: 'viewer',
|
|
160
172
|
fcp_backup_list_sites: 'viewer',
|
|
161
173
|
fcp_backup_get_config: 'viewer',
|
|
162
174
|
fcp_backup_list_eligible: 'viewer',
|
|
@@ -346,7 +358,7 @@ async function initializeProjectDetection() {
|
|
|
346
358
|
}
|
|
347
359
|
}
|
|
348
360
|
// API Client
|
|
349
|
-
class FCPClient {
|
|
361
|
+
export class FCPClient {
|
|
350
362
|
baseUrl;
|
|
351
363
|
token;
|
|
352
364
|
defaultTimeout = 15000; // 15 seconds
|
|
@@ -795,6 +807,109 @@ class FCPClient {
|
|
|
795
807
|
return this.fetchText(`/api/infrastructure/trusted-ips/export${qs ? `?${qs}` : ''}`);
|
|
796
808
|
}
|
|
797
809
|
// ============================================================================
|
|
810
|
+
// Tasker Freeze Management Methods
|
|
811
|
+
// ============================================================================
|
|
812
|
+
async listFreezes() {
|
|
813
|
+
return this.fetch('/api/ticket-workflow/freeze');
|
|
814
|
+
}
|
|
815
|
+
async freezeRepo(input) {
|
|
816
|
+
return this.fetch('/api/ticket-workflow/freeze', {
|
|
817
|
+
method: 'POST',
|
|
818
|
+
body: JSON.stringify(input),
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
async updateFreeze(id, updates) {
|
|
822
|
+
return this.fetch('/api/ticket-workflow/freeze', {
|
|
823
|
+
method: 'PATCH',
|
|
824
|
+
body: JSON.stringify({ id, ...updates }),
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
async unfreeze(input) {
|
|
828
|
+
const hasId = input.id !== undefined && input.id !== null;
|
|
829
|
+
const hasRepo = typeof input.repo === 'string' && input.repo.length > 0;
|
|
830
|
+
if (hasId === hasRepo) {
|
|
831
|
+
throw new Error('unfreeze requires exactly one of "id" or "repo"');
|
|
832
|
+
}
|
|
833
|
+
const body = hasId ? { id: input.id } : { repo: input.repo };
|
|
834
|
+
return this.fetch('/api/ticket-workflow/freeze', {
|
|
835
|
+
method: 'DELETE',
|
|
836
|
+
body: JSON.stringify(body),
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
// ============================================================================
|
|
840
|
+
// Certificate Methods
|
|
841
|
+
// ============================================================================
|
|
842
|
+
async listCertificates(filters) {
|
|
843
|
+
const p = new URLSearchParams();
|
|
844
|
+
if (filters?.status)
|
|
845
|
+
p.append('status', filters.status);
|
|
846
|
+
if (filters?.cluster)
|
|
847
|
+
p.append('cluster', filters.cluster);
|
|
848
|
+
if (filters?.namespace)
|
|
849
|
+
p.append('namespace', filters.namespace);
|
|
850
|
+
if (filters?.certType)
|
|
851
|
+
p.append('certType', filters.certType);
|
|
852
|
+
if (filters?.expiringWithinDays != null)
|
|
853
|
+
p.append('expiringWithinDays', String(filters.expiringWithinDays));
|
|
854
|
+
if (filters?.sortBy)
|
|
855
|
+
p.append('sortBy', filters.sortBy);
|
|
856
|
+
if (filters?.sortDir)
|
|
857
|
+
p.append('sortDir', filters.sortDir);
|
|
858
|
+
if (filters?.page != null)
|
|
859
|
+
p.append('page', String(filters.page));
|
|
860
|
+
if (filters?.limit != null)
|
|
861
|
+
p.append('limit', String(filters.limit));
|
|
862
|
+
const qs = p.toString();
|
|
863
|
+
return this.fetch(`/api/certificates${qs ? `?${qs}` : ''}`);
|
|
864
|
+
}
|
|
865
|
+
async getCertificate(certId) {
|
|
866
|
+
return this.fetch(`/api/certificates/${encodeURIComponent(String(certId))}`);
|
|
867
|
+
}
|
|
868
|
+
async scanCertificates(input) {
|
|
869
|
+
return this.fetch('/api/certificates/scan', {
|
|
870
|
+
method: 'POST',
|
|
871
|
+
body: JSON.stringify(input || {}),
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
// ============================================================================
|
|
875
|
+
// Tasker Job Control Methods
|
|
876
|
+
// ============================================================================
|
|
877
|
+
async spawnTaskJob(input) {
|
|
878
|
+
return this.fetch('/api/ticket-workflow/spawn', {
|
|
879
|
+
method: 'POST',
|
|
880
|
+
body: JSON.stringify(input),
|
|
881
|
+
});
|
|
882
|
+
}
|
|
883
|
+
async getJobStatus(opts) {
|
|
884
|
+
const p = new URLSearchParams();
|
|
885
|
+
if (opts.job_id)
|
|
886
|
+
p.append('job_id', opts.job_id);
|
|
887
|
+
if (opts.task_id)
|
|
888
|
+
p.append('task_id', opts.task_id);
|
|
889
|
+
const qs = p.toString();
|
|
890
|
+
return this.fetch(`/api/ticket-workflow/status${qs ? `?${qs}` : ''}`);
|
|
891
|
+
}
|
|
892
|
+
async listJobs(opts) {
|
|
893
|
+
const qs = opts?.refresh ? '?refresh=true' : '';
|
|
894
|
+
return this.fetch(`/api/ticket-workflow/queue${qs}`);
|
|
895
|
+
}
|
|
896
|
+
async approveJob(id) {
|
|
897
|
+
return this.fetch(`/api/ticket-workflow/jobs/${encodeURIComponent(id)}/approve`, {
|
|
898
|
+
method: 'POST',
|
|
899
|
+
body: JSON.stringify({}),
|
|
900
|
+
});
|
|
901
|
+
}
|
|
902
|
+
async overrideMergeWindow(id, input) {
|
|
903
|
+
const path = `/api/ticket-workflow/jobs/${encodeURIComponent(id)}/override`;
|
|
904
|
+
if (input.action === 'clear') {
|
|
905
|
+
return this.fetch(path, { method: 'DELETE' });
|
|
906
|
+
}
|
|
907
|
+
const body = { reason: input.reason };
|
|
908
|
+
if (input.ttl_minutes != null)
|
|
909
|
+
body.ttl_minutes = input.ttl_minutes;
|
|
910
|
+
return this.fetch(path, { method: 'POST', body: JSON.stringify(body) });
|
|
911
|
+
}
|
|
912
|
+
// ============================================================================
|
|
798
913
|
// Backup Management Methods
|
|
799
914
|
// ============================================================================
|
|
800
915
|
async backupListSites() {
|
|
@@ -3075,6 +3190,153 @@ const TOOLS = [
|
|
|
3075
3190
|
},
|
|
3076
3191
|
},
|
|
3077
3192
|
},
|
|
3193
|
+
{
|
|
3194
|
+
name: 'fcp_list_freezes',
|
|
3195
|
+
description: 'List Tasker auto-merge freezes. Returns frozen_repos (active now), scheduled_repos (future windows), and available_repos (every repo you may freeze, with project keys + domains). A frozen repo has its release/security PRs held from the 6-7 AM MT deployment window. Call this before fcp_freeze_repo to pick a valid repo and avoid duplicate freezes.',
|
|
3196
|
+
inputSchema: {
|
|
3197
|
+
type: 'object',
|
|
3198
|
+
properties: {},
|
|
3199
|
+
},
|
|
3200
|
+
},
|
|
3201
|
+
{
|
|
3202
|
+
name: 'fcp_freeze_repo',
|
|
3203
|
+
description: 'Schedule a Tasker auto-merge freeze for a repo (blocks release-PR auto-promotion + security auto-merge while active). Provide either days (1-90) or an explicit ends_at; starts_at defaults to now and cannot be backdated >5 min. The repo must exist in github_repo_mappings (else 404 \u2014 use fcp_list_freezes available_repos). Appends a new window each call.',
|
|
3204
|
+
inputSchema: {
|
|
3205
|
+
type: 'object',
|
|
3206
|
+
properties: {
|
|
3207
|
+
repo: { type: 'string', description: 'owner/repo, e.g. "fruition/metroairport"' },
|
|
3208
|
+
reason: { type: 'string', description: 'Why the repo is being frozen (required)' },
|
|
3209
|
+
days: { type: 'number', description: 'Freeze length in days (1-90); alternative to ends_at' },
|
|
3210
|
+
starts_at: { type: 'string', description: 'ISO-8601 start (optional; defaults to now, no backdating >5 min)' },
|
|
3211
|
+
ends_at: { type: 'string', description: 'ISO-8601 end (alternative to days)' },
|
|
3212
|
+
},
|
|
3213
|
+
required: ['repo', 'reason'],
|
|
3214
|
+
},
|
|
3215
|
+
},
|
|
3216
|
+
{
|
|
3217
|
+
name: 'fcp_update_freeze',
|
|
3218
|
+
description: 'Edit an existing freeze by id (from fcp_list_freezes). Change the window (starts_at / ends_at, or days as a shorthand for ends_at) and/or the reason. Window rules match fcp_freeze_repo (<=90 days, no backdating >5 min).',
|
|
3219
|
+
inputSchema: {
|
|
3220
|
+
type: 'object',
|
|
3221
|
+
properties: {
|
|
3222
|
+
id: { type: 'number', description: 'Freeze id to edit' },
|
|
3223
|
+
starts_at: { type: 'string', description: 'New ISO-8601 start' },
|
|
3224
|
+
ends_at: { type: 'string', description: 'New ISO-8601 end' },
|
|
3225
|
+
days: { type: 'number', description: 'New length in days (recomputes ends_at from starts_at)' },
|
|
3226
|
+
reason: { type: 'string', description: 'New reason' },
|
|
3227
|
+
},
|
|
3228
|
+
required: ['id'],
|
|
3229
|
+
},
|
|
3230
|
+
},
|
|
3231
|
+
{
|
|
3232
|
+
name: 'fcp_unfreeze',
|
|
3233
|
+
description: 'Remove a Tasker freeze. Pass exactly one of: id (remove that single freeze) or repo (remove ALL active + scheduled freezes for that owner/repo). Lifting a freeze lets a held deploy through, so this is a super_admin action.',
|
|
3234
|
+
inputSchema: {
|
|
3235
|
+
type: 'object',
|
|
3236
|
+
properties: {
|
|
3237
|
+
id: { type: 'number', description: 'Freeze id to remove (single)' },
|
|
3238
|
+
repo: { type: 'string', description: 'owner/repo to clear all active+scheduled freezes for' },
|
|
3239
|
+
},
|
|
3240
|
+
},
|
|
3241
|
+
},
|
|
3242
|
+
// ============================================================================
|
|
3243
|
+
// Certificate Tools
|
|
3244
|
+
// ============================================================================
|
|
3245
|
+
{
|
|
3246
|
+
name: 'fcp_list_certificates',
|
|
3247
|
+
description: 'List TLS certificates across the fleet (cert-monitor). Filter by status (valid|warning|critical|expired), expiringWithinDays, cluster, namespace, certType; sort and paginate. Use to find certs about to expire before a migration/cutover.',
|
|
3248
|
+
inputSchema: {
|
|
3249
|
+
type: 'object',
|
|
3250
|
+
properties: {
|
|
3251
|
+
status: { type: 'string', description: 'valid | warning | critical | expired | unknown' },
|
|
3252
|
+
expiringWithinDays: { type: 'number', description: 'Only certs expiring within N days' },
|
|
3253
|
+
cluster: { type: 'string', description: 'Filter by k8s cluster' },
|
|
3254
|
+
namespace: { type: 'string', description: 'Filter by namespace' },
|
|
3255
|
+
certType: { type: 'string', description: 'Filter by certificate type' },
|
|
3256
|
+
sortBy: { type: 'string', description: 'name | cluster | namespace | certType | status | expiry | subjectCn' },
|
|
3257
|
+
sortDir: { type: 'string', enum: ['asc', 'desc'], description: 'Sort direction (default asc)' },
|
|
3258
|
+
page: { type: 'number', description: 'Page number (1-based)' },
|
|
3259
|
+
limit: { type: 'number', description: 'Page size' },
|
|
3260
|
+
},
|
|
3261
|
+
},
|
|
3262
|
+
},
|
|
3263
|
+
{
|
|
3264
|
+
name: 'fcp_get_certificate',
|
|
3265
|
+
description: 'Get a single certificate by id, including issuer, SANs, expiry, and history.',
|
|
3266
|
+
inputSchema: {
|
|
3267
|
+
type: 'object',
|
|
3268
|
+
properties: { certId: { type: 'string', description: 'Certificate id' } },
|
|
3269
|
+
required: ['certId'],
|
|
3270
|
+
},
|
|
3271
|
+
},
|
|
3272
|
+
{
|
|
3273
|
+
name: 'fcp_scan_certificates',
|
|
3274
|
+
description: 'Trigger a cert-monitor scan run across clusters to refresh certificate inventory and expiry. Pass dryRun=true to compute without persisting.',
|
|
3275
|
+
inputSchema: {
|
|
3276
|
+
type: 'object',
|
|
3277
|
+
properties: { dryRun: { type: 'boolean', description: 'Compute without writing results (default false)' } },
|
|
3278
|
+
},
|
|
3279
|
+
},
|
|
3280
|
+
// ============================================================================
|
|
3281
|
+
// Tasker Job Control Tools
|
|
3282
|
+
// ============================================================================
|
|
3283
|
+
{
|
|
3284
|
+
name: 'fcp_spawn_task_job',
|
|
3285
|
+
description: 'Spawn a Tasker automated code-change job for an Unroo task (Claude Code in K8s -> PR). Requires task_id, task_title, project_key. Rejects if a job is already in progress for the task.',
|
|
3286
|
+
inputSchema: {
|
|
3287
|
+
type: 'object',
|
|
3288
|
+
properties: {
|
|
3289
|
+
task_id: { type: 'string', description: 'Unroo task id' },
|
|
3290
|
+
task_title: { type: 'string', description: 'Task title' },
|
|
3291
|
+
project_key: { type: 'string', description: 'Project key (resolves the repo)' },
|
|
3292
|
+
task_description: { type: 'string', description: 'Optional task description / instructions' },
|
|
3293
|
+
labels: { type: 'array', items: { type: 'string' }, description: 'Optional labels' },
|
|
3294
|
+
},
|
|
3295
|
+
required: ['task_id', 'task_title', 'project_key'],
|
|
3296
|
+
},
|
|
3297
|
+
},
|
|
3298
|
+
{
|
|
3299
|
+
name: 'fcp_get_job_status',
|
|
3300
|
+
description: 'Get Tasker job status. Pass job_id or task_id for a specific job; omit both for all jobs + stats.',
|
|
3301
|
+
inputSchema: {
|
|
3302
|
+
type: 'object',
|
|
3303
|
+
properties: {
|
|
3304
|
+
job_id: { type: 'string', description: 'Tasker job id' },
|
|
3305
|
+
task_id: { type: 'string', description: 'Unroo task id (alternative to job_id)' },
|
|
3306
|
+
},
|
|
3307
|
+
},
|
|
3308
|
+
},
|
|
3309
|
+
{
|
|
3310
|
+
name: 'fcp_list_jobs',
|
|
3311
|
+
description: 'List the current Tasker job queue. Pass refresh=true to re-sync statuses from K8s first.',
|
|
3312
|
+
inputSchema: {
|
|
3313
|
+
type: 'object',
|
|
3314
|
+
properties: { refresh: { type: 'boolean', description: 'Re-sync from K8s before listing (default false)' } },
|
|
3315
|
+
},
|
|
3316
|
+
},
|
|
3317
|
+
{
|
|
3318
|
+
name: 'fcp_approve_job',
|
|
3319
|
+
description: 'Approve the merge for a Tasker job that requires human sign-off (e.g. HIGH/CRITICAL security PRs). The job still respects its deploy window unless overridden.',
|
|
3320
|
+
inputSchema: {
|
|
3321
|
+
type: 'object',
|
|
3322
|
+
properties: { id: { type: 'string', description: 'Tasker job id' } },
|
|
3323
|
+
required: ['id'],
|
|
3324
|
+
},
|
|
3325
|
+
},
|
|
3326
|
+
{
|
|
3327
|
+
name: 'fcp_override_merge_window',
|
|
3328
|
+
description: 'Force-allow a Tasker auto-merge OUTSIDE its configured deploy window (super_admin). action=set grants an override for ttl_minutes (reason required); action=clear cancels it. Bypasses the safety gate \u2014 use deliberately.',
|
|
3329
|
+
inputSchema: {
|
|
3330
|
+
type: 'object',
|
|
3331
|
+
properties: {
|
|
3332
|
+
id: { type: 'string', description: 'Tasker job id' },
|
|
3333
|
+
action: { type: 'string', enum: ['set', 'clear'], description: 'set = grant override, clear = cancel' },
|
|
3334
|
+
reason: { type: 'string', description: 'Justification (required when action=set)' },
|
|
3335
|
+
ttl_minutes: { type: 'number', description: 'How long the override lasts (when action=set)' },
|
|
3336
|
+
},
|
|
3337
|
+
required: ['id', 'action'],
|
|
3338
|
+
},
|
|
3339
|
+
},
|
|
3078
3340
|
// ============================================================================
|
|
3079
3341
|
// Backup Management Tools
|
|
3080
3342
|
// ============================================================================
|
|
@@ -4924,6 +5186,93 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
4924
5186
|
};
|
|
4925
5187
|
}
|
|
4926
5188
|
// ============================================================================
|
|
5189
|
+
// Tasker Freeze Management Handlers
|
|
5190
|
+
// ============================================================================
|
|
5191
|
+
case 'fcp_list_freezes': {
|
|
5192
|
+
const result = await client.listFreezes();
|
|
5193
|
+
return {
|
|
5194
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
5195
|
+
};
|
|
5196
|
+
}
|
|
5197
|
+
case 'fcp_freeze_repo': {
|
|
5198
|
+
const { repo, reason, days, starts_at, ends_at } = args;
|
|
5199
|
+
const result = await client.freezeRepo({ repo, reason, days, starts_at, ends_at });
|
|
5200
|
+
return {
|
|
5201
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
5202
|
+
};
|
|
5203
|
+
}
|
|
5204
|
+
case 'fcp_update_freeze': {
|
|
5205
|
+
const { id, starts_at, ends_at, days, reason } = args;
|
|
5206
|
+
const updates = {};
|
|
5207
|
+
if (starts_at !== undefined)
|
|
5208
|
+
updates.starts_at = starts_at;
|
|
5209
|
+
if (ends_at !== undefined)
|
|
5210
|
+
updates.ends_at = ends_at;
|
|
5211
|
+
if (days !== undefined)
|
|
5212
|
+
updates.days = days;
|
|
5213
|
+
if (reason !== undefined)
|
|
5214
|
+
updates.reason = reason;
|
|
5215
|
+
const result = await client.updateFreeze(id, updates);
|
|
5216
|
+
return {
|
|
5217
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
5218
|
+
};
|
|
5219
|
+
}
|
|
5220
|
+
case 'fcp_unfreeze': {
|
|
5221
|
+
const { id, repo } = args;
|
|
5222
|
+
const result = await client.unfreeze({ id, repo });
|
|
5223
|
+
return {
|
|
5224
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
5225
|
+
};
|
|
5226
|
+
}
|
|
5227
|
+
// ============================================================================
|
|
5228
|
+
// Certificate Handlers
|
|
5229
|
+
// ============================================================================
|
|
5230
|
+
case 'fcp_list_certificates': {
|
|
5231
|
+
const result = await client.listCertificates(args);
|
|
5232
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5233
|
+
}
|
|
5234
|
+
case 'fcp_get_certificate': {
|
|
5235
|
+
const { certId } = args;
|
|
5236
|
+
const result = await client.getCertificate(certId);
|
|
5237
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5238
|
+
}
|
|
5239
|
+
case 'fcp_scan_certificates': {
|
|
5240
|
+
const { dryRun } = args;
|
|
5241
|
+
const result = await client.scanCertificates({ dryRun });
|
|
5242
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5243
|
+
}
|
|
5244
|
+
// ============================================================================
|
|
5245
|
+
// Tasker Job Control Handlers
|
|
5246
|
+
// ============================================================================
|
|
5247
|
+
case 'fcp_spawn_task_job': {
|
|
5248
|
+
const { task_id, task_title, project_key, task_description, labels } = args;
|
|
5249
|
+
const result = await client.spawnTaskJob({ task_id, task_title, project_key, task_description, labels });
|
|
5250
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5251
|
+
}
|
|
5252
|
+
case 'fcp_get_job_status': {
|
|
5253
|
+
const { job_id, task_id } = args;
|
|
5254
|
+
const result = await client.getJobStatus({ job_id, task_id });
|
|
5255
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5256
|
+
}
|
|
5257
|
+
case 'fcp_list_jobs': {
|
|
5258
|
+
const { refresh } = args;
|
|
5259
|
+
const result = await client.listJobs({ refresh });
|
|
5260
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5261
|
+
}
|
|
5262
|
+
case 'fcp_approve_job': {
|
|
5263
|
+
const { id } = args;
|
|
5264
|
+
const result = await client.approveJob(id);
|
|
5265
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5266
|
+
}
|
|
5267
|
+
case 'fcp_override_merge_window': {
|
|
5268
|
+
const { id, action, reason, ttl_minutes } = args;
|
|
5269
|
+
if (action === 'set' && (!reason || !reason.trim())) {
|
|
5270
|
+
throw new Error('fcp_override_merge_window: reason is required when action=set');
|
|
5271
|
+
}
|
|
5272
|
+
const result = await client.overrideMergeWindow(id, { action, reason, ttl_minutes });
|
|
5273
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
5274
|
+
}
|
|
5275
|
+
// ============================================================================
|
|
4927
5276
|
// Backup Management Handlers
|
|
4928
5277
|
// ============================================================================
|
|
4929
5278
|
case 'fcp_backup_list_sites': {
|
|
@@ -5581,7 +5930,7 @@ if (process.argv[2] === 'sync-skills') {
|
|
|
5581
5930
|
process.exit(1);
|
|
5582
5931
|
});
|
|
5583
5932
|
}
|
|
5584
|
-
else {
|
|
5933
|
+
else if (!process.env.VITEST) {
|
|
5585
5934
|
main().catch((error) => {
|
|
5586
5935
|
console.error('Fatal error:', error);
|
|
5587
5936
|
process.exit(1);
|
package/dist/skills-sync.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* - `private: true` in frontmatter also opts out.
|
|
23
23
|
* - Network failures and missing auth never block startup — we log + continue.
|
|
24
24
|
*/
|
|
25
|
+
import { basename } from 'path';
|
|
25
26
|
export interface SkillFrontmatter {
|
|
26
27
|
name?: string;
|
|
27
28
|
description?: string;
|
|
@@ -151,5 +152,5 @@ export declare const __test__: {
|
|
|
151
152
|
detectSecret: typeof detectSecret;
|
|
152
153
|
pushSkipReason: typeof pushSkipReason;
|
|
153
154
|
hashBody: typeof hashBody;
|
|
154
|
-
basename:
|
|
155
|
+
basename: typeof basename;
|
|
155
156
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fruition/fcp-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
4
4
|
"description": "MCP Server for FCP Launch Coordination System - enables Claude Code to interact with FCP launches and track development time",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|