@burdenoff/mcp-libs 2026.908.1 → 2026.928.1

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.
@@ -0,0 +1,2097 @@
1
+ import { mcpToolName, mcpResourceUri, mcpPromptName, errorResult, jsonResult } from '../../chunk-BSNL65PZ.js';
2
+ import { z } from 'zod';
3
+
4
+ // src/modules/fluidgrids/operations.ts
5
+ var LIST_WORKFLOWS = `
6
+ query ListWorkflows($input: ListWorkflowDefinitionsInput!) {
7
+ workflowDefinitions(input: $input) {
8
+ items {
9
+ id
10
+ workflowKey
11
+ name
12
+ description
13
+ version
14
+ status
15
+ category
16
+ tags
17
+ isActive
18
+ totalVersions
19
+ createdAt
20
+ updatedAt
21
+ }
22
+ total
23
+ hasMore
24
+ }
25
+ }
26
+ `;
27
+ var GET_WORKFLOW = `
28
+ query GetWorkflow($id: ID, $workflowKey: String, $version: String) {
29
+ workflowDefinition(id: $id, workflowKey: $workflowKey, version: $version) {
30
+ id
31
+ workflowKey
32
+ name
33
+ description
34
+ version
35
+ status
36
+ category
37
+ tags
38
+ icon
39
+ isActive
40
+ totalVersions
41
+ definitionJson
42
+ createdAt
43
+ updatedAt
44
+ }
45
+ }
46
+ `;
47
+ var GET_WORKFLOW_VERSIONS = `
48
+ query GetWorkflowVersions($workflowKey: String!) {
49
+ workflowVersions(workflowKey: $workflowKey) {
50
+ id
51
+ workflowKey
52
+ name
53
+ description
54
+ version
55
+ status
56
+ category
57
+ tags
58
+ icon
59
+ isActive
60
+ totalVersions
61
+ createdAt
62
+ updatedAt
63
+ }
64
+ }
65
+ `;
66
+ var LIST_RUNS = `
67
+ query ListRuns($input: ListWorkflowRunsInput!) {
68
+ workflowRuns(input: $input) {
69
+ items {
70
+ id
71
+ workflowId
72
+ workflowKey
73
+ version
74
+ status
75
+ startedAt
76
+ completedAt
77
+ duration
78
+ triggeredById
79
+ errorMessage
80
+ errorType
81
+ progress
82
+ totalNodes
83
+ completedNodes
84
+ failedNodes
85
+ }
86
+ total
87
+ hasMore
88
+ }
89
+ }
90
+ `;
91
+ var GET_RUN = `
92
+ query GetRun($id: ID!) {
93
+ workflowRun(id: $id) {
94
+ id
95
+ workflowId
96
+ workflowKey
97
+ version
98
+ status
99
+ startedAt
100
+ completedAt
101
+ duration
102
+ triggeredById
103
+ triggerData
104
+ triggerNodeId
105
+ errorMessage
106
+ errorType
107
+ progress
108
+ totalNodes
109
+ completedNodes
110
+ failedNodes
111
+ skippedNodes
112
+ nodeStates {
113
+ nodeId
114
+ nodeType
115
+ status
116
+ error
117
+ output
118
+ }
119
+ }
120
+ }
121
+ `;
122
+ var GET_RUN_LOGS = `
123
+ query GetRunLogs(
124
+ $runId: ID!
125
+ $nodeId: String
126
+ $minLevel: RunLogLevel
127
+ $limit: Int
128
+ $after: String
129
+ $search: String
130
+ $includeChildRuns: Boolean
131
+ ) {
132
+ workflowRunLogs(
133
+ runId: $runId
134
+ nodeId: $nodeId
135
+ minLevel: $minLevel
136
+ limit: $limit
137
+ after: $after
138
+ search: $search
139
+ includeChildRuns: $includeChildRuns
140
+ ) {
141
+ lines {
142
+ id
143
+ runId
144
+ nodeId
145
+ level
146
+ message
147
+ timestamp
148
+ data
149
+ attempt
150
+ phase
151
+ stream
152
+ truncated
153
+ }
154
+ hasMore
155
+ nextCursor
156
+ limitReached
157
+ }
158
+ }
159
+ `;
160
+ var LIST_NODES = `
161
+ query ListNodes(
162
+ $nodeType: String
163
+ $publishType: PublishType
164
+ $status: NodeConfigStatus
165
+ $pagination: WorkflowPaginationInput
166
+ ) {
167
+ nodeEndpointConfigs(
168
+ nodeType: $nodeType
169
+ publishType: $publishType
170
+ status: $status
171
+ pagination: $pagination
172
+ ) {
173
+ configs {
174
+ id
175
+ nodeType
176
+ nodeVersion
177
+ name
178
+ description
179
+ category
180
+ icon
181
+ logo
182
+ keywords
183
+ kind
184
+ author
185
+ publishType
186
+ status
187
+ isLatest
188
+ endpointUrl
189
+ operations
190
+ supportsAdapterMode
191
+ adapterOutputType
192
+ createdAt
193
+ updatedAt
194
+ }
195
+ pagination {
196
+ total
197
+ limit
198
+ offset
199
+ hasMore
200
+ }
201
+ }
202
+ }
203
+ `;
204
+ var GET_NODE = `
205
+ query GetNode($nodeType: String!, $nodeVersion: String!) {
206
+ nodeEndpointConfig(nodeType: $nodeType, nodeVersion: $nodeVersion) {
207
+ id
208
+ nodeType
209
+ nodeVersion
210
+ name
211
+ description
212
+ category
213
+ icon
214
+ logo
215
+ keywords
216
+ kind
217
+ author
218
+ publishType
219
+ status
220
+ isLatest
221
+ endpointUrl
222
+ operations
223
+ supportsAdapterMode
224
+ adapterOutputType
225
+ createdAt
226
+ updatedAt
227
+ healthCheckUrl
228
+ nodeAdapters
229
+ }
230
+ }
231
+ `;
232
+ var LIST_CREDENTIALS = `
233
+ query ListCredentials($filter: ConnectionFilterInput, $pagination: IntegrationsPaginationInput) {
234
+ getConnections(filter: $filter, pagination: $pagination) {
235
+ items {
236
+ id
237
+ name
238
+ description
239
+ status
240
+ providerId
241
+ provider {
242
+ id
243
+ key
244
+ name
245
+ category
246
+ authType
247
+ icon
248
+ }
249
+ credentialSource
250
+ externalAccountId
251
+ externalAccountName
252
+ externalAccountEmail
253
+ grantedScopes
254
+ lastUsedAt
255
+ lastHealthCheck
256
+ errorMessage
257
+ createdAt
258
+ updatedAt
259
+ }
260
+ total
261
+ hasMore
262
+ }
263
+ }
264
+ `;
265
+ var GET_CREDENTIAL = `
266
+ query GetCredential($id: ID!) {
267
+ getConnection(id: $id) {
268
+ id
269
+ name
270
+ description
271
+ status
272
+ providerId
273
+ provider {
274
+ id
275
+ key
276
+ name
277
+ description
278
+ category
279
+ authType
280
+ configSchema
281
+ availableScopes
282
+ defaultScopes
283
+ icon
284
+ docsUrl
285
+ }
286
+ config
287
+ metadata
288
+ credentialSource
289
+ externalAccountId
290
+ externalAccountName
291
+ externalAccountEmail
292
+ grantedScopes
293
+ lastUsedAt
294
+ lastHealthCheck
295
+ errorMessage
296
+ workspaceId
297
+ createdAt
298
+ updatedAt
299
+ }
300
+ }
301
+ `;
302
+ var LIST_CREDENTIAL_TYPES = `
303
+ query ListCredentialTypes($filter: ProviderFilterInput, $pagination: IntegrationsPaginationInput) {
304
+ getProviders(filter: $filter, pagination: $pagination) {
305
+ items {
306
+ id
307
+ key
308
+ name
309
+ description
310
+ category
311
+ authType
312
+ configSchema
313
+ availableScopes
314
+ defaultScopes
315
+ icon
316
+ docsUrl
317
+ isBuiltIn
318
+ isEnabled
319
+ connectionCount
320
+ }
321
+ total
322
+ hasMore
323
+ }
324
+ }
325
+ `;
326
+ var LIST_WEBHOOKS = `
327
+ query ListWebhooks($status: EventStatus, $workflowKey: String) {
328
+ eventRegistrations(status: $status, workflowKey: $workflowKey) {
329
+ id
330
+ name
331
+ description
332
+ workflowKey
333
+ triggerNodeId
334
+ eventSource
335
+ eventType
336
+ status
337
+ isActive
338
+ webhookUrl
339
+ webhookToken
340
+ validationMethod
341
+ signatureHeader
342
+ apiKeyHeader
343
+ payloadMapping
344
+ config
345
+ tags
346
+ totalTriggers
347
+ successfulTriggers
348
+ failedTriggers
349
+ lastTriggeredAt
350
+ createdAt
351
+ updatedAt
352
+ }
353
+ }
354
+ `;
355
+ var GET_WEBHOOK = `
356
+ query GetWebhook($id: ID!) {
357
+ eventRegistration(id: $id) {
358
+ id
359
+ name
360
+ description
361
+ workflowKey
362
+ triggerNodeId
363
+ eventSource
364
+ eventType
365
+ status
366
+ isActive
367
+ webhookUrl
368
+ webhookToken
369
+ validationMethod
370
+ signatureHeader
371
+ apiKeyHeader
372
+ payloadMapping
373
+ config
374
+ tags
375
+ totalTriggers
376
+ successfulTriggers
377
+ failedTriggers
378
+ lastTriggeredAt
379
+ createdAt
380
+ updatedAt
381
+ projectId
382
+ workspaceId
383
+ createdById
384
+ }
385
+ }
386
+ `;
387
+ var LIST_SCHEDULED_JOBS = `
388
+ query ListScheduledJobs($enabled: Boolean, $workflowKey: String, $pagination: WorkflowPaginationInput) {
389
+ workflowScheduledJobs(enabled: $enabled, workflowKey: $workflowKey, pagination: $pagination) {
390
+ jobs {
391
+ id
392
+ name
393
+ workflowKey
394
+ version
395
+ schedule
396
+ enabled
397
+ nextRun
398
+ lastRun
399
+ config
400
+ createdAt
401
+ updatedAt
402
+ }
403
+ pagination {
404
+ total
405
+ limit
406
+ offset
407
+ hasMore
408
+ }
409
+ }
410
+ }
411
+ `;
412
+ var GET_SCHEDULED_JOB = `
413
+ query GetScheduledJob($jobId: ID!) {
414
+ workflowScheduledJob(jobId: $jobId) {
415
+ id
416
+ name
417
+ workflowKey
418
+ version
419
+ schedule
420
+ enabled
421
+ nextRun
422
+ lastRun
423
+ config
424
+ createdAt
425
+ updatedAt
426
+ workspaceId
427
+ }
428
+ }
429
+ `;
430
+ var GET_DASHBOARD_SUMMARY = `
431
+ query DashboardSummary($projectId: String) {
432
+ dashboardSummary(projectId: $projectId) {
433
+ userId
434
+ username
435
+ workflowsCount
436
+ activeWorkflowsCount
437
+ archivedWorkflowsCount
438
+ runsCountTotal
439
+ runsCompletedCount
440
+ runsFailedCount
441
+ runsCancelledCount
442
+ runsPendingCount
443
+ runsRunningCount
444
+ runsWaitingCount
445
+ runsCompletedLast24h
446
+ runsFailedLast24h
447
+ runsCompletedLast7d
448
+ runsFailedLast7d
449
+ runsCompletedLast30d
450
+ runsFailedLast30d
451
+ totalNodesExecutedCount
452
+ workflowSuccessRate
453
+ avgWorkflowExecutionTimeSeconds
454
+ avgNodeExecutionTimeSeconds
455
+ recentRuns {
456
+ id
457
+ workflowKey
458
+ version
459
+ status
460
+ startedAt
461
+ completedAt
462
+ duration
463
+ }
464
+ recentWorkflows {
465
+ workflowKey
466
+ name
467
+ version
468
+ updatedAt
469
+ }
470
+ nodeUsageStats {
471
+ nodeType
472
+ totalExecutions
473
+ successCount
474
+ failureCount
475
+ avgExecutionTime
476
+ }
477
+ }
478
+ }
479
+ `;
480
+ var GET_USAGE_METRICS = `
481
+ query GetUsageMetrics($input: UsageQueryInput!) {
482
+ usageMetrics(input: $input) {
483
+ period
484
+ workflowMetrics {
485
+ totalRuns
486
+ successfulRuns
487
+ failedRuns
488
+ cancelledRuns
489
+ totalDurationSeconds
490
+ averageDurationSeconds
491
+ minDurationSeconds
492
+ maxDurationSeconds
493
+ medianDurationSeconds
494
+ }
495
+ nodeMetrics {
496
+ totalNodes
497
+ successfulNodes
498
+ failedNodes
499
+ skippedNodes
500
+ totalDurationSeconds
501
+ averageDurationSeconds
502
+ nodeTypeBreakdown
503
+ }
504
+ }
505
+ }
506
+ `;
507
+ var SEARCH = `
508
+ query Search($input: SearchRequestInput!) {
509
+ search(input: $input) {
510
+ query
511
+ results
512
+ entityCounts
513
+ totalResults
514
+ metadata
515
+ }
516
+ }
517
+ `;
518
+ var SEARCH_BY_ENTITY_TYPE = `
519
+ query SearchByEntityType($entityType: String!, $query: String!, $filters: SearchFilterInput, $limit: Int, $offset: Int) {
520
+ searchByEntityType(entityType: $entityType, query: $query, filters: $filters, limit: $limit, offset: $offset) {
521
+ query
522
+ results
523
+ entityCounts
524
+ totalResults
525
+ metadata
526
+ }
527
+ }
528
+ `;
529
+ var GET_SYSTEM_CONFIG = `
530
+ query GetSystemConfig {
531
+ systemConfig {
532
+ version
533
+ revision
534
+ environment
535
+ deploymentType
536
+ hostname
537
+ hostIp
538
+ }
539
+ }
540
+ `;
541
+ var CREATE_WORKFLOW = `
542
+ mutation CreateWorkflow($input: CreateWorkflowDefinitionInput!) {
543
+ createWorkflowDefinition(input: $input) {
544
+ id
545
+ workflowKey
546
+ name
547
+ description
548
+ version
549
+ status
550
+ category
551
+ tags
552
+ icon
553
+ isActive
554
+ totalVersions
555
+ createdAt
556
+ updatedAt
557
+ }
558
+ }
559
+ `;
560
+ var UPDATE_WORKFLOW = `
561
+ mutation UpdateWorkflow($id: ID!, $input: UpdateWorkflowDefinitionInput!) {
562
+ updateWorkflowDefinition(id: $id, input: $input) {
563
+ id
564
+ workflowKey
565
+ name
566
+ description
567
+ version
568
+ status
569
+ category
570
+ tags
571
+ icon
572
+ isActive
573
+ totalVersions
574
+ createdAt
575
+ updatedAt
576
+ }
577
+ }
578
+ `;
579
+ var DELETE_WORKFLOW = `
580
+ mutation DeleteWorkflow($workflowKey: String!, $version: String) {
581
+ deleteWorkflowDefinition(workflowKey: $workflowKey, version: $version)
582
+ }
583
+ `;
584
+ var TRIGGER_WORKFLOW = `
585
+ mutation TriggerWorkflow($input: TriggerWorkflowInput!) {
586
+ triggerWorkflow(input: $input) {
587
+ runId
588
+ status
589
+ workflowKey
590
+ version
591
+ triggerNodeId
592
+ }
593
+ }
594
+ `;
595
+ var PUBLISH_WORKFLOW = `
596
+ mutation PublishWorkflow($id: ID!) {
597
+ publishWorkflow(id: $id) {
598
+ id
599
+ workflowKey
600
+ name
601
+ description
602
+ version
603
+ status
604
+ category
605
+ tags
606
+ icon
607
+ isActive
608
+ totalVersions
609
+ createdAt
610
+ updatedAt
611
+ }
612
+ }
613
+ `;
614
+ var ACTIVATE_WORKFLOW = `
615
+ mutation ActivateWorkflow($id: ID!) {
616
+ activateWorkflowDefinition(id: $id) {
617
+ id
618
+ workflowKey
619
+ name
620
+ description
621
+ version
622
+ status
623
+ category
624
+ tags
625
+ icon
626
+ isActive
627
+ totalVersions
628
+ createdAt
629
+ updatedAt
630
+ }
631
+ }
632
+ `;
633
+ var DEACTIVATE_WORKFLOW = `
634
+ mutation DeactivateWorkflow($id: ID!) {
635
+ deactivateWorkflowDefinition(id: $id) {
636
+ id
637
+ workflowKey
638
+ name
639
+ description
640
+ version
641
+ status
642
+ category
643
+ tags
644
+ icon
645
+ isActive
646
+ totalVersions
647
+ createdAt
648
+ updatedAt
649
+ }
650
+ }
651
+ `;
652
+ var DUPLICATE_WORKFLOW = `
653
+ mutation DuplicateWorkflow($workflowKey: String!, $version: String!, $input: DuplicateWorkflowInput!) {
654
+ duplicateWorkflow(workflowKey: $workflowKey, version: $version, input: $input) {
655
+ success
656
+ message
657
+ workflow {
658
+ id
659
+ workflowKey
660
+ name
661
+ description
662
+ version
663
+ status
664
+ category
665
+ tags
666
+ icon
667
+ isActive
668
+ totalVersions
669
+ createdAt
670
+ updatedAt
671
+ }
672
+ }
673
+ }
674
+ `;
675
+ var ARCHIVE_WORKFLOW = `
676
+ mutation ArchiveWorkflow($id: ID!) {
677
+ archiveWorkflow(id: $id) {
678
+ id
679
+ status
680
+ }
681
+ }
682
+ `;
683
+ var CANCEL_RUN = `
684
+ mutation CancelRun($id: ID!) {
685
+ cancelWorkflowRun(id: $id) {
686
+ id
687
+ status
688
+ completedAt
689
+ errorMessage
690
+ }
691
+ }
692
+ `;
693
+ var PAUSE_RUN = `
694
+ mutation PauseRun($id: ID!) {
695
+ pauseWorkflowRun(id: $id) {
696
+ id
697
+ status
698
+ completedAt
699
+ errorMessage
700
+ }
701
+ }
702
+ `;
703
+ var RESUME_RUN = `
704
+ mutation ResumeRun($id: ID!, $payload: JSON) {
705
+ resumeWorkflowRun(id: $id, payload: $payload) {
706
+ success
707
+ message
708
+ resumedFromNodeId
709
+ run {
710
+ id
711
+ status
712
+ completedAt
713
+ errorMessage
714
+ }
715
+ }
716
+ }
717
+ `;
718
+ var RETRY_RUN = `
719
+ mutation RetryNode($id: ID!, $nodeId: String!) {
720
+ retryNode(id: $id, nodeId: $nodeId) {
721
+ id
722
+ nodeId
723
+ nodeType
724
+ status
725
+ error
726
+ attemptCount
727
+ }
728
+ }
729
+ `;
730
+ var CREATE_CREDENTIAL = `
731
+ mutation CreateCredential($input: CreateConnectionInput!) {
732
+ createConnection(input: $input) {
733
+ id
734
+ name
735
+ description
736
+ status
737
+ providerId
738
+ provider {
739
+ id
740
+ key
741
+ name
742
+ authType
743
+ }
744
+ credentialSource
745
+ createdAt
746
+ }
747
+ }
748
+ `;
749
+ var AUTHENTICATE_CREDENTIAL_API_KEY = `
750
+ mutation AuthenticateCredentialApiKey($input: ApiKeyAuthInput!) {
751
+ authenticateWithApiKey(input: $input) {
752
+ id
753
+ name
754
+ status
755
+ grantedScopes
756
+ externalAccountName
757
+ errorMessage
758
+ updatedAt
759
+ }
760
+ }
761
+ `;
762
+ var AUTHENTICATE_CREDENTIAL_BASIC = `
763
+ mutation AuthenticateCredentialBasic($input: BasicAuthInput!) {
764
+ authenticateWithBasicAuth(input: $input) {
765
+ id
766
+ name
767
+ status
768
+ grantedScopes
769
+ externalAccountName
770
+ errorMessage
771
+ updatedAt
772
+ }
773
+ }
774
+ `;
775
+ var UPDATE_CREDENTIAL = `
776
+ mutation UpdateCredential($id: ID!, $input: UpdateConnectionInput!) {
777
+ updateConnection(id: $id, input: $input) {
778
+ id
779
+ name
780
+ description
781
+ status
782
+ config
783
+ updatedAt
784
+ }
785
+ }
786
+ `;
787
+ var DELETE_CREDENTIAL = `
788
+ mutation DeleteCredential($id: ID!, $deleteVaultSecret: Boolean) {
789
+ deleteConnection(id: $id, deleteVaultSecret: $deleteVaultSecret)
790
+ }
791
+ `;
792
+ var TEST_CREDENTIAL = `
793
+ mutation TestCredential($connectionId: ID!) {
794
+ testConnection(connectionId: $connectionId) {
795
+ success
796
+ message
797
+ latencyMs
798
+ }
799
+ }
800
+ `;
801
+ var CREATE_WEBHOOK = `
802
+ mutation CreateWebhook($input: CreateEventRegistrationInput!) {
803
+ createEventRegistration(input: $input) {
804
+ id
805
+ name
806
+ workflowKey
807
+ triggerNodeId
808
+ isActive
809
+ status
810
+ webhookUrl
811
+ webhookToken
812
+ updatedAt
813
+ createdAt
814
+ }
815
+ }
816
+ `;
817
+ var UPDATE_WEBHOOK = `
818
+ mutation UpdateWebhook($id: ID!, $input: UpdateEventRegistrationInput!) {
819
+ updateEventRegistration(id: $id, input: $input) {
820
+ id
821
+ name
822
+ workflowKey
823
+ triggerNodeId
824
+ isActive
825
+ status
826
+ webhookUrl
827
+ webhookToken
828
+ updatedAt
829
+ }
830
+ }
831
+ `;
832
+ var DELETE_WEBHOOK = `
833
+ mutation DeleteWebhook($id: ID!) {
834
+ deleteEventRegistration(id: $id)
835
+ }
836
+ `;
837
+ var TOGGLE_WEBHOOK = `
838
+ mutation ToggleWebhook($id: ID!, $isActive: Boolean!) {
839
+ toggleEventRegistration(id: $id, isActive: $isActive) {
840
+ id
841
+ name
842
+ workflowKey
843
+ triggerNodeId
844
+ isActive
845
+ status
846
+ webhookUrl
847
+ webhookToken
848
+ updatedAt
849
+ }
850
+ }
851
+ `;
852
+ var CREATE_SCHEDULED_JOB = `
853
+ mutation CreateScheduledJob($input: ScheduledJobInput!) {
854
+ createWorkflowScheduledJob(input: $input) {
855
+ success
856
+ message
857
+ job {
858
+ id
859
+ name
860
+ workflowKey
861
+ version
862
+ schedule
863
+ enabled
864
+ nextRun
865
+ lastRun
866
+ config
867
+ createdAt
868
+ updatedAt
869
+ }
870
+ }
871
+ }
872
+ `;
873
+ var UPDATE_SCHEDULED_JOB = `
874
+ mutation UpdateScheduledJob($jobId: ID!, $input: WorkflowUpdateScheduledJobInput!) {
875
+ updateWorkflowScheduledJob(jobId: $jobId, input: $input) {
876
+ success
877
+ message
878
+ job {
879
+ id
880
+ name
881
+ workflowKey
882
+ version
883
+ schedule
884
+ enabled
885
+ nextRun
886
+ lastRun
887
+ config
888
+ createdAt
889
+ updatedAt
890
+ }
891
+ }
892
+ }
893
+ `;
894
+ var DELETE_SCHEDULED_JOB = `
895
+ mutation DeleteScheduledJob($jobId: ID!) {
896
+ deleteWorkflowScheduledJob(jobId: $jobId) {
897
+ success
898
+ message
899
+ }
900
+ }
901
+ `;
902
+
903
+ // src/modules/fluidgrids/tools/helpers.ts
904
+ function isClientErrorShape(error) {
905
+ return typeof error === "object" && error !== null && "response" in error && "request" in error;
906
+ }
907
+ function safeErrorMessage(error) {
908
+ if (isClientErrorShape(error)) {
909
+ const errors = error.response?.errors;
910
+ if (Array.isArray(errors) && errors.length > 0) {
911
+ const joined = errors.map((e) => e?.message).filter((m) => typeof m === "string" && m.length > 0).join("; ");
912
+ if (joined) return joined;
913
+ }
914
+ const status = error.response?.status;
915
+ return status === void 0 ? "GraphQL request failed" : `GraphQL error (status ${status})`;
916
+ }
917
+ return error instanceof Error ? error.message : String(error);
918
+ }
919
+ async function runTool(ctx, label, run) {
920
+ try {
921
+ return await run();
922
+ } catch (error) {
923
+ const message = safeErrorMessage(error);
924
+ ctx.logger.error(`fluidgrids ${label} failed`, { error: message });
925
+ return errorResult(`Failed (${label}): ${message}`);
926
+ }
927
+ }
928
+ function definedInput(obj) {
929
+ const out = {};
930
+ for (const [key, value] of Object.entries(obj)) {
931
+ if (value !== void 0) out[key] = value;
932
+ }
933
+ return out;
934
+ }
935
+ function workflowPagination(limit, offset) {
936
+ if (limit === void 0 && offset === void 0) return void 0;
937
+ return definedInput({ limit, offset });
938
+ }
939
+
940
+ // src/modules/fluidgrids/tools/credentials.ts
941
+ function pagination(limit, offset) {
942
+ if (limit === void 0 && offset === void 0) return void 0;
943
+ return definedInput({ limit, offset });
944
+ }
945
+ function registerCredentialTools(server, ctx, track) {
946
+ server.registerTool(
947
+ track(mcpToolName(ctx.productName, "credentials_list")),
948
+ {
949
+ title: "List Credentials",
950
+ description: "List stored connections (credentials) available to workflows.",
951
+ annotations: { readOnlyHint: true },
952
+ inputSchema: {
953
+ providerId: z.string().optional().describe("Filter by provider ID"),
954
+ name: z.string().optional().describe("Filter by name"),
955
+ limit: z.number().optional().describe("Max results"),
956
+ offset: z.number().optional().describe("Offset for pagination")
957
+ }
958
+ },
959
+ async ({ providerId, name, limit, offset }) => runTool(ctx, "credentials_list", async () => {
960
+ const filter = definedInput({ providerId, name });
961
+ const data = await ctx.gql.workspace.request(
962
+ LIST_CREDENTIALS,
963
+ {
964
+ filter: Object.keys(filter).length > 0 ? filter : void 0,
965
+ pagination: pagination(limit, offset)
966
+ }
967
+ );
968
+ return jsonResult(data.getConnections);
969
+ })
970
+ );
971
+ server.registerTool(
972
+ track(mcpToolName(ctx.productName, "credentials_get")),
973
+ {
974
+ title: "Get Credential",
975
+ description: "Get one connection by ID. Secret material is never returned.",
976
+ annotations: { readOnlyHint: true },
977
+ inputSchema: { id: z.string().describe("Connection ID") }
978
+ },
979
+ async ({ id }) => runTool(ctx, "credentials_get", async () => {
980
+ const data = await ctx.gql.workspace.request(GET_CREDENTIAL, {
981
+ id
982
+ });
983
+ return jsonResult(data.getConnection);
984
+ })
985
+ );
986
+ server.registerTool(
987
+ track(mcpToolName(ctx.productName, "credentials_list_types")),
988
+ {
989
+ title: "List Credential Types",
990
+ description: "List the providers a connection can be created against.",
991
+ annotations: { readOnlyHint: true },
992
+ inputSchema: {
993
+ name: z.string().optional().describe("Filter by provider name"),
994
+ limit: z.number().optional().describe("Max results"),
995
+ offset: z.number().optional().describe("Offset for pagination")
996
+ }
997
+ },
998
+ async ({ name, limit, offset }) => runTool(ctx, "credentials_list_types", async () => {
999
+ const filter = definedInput({ name });
1000
+ const data = await ctx.gql.workspace.request(
1001
+ LIST_CREDENTIAL_TYPES,
1002
+ {
1003
+ filter: Object.keys(filter).length > 0 ? filter : void 0,
1004
+ pagination: pagination(limit, offset)
1005
+ }
1006
+ );
1007
+ return jsonResult(data.getProviders);
1008
+ })
1009
+ );
1010
+ server.registerTool(
1011
+ track(mcpToolName(ctx.productName, "credentials_create")),
1012
+ {
1013
+ title: "Create Credential",
1014
+ description: "Create a connection against a provider. Secrets go to the vault; pass a reference, never a raw secret in config.",
1015
+ inputSchema: {
1016
+ name: z.string().describe("Connection name"),
1017
+ providerId: z.string().describe("Provider ID"),
1018
+ description: z.string().optional().describe("Description"),
1019
+ config: z.unknown().optional().describe("Non-secret provider config as JSON"),
1020
+ context: z.unknown().optional().describe("Context JSON"),
1021
+ vaultId: z.string().optional().describe("Vault to store secret material in"),
1022
+ credentialSecretId: z.string().optional().describe("Existing vault secret reference"),
1023
+ managedSecretName: z.string().optional().describe("Managed secret name")
1024
+ }
1025
+ },
1026
+ async (args) => runTool(ctx, "credentials_create", async () => {
1027
+ const data = await ctx.gql.workspace.request(
1028
+ CREATE_CREDENTIAL,
1029
+ { input: definedInput({ ...args }) }
1030
+ );
1031
+ return jsonResult(data.createConnection);
1032
+ })
1033
+ );
1034
+ server.registerTool(
1035
+ track(mcpToolName(ctx.productName, "credentials_update")),
1036
+ {
1037
+ title: "Update Credential",
1038
+ description: "Update a connection\u2019s name, description or non-secret config.",
1039
+ inputSchema: {
1040
+ id: z.string().describe("Connection ID"),
1041
+ name: z.string().optional().describe("Name"),
1042
+ description: z.string().optional().describe("Description"),
1043
+ config: z.unknown().optional().describe("Non-secret provider config as JSON")
1044
+ }
1045
+ },
1046
+ async ({ id, ...input }) => runTool(ctx, "credentials_update", async () => {
1047
+ const data = await ctx.gql.workspace.request(
1048
+ UPDATE_CREDENTIAL,
1049
+ { id, input: definedInput(input) }
1050
+ );
1051
+ return jsonResult(data.updateConnection);
1052
+ })
1053
+ );
1054
+ server.registerTool(
1055
+ track(mcpToolName(ctx.productName, "credentials_delete")),
1056
+ {
1057
+ title: "Delete Credential",
1058
+ description: "Delete a connection. Set deleteVaultSecret to also destroy the stored secret \u2014 that is irreversible.",
1059
+ annotations: { destructiveHint: true },
1060
+ inputSchema: {
1061
+ id: z.string().describe("Connection ID"),
1062
+ deleteVaultSecret: z.boolean().optional().describe("Also delete the vault secret")
1063
+ }
1064
+ },
1065
+ async ({ id, deleteVaultSecret }) => runTool(ctx, "credentials_delete", async () => {
1066
+ const data = await ctx.gql.workspace.request(
1067
+ DELETE_CREDENTIAL,
1068
+ { id, deleteVaultSecret }
1069
+ );
1070
+ return jsonResult(data.deleteConnection);
1071
+ })
1072
+ );
1073
+ server.registerTool(
1074
+ track(mcpToolName(ctx.productName, "credentials_test")),
1075
+ {
1076
+ title: "Test Credential",
1077
+ description: "Verify a connection can authenticate against its provider.",
1078
+ annotations: { readOnlyHint: true },
1079
+ inputSchema: { connectionId: z.string().describe("Connection ID") }
1080
+ },
1081
+ async ({ connectionId }) => runTool(ctx, "credentials_test", async () => {
1082
+ const data = await ctx.gql.workspace.request(TEST_CREDENTIAL, {
1083
+ connectionId
1084
+ });
1085
+ return jsonResult(data.testConnection);
1086
+ })
1087
+ );
1088
+ server.registerTool(
1089
+ track(mcpToolName(ctx.productName, "credentials_auth_api_key")),
1090
+ {
1091
+ title: "Authenticate Credential (API key)",
1092
+ description: "Attach an API key to a connection via the API-key auth flow.",
1093
+ inputSchema: {
1094
+ connectionId: z.string().describe("Connection ID"),
1095
+ apiKey: z.string().describe("API key to store")
1096
+ }
1097
+ },
1098
+ async ({ connectionId, apiKey }) => runTool(ctx, "credentials_auth_api_key", async () => {
1099
+ const data = await ctx.gql.workspace.request(
1100
+ AUTHENTICATE_CREDENTIAL_API_KEY,
1101
+ { input: { connectionId, apiKey } }
1102
+ );
1103
+ return jsonResult(data.authenticateWithApiKey);
1104
+ })
1105
+ );
1106
+ server.registerTool(
1107
+ track(mcpToolName(ctx.productName, "credentials_auth_basic")),
1108
+ {
1109
+ title: "Authenticate Credential (basic)",
1110
+ description: "Attach basic-auth credentials to a connection.",
1111
+ inputSchema: {
1112
+ connectionId: z.string().describe("Connection ID"),
1113
+ username: z.string().describe("Username"),
1114
+ password: z.string().describe("Password")
1115
+ }
1116
+ },
1117
+ async ({ connectionId, username, password }) => runTool(ctx, "credentials_auth_basic", async () => {
1118
+ const data = await ctx.gql.workspace.request(
1119
+ AUTHENTICATE_CREDENTIAL_BASIC,
1120
+ { input: { connectionId, username, password } }
1121
+ );
1122
+ return jsonResult(data.authenticateWithBasicAuth);
1123
+ })
1124
+ );
1125
+ }
1126
+ function registerInsightTools(server, ctx, track) {
1127
+ server.registerTool(
1128
+ track(mcpToolName(ctx.productName, "dashboard_summary")),
1129
+ {
1130
+ title: "Dashboard Summary",
1131
+ description: "Workflow, run and failure counters for the current workspace.",
1132
+ annotations: { readOnlyHint: true },
1133
+ inputSchema: { projectId: z.string().optional().describe("Scope to one project") }
1134
+ },
1135
+ async ({ projectId }) => runTool(ctx, "dashboard_summary", async () => {
1136
+ const data = await ctx.gql.workspace.request(
1137
+ GET_DASHBOARD_SUMMARY,
1138
+ { projectId }
1139
+ );
1140
+ return jsonResult(data.dashboardSummary);
1141
+ })
1142
+ );
1143
+ server.registerTool(
1144
+ track(mcpToolName(ctx.productName, "usage_metrics")),
1145
+ {
1146
+ title: "Usage Metrics",
1147
+ description: "Usage metrics over a date range \u2014 run minutes and execution counts.",
1148
+ annotations: { readOnlyHint: true },
1149
+ inputSchema: {
1150
+ startDate: z.string().describe("ISO 8601 start of the range"),
1151
+ endDate: z.string().describe("ISO 8601 end of the range"),
1152
+ userId: z.string().optional().describe("Scope to one user"),
1153
+ contextFilter: z.unknown().optional().describe("Context filter as JSON")
1154
+ }
1155
+ },
1156
+ async (args) => runTool(ctx, "usage_metrics", async () => {
1157
+ const data = await ctx.gql.workspace.request(GET_USAGE_METRICS, {
1158
+ input: definedInput({ ...args })
1159
+ });
1160
+ return jsonResult(data.usageMetrics);
1161
+ })
1162
+ );
1163
+ server.registerTool(
1164
+ track(mcpToolName(ctx.productName, "search")),
1165
+ {
1166
+ title: "Search",
1167
+ description: "Search across FluidGrids entities. Narrow with entityTypes when you know it.",
1168
+ annotations: { readOnlyHint: true },
1169
+ inputSchema: {
1170
+ query: z.string().describe("Search query"),
1171
+ entityTypes: z.array(z.string()).optional().describe("Restrict to these entity types"),
1172
+ filters: z.unknown().optional().describe("Additional filters as JSON"),
1173
+ highlight: z.boolean().optional().describe("Return highlighted snippets"),
1174
+ limit: z.number().optional().describe("Max results"),
1175
+ offset: z.number().optional().describe("Offset for pagination")
1176
+ }
1177
+ },
1178
+ async (args) => runTool(ctx, "search", async () => {
1179
+ const data = await ctx.gql.workspace.request(SEARCH, {
1180
+ input: definedInput({ ...args })
1181
+ });
1182
+ return jsonResult(data.search);
1183
+ })
1184
+ );
1185
+ server.registerTool(
1186
+ track(mcpToolName(ctx.productName, "search_by_entity_type")),
1187
+ {
1188
+ title: "Search By Entity Type",
1189
+ description: "Search within a single entity type.",
1190
+ annotations: { readOnlyHint: true },
1191
+ inputSchema: {
1192
+ entityType: z.string().describe("Entity type to search"),
1193
+ query: z.string().describe("Search query"),
1194
+ filters: z.unknown().optional().describe("Additional filters as JSON"),
1195
+ limit: z.number().optional().describe("Max results"),
1196
+ offset: z.number().optional().describe("Offset for pagination")
1197
+ }
1198
+ },
1199
+ async (args) => runTool(ctx, "search_by_entity_type", async () => {
1200
+ const data = await ctx.gql.workspace.request(
1201
+ SEARCH_BY_ENTITY_TYPE,
1202
+ definedInput({ ...args })
1203
+ );
1204
+ return jsonResult(data.searchByEntityType);
1205
+ })
1206
+ );
1207
+ server.registerTool(
1208
+ track(mcpToolName(ctx.productName, "system_config")),
1209
+ {
1210
+ title: "System Config",
1211
+ description: "Read the workflow engine\u2019s effective system configuration.",
1212
+ annotations: { readOnlyHint: true },
1213
+ inputSchema: {}
1214
+ },
1215
+ async () => runTool(ctx, "system_config", async () => {
1216
+ const data = await ctx.gql.workspace.request(GET_SYSTEM_CONFIG);
1217
+ return jsonResult(data.systemConfig);
1218
+ })
1219
+ );
1220
+ }
1221
+ var PublishTypeEnum = z.enum(["BUILTIN", "CUSTOM", "STORE"]);
1222
+ var NodeConfigStatusEnum = z.enum(["AVAILABLE", "DEPRECATED", "DISABLED"]);
1223
+ function registerNodeTools(server, ctx, track) {
1224
+ server.registerTool(
1225
+ track(mcpToolName(ctx.productName, "nodes_list")),
1226
+ {
1227
+ title: "List Nodes",
1228
+ description: "List the node types available to build workflows with, from the node endpoint config registry.",
1229
+ annotations: { readOnlyHint: true },
1230
+ inputSchema: {
1231
+ nodeType: z.string().optional().describe("Filter by node type"),
1232
+ publishType: PublishTypeEnum.optional().describe("BUILTIN, CUSTOM or STORE"),
1233
+ status: NodeConfigStatusEnum.optional().describe("Filter by availability"),
1234
+ limit: z.number().optional().describe("Max results"),
1235
+ offset: z.number().optional().describe("Offset for pagination")
1236
+ }
1237
+ },
1238
+ async ({ nodeType, publishType, status, limit, offset }) => runTool(ctx, "nodes_list", async () => {
1239
+ const data = await ctx.gql.workspace.request(LIST_NODES, {
1240
+ nodeType,
1241
+ publishType,
1242
+ status,
1243
+ pagination: workflowPagination(limit, offset)
1244
+ });
1245
+ return jsonResult(data.nodeEndpointConfigs);
1246
+ })
1247
+ );
1248
+ server.registerTool(
1249
+ track(mcpToolName(ctx.productName, "nodes_get")),
1250
+ {
1251
+ title: "Get Node",
1252
+ description: "Get one node type at a specific version, including its input fields and operations.",
1253
+ annotations: { readOnlyHint: true },
1254
+ inputSchema: {
1255
+ nodeType: z.string().describe("Node type identifier"),
1256
+ nodeVersion: z.string().describe("Node version")
1257
+ }
1258
+ },
1259
+ async ({ nodeType, nodeVersion }) => runTool(ctx, "nodes_get", async () => {
1260
+ const data = await ctx.gql.workspace.request(GET_NODE, {
1261
+ nodeType,
1262
+ nodeVersion
1263
+ });
1264
+ return jsonResult(data.nodeEndpointConfig);
1265
+ })
1266
+ );
1267
+ }
1268
+ var RunStatusEnum = z.enum([
1269
+ "CANCELLED",
1270
+ "COMPLETED",
1271
+ "FAILED",
1272
+ "PENDING",
1273
+ "RUNNING",
1274
+ "TERMINATED",
1275
+ "WAITING"
1276
+ ]);
1277
+ var RunLogLevelEnum = z.enum(["DEBUG", "ERROR", "INFO", "WARN"]);
1278
+ function registerRunTools(server, ctx, track) {
1279
+ server.registerTool(
1280
+ track(mcpToolName(ctx.productName, "runs_list")),
1281
+ {
1282
+ title: "List Runs",
1283
+ description: "List workflow runs, optionally filtered by workflowKey and status.",
1284
+ annotations: { readOnlyHint: true },
1285
+ inputSchema: {
1286
+ workflowKey: z.string().optional().describe("Filter by workflow key"),
1287
+ status: RunStatusEnum.optional().describe("Filter by run status"),
1288
+ limit: z.number().optional().describe("Max results (default 10)"),
1289
+ offset: z.number().optional().describe("Offset for pagination (default 0)")
1290
+ }
1291
+ },
1292
+ async ({ workflowKey, status, limit, offset }) => runTool(ctx, "runs_list", async () => {
1293
+ const data = await ctx.gql.workspace.request(LIST_RUNS, {
1294
+ input: definedInput({ workflowKey, status, limit, offset })
1295
+ });
1296
+ return jsonResult(data.workflowRuns);
1297
+ })
1298
+ );
1299
+ server.registerTool(
1300
+ track(mcpToolName(ctx.productName, "runs_get")),
1301
+ {
1302
+ title: "Get Run",
1303
+ description: "Get one workflow run, including per-node state. Poll this to follow a run to a terminal status.",
1304
+ annotations: { readOnlyHint: true },
1305
+ inputSchema: { id: z.string().describe("Run ID") }
1306
+ },
1307
+ async ({ id }) => runTool(ctx, "runs_get", async () => {
1308
+ const data = await ctx.gql.workspace.request(GET_RUN, { id });
1309
+ return jsonResult(data.workflowRun);
1310
+ })
1311
+ );
1312
+ server.registerTool(
1313
+ track(mcpToolName(ctx.productName, "runs_logs")),
1314
+ {
1315
+ title: "Get Run Logs",
1316
+ description: "Read a run log, newest page first. Keyset paginated: pass the previous page cursor as `after`.",
1317
+ annotations: { readOnlyHint: true },
1318
+ inputSchema: {
1319
+ runId: z.string().describe("Run ID"),
1320
+ nodeId: z.string().optional().describe("Restrict to one node"),
1321
+ minLevel: RunLogLevelEnum.optional().describe("Minimum log level"),
1322
+ limit: z.number().optional().describe("Max log lines"),
1323
+ after: z.string().optional().describe("Keyset cursor from a previous page"),
1324
+ search: z.string().optional().describe("Substring filter"),
1325
+ includeChildRuns: z.boolean().optional().describe("Include logs from child runs")
1326
+ }
1327
+ },
1328
+ async (args) => runTool(ctx, "runs_logs", async () => {
1329
+ const data = await ctx.gql.workspace.request(
1330
+ GET_RUN_LOGS,
1331
+ definedInput({ ...args })
1332
+ );
1333
+ return jsonResult(data.workflowRunLogs);
1334
+ })
1335
+ );
1336
+ server.registerTool(
1337
+ track(mcpToolName(ctx.productName, "runs_cancel")),
1338
+ {
1339
+ title: "Cancel Run",
1340
+ description: "Cancel an in-flight run. Terminal runs cannot be cancelled.",
1341
+ annotations: { destructiveHint: true },
1342
+ inputSchema: { id: z.string().describe("Run ID") }
1343
+ },
1344
+ async ({ id }) => runTool(ctx, "runs_cancel", async () => {
1345
+ const data = await ctx.gql.workspace.request(CANCEL_RUN, {
1346
+ id
1347
+ });
1348
+ return jsonResult(data.cancelWorkflowRun);
1349
+ })
1350
+ );
1351
+ server.registerTool(
1352
+ track(mcpToolName(ctx.productName, "runs_pause")),
1353
+ {
1354
+ title: "Pause Run",
1355
+ description: "Pause a running workflow run.",
1356
+ inputSchema: { id: z.string().describe("Run ID") }
1357
+ },
1358
+ async ({ id }) => runTool(ctx, "runs_pause", async () => {
1359
+ const data = await ctx.gql.workspace.request(PAUSE_RUN, {
1360
+ id
1361
+ });
1362
+ return jsonResult(data.pauseWorkflowRun);
1363
+ })
1364
+ );
1365
+ server.registerTool(
1366
+ track(mcpToolName(ctx.productName, "runs_resume")),
1367
+ {
1368
+ title: "Resume Run",
1369
+ description: "Resume a paused or waiting run. `payload` supplies the data a Wait node is blocked on.",
1370
+ inputSchema: {
1371
+ id: z.string().describe("Run ID"),
1372
+ payload: z.unknown().optional().describe("Payload to resume with")
1373
+ }
1374
+ },
1375
+ async ({ id, payload }) => runTool(ctx, "runs_resume", async () => {
1376
+ const data = await ctx.gql.workspace.request(RESUME_RUN, {
1377
+ id,
1378
+ payload
1379
+ });
1380
+ return jsonResult(data.resumeWorkflowRun);
1381
+ })
1382
+ );
1383
+ server.registerTool(
1384
+ track(mcpToolName(ctx.productName, "runs_retry_node")),
1385
+ {
1386
+ title: "Retry Node",
1387
+ description: "Re-execute one failed node within a run, continuing from there.",
1388
+ inputSchema: {
1389
+ id: z.string().describe("Run ID"),
1390
+ nodeId: z.string().describe("Node ID to retry")
1391
+ }
1392
+ },
1393
+ async ({ id, nodeId }) => runTool(ctx, "runs_retry_node", async () => {
1394
+ const data = await ctx.gql.workspace.request(RETRY_RUN, {
1395
+ id,
1396
+ nodeId
1397
+ });
1398
+ return jsonResult(data.retryNode);
1399
+ })
1400
+ );
1401
+ }
1402
+ function registerScheduledJobTools(server, ctx, track) {
1403
+ server.registerTool(
1404
+ track(mcpToolName(ctx.productName, "scheduled_jobs_list")),
1405
+ {
1406
+ title: "List Scheduled Jobs",
1407
+ description: "List schedules that trigger workflows on a cron or interval.",
1408
+ annotations: { readOnlyHint: true },
1409
+ inputSchema: {
1410
+ enabled: z.boolean().optional().describe("Filter by enabled state"),
1411
+ workflowKey: z.string().optional().describe("Filter by workflow key"),
1412
+ limit: z.number().optional().describe("Max results"),
1413
+ offset: z.number().optional().describe("Offset for pagination")
1414
+ }
1415
+ },
1416
+ async ({ enabled, workflowKey, limit, offset }) => runTool(ctx, "scheduled_jobs_list", async () => {
1417
+ const data = await ctx.gql.workspace.request(
1418
+ LIST_SCHEDULED_JOBS,
1419
+ { enabled, workflowKey, pagination: workflowPagination(limit, offset) }
1420
+ );
1421
+ return jsonResult(data.workflowScheduledJobs);
1422
+ })
1423
+ );
1424
+ server.registerTool(
1425
+ track(mcpToolName(ctx.productName, "scheduled_jobs_get")),
1426
+ {
1427
+ title: "Get Scheduled Job",
1428
+ description: "Get one scheduled job by ID.",
1429
+ annotations: { readOnlyHint: true },
1430
+ inputSchema: { jobId: z.string().describe("Scheduled job ID") }
1431
+ },
1432
+ async ({ jobId }) => runTool(ctx, "scheduled_jobs_get", async () => {
1433
+ const data = await ctx.gql.workspace.request(
1434
+ GET_SCHEDULED_JOB,
1435
+ { jobId }
1436
+ );
1437
+ return jsonResult(data.workflowScheduledJob);
1438
+ })
1439
+ );
1440
+ server.registerTool(
1441
+ track(mcpToolName(ctx.productName, "scheduled_jobs_create")),
1442
+ {
1443
+ title: "Create Scheduled Job",
1444
+ description: "Schedule a workflow. `schedule` is the cron or interval expression the scheduler service evaluates.",
1445
+ inputSchema: {
1446
+ name: z.string().describe("Job name"),
1447
+ workflowKey: z.string().describe("Workflow key to run"),
1448
+ version: z.string().describe("Workflow version"),
1449
+ schedule: z.string().describe("Cron or interval expression"),
1450
+ enabled: z.boolean().optional().describe("Start enabled (default true)"),
1451
+ config: z.unknown().optional().describe("Job config as JSON")
1452
+ }
1453
+ },
1454
+ async (args) => runTool(ctx, "scheduled_jobs_create", async () => {
1455
+ const data = await ctx.gql.workspace.request(
1456
+ CREATE_SCHEDULED_JOB,
1457
+ { input: definedInput({ ...args }) }
1458
+ );
1459
+ return jsonResult(data.createWorkflowScheduledJob);
1460
+ })
1461
+ );
1462
+ server.registerTool(
1463
+ track(mcpToolName(ctx.productName, "scheduled_jobs_update")),
1464
+ {
1465
+ title: "Update Scheduled Job",
1466
+ description: "Update a scheduled job\u2019s name, schedule, config or enabled state.",
1467
+ inputSchema: {
1468
+ jobId: z.string().describe("Scheduled job ID"),
1469
+ name: z.string().optional().describe("Name"),
1470
+ schedule: z.string().optional().describe("Cron or interval expression"),
1471
+ enabled: z.boolean().optional().describe("Enabled state"),
1472
+ config: z.unknown().optional().describe("Job config as JSON")
1473
+ }
1474
+ },
1475
+ async ({ jobId, ...input }) => runTool(ctx, "scheduled_jobs_update", async () => {
1476
+ const data = await ctx.gql.workspace.request(
1477
+ UPDATE_SCHEDULED_JOB,
1478
+ { jobId, input: definedInput(input) }
1479
+ );
1480
+ return jsonResult(data.updateWorkflowScheduledJob);
1481
+ })
1482
+ );
1483
+ server.registerTool(
1484
+ track(mcpToolName(ctx.productName, "scheduled_jobs_delete")),
1485
+ {
1486
+ title: "Delete Scheduled Job",
1487
+ description: "Delete a scheduled job permanently.",
1488
+ annotations: { destructiveHint: true },
1489
+ inputSchema: { jobId: z.string().describe("Scheduled job ID") }
1490
+ },
1491
+ async ({ jobId }) => runTool(ctx, "scheduled_jobs_delete", async () => {
1492
+ const data = await ctx.gql.workspace.request(
1493
+ DELETE_SCHEDULED_JOB,
1494
+ { jobId }
1495
+ );
1496
+ return jsonResult(data.deleteWorkflowScheduledJob);
1497
+ })
1498
+ );
1499
+ }
1500
+ var EventStatusEnum = z.enum(["ACTIVE", "ARCHIVED", "DISABLED", "PAUSED"]);
1501
+ function registerWebhookTools(server, ctx, track) {
1502
+ server.registerTool(
1503
+ track(mcpToolName(ctx.productName, "webhooks_list")),
1504
+ {
1505
+ title: "List Webhooks",
1506
+ description: "List event registrations (webhooks) that can trigger workflows.",
1507
+ annotations: { readOnlyHint: true },
1508
+ inputSchema: {
1509
+ status: EventStatusEnum.optional().describe("Filter by status"),
1510
+ workflowKey: z.string().optional().describe("Filter by workflow key")
1511
+ }
1512
+ },
1513
+ async ({ status, workflowKey }) => runTool(ctx, "webhooks_list", async () => {
1514
+ const data = await ctx.gql.workspace.request(
1515
+ LIST_WEBHOOKS,
1516
+ { status, workflowKey }
1517
+ );
1518
+ return jsonResult(data.eventRegistrations);
1519
+ })
1520
+ );
1521
+ server.registerTool(
1522
+ track(mcpToolName(ctx.productName, "webhooks_get")),
1523
+ {
1524
+ title: "Get Webhook",
1525
+ description: "Get one event registration by ID.",
1526
+ annotations: { readOnlyHint: true },
1527
+ inputSchema: { id: z.string().describe("Event registration ID") }
1528
+ },
1529
+ async ({ id }) => runTool(ctx, "webhooks_get", async () => {
1530
+ const data = await ctx.gql.workspace.request(GET_WEBHOOK, {
1531
+ id
1532
+ });
1533
+ return jsonResult(data.eventRegistration);
1534
+ })
1535
+ );
1536
+ server.registerTool(
1537
+ track(mcpToolName(ctx.productName, "webhooks_create")),
1538
+ {
1539
+ title: "Create Webhook",
1540
+ description: "Register an event source that triggers a workflow. triggerNodeId names the trigger node the event enters at.",
1541
+ inputSchema: {
1542
+ name: z.string().describe("Registration name"),
1543
+ workflowKey: z.string().describe("Workflow key to trigger"),
1544
+ triggerNodeId: z.string().describe("Trigger node ID"),
1545
+ eventSource: z.string().optional().describe("Event source identifier"),
1546
+ eventType: z.string().optional().describe("Event type"),
1547
+ description: z.string().optional().describe("Description"),
1548
+ config: z.unknown().optional().describe("Source-specific config as JSON"),
1549
+ payloadMapping: z.unknown().optional().describe("Payload mapping as JSON"),
1550
+ validationMethod: z.string().optional().describe("Signature validation method"),
1551
+ signatureHeader: z.string().optional().describe("Header carrying the signature"),
1552
+ apiKeyHeader: z.string().optional().describe("Header carrying the API key"),
1553
+ secretToken: z.string().optional().describe("Shared secret for validation"),
1554
+ projectId: z.string().optional().describe("Owning project ID"),
1555
+ tags: z.array(z.string()).optional().describe("Tags")
1556
+ }
1557
+ },
1558
+ async (args) => runTool(ctx, "webhooks_create", async () => {
1559
+ const data = await ctx.gql.workspace.request(
1560
+ CREATE_WEBHOOK,
1561
+ { input: definedInput({ ...args }) }
1562
+ );
1563
+ return jsonResult(data.createEventRegistration);
1564
+ })
1565
+ );
1566
+ server.registerTool(
1567
+ track(mcpToolName(ctx.productName, "webhooks_update")),
1568
+ {
1569
+ title: "Update Webhook",
1570
+ description: "Update an event registration.",
1571
+ inputSchema: {
1572
+ id: z.string().describe("Event registration ID"),
1573
+ name: z.string().optional().describe("Name"),
1574
+ description: z.string().optional().describe("Description"),
1575
+ status: EventStatusEnum.optional().describe("Status"),
1576
+ isActive: z.boolean().optional().describe("Active flag"),
1577
+ config: z.unknown().optional().describe("Config as JSON"),
1578
+ payloadMapping: z.unknown().optional().describe("Payload mapping as JSON"),
1579
+ validationMethod: z.string().optional().describe("Signature validation method"),
1580
+ secretToken: z.string().optional().describe("Shared secret"),
1581
+ tags: z.array(z.string()).optional().describe("Tags")
1582
+ }
1583
+ },
1584
+ async ({ id, ...input }) => runTool(ctx, "webhooks_update", async () => {
1585
+ const data = await ctx.gql.workspace.request(
1586
+ UPDATE_WEBHOOK,
1587
+ { id, input: definedInput(input) }
1588
+ );
1589
+ return jsonResult(data.updateEventRegistration);
1590
+ })
1591
+ );
1592
+ server.registerTool(
1593
+ track(mcpToolName(ctx.productName, "webhooks_toggle")),
1594
+ {
1595
+ title: "Toggle Webhook",
1596
+ description: "Enable or disable an event registration without deleting it.",
1597
+ inputSchema: {
1598
+ id: z.string().describe("Event registration ID"),
1599
+ isActive: z.boolean().describe("True to enable, false to disable")
1600
+ }
1601
+ },
1602
+ async ({ id, isActive }) => runTool(ctx, "webhooks_toggle", async () => {
1603
+ const data = await ctx.gql.workspace.request(
1604
+ TOGGLE_WEBHOOK,
1605
+ { id, isActive }
1606
+ );
1607
+ return jsonResult(data.toggleEventRegistration);
1608
+ })
1609
+ );
1610
+ server.registerTool(
1611
+ track(mcpToolName(ctx.productName, "webhooks_delete")),
1612
+ {
1613
+ title: "Delete Webhook",
1614
+ description: "Delete an event registration permanently.",
1615
+ annotations: { destructiveHint: true },
1616
+ inputSchema: { id: z.string().describe("Event registration ID") }
1617
+ },
1618
+ async ({ id }) => runTool(ctx, "webhooks_delete", async () => {
1619
+ const data = await ctx.gql.workspace.request(
1620
+ DELETE_WEBHOOK,
1621
+ { id }
1622
+ );
1623
+ return jsonResult(data.deleteEventRegistration);
1624
+ })
1625
+ );
1626
+ }
1627
+ var WorkflowStatusEnum = z.enum(["ACTIVE", "ARCHIVED", "DEPRECATED", "DRAFT"]);
1628
+ function registerWorkflowTools(server, ctx, track) {
1629
+ server.registerTool(
1630
+ track(mcpToolName(ctx.productName, "workflows_list")),
1631
+ {
1632
+ title: "List Workflows",
1633
+ description: "List FluidGrids workflow definitions with optional filters and pagination. Use latestOnly to collapse a workflowKey to its newest version.",
1634
+ annotations: { readOnlyHint: true },
1635
+ inputSchema: {
1636
+ status: WorkflowStatusEnum.optional().describe("Filter by workflow status"),
1637
+ category: z.string().optional().describe("Filter by category"),
1638
+ tags: z.array(z.string()).optional().describe("Filter by tags"),
1639
+ latestOnly: z.boolean().optional().describe("Return only the latest version per workflowKey"),
1640
+ limit: z.number().optional().describe("Max results (default 10)"),
1641
+ offset: z.number().optional().describe("Offset for pagination (default 0)")
1642
+ }
1643
+ },
1644
+ async ({ status, category, tags, latestOnly, limit, offset }) => runTool(ctx, "workflows_list", async () => {
1645
+ const data = await ctx.gql.workspace.request(
1646
+ LIST_WORKFLOWS,
1647
+ { input: definedInput({ status, category, tags, latestOnly, limit, offset }) }
1648
+ );
1649
+ return jsonResult(data.workflowDefinitions);
1650
+ })
1651
+ );
1652
+ server.registerTool(
1653
+ track(mcpToolName(ctx.productName, "workflows_get")),
1654
+ {
1655
+ title: "Get Workflow",
1656
+ description: "Get a single workflow definition by id, or by workflowKey (optionally pinned to a version). Without a version the executable version is resolved.",
1657
+ annotations: { readOnlyHint: true },
1658
+ inputSchema: {
1659
+ id: z.string().optional().describe("Workflow definition ID"),
1660
+ workflowKey: z.string().optional().describe("Workflow key (alternative to id)"),
1661
+ version: z.string().optional().describe("Pin to a specific version")
1662
+ }
1663
+ },
1664
+ async ({ id, workflowKey, version }) => runTool(ctx, "workflows_get", async () => {
1665
+ const data = await ctx.gql.workspace.request(
1666
+ GET_WORKFLOW,
1667
+ {
1668
+ id,
1669
+ workflowKey,
1670
+ version
1671
+ }
1672
+ );
1673
+ return jsonResult(data.workflowDefinition);
1674
+ })
1675
+ );
1676
+ server.registerTool(
1677
+ track(mcpToolName(ctx.productName, "workflows_versions")),
1678
+ {
1679
+ title: "List Workflow Versions",
1680
+ description: "List every stored version of one workflowKey.",
1681
+ annotations: { readOnlyHint: true },
1682
+ inputSchema: { workflowKey: z.string().describe("Workflow key") }
1683
+ },
1684
+ async ({ workflowKey }) => runTool(ctx, "workflows_versions", async () => {
1685
+ const data = await ctx.gql.workspace.request(
1686
+ GET_WORKFLOW_VERSIONS,
1687
+ { workflowKey }
1688
+ );
1689
+ return jsonResult(data.workflowVersions);
1690
+ })
1691
+ );
1692
+ server.registerTool(
1693
+ track(mcpToolName(ctx.productName, "workflows_create")),
1694
+ {
1695
+ title: "Create Workflow",
1696
+ description: "Create a workflow definition. definitionJson is the node/edge graph; workflowKey plus version identify it.",
1697
+ inputSchema: {
1698
+ workflowKey: z.string().describe("Stable key identifying the workflow"),
1699
+ name: z.string().describe("Human-readable name"),
1700
+ version: z.string().describe('Version string, e.g. "1.0.0"'),
1701
+ definitionJson: z.unknown().describe("Workflow graph (nodes + edges) as JSON"),
1702
+ description: z.string().optional().describe("Description"),
1703
+ category: z.string().optional().describe("Category"),
1704
+ icon: z.string().optional().describe("Icon identifier"),
1705
+ alias: z.string().optional().describe("Alias"),
1706
+ projectId: z.string().optional().describe("Owning project ID"),
1707
+ context: z.unknown().optional().describe("Context JSON"),
1708
+ tags: z.array(z.string()).optional().describe("Tags")
1709
+ }
1710
+ },
1711
+ async (args) => runTool(ctx, "workflows_create", async () => {
1712
+ const data = await ctx.gql.workspace.request(
1713
+ CREATE_WORKFLOW,
1714
+ { input: definedInput({ ...args }) }
1715
+ );
1716
+ return jsonResult(data.createWorkflowDefinition);
1717
+ })
1718
+ );
1719
+ server.registerTool(
1720
+ track(mcpToolName(ctx.productName, "workflows_update")),
1721
+ {
1722
+ title: "Update Workflow",
1723
+ description: "Update a workflow definition by id. Saving a change to a published workflow forks a new version rather than mutating the active one.",
1724
+ inputSchema: {
1725
+ id: z.string().describe("Workflow definition ID"),
1726
+ name: z.string().optional().describe("Name"),
1727
+ description: z.string().optional().describe("Description"),
1728
+ definitionJson: z.unknown().optional().describe("Workflow graph as JSON"),
1729
+ category: z.string().optional().describe("Category"),
1730
+ icon: z.string().optional().describe("Icon identifier"),
1731
+ alias: z.string().optional().describe("Alias"),
1732
+ context: z.unknown().optional().describe("Context JSON"),
1733
+ tags: z.array(z.string()).optional().describe("Tags"),
1734
+ version: z.string().optional().describe("Version")
1735
+ }
1736
+ },
1737
+ async ({ id, ...input }) => runTool(ctx, "workflows_update", async () => {
1738
+ const data = await ctx.gql.workspace.request(
1739
+ UPDATE_WORKFLOW,
1740
+ { id, input: definedInput(input) }
1741
+ );
1742
+ return jsonResult(data.updateWorkflowDefinition);
1743
+ })
1744
+ );
1745
+ server.registerTool(
1746
+ track(mcpToolName(ctx.productName, "workflows_delete")),
1747
+ {
1748
+ title: "Delete Workflow",
1749
+ description: "Delete a workflow by key. Without a version every version of that key is deleted.",
1750
+ annotations: { destructiveHint: true },
1751
+ inputSchema: {
1752
+ workflowKey: z.string().describe("Workflow key"),
1753
+ version: z.string().optional().describe("Delete only this version")
1754
+ }
1755
+ },
1756
+ async ({ workflowKey, version }) => runTool(ctx, "workflows_delete", async () => {
1757
+ const data = await ctx.gql.workspace.request(
1758
+ DELETE_WORKFLOW,
1759
+ { workflowKey, version }
1760
+ );
1761
+ return jsonResult(data.deleteWorkflowDefinition);
1762
+ })
1763
+ );
1764
+ server.registerTool(
1765
+ track(mcpToolName(ctx.productName, "workflows_trigger")),
1766
+ {
1767
+ title: "Trigger Workflow",
1768
+ description: "Start a workflow run. triggerNodeId names the trigger node to start from; stopAtNodeId runs only up to a node (step debugging).",
1769
+ inputSchema: {
1770
+ workflowKey: z.string().describe("Workflow key"),
1771
+ version: z.string().describe("Workflow version"),
1772
+ triggerNodeId: z.string().describe("ID of the trigger node to start from"),
1773
+ triggerData: z.unknown().optional().describe("Payload passed to the trigger node"),
1774
+ context: z.unknown().optional().describe("Run context JSON"),
1775
+ stopAtNodeId: z.string().optional().describe("Stop after this node and mark the run COMPLETED")
1776
+ }
1777
+ },
1778
+ async (args) => runTool(ctx, "workflows_trigger", async () => {
1779
+ const data = await ctx.gql.workspace.request(
1780
+ TRIGGER_WORKFLOW,
1781
+ { input: definedInput({ ...args }) }
1782
+ );
1783
+ return jsonResult(data.triggerWorkflow);
1784
+ })
1785
+ );
1786
+ server.registerTool(
1787
+ track(mcpToolName(ctx.productName, "workflows_publish")),
1788
+ {
1789
+ title: "Publish Workflow",
1790
+ description: "Publish a workflow definition, making that version the executable one.",
1791
+ inputSchema: { id: z.string().describe("Workflow definition ID") }
1792
+ },
1793
+ async ({ id }) => runTool(ctx, "workflows_publish", async () => {
1794
+ const data = await ctx.gql.workspace.request(
1795
+ PUBLISH_WORKFLOW,
1796
+ { id }
1797
+ );
1798
+ return jsonResult(data.publishWorkflow);
1799
+ })
1800
+ );
1801
+ server.registerTool(
1802
+ track(mcpToolName(ctx.productName, "workflows_activate")),
1803
+ {
1804
+ title: "Activate Workflow",
1805
+ description: "Activate a workflow definition. Exactly one version per workflowKey may be ACTIVE.",
1806
+ inputSchema: { id: z.string().describe("Workflow definition ID") }
1807
+ },
1808
+ async ({ id }) => runTool(ctx, "workflows_activate", async () => {
1809
+ const data = await ctx.gql.workspace.request(
1810
+ ACTIVATE_WORKFLOW,
1811
+ { id }
1812
+ );
1813
+ return jsonResult(data.activateWorkflowDefinition);
1814
+ })
1815
+ );
1816
+ server.registerTool(
1817
+ track(mcpToolName(ctx.productName, "workflows_deactivate")),
1818
+ {
1819
+ title: "Deactivate Workflow",
1820
+ description: "Deactivate a workflow definition so no version of the key is executable.",
1821
+ inputSchema: { id: z.string().describe("Workflow definition ID") }
1822
+ },
1823
+ async ({ id }) => runTool(ctx, "workflows_deactivate", async () => {
1824
+ const data = await ctx.gql.workspace.request(
1825
+ DEACTIVATE_WORKFLOW,
1826
+ { id }
1827
+ );
1828
+ return jsonResult(data.deactivateWorkflowDefinition);
1829
+ })
1830
+ );
1831
+ server.registerTool(
1832
+ track(mcpToolName(ctx.productName, "workflows_duplicate")),
1833
+ {
1834
+ title: "Duplicate Workflow",
1835
+ description: "Copy an existing workflow version to a new workflowKey.",
1836
+ inputSchema: {
1837
+ workflowKey: z.string().describe("Source workflow key"),
1838
+ version: z.string().describe("Source version"),
1839
+ newWorkflowKey: z.string().describe("Key for the copy"),
1840
+ newVersion: z.string().optional().describe("Version for the copy")
1841
+ }
1842
+ },
1843
+ async ({ workflowKey, version, newWorkflowKey, newVersion }) => runTool(ctx, "workflows_duplicate", async () => {
1844
+ const data = await ctx.gql.workspace.request(
1845
+ DUPLICATE_WORKFLOW,
1846
+ { workflowKey, version, input: definedInput({ newWorkflowKey, newVersion }) }
1847
+ );
1848
+ return jsonResult(data.duplicateWorkflow);
1849
+ })
1850
+ );
1851
+ server.registerTool(
1852
+ track(mcpToolName(ctx.productName, "workflows_archive")),
1853
+ {
1854
+ title: "Archive Workflow",
1855
+ description: "Archive a workflow definition. Reversible: archived workflows still list.",
1856
+ annotations: { destructiveHint: true },
1857
+ inputSchema: { id: z.string().describe("Workflow definition ID") }
1858
+ },
1859
+ async ({ id }) => runTool(ctx, "workflows_archive", async () => {
1860
+ const data = await ctx.gql.workspace.request(
1861
+ ARCHIVE_WORKFLOW,
1862
+ { id }
1863
+ );
1864
+ return jsonResult(data.archiveWorkflow);
1865
+ })
1866
+ );
1867
+ }
1868
+ function registerFluidgridsPrompts(server, ctx, track) {
1869
+ const p = ctx.productName;
1870
+ const buildName = track(mcpPromptName(p, "build-workflow"));
1871
+ const debugName = track(mcpPromptName(p, "debug-run"));
1872
+ server.registerPrompt(
1873
+ buildName,
1874
+ {
1875
+ title: "Build a Workflow",
1876
+ description: "Guide for authoring a FluidGrids workflow end to end: pick nodes, create the definition, publish a version, then trigger it and confirm the run completes.",
1877
+ argsSchema: {
1878
+ goal: z.string().optional().describe("What the workflow should do"),
1879
+ workflowKey: z.string().optional().describe("Workflow key to use")
1880
+ }
1881
+ },
1882
+ ({ goal, workflowKey }) => {
1883
+ ctx.logger.debug(`Prompt ${buildName} called`, { goal, workflowKey });
1884
+ const goalNote = goal ? `The workflow should: ${goal}` : "Ask the user what the workflow should do before building anything.";
1885
+ const keyNote = workflowKey ? `Use the workflowKey "${workflowKey}".` : "Choose a stable, descriptive workflowKey and confirm it with the user.";
1886
+ return {
1887
+ messages: [
1888
+ {
1889
+ role: "user",
1890
+ content: {
1891
+ type: "text",
1892
+ text: `Build a FluidGrids workflow.
1893
+
1894
+ ${goalNote}
1895
+ ${keyNote}
1896
+
1897
+ Follow this order and stop if a step fails:
1898
+
1899
+ 1. \`${p}_nodes_list\` \u2014 find the node types you need. Use \`${p}_nodes_get\` to read a
1900
+ node's input fields before wiring it; do not guess field names.
1901
+ 2. \`${p}_workflows_create\` \u2014 build \`definitionJson\` as a graph of nodes and edges.
1902
+ Exactly one trigger node. Note its node id: triggering needs it.
1903
+ 3. \`${p}_workflows_publish\` then \`${p}_workflows_activate\` \u2014 only an active version
1904
+ is executable, and only one version per key may be ACTIVE.
1905
+ 4. \`${p}_workflows_trigger\` \u2014 pass \`triggerNodeId\` and any \`triggerData\`.
1906
+ 5. \`${p}_runs_get\` \u2014 poll until status is terminal (COMPLETED, FAILED, CANCELLED or
1907
+ TERMINATED). Statuses are UPPERCASE.
1908
+ 6. If it did not complete, run \`${p}_debug-run\` on the run id.
1909
+
1910
+ If the workflow needs credentials, create them with \`${p}_credentials_create\` and
1911
+ verify with \`${p}_credentials_test\` BEFORE triggering \u2014 a missing connection fails
1912
+ the run at the node, not at save time.`
1913
+ }
1914
+ }
1915
+ ]
1916
+ };
1917
+ }
1918
+ );
1919
+ server.registerPrompt(
1920
+ debugName,
1921
+ {
1922
+ title: "Debug a Run",
1923
+ description: "Guide for diagnosing a FluidGrids run that failed or stalled: read node state, read the log, then retry the failing node or fix the definition.",
1924
+ argsSchema: { runId: z.string().optional().describe("Run ID to diagnose") }
1925
+ },
1926
+ ({ runId }) => {
1927
+ ctx.logger.debug(`Prompt ${debugName} called`, { runId });
1928
+ const runNote = runId ? `Diagnose run "${runId}".` : `Ask for the run id, or find it with \`${p}_runs_list\` filtered to status FAILED.`;
1929
+ return {
1930
+ messages: [
1931
+ {
1932
+ role: "user",
1933
+ content: {
1934
+ type: "text",
1935
+ text: `Diagnose a FluidGrids run.
1936
+
1937
+ ${runNote}
1938
+
1939
+ 1. \`${p}_runs_get\` \u2014 read the run and its per-node state. Identify the FIRST node that
1940
+ did not succeed; later failures are usually consequences of it.
1941
+ 2. \`${p}_runs_logs\` \u2014 read that node's log with \`nodeId\` set, \`minLevel\` ERROR first,
1942
+ then widen to WARN/INFO if the error alone is not conclusive.
1943
+ 3. Classify before acting:
1944
+ - credential/auth error -> \`${p}_credentials_test\` the connection the node uses
1945
+ - bad input -> compare against \`${p}_nodes_get\` input fields for that node type
1946
+ - transient/upstream -> \`${p}_runs_retry_node\` is appropriate
1947
+ - wrong graph -> fix \`definitionJson\` via \`${p}_workflows_update\` (this forks a new
1948
+ version), then publish, activate and trigger again
1949
+ 4. Only retry once you know which class it is. Retrying a bad definition just
1950
+ reproduces the failure.
1951
+
1952
+ A run stuck in WAITING is not failed \u2014 it is blocked on a Wait node. Resume it with
1953
+ \`${p}_runs_resume\` and the payload it expects.`
1954
+ }
1955
+ }
1956
+ ]
1957
+ };
1958
+ }
1959
+ );
1960
+ }
1961
+
1962
+ // src/modules/fluidgrids/resources.ts
1963
+ function registerFluidgridsResources(server, ctx, track) {
1964
+ const schemaUri = track(mcpResourceUri(ctx.productName, "schema"));
1965
+ const nodesUri = track(mcpResourceUri(ctx.productName, "nodes"));
1966
+ server.registerResource(
1967
+ "fluidgrids-schema",
1968
+ schemaUri,
1969
+ {
1970
+ title: "FluidGrids Domain Schema",
1971
+ description: "Overview of the FluidGrids workflow-automation domain \u2014 entities, enums, and the per-entity tool surface.",
1972
+ mimeType: "text/plain"
1973
+ },
1974
+ async () => {
1975
+ ctx.logger.debug(`Resource ${schemaUri} requested`);
1976
+ const schema = `# FluidGrids Domain (Overview)
1977
+
1978
+ Visual workflow automation. A workflow is a graph of nodes; running one produces a run.
1979
+
1980
+ ## Core entities
1981
+ - WorkflowDefinition \u2014 identified by (workflowKey, version). Many versions per key;
1982
+ at most ONE is ACTIVE. Saving over a published version forks a new version.
1983
+ - WorkflowRun \u2014 one execution. Has per-node state and a log stream.
1984
+ - NodeEndpointConfig \u2014 an available node type at a version (BUILTIN | CUSTOM | STORE).
1985
+ - Connection \u2014 a stored credential against a Provider. Secrets live in the vault.
1986
+ - EventRegistration \u2014 an event source (webhook) that triggers a workflow.
1987
+ - ScheduledJob \u2014 a cron/interval schedule that triggers a workflow.
1988
+
1989
+ ## Enums
1990
+ - WorkflowStatus: ACTIVE | ARCHIVED | DEPRECATED | DRAFT
1991
+ - RunStatus: PENDING | RUNNING | WAITING | COMPLETED | FAILED | CANCELLED | TERMINATED
1992
+ (UPPERCASE on the wire \u2014 comparing lowercase is a known source of hangs)
1993
+ - RunLogLevel: DEBUG | INFO | WARN | ERROR
1994
+ - PublishType: BUILTIN | CUSTOM | STORE
1995
+ - NodeConfigStatus: AVAILABLE | DEPRECATED | DISABLED
1996
+ - EventStatus: ACTIVE | PAUSED | DISABLED | ARCHIVED
1997
+
1998
+ ## Typical sequence
1999
+ 1. ${ctx.productName}_nodes_list \u2014 see what nodes exist
2000
+ 2. ${ctx.productName}_workflows_create \u2014 create a definition with a definitionJson graph
2001
+ 3. ${ctx.productName}_workflows_publish / _activate \u2014 make a version executable
2002
+ 4. ${ctx.productName}_workflows_trigger \u2014 start a run
2003
+ 5. ${ctx.productName}_runs_get / _runs_logs \u2014 follow it to a terminal status
2004
+
2005
+ ## Tier
2006
+ Every tool here is workspace tier and needs a workspace context. Sign in and
2007
+ select a workspace with the auth tools first.
2008
+ `;
2009
+ return { contents: [{ uri: schemaUri, mimeType: "text/plain", text: schema }] };
2010
+ }
2011
+ );
2012
+ server.registerResource(
2013
+ "fluidgrids-nodes",
2014
+ nodesUri,
2015
+ {
2016
+ title: "FluidGrids Node Catalogue",
2017
+ description: "The node types currently available to build workflows with, read live from the node endpoint config registry.",
2018
+ mimeType: "application/json"
2019
+ },
2020
+ async () => {
2021
+ ctx.logger.debug(`Resource ${nodesUri} requested`);
2022
+ try {
2023
+ const data = await ctx.gql.workspace.request(LIST_NODES, {
2024
+ status: "AVAILABLE"
2025
+ });
2026
+ return {
2027
+ contents: [
2028
+ {
2029
+ uri: nodesUri,
2030
+ mimeType: "application/json",
2031
+ text: JSON.stringify(data.nodeEndpointConfigs, null, 2)
2032
+ }
2033
+ ]
2034
+ };
2035
+ } catch (error) {
2036
+ const message = safeErrorMessage(error);
2037
+ ctx.logger.error("fluidgrids nodes resource failed", { error: message });
2038
+ return {
2039
+ contents: [
2040
+ {
2041
+ uri: nodesUri,
2042
+ mimeType: "application/json",
2043
+ text: JSON.stringify(
2044
+ {
2045
+ error: message,
2046
+ hint: "Sign in and select a workspace first \u2014 the node registry is workspace-scoped."
2047
+ },
2048
+ null,
2049
+ 2
2050
+ )
2051
+ }
2052
+ ]
2053
+ };
2054
+ }
2055
+ }
2056
+ );
2057
+ }
2058
+
2059
+ // src/modules/fluidgrids/index.ts
2060
+ var fluidgridsModule = {
2061
+ id: "fluidgrids",
2062
+ version: "0.0.1",
2063
+ displayName: "FluidGrids",
2064
+ capabilities: { tools: {}, resources: {}, prompts: {} },
2065
+ register(server, ctx) {
2066
+ const tools = [];
2067
+ const resources = [];
2068
+ const prompts = [];
2069
+ const trackTool = (n) => {
2070
+ tools.push(n);
2071
+ return n;
2072
+ };
2073
+ const trackResource = (uri) => {
2074
+ resources.push(uri);
2075
+ return uri;
2076
+ };
2077
+ const trackPrompt = (n) => {
2078
+ prompts.push(n);
2079
+ return n;
2080
+ };
2081
+ registerWorkflowTools(server, ctx, trackTool);
2082
+ registerRunTools(server, ctx, trackTool);
2083
+ registerNodeTools(server, ctx, trackTool);
2084
+ registerCredentialTools(server, ctx, trackTool);
2085
+ registerWebhookTools(server, ctx, trackTool);
2086
+ registerScheduledJobTools(server, ctx, trackTool);
2087
+ registerInsightTools(server, ctx, trackTool);
2088
+ registerFluidgridsResources(server, ctx, trackResource);
2089
+ registerFluidgridsPrompts(server, ctx, trackPrompt);
2090
+ return { tools, resources, prompts };
2091
+ }
2092
+ };
2093
+ var fluidgrids_default = fluidgridsModule;
2094
+
2095
+ export { fluidgrids_default as default };
2096
+ //# sourceMappingURL=index.js.map
2097
+ //# sourceMappingURL=index.js.map