@walkeros/mcp 3.0.2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +331 -386
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import { z } from "zod";
|
|
|
14
14
|
var ValidateOutputShape = {
|
|
15
15
|
valid: z.boolean().describe("Whether validation passed"),
|
|
16
16
|
type: z.union([
|
|
17
|
-
z.enum(["contract", "event", "flow", "mapping"]),
|
|
17
|
+
z.enum(["contract", "entry", "event", "flow", "mapping"]),
|
|
18
18
|
z.string().regex(/^(destinations|sources|transformers)\.\w+$/)
|
|
19
19
|
]).describe("What was validated"),
|
|
20
20
|
errors: z.array(
|
|
@@ -56,15 +56,10 @@ var SimulateOutputShape = {
|
|
|
56
56
|
z.object({
|
|
57
57
|
received: z.boolean().describe("Whether destination received the event"),
|
|
58
58
|
calls: z.number().describe("Number of API calls made"),
|
|
59
|
-
payload: z.unknown().optional().describe("
|
|
59
|
+
payload: z.unknown().optional().describe("Full payload (only when verbose: true)")
|
|
60
60
|
})
|
|
61
61
|
).optional().describe("Per-destination results"),
|
|
62
|
-
|
|
63
|
-
name: z.string(),
|
|
64
|
-
step: z.string(),
|
|
65
|
-
match: z.boolean(),
|
|
66
|
-
diff: z.string().optional()
|
|
67
|
-
}).optional().describe("Example comparison result when using example parameter"),
|
|
62
|
+
capturedEvents: z.array(z.record(z.string(), z.unknown())).optional().describe("Events captured by source simulation"),
|
|
68
63
|
duration: z.number().optional().describe("Simulation duration in ms")
|
|
69
64
|
};
|
|
70
65
|
var PushOutputShape = {
|
|
@@ -85,60 +80,17 @@ var ExamplesListOutputShape = {
|
|
|
85
80
|
hasIn: z.boolean().describe("Whether the example has an input value"),
|
|
86
81
|
hasOut: z.boolean().describe("Whether the example has an output value"),
|
|
87
82
|
hasMapping: z.boolean().describe("Whether the example has a mapping configuration"),
|
|
83
|
+
hasTrigger: z.boolean().describe("Whether the example has trigger metadata"),
|
|
88
84
|
in: z.unknown().optional().describe("Input event data"),
|
|
89
85
|
out: z.unknown().optional().describe("Expected output data"),
|
|
90
|
-
mapping: z.unknown().optional().describe("Mapping configuration for destinations")
|
|
86
|
+
mapping: z.unknown().optional().describe("Mapping configuration for destinations"),
|
|
87
|
+
trigger: z.object({
|
|
88
|
+
type: z.string().optional(),
|
|
89
|
+
options: z.unknown().optional()
|
|
90
|
+
}).optional().describe("Trigger metadata for source simulation")
|
|
91
91
|
})
|
|
92
92
|
).describe("Step examples")
|
|
93
93
|
};
|
|
94
|
-
var PackageSearchOutputShape = {
|
|
95
|
-
package: z.string().describe("Package name"),
|
|
96
|
-
version: z.string().describe("Package version"),
|
|
97
|
-
description: z.string().optional().describe("Package description"),
|
|
98
|
-
type: z.string().optional().describe("Package type (destination, source, transformer)"),
|
|
99
|
-
platform: z.string().optional().describe("Target platform (web, server)"),
|
|
100
|
-
hintKeys: z.array(z.string()).describe("Available hint keys (use package_get section=hints to read)"),
|
|
101
|
-
exampleSummaries: z.array(
|
|
102
|
-
z.object({
|
|
103
|
-
name: z.string().describe("Example name"),
|
|
104
|
-
description: z.string().optional().describe("What this example shows")
|
|
105
|
-
})
|
|
106
|
-
).describe(
|
|
107
|
-
"Step example names and descriptions (use package_get section=examples to read full content)"
|
|
108
|
-
)
|
|
109
|
-
};
|
|
110
|
-
var PackageSchemaOutputShape = {
|
|
111
|
-
package: z.string().describe("Package name"),
|
|
112
|
-
version: z.string().describe("Package version"),
|
|
113
|
-
type: z.string().describe("Package type (destination, source, transformer)"),
|
|
114
|
-
platform: z.string().describe("Target platform (web, server)"),
|
|
115
|
-
schemas: z.record(z.string(), z.unknown()).optional().describe("JSON Schemas for settings and mapping"),
|
|
116
|
-
examples: z.record(z.string(), z.unknown()).optional().describe(
|
|
117
|
-
"Full configuration examples (included when section=examples or section=all)"
|
|
118
|
-
),
|
|
119
|
-
exampleSummaries: z.array(
|
|
120
|
-
z.object({
|
|
121
|
-
name: z.string().describe("Example name"),
|
|
122
|
-
description: z.string().optional().describe("What this example shows")
|
|
123
|
-
})
|
|
124
|
-
).optional().describe(
|
|
125
|
-
"Example names and descriptions (included in default/summary mode)"
|
|
126
|
-
),
|
|
127
|
-
hints: z.record(
|
|
128
|
-
z.string(),
|
|
129
|
-
z.object({
|
|
130
|
-
text: z.string(),
|
|
131
|
-
code: z.array(
|
|
132
|
-
z.object({
|
|
133
|
-
lang: z.string().optional(),
|
|
134
|
-
code: z.string()
|
|
135
|
-
})
|
|
136
|
-
).optional()
|
|
137
|
-
})
|
|
138
|
-
).optional().describe(
|
|
139
|
-
"Hints \u2014 text only in summary mode, with code blocks when section=hints or section=all"
|
|
140
|
-
)
|
|
141
|
-
};
|
|
142
94
|
|
|
143
95
|
// src/tools/validate.ts
|
|
144
96
|
function registerFlowValidateTool(server2) {
|
|
@@ -270,6 +222,7 @@ function formatBytes(bytes) {
|
|
|
270
222
|
}
|
|
271
223
|
|
|
272
224
|
// src/tools/simulate.ts
|
|
225
|
+
import { z as z3 } from "zod";
|
|
273
226
|
import { simulate } from "@walkeros/cli";
|
|
274
227
|
import { schemas as schemas3 } from "@walkeros/cli/dev";
|
|
275
228
|
import { mcpResult as mcpResult3, mcpError as mcpError3 } from "@walkeros/core";
|
|
@@ -278,8 +231,17 @@ function registerFlowSimulateTool(server2) {
|
|
|
278
231
|
"flow_simulate",
|
|
279
232
|
{
|
|
280
233
|
title: "Simulate Flow",
|
|
281
|
-
description: 'Simulate events through a walkerOS flow without making real API calls.
|
|
282
|
-
inputSchema:
|
|
234
|
+
description: 'Simulate events through a walkerOS flow without making real API calls. For destinations: event is a walkerOS event { name: "entity action", data: {...} }. For sources: event is { content: ..., trigger?: { type?, options? }, env?: {...} }. Use step to target a specific step. Use flow_examples to discover available test data.',
|
|
235
|
+
inputSchema: {
|
|
236
|
+
configPath: schemas3.SimulateInputShape.configPath,
|
|
237
|
+
event: z3.union([z3.record(z3.string(), z3.unknown()), z3.string()]).optional().describe(
|
|
238
|
+
"For destinations: { name, data }. For sources: { content, trigger?, env? }. Can also be a JSON string or file path."
|
|
239
|
+
),
|
|
240
|
+
flow: schemas3.SimulateInputShape.flow,
|
|
241
|
+
platform: schemas3.SimulateInputShape.platform,
|
|
242
|
+
step: schemas3.SimulateInputShape.step,
|
|
243
|
+
verbose: z3.boolean().optional().describe("Include full payload per destination (default: false)")
|
|
244
|
+
},
|
|
283
245
|
outputSchema: SimulateOutputShape,
|
|
284
246
|
annotations: {
|
|
285
247
|
readOnlyHint: true,
|
|
@@ -288,26 +250,51 @@ function registerFlowSimulateTool(server2) {
|
|
|
288
250
|
openWorldHint: false
|
|
289
251
|
}
|
|
290
252
|
},
|
|
291
|
-
async ({ configPath, event, flow, platform,
|
|
253
|
+
async ({ configPath, event, flow, platform, step, verbose }) => {
|
|
292
254
|
try {
|
|
293
|
-
if (!event
|
|
294
|
-
throw new Error(
|
|
255
|
+
if (!event) {
|
|
256
|
+
throw new Error(
|
|
257
|
+
"event is required. For sources provide { content, trigger? }, for destinations provide { name, data }."
|
|
258
|
+
);
|
|
295
259
|
}
|
|
296
260
|
const raw = await simulate(configPath, event, {
|
|
297
261
|
json: true,
|
|
298
262
|
flow,
|
|
299
263
|
platform,
|
|
300
|
-
example,
|
|
301
264
|
step
|
|
302
265
|
});
|
|
266
|
+
if (raw.capturedEvents) {
|
|
267
|
+
const eventCount = raw.capturedEvents.length;
|
|
268
|
+
const summary2 = `Source captured ${eventCount} event${eventCount !== 1 ? "s" : ""}`;
|
|
269
|
+
return mcpResult3(
|
|
270
|
+
{
|
|
271
|
+
success: raw.success,
|
|
272
|
+
error: raw.error,
|
|
273
|
+
summary: summary2,
|
|
274
|
+
capturedEvents: raw.capturedEvents,
|
|
275
|
+
duration: raw.duration
|
|
276
|
+
},
|
|
277
|
+
summary2,
|
|
278
|
+
{
|
|
279
|
+
next: eventCount > 0 ? [
|
|
280
|
+
"Use flow_simulate with a destination step to test downstream processing"
|
|
281
|
+
] : [
|
|
282
|
+
"Check source package examples with package_get, verify trigger type matches"
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
}
|
|
303
287
|
const destinations = {};
|
|
304
288
|
if (raw.usage) {
|
|
305
289
|
for (const [name, calls] of Object.entries(raw.usage)) {
|
|
306
|
-
|
|
290
|
+
const summary2 = {
|
|
307
291
|
received: calls.length > 0,
|
|
308
|
-
calls: calls.length
|
|
309
|
-
payload: calls.length > 0 ? calls[calls.length - 1] : void 0
|
|
292
|
+
calls: calls.length
|
|
310
293
|
};
|
|
294
|
+
if (verbose && calls.length > 0) {
|
|
295
|
+
summary2.payload = calls[calls.length - 1];
|
|
296
|
+
}
|
|
297
|
+
destinations[name] = summary2;
|
|
311
298
|
}
|
|
312
299
|
}
|
|
313
300
|
const destCount = Object.keys(destinations).length;
|
|
@@ -316,13 +303,11 @@ function registerFlowSimulateTool(server2) {
|
|
|
316
303
|
).length;
|
|
317
304
|
const warnings = [];
|
|
318
305
|
if (destCount === 0) {
|
|
319
|
-
warnings.push(
|
|
320
|
-
"No destinations found in flow configuration. Check that your flow defines at least one destination."
|
|
321
|
-
);
|
|
306
|
+
warnings.push("No destinations found in flow configuration.");
|
|
322
307
|
}
|
|
323
308
|
if (destCount > 0 && receivedCount === 0) {
|
|
324
309
|
warnings.push(
|
|
325
|
-
"No destinations received the event. Check: mapping keys use nested entity\u2192action structure
|
|
310
|
+
"No destinations received the event. Check: mapping keys use nested entity\u2192action structure, event name matches, consent is granted."
|
|
326
311
|
);
|
|
327
312
|
}
|
|
328
313
|
const summary = `${receivedCount}/${destCount} destinations received the event`;
|
|
@@ -331,7 +316,6 @@ function registerFlowSimulateTool(server2) {
|
|
|
331
316
|
error: raw.error,
|
|
332
317
|
summary,
|
|
333
318
|
destinations: destCount > 0 ? destinations : void 0,
|
|
334
|
-
exampleMatch: raw.exampleMatch,
|
|
335
319
|
duration: raw.duration
|
|
336
320
|
};
|
|
337
321
|
return mcpResult3(result, summary, {
|
|
@@ -346,6 +330,7 @@ function registerFlowSimulateTool(server2) {
|
|
|
346
330
|
}
|
|
347
331
|
|
|
348
332
|
// src/tools/push.ts
|
|
333
|
+
import { z as z4 } from "zod";
|
|
349
334
|
import { push } from "@walkeros/cli";
|
|
350
335
|
import { schemas as schemas4 } from "@walkeros/cli/dev";
|
|
351
336
|
import { mcpResult as mcpResult4, mcpError as mcpError4 } from "@walkeros/core";
|
|
@@ -355,7 +340,14 @@ function registerFlowPushTool(server2) {
|
|
|
355
340
|
{
|
|
356
341
|
title: "Push Events",
|
|
357
342
|
description: "Push a real event through a walkerOS flow to actual destinations. Makes real API calls to real endpoints. Best suited for server-side flows \u2014 web flows should use flow_simulate for testing.",
|
|
358
|
-
inputSchema:
|
|
343
|
+
inputSchema: {
|
|
344
|
+
configPath: schemas4.PushInputShape.configPath,
|
|
345
|
+
event: z4.record(z4.string(), z4.unknown()).describe(
|
|
346
|
+
'Event object, e.g. { name: "page view", data: { title: "Home" } }'
|
|
347
|
+
),
|
|
348
|
+
flow: schemas4.PushInputShape.flow,
|
|
349
|
+
platform: schemas4.PushInputShape.platform
|
|
350
|
+
},
|
|
359
351
|
outputSchema: PushOutputShape,
|
|
360
352
|
annotations: {
|
|
361
353
|
readOnlyHint: false,
|
|
@@ -390,7 +382,7 @@ function registerFlowPushTool(server2) {
|
|
|
390
382
|
}
|
|
391
383
|
|
|
392
384
|
// src/tools/examples.ts
|
|
393
|
-
import { z as
|
|
385
|
+
import { z as z5 } from "zod";
|
|
394
386
|
import { loadJsonConfig } from "@walkeros/cli";
|
|
395
387
|
import { mcpResult as mcpResult5, mcpError as mcpError5 } from "@walkeros/core";
|
|
396
388
|
function registerFlowExamplesTool(server2) {
|
|
@@ -400,10 +392,12 @@ function registerFlowExamplesTool(server2) {
|
|
|
400
392
|
title: "Flow Examples",
|
|
401
393
|
description: "List all step examples in a walkerOS flow configuration. Shows example names, step locations, and in/out shapes. Use this to discover available test fixtures and simulation data.",
|
|
402
394
|
inputSchema: {
|
|
403
|
-
configPath:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
395
|
+
configPath: z5.string().min(1).describe(
|
|
396
|
+
"Path to flow configuration file, URL, or inline JSON string"
|
|
397
|
+
),
|
|
398
|
+
flow: z5.string().optional().describe("Flow name for multi-flow configs"),
|
|
399
|
+
step: z5.string().optional().describe('Filter to a specific step (e.g., "destination.gtag")'),
|
|
400
|
+
full: z5.boolean().optional().describe(
|
|
407
401
|
"Return full in/out/mapping data for each example (default: false, returns metadata only)"
|
|
408
402
|
)
|
|
409
403
|
},
|
|
@@ -451,7 +445,13 @@ function registerFlowExamplesTool(server2) {
|
|
|
451
445
|
hasIn: ex.in !== void 0,
|
|
452
446
|
hasOut: ex.out !== void 0,
|
|
453
447
|
hasMapping: ex.mapping !== void 0,
|
|
454
|
-
|
|
448
|
+
hasTrigger: ex.trigger !== void 0,
|
|
449
|
+
...full ? {
|
|
450
|
+
in: ex.in,
|
|
451
|
+
out: ex.out,
|
|
452
|
+
mapping: ex.mapping,
|
|
453
|
+
trigger: ex.trigger
|
|
454
|
+
} : {}
|
|
455
455
|
});
|
|
456
456
|
}
|
|
457
457
|
}
|
|
@@ -465,7 +465,7 @@ function registerFlowExamplesTool(server2) {
|
|
|
465
465
|
const totalExamples = examples.length;
|
|
466
466
|
const summary = `${totalExamples} examples across ${stepSet.size} steps`;
|
|
467
467
|
const hints = {
|
|
468
|
-
next: ["Use flow_simulate with
|
|
468
|
+
next: ["Use flow_simulate with step and event to simulate"]
|
|
469
469
|
};
|
|
470
470
|
if (totalExamples === 0) {
|
|
471
471
|
hints.warnings = [
|
|
@@ -481,207 +481,85 @@ function registerFlowExamplesTool(server2) {
|
|
|
481
481
|
}
|
|
482
482
|
|
|
483
483
|
// src/tools/package.ts
|
|
484
|
-
import { z as
|
|
485
|
-
import {
|
|
484
|
+
import { z as z6 } from "zod";
|
|
485
|
+
import {
|
|
486
|
+
fetchPackage,
|
|
487
|
+
mergeConfigSchema,
|
|
488
|
+
mcpResult as mcpResult6,
|
|
489
|
+
mcpError as mcpError6
|
|
490
|
+
} from "@walkeros/core";
|
|
486
491
|
|
|
487
|
-
// src/
|
|
488
|
-
var
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
name: "@walkeros/web-destination-meta",
|
|
498
|
-
type: "destination",
|
|
499
|
-
platform: "web",
|
|
500
|
-
description: "Meta (Facebook) Pixel"
|
|
501
|
-
},
|
|
502
|
-
{
|
|
503
|
-
name: "@walkeros/web-destination-plausible",
|
|
504
|
-
type: "destination",
|
|
505
|
-
platform: "web",
|
|
506
|
-
description: "Plausible Analytics"
|
|
507
|
-
},
|
|
508
|
-
{
|
|
509
|
-
name: "@walkeros/web-destination-snowplow",
|
|
510
|
-
type: "destination",
|
|
511
|
-
platform: "web",
|
|
512
|
-
description: "Snowplow Analytics"
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
name: "@walkeros/web-destination-piwikpro",
|
|
516
|
-
type: "destination",
|
|
517
|
-
platform: "web",
|
|
518
|
-
description: "Piwik PRO Analytics"
|
|
519
|
-
},
|
|
520
|
-
{
|
|
521
|
-
name: "@walkeros/web-destination-api",
|
|
522
|
-
type: "destination",
|
|
523
|
-
platform: "web",
|
|
524
|
-
description: "Generic HTTP API destination"
|
|
525
|
-
},
|
|
526
|
-
// Server Destinations
|
|
527
|
-
{
|
|
528
|
-
name: "@walkeros/server-destination-gcp",
|
|
529
|
-
type: "destination",
|
|
530
|
-
platform: "server",
|
|
531
|
-
description: "Google Cloud Platform (BigQuery)"
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
name: "@walkeros/server-destination-aws",
|
|
535
|
-
type: "destination",
|
|
536
|
-
platform: "server",
|
|
537
|
-
description: "AWS (Firehose)"
|
|
538
|
-
},
|
|
539
|
-
{
|
|
540
|
-
name: "@walkeros/server-destination-meta",
|
|
541
|
-
type: "destination",
|
|
542
|
-
platform: "server",
|
|
543
|
-
description: "Meta Conversions API (server-side)"
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
name: "@walkeros/server-destination-api",
|
|
547
|
-
type: "destination",
|
|
548
|
-
platform: "server",
|
|
549
|
-
description: "Generic HTTP API destination (server)"
|
|
550
|
-
},
|
|
551
|
-
{
|
|
552
|
-
name: "@walkeros/server-destination-datamanager",
|
|
553
|
-
type: "destination",
|
|
554
|
-
platform: "server",
|
|
555
|
-
description: "Google Data Manager"
|
|
556
|
-
},
|
|
557
|
-
// Web Sources
|
|
558
|
-
{
|
|
559
|
-
name: "@walkeros/web-source-browser",
|
|
560
|
-
type: "source",
|
|
561
|
-
platform: "web",
|
|
562
|
-
description: "Browser DOM event capture (clicks, page views, forms)"
|
|
563
|
-
},
|
|
564
|
-
{
|
|
565
|
-
name: "@walkeros/web-source-datalayer",
|
|
566
|
-
type: "source",
|
|
567
|
-
platform: "web",
|
|
568
|
-
description: "Google Tag Manager dataLayer bridge"
|
|
569
|
-
},
|
|
570
|
-
{
|
|
571
|
-
name: "@walkeros/web-source-session",
|
|
572
|
-
type: "source",
|
|
573
|
-
platform: "web",
|
|
574
|
-
description: "Session tracking source"
|
|
575
|
-
},
|
|
576
|
-
// CMP Sources
|
|
577
|
-
{
|
|
578
|
-
name: "@walkeros/web-source-cmp-cookiefirst",
|
|
579
|
-
type: "source",
|
|
580
|
-
platform: "web",
|
|
581
|
-
description: "CookieFirst consent management"
|
|
582
|
-
},
|
|
583
|
-
{
|
|
584
|
-
name: "@walkeros/web-source-cmp-cookiepro",
|
|
585
|
-
type: "source",
|
|
586
|
-
platform: "web",
|
|
587
|
-
description: "CookiePro/OneTrust consent management"
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
name: "@walkeros/web-source-cmp-usercentrics",
|
|
591
|
-
type: "source",
|
|
592
|
-
platform: "web",
|
|
593
|
-
description: "Usercentrics consent management"
|
|
594
|
-
},
|
|
595
|
-
// Server Sources
|
|
596
|
-
{
|
|
597
|
-
name: "@walkeros/server-source-express",
|
|
598
|
-
type: "source",
|
|
599
|
-
platform: "server",
|
|
600
|
-
description: "Express.js HTTP event endpoint"
|
|
601
|
-
},
|
|
602
|
-
{
|
|
603
|
-
name: "@walkeros/server-source-fetch",
|
|
604
|
-
type: "source",
|
|
605
|
-
platform: "server",
|
|
606
|
-
description: "Web Fetch API source (Cloudflare, Vercel Edge, Deno, Bun)"
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
name: "@walkeros/server-source-aws",
|
|
610
|
-
type: "source",
|
|
611
|
-
platform: "server",
|
|
612
|
-
description: "AWS sources (Lambda, API Gateway, Function URLs)"
|
|
613
|
-
},
|
|
614
|
-
{
|
|
615
|
-
name: "@walkeros/server-source-gcp",
|
|
616
|
-
type: "source",
|
|
617
|
-
platform: "server",
|
|
618
|
-
description: "GCP sources (Cloud Functions)"
|
|
619
|
-
},
|
|
620
|
-
// Transformers
|
|
621
|
-
{
|
|
622
|
-
name: "@walkeros/transformer-router",
|
|
623
|
-
type: "transformer",
|
|
624
|
-
platform: "universal",
|
|
625
|
-
description: "Route events to different destination subsets"
|
|
626
|
-
},
|
|
627
|
-
{
|
|
628
|
-
name: "@walkeros/transformer-validator",
|
|
629
|
-
type: "transformer",
|
|
630
|
-
platform: "universal",
|
|
631
|
-
description: "Event validation using JSON Schema"
|
|
632
|
-
},
|
|
633
|
-
{
|
|
634
|
-
name: "@walkeros/server-transformer-fingerprint",
|
|
635
|
-
type: "transformer",
|
|
636
|
-
platform: "server",
|
|
637
|
-
description: "Device fingerprinting for anonymous user identification"
|
|
638
|
-
},
|
|
639
|
-
{
|
|
640
|
-
name: "@walkeros/server-transformer-cache",
|
|
641
|
-
type: "transformer",
|
|
642
|
-
platform: "server",
|
|
643
|
-
description: "HTTP response caching with LRU eviction"
|
|
644
|
-
},
|
|
645
|
-
{
|
|
646
|
-
name: "@walkeros/server-transformer-file",
|
|
647
|
-
type: "transformer",
|
|
648
|
-
platform: "server",
|
|
649
|
-
description: "File serving transformer for static files"
|
|
650
|
-
},
|
|
651
|
-
// Stores
|
|
652
|
-
{
|
|
653
|
-
name: "@walkeros/store-memory",
|
|
654
|
-
type: "store",
|
|
655
|
-
platform: "universal",
|
|
656
|
-
description: "In-memory key-value store with LRU eviction and TTL"
|
|
657
|
-
},
|
|
658
|
-
{
|
|
659
|
-
name: "@walkeros/server-store-fs",
|
|
660
|
-
type: "store",
|
|
661
|
-
platform: "server",
|
|
662
|
-
description: "File system key-value store"
|
|
663
|
-
},
|
|
664
|
-
{
|
|
665
|
-
name: "@walkeros/server-store-s3",
|
|
666
|
-
type: "store",
|
|
667
|
-
platform: "server",
|
|
668
|
-
description: "AWS S3 key-value store"
|
|
669
|
-
},
|
|
670
|
-
{
|
|
671
|
-
name: "@walkeros/server-store-gcs",
|
|
672
|
-
type: "store",
|
|
673
|
-
platform: "server",
|
|
674
|
-
description: "Google Cloud Storage key-value store"
|
|
492
|
+
// src/catalog.ts
|
|
493
|
+
var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
|
|
494
|
+
var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
|
|
495
|
+
var WALKEROS_JSON_PATH = "dist/walkerOS.json";
|
|
496
|
+
var CACHE_TTL = 5 * 60 * 1e3;
|
|
497
|
+
var cache;
|
|
498
|
+
function normalizePlatform(platform) {
|
|
499
|
+
if (platform == null) return [];
|
|
500
|
+
if (typeof platform === "string") {
|
|
501
|
+
return platform === "universal" ? ["web", "server"] : [platform];
|
|
675
502
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
503
|
+
if (Array.isArray(platform)) {
|
|
504
|
+
return platform.filter((v) => typeof v === "string");
|
|
505
|
+
}
|
|
506
|
+
return [];
|
|
507
|
+
}
|
|
508
|
+
async function fetchCatalog(filters) {
|
|
509
|
+
if (cache && Date.now() - cache.timestamp < CACHE_TTL) {
|
|
510
|
+
return applyFilters(cache.entries, filters);
|
|
511
|
+
}
|
|
512
|
+
let entries;
|
|
513
|
+
try {
|
|
514
|
+
entries = await fetchFromNpm();
|
|
515
|
+
} catch {
|
|
516
|
+
return [];
|
|
517
|
+
}
|
|
518
|
+
cache = { entries, timestamp: Date.now() };
|
|
519
|
+
return applyFilters(entries, filters);
|
|
520
|
+
}
|
|
521
|
+
async function fetchFromNpm() {
|
|
522
|
+
const res = await fetch(`${NPM_SEARCH_URL}?text=@walkeros/&size=250`, {
|
|
523
|
+
signal: AbortSignal.timeout(1e4)
|
|
524
|
+
});
|
|
525
|
+
if (!res.ok) throw new Error(`npm search failed: ${res.status}`);
|
|
526
|
+
const data = await res.json();
|
|
527
|
+
const metaResults = await Promise.allSettled(
|
|
528
|
+
data.objects.map((obj) => enrichWithMeta(obj.package))
|
|
529
|
+
);
|
|
530
|
+
return metaResults.filter(
|
|
531
|
+
(r) => r.status === "fulfilled"
|
|
532
|
+
).map((r) => r.value).filter((entry) => entry !== void 0);
|
|
533
|
+
}
|
|
534
|
+
async function enrichWithMeta(pkg) {
|
|
535
|
+
try {
|
|
536
|
+
const res = await fetch(
|
|
537
|
+
`${JSDELIVR_BASE}/${pkg.name}@${pkg.version}/${WALKEROS_JSON_PATH}`,
|
|
538
|
+
{ signal: AbortSignal.timeout(5e3) }
|
|
539
|
+
);
|
|
540
|
+
if (!res.ok) return void 0;
|
|
541
|
+
const json = await res.json();
|
|
542
|
+
const meta = json.$meta;
|
|
543
|
+
if (!meta || typeof meta.type !== "string") return void 0;
|
|
544
|
+
return {
|
|
545
|
+
name: pkg.name,
|
|
546
|
+
version: pkg.version,
|
|
547
|
+
description: pkg.description,
|
|
548
|
+
type: meta.type,
|
|
549
|
+
platform: normalizePlatform(meta.platform)
|
|
550
|
+
};
|
|
551
|
+
} catch {
|
|
552
|
+
return void 0;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function applyFilters(entries, filters) {
|
|
556
|
+
let results = entries;
|
|
679
557
|
if (filters?.type) {
|
|
680
|
-
results = results.filter((
|
|
558
|
+
results = results.filter((e) => e.type === filters.type);
|
|
681
559
|
}
|
|
682
560
|
if (filters?.platform) {
|
|
683
561
|
results = results.filter(
|
|
684
|
-
(
|
|
562
|
+
(e) => e.platform.length === 0 || e.platform.includes(filters.platform)
|
|
685
563
|
);
|
|
686
564
|
}
|
|
687
565
|
return results;
|
|
@@ -695,14 +573,14 @@ function registerPackageSearchTool(server2) {
|
|
|
695
573
|
title: "Search Package",
|
|
696
574
|
description: "Browse walkerOS packages or look up a specific one. Without package name: returns catalog filtered by type/platform. With package name: returns metadata, hint keys, and example summaries.",
|
|
697
575
|
inputSchema: {
|
|
698
|
-
package:
|
|
576
|
+
package: z6.string().min(1).optional().describe(
|
|
699
577
|
"Exact npm package name for detailed lookup (e.g., @walkeros/web-destination-snowplow)"
|
|
700
578
|
),
|
|
701
|
-
type:
|
|
702
|
-
platform:
|
|
579
|
+
type: z6.enum(["source", "destination", "transformer", "store"]).optional().describe("Filter by package type (browse mode)"),
|
|
580
|
+
platform: z6.enum(["web", "server"]).optional().describe(
|
|
703
581
|
"Filter by platform (browse mode, includes universal packages)"
|
|
704
582
|
),
|
|
705
|
-
version:
|
|
583
|
+
version: z6.string().optional().describe("Package version for detailed lookup (default: latest)")
|
|
706
584
|
},
|
|
707
585
|
// No outputSchema: browse mode returns {catalog, count}, lookup returns metadata — incompatible shapes
|
|
708
586
|
annotations: {
|
|
@@ -714,7 +592,7 @@ function registerPackageSearchTool(server2) {
|
|
|
714
592
|
},
|
|
715
593
|
async ({ package: packageName, type, platform, version }) => {
|
|
716
594
|
if (!packageName) {
|
|
717
|
-
const catalog =
|
|
595
|
+
const catalog = await fetchCatalog({ type, platform });
|
|
718
596
|
const result = { catalog, count: catalog.length };
|
|
719
597
|
const summary = `${catalog.length} packages found`;
|
|
720
598
|
return mcpResult6(result, summary, {
|
|
@@ -728,7 +606,7 @@ function registerPackageSearchTool(server2) {
|
|
|
728
606
|
version: info.version,
|
|
729
607
|
description: info.description,
|
|
730
608
|
type: info.type,
|
|
731
|
-
platform: info.platform,
|
|
609
|
+
platform: normalizePlatform(info.platform),
|
|
732
610
|
hintKeys: info.hintKeys,
|
|
733
611
|
exampleSummaries: info.exampleSummaries
|
|
734
612
|
};
|
|
@@ -752,15 +630,15 @@ function registerGetPackageSchemaTool(server2) {
|
|
|
752
630
|
title: "Get Package",
|
|
753
631
|
description: 'Fetch walkerOS package details from npm. By default returns schemas + hint texts + example summaries (lightweight). Use section parameter to get full content: "hints" (with code blocks), "examples" (full in/out data), or "all" (everything). Use package_search first to browse available packages.',
|
|
754
632
|
inputSchema: {
|
|
755
|
-
package:
|
|
633
|
+
package: z6.string().min(1).describe(
|
|
756
634
|
"Exact npm package name (e.g., @walkeros/web-destination-snowplow)"
|
|
757
635
|
),
|
|
758
|
-
version:
|
|
759
|
-
section:
|
|
636
|
+
version: z6.string().optional().describe("Package version (default: latest)"),
|
|
637
|
+
section: z6.enum(["hints", "examples", "all"]).optional().describe(
|
|
760
638
|
"Section to expand with full content. Default: summary view with schemas + hint texts + example descriptions"
|
|
761
639
|
)
|
|
762
640
|
},
|
|
763
|
-
outputSchema
|
|
641
|
+
// No outputSchema — removed to avoid SDK -32602 crashes on unexpected field values
|
|
764
642
|
annotations: {
|
|
765
643
|
readOnlyHint: true,
|
|
766
644
|
destructiveHint: false,
|
|
@@ -771,12 +649,24 @@ function registerGetPackageSchemaTool(server2) {
|
|
|
771
649
|
async ({ package: packageName, version, section }) => {
|
|
772
650
|
try {
|
|
773
651
|
const info = await fetchPackage(packageName, { version });
|
|
652
|
+
const mergedSchemas = {};
|
|
653
|
+
if (info.type) {
|
|
654
|
+
mergedSchemas.config = mergeConfigSchema(
|
|
655
|
+
info.type,
|
|
656
|
+
info.schemas
|
|
657
|
+
);
|
|
658
|
+
}
|
|
659
|
+
for (const [key, value] of Object.entries(info.schemas)) {
|
|
660
|
+
if (key !== "settings") {
|
|
661
|
+
mergedSchemas[key] = value;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
774
664
|
const result = {
|
|
775
665
|
package: info.packageName,
|
|
776
666
|
version: info.version,
|
|
777
667
|
type: info.type,
|
|
778
|
-
platform: info.platform,
|
|
779
|
-
schemas:
|
|
668
|
+
platform: normalizePlatform(info.platform),
|
|
669
|
+
schemas: mergedSchemas
|
|
780
670
|
};
|
|
781
671
|
if (info.hints) {
|
|
782
672
|
if (section === "hints" || section === "all") {
|
|
@@ -810,7 +700,7 @@ function registerGetPackageSchemaTool(server2) {
|
|
|
810
700
|
}
|
|
811
701
|
|
|
812
702
|
// src/tools/flow-load.ts
|
|
813
|
-
import { z as
|
|
703
|
+
import { z as z7 } from "zod";
|
|
814
704
|
import { loadJsonConfig as loadJsonConfig2 } from "@walkeros/cli";
|
|
815
705
|
import { mcpResult as mcpResult7, mcpError as mcpError7 } from "@walkeros/core";
|
|
816
706
|
var WEB_SKELETON = {
|
|
@@ -842,16 +732,16 @@ function registerFlowLoadTool(server2) {
|
|
|
842
732
|
title: "Load or Create Flow",
|
|
843
733
|
description: "Load an existing flow configuration from a local file path, URL, or walkerOS API (by flow ID). Or create a new empty flow by specifying a platform (web or server). Use the add-step prompt to add sources, destinations, transformers, or stores to the flow.",
|
|
844
734
|
inputSchema: {
|
|
845
|
-
source:
|
|
846
|
-
"Flow source: local file path (./flow.json), URL (https://...), or API flow ID (cfg_...). Omit to create a new flow."
|
|
735
|
+
source: z7.string().optional().describe(
|
|
736
|
+
"Flow source: local file path (./flow.json), URL (https://...), inline JSON string, or API flow ID (cfg_...). Omit to create a new flow."
|
|
847
737
|
),
|
|
848
|
-
platform:
|
|
738
|
+
platform: z7.enum(["web", "server"]).optional().describe(
|
|
849
739
|
"Platform for new flows. Required when source is omitted. web = browser tracking, server = Node.js HTTP."
|
|
850
740
|
)
|
|
851
741
|
},
|
|
852
742
|
outputSchema: {
|
|
853
|
-
version:
|
|
854
|
-
flows:
|
|
743
|
+
version: z7.number().describe("Flow config version"),
|
|
744
|
+
flows: z7.record(z7.string(), z7.unknown()).describe("Flow definitions")
|
|
855
745
|
},
|
|
856
746
|
annotations: {
|
|
857
747
|
readOnlyHint: true,
|
|
@@ -907,7 +797,7 @@ function registerFlowLoadTool(server2) {
|
|
|
907
797
|
}
|
|
908
798
|
|
|
909
799
|
// src/tools/feedback.ts
|
|
910
|
-
import { z as
|
|
800
|
+
import { z as z8 } from "zod";
|
|
911
801
|
import { feedback, readConfig, writeConfig } from "@walkeros/cli";
|
|
912
802
|
import { mcpResult as mcpResult8, mcpError as mcpError8 } from "@walkeros/core";
|
|
913
803
|
function registerFeedbackTool(server2) {
|
|
@@ -917,8 +807,8 @@ function registerFeedbackTool(server2) {
|
|
|
917
807
|
title: "Send Feedback",
|
|
918
808
|
description: "Send feedback about walkerOS",
|
|
919
809
|
inputSchema: {
|
|
920
|
-
text:
|
|
921
|
-
anonymous:
|
|
810
|
+
text: z8.string().describe("Your feedback text"),
|
|
811
|
+
anonymous: z8.boolean().optional().describe(
|
|
922
812
|
"Include user/project info? false = include, true = anonymous. Only needed on first call if not yet configured."
|
|
923
813
|
)
|
|
924
814
|
},
|
|
@@ -952,7 +842,7 @@ function registerFeedbackTool(server2) {
|
|
|
952
842
|
writeConfig({ ...base, anonymousFeedback: anonymous });
|
|
953
843
|
}
|
|
954
844
|
const isAnonymous = explicitAnonymous ?? anonymous ?? true;
|
|
955
|
-
await feedback(text, { anonymous: isAnonymous });
|
|
845
|
+
await feedback(text, { anonymous: isAnonymous, version: "3.1.0" });
|
|
956
846
|
return mcpResult8({ ok: true }, "Feedback sent. Thanks!");
|
|
957
847
|
} catch (error) {
|
|
958
848
|
return mcpError8(error);
|
|
@@ -962,7 +852,7 @@ function registerFeedbackTool(server2) {
|
|
|
962
852
|
}
|
|
963
853
|
|
|
964
854
|
// src/tools/api.ts
|
|
965
|
-
import { z as
|
|
855
|
+
import { z as z10 } from "zod";
|
|
966
856
|
import {
|
|
967
857
|
whoami,
|
|
968
858
|
listProjects,
|
|
@@ -986,11 +876,11 @@ import {
|
|
|
986
876
|
import { mcpResult as mcpResult9, mcpError as mcpError9 } from "@walkeros/core";
|
|
987
877
|
|
|
988
878
|
// src/schemas/api-output.ts
|
|
989
|
-
import { z as
|
|
879
|
+
import { z as z9 } from "zod";
|
|
990
880
|
var ApiOutputShape = {
|
|
991
|
-
action:
|
|
992
|
-
ok:
|
|
993
|
-
data:
|
|
881
|
+
action: z9.string().describe("Action that was executed"),
|
|
882
|
+
ok: z9.boolean().describe("Whether the action succeeded"),
|
|
883
|
+
data: z9.unknown().describe("Action-specific result data")
|
|
994
884
|
};
|
|
995
885
|
|
|
996
886
|
// src/tools/api.ts
|
|
@@ -1018,21 +908,26 @@ function registerApiTool(server2) {
|
|
|
1018
908
|
"api",
|
|
1019
909
|
{
|
|
1020
910
|
title: "walkerOS Cloud API",
|
|
1021
|
-
description: "Manage walkerOS cloud projects, flows, and deployments. Requires WALKEROS_TOKEN env var.\n\nActions:\n- whoami \u2014 verify token, get user info\n- project.list/get/create/update/delete \u2014 manage projects\n- flow.list/get/create/update/delete/duplicate \u2014 manage flow configs\n- deploy \u2014 deploy a flow (auto-detects web/server)\n- deployment.get/list/create/delete \u2014 manage deployments\n\nParameters vary by action.
|
|
911
|
+
description: "Manage walkerOS cloud projects, flows, and deployments. Requires WALKEROS_TOKEN env var.\n\nActions:\n- whoami \u2014 verify token, get user info\n- project.list/get/create/update/delete \u2014 manage projects\n- flow.list/get/create/update/delete/duplicate \u2014 manage flow configs\n- deploy \u2014 deploy a flow (auto-detects web/server)\n- deployment.get/list/create/delete \u2014 manage deployments\n\nParameters vary by action. content = Flow.Config JSON for flow.create/update.",
|
|
1022
912
|
inputSchema: {
|
|
1023
|
-
action:
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
913
|
+
action: z10.enum(ACTIONS).describe("API action to perform"),
|
|
914
|
+
projectId: z10.string().optional().describe(
|
|
915
|
+
"Project ID (proj_...). Required for: project.get/update/delete, flow.create, flow.list. Falls back to WALKEROS_PROJECT_ID env var."
|
|
916
|
+
),
|
|
917
|
+
flowId: z10.string().optional().describe(
|
|
918
|
+
"Flow ID (flow_...) or config ID (cfg_...). Required for: flow.get, flow.update, flow.delete, flow.duplicate, deploy. For deployment.get/delete: can be a deployment slug."
|
|
919
|
+
),
|
|
920
|
+
name: z10.string().optional().describe("Name for create/update operations"),
|
|
921
|
+
content: z10.record(z10.string(), z10.unknown()).optional().describe("Flow.Config JSON for flow operations"),
|
|
922
|
+
patch: z10.boolean().optional().describe("Use merge-patch for flow.update (default: true)"),
|
|
923
|
+
wait: z10.boolean().optional().describe("Wait for deploy to complete (default: true)"),
|
|
924
|
+
flowName: z10.string().optional().describe("Flow name for multi-settings flows"),
|
|
925
|
+
fields: z10.array(z10.string()).optional().describe("Dot-path field selectors for flow.get"),
|
|
926
|
+
type: z10.enum(["web", "server"]).optional().describe("Deployment type for deployment.create"),
|
|
927
|
+
sort: z10.string().optional().describe("Sort field for list operations"),
|
|
928
|
+
order: z10.enum(["asc", "desc"]).optional().describe("Sort order"),
|
|
929
|
+
status: z10.string().optional().describe("Status filter for deployment.list"),
|
|
930
|
+
includeDeleted: z10.boolean().optional().describe("Include deleted items in lists")
|
|
1036
931
|
},
|
|
1037
932
|
outputSchema: ApiOutputShape,
|
|
1038
933
|
annotations: {
|
|
@@ -1045,7 +940,8 @@ function registerApiTool(server2) {
|
|
|
1045
940
|
async (params, extra) => {
|
|
1046
941
|
const {
|
|
1047
942
|
action,
|
|
1048
|
-
|
|
943
|
+
projectId,
|
|
944
|
+
flowId,
|
|
1049
945
|
name,
|
|
1050
946
|
content,
|
|
1051
947
|
patch,
|
|
@@ -1075,7 +971,7 @@ function registerApiTool(server2) {
|
|
|
1075
971
|
break;
|
|
1076
972
|
}
|
|
1077
973
|
case "project.get": {
|
|
1078
|
-
data = await getProject({ projectId
|
|
974
|
+
data = await getProject({ projectId });
|
|
1079
975
|
summary = `Project "${data.name}"`;
|
|
1080
976
|
break;
|
|
1081
977
|
}
|
|
@@ -1087,19 +983,19 @@ function registerApiTool(server2) {
|
|
|
1087
983
|
}
|
|
1088
984
|
case "project.update": {
|
|
1089
985
|
if (!name) throw new Error("name required for project.update");
|
|
1090
|
-
data = await updateProject({ projectId
|
|
986
|
+
data = await updateProject({ projectId, name });
|
|
1091
987
|
summary = `Updated project "${name}"`;
|
|
1092
988
|
break;
|
|
1093
989
|
}
|
|
1094
990
|
case "project.delete": {
|
|
1095
|
-
data = await deleteProject({ projectId
|
|
1096
|
-
summary = `Deleted project ${
|
|
991
|
+
data = await deleteProject({ projectId });
|
|
992
|
+
summary = `Deleted project ${projectId ?? "default"}`;
|
|
1097
993
|
break;
|
|
1098
994
|
}
|
|
1099
995
|
// Flows
|
|
1100
996
|
case "flow.list": {
|
|
1101
997
|
data = await listFlows({
|
|
1102
|
-
projectId
|
|
998
|
+
projectId,
|
|
1103
999
|
sort,
|
|
1104
1000
|
order,
|
|
1105
1001
|
includeDeleted
|
|
@@ -1108,70 +1004,97 @@ function registerApiTool(server2) {
|
|
|
1108
1004
|
break;
|
|
1109
1005
|
}
|
|
1110
1006
|
case "flow.get": {
|
|
1111
|
-
if (!
|
|
1112
|
-
data = await getFlow({ flowId
|
|
1113
|
-
summary = `Flow "${data.name}" (${
|
|
1007
|
+
if (!flowId) throw new Error("flowId required for flow.get");
|
|
1008
|
+
data = await getFlow({ flowId, projectId, fields });
|
|
1009
|
+
summary = `Flow "${data.name}" (${flowId})`;
|
|
1114
1010
|
break;
|
|
1115
1011
|
}
|
|
1116
1012
|
case "flow.create": {
|
|
1117
1013
|
if (!name) throw new Error("name required for flow.create");
|
|
1118
1014
|
if (!content) throw new Error("content required for flow.create");
|
|
1119
|
-
data = await createFlow({ name, content });
|
|
1015
|
+
data = await createFlow({ name, content, projectId });
|
|
1120
1016
|
summary = `Created flow "${name}" (${data.id})`;
|
|
1121
1017
|
break;
|
|
1122
1018
|
}
|
|
1123
1019
|
case "flow.update": {
|
|
1124
|
-
if (!
|
|
1020
|
+
if (!flowId) throw new Error("flowId required for flow.update");
|
|
1125
1021
|
data = await updateFlow({
|
|
1126
|
-
flowId
|
|
1022
|
+
flowId,
|
|
1127
1023
|
name,
|
|
1128
1024
|
content,
|
|
1025
|
+
projectId,
|
|
1129
1026
|
mergePatch: patch ?? true
|
|
1130
1027
|
});
|
|
1131
|
-
summary = `Updated flow ${
|
|
1028
|
+
summary = `Updated flow ${flowId}`;
|
|
1132
1029
|
break;
|
|
1133
1030
|
}
|
|
1134
1031
|
case "flow.delete": {
|
|
1135
|
-
if (!
|
|
1136
|
-
data = await deleteFlow({ flowId
|
|
1137
|
-
summary = `Deleted flow ${
|
|
1032
|
+
if (!flowId) throw new Error("flowId required for flow.delete");
|
|
1033
|
+
data = await deleteFlow({ flowId, projectId });
|
|
1034
|
+
summary = `Deleted flow ${flowId}`;
|
|
1138
1035
|
break;
|
|
1139
1036
|
}
|
|
1140
1037
|
case "flow.duplicate": {
|
|
1141
|
-
if (!
|
|
1142
|
-
data = await duplicateFlow({ flowId
|
|
1143
|
-
summary = `Duplicated flow ${
|
|
1038
|
+
if (!flowId) throw new Error("flowId required for flow.duplicate");
|
|
1039
|
+
data = await duplicateFlow({ flowId, name, projectId });
|
|
1040
|
+
summary = `Duplicated flow ${flowId}`;
|
|
1144
1041
|
break;
|
|
1145
1042
|
}
|
|
1146
1043
|
// Deploy
|
|
1147
1044
|
case "deploy": {
|
|
1148
|
-
if (!
|
|
1045
|
+
if (!flowId) throw new Error("flowId required for deploy");
|
|
1149
1046
|
const progressToken = extra._meta?.progressToken;
|
|
1047
|
+
const DEPLOY_TIMEOUT_MS = 9e4;
|
|
1048
|
+
const timeoutSignal = AbortSignal.timeout(DEPLOY_TIMEOUT_MS);
|
|
1049
|
+
const combinedAbort = new AbortController();
|
|
1050
|
+
const onAbort = () => combinedAbort.abort();
|
|
1051
|
+
timeoutSignal.addEventListener("abort", onAbort);
|
|
1052
|
+
extra.signal?.addEventListener("abort", onAbort);
|
|
1150
1053
|
data = await deploy({
|
|
1151
|
-
flowId
|
|
1054
|
+
flowId,
|
|
1055
|
+
projectId,
|
|
1152
1056
|
wait: wait ?? true,
|
|
1153
1057
|
flowName,
|
|
1058
|
+
timeout: DEPLOY_TIMEOUT_MS,
|
|
1154
1059
|
onStatus: (s, sub) => {
|
|
1155
1060
|
if (!progressToken) return;
|
|
1061
|
+
const key = sub ? `${s}:${sub}` : s;
|
|
1156
1062
|
const stages = {
|
|
1157
|
-
bundling:
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1063
|
+
"bundling:building": {
|
|
1064
|
+
progress: 20,
|
|
1065
|
+
label: "Building bundle..."
|
|
1066
|
+
},
|
|
1067
|
+
"deploying:publishing": {
|
|
1068
|
+
progress: 60,
|
|
1069
|
+
label: "Publishing to CDN..."
|
|
1070
|
+
},
|
|
1071
|
+
"deploying:provisioning": {
|
|
1072
|
+
progress: 60,
|
|
1073
|
+
label: "Provisioning container..."
|
|
1074
|
+
},
|
|
1075
|
+
"deploying:starting": {
|
|
1076
|
+
progress: 80,
|
|
1077
|
+
label: "Starting container..."
|
|
1078
|
+
},
|
|
1079
|
+
published: { progress: 100, label: "Published" },
|
|
1080
|
+
active: { progress: 100, label: "Active" },
|
|
1081
|
+
failed: { progress: 100, label: "Failed" }
|
|
1162
1082
|
};
|
|
1083
|
+
const stage = stages[key] ?? stages[s] ?? { progress: 10, label: key };
|
|
1163
1084
|
extra.sendNotification({
|
|
1164
1085
|
method: "notifications/progress",
|
|
1165
1086
|
params: {
|
|
1166
1087
|
progressToken,
|
|
1167
|
-
progress:
|
|
1088
|
+
progress: stage.progress,
|
|
1168
1089
|
total: 100,
|
|
1169
|
-
message:
|
|
1090
|
+
message: stage.label
|
|
1170
1091
|
}
|
|
1171
1092
|
});
|
|
1172
1093
|
},
|
|
1173
|
-
signal:
|
|
1094
|
+
signal: combinedAbort.signal
|
|
1174
1095
|
});
|
|
1096
|
+
timeoutSignal.removeEventListener("abort", onAbort);
|
|
1097
|
+
extra.signal?.removeEventListener("abort", onAbort);
|
|
1175
1098
|
const st = data.status;
|
|
1176
1099
|
const deployData = data;
|
|
1177
1100
|
if (st === "failed") {
|
|
@@ -1180,7 +1103,7 @@ function registerApiTool(server2) {
|
|
|
1180
1103
|
next: ["Run flow_validate to check your configuration"]
|
|
1181
1104
|
});
|
|
1182
1105
|
} else {
|
|
1183
|
-
summary = `Deployed flow ${
|
|
1106
|
+
summary = `Deployed flow ${flowId} \u2014 status: ${st}`;
|
|
1184
1107
|
const publicUrl = deployData.publicUrl;
|
|
1185
1108
|
const containerUrl = deployData.containerUrl;
|
|
1186
1109
|
const deployType = deployData.type;
|
|
@@ -1202,21 +1125,21 @@ function registerApiTool(server2) {
|
|
|
1202
1125
|
}
|
|
1203
1126
|
// Deployments
|
|
1204
1127
|
case "deployment.get": {
|
|
1205
|
-
if (!
|
|
1128
|
+
if (!flowId)
|
|
1206
1129
|
throw new Error(
|
|
1207
|
-
"
|
|
1130
|
+
"flowId (flowId or slug) required for deployment.get"
|
|
1208
1131
|
);
|
|
1209
1132
|
try {
|
|
1210
|
-
data = await getDeployment({ flowId
|
|
1133
|
+
data = await getDeployment({ flowId, flowName });
|
|
1211
1134
|
} catch {
|
|
1212
|
-
data = await getDeploymentBySlug({ slug:
|
|
1135
|
+
data = await getDeploymentBySlug({ slug: flowId });
|
|
1213
1136
|
}
|
|
1214
|
-
summary = `Deployment ${data.slug ??
|
|
1137
|
+
summary = `Deployment ${data.slug ?? flowId} \u2014 ${data.status}`;
|
|
1215
1138
|
break;
|
|
1216
1139
|
}
|
|
1217
1140
|
case "deployment.list": {
|
|
1218
1141
|
data = await listDeployments({
|
|
1219
|
-
projectId
|
|
1142
|
+
projectId,
|
|
1220
1143
|
type,
|
|
1221
1144
|
status
|
|
1222
1145
|
});
|
|
@@ -1228,15 +1151,15 @@ function registerApiTool(server2) {
|
|
|
1228
1151
|
throw new Error(
|
|
1229
1152
|
"type (web/server) required for deployment.create"
|
|
1230
1153
|
);
|
|
1231
|
-
data = await createDep({ type, label: name, projectId
|
|
1154
|
+
data = await createDep({ type, label: name, projectId });
|
|
1232
1155
|
summary = `Created ${type} deployment ${data.slug}`;
|
|
1233
1156
|
break;
|
|
1234
1157
|
}
|
|
1235
1158
|
case "deployment.delete": {
|
|
1236
|
-
if (!
|
|
1237
|
-
throw new Error("
|
|
1238
|
-
data = await deleteDep({ slug:
|
|
1239
|
-
summary = `Deleted deployment ${
|
|
1159
|
+
if (!flowId)
|
|
1160
|
+
throw new Error("flowId (slug) required for deployment.delete");
|
|
1161
|
+
data = await deleteDep({ slug: flowId });
|
|
1162
|
+
summary = `Deleted deployment ${flowId}`;
|
|
1240
1163
|
break;
|
|
1241
1164
|
}
|
|
1242
1165
|
default:
|
|
@@ -1247,6 +1170,22 @@ function registerApiTool(server2) {
|
|
|
1247
1170
|
return mcpResult9({ action, ok: true, data }, summary);
|
|
1248
1171
|
} catch (error) {
|
|
1249
1172
|
const msg = error instanceof Error ? error.message : "";
|
|
1173
|
+
const name2 = error instanceof Error ? error.name : "";
|
|
1174
|
+
if (action === "deploy" && (name2 === "AbortError" || name2 === "TimeoutError" || msg.includes("abort"))) {
|
|
1175
|
+
return mcpResult9(
|
|
1176
|
+
{
|
|
1177
|
+
action,
|
|
1178
|
+
ok: true,
|
|
1179
|
+
data: { status: "deploying", flowId }
|
|
1180
|
+
},
|
|
1181
|
+
`Deploy in progress (timed out waiting). Use deployment.list with projectId to check status.`,
|
|
1182
|
+
{
|
|
1183
|
+
next: [
|
|
1184
|
+
'Use api(action: "deployment.list") to check current status'
|
|
1185
|
+
]
|
|
1186
|
+
}
|
|
1187
|
+
);
|
|
1188
|
+
}
|
|
1250
1189
|
if (msg.includes("401") || msg.includes("403") || msg.includes("Unauthorized"))
|
|
1251
1190
|
return mcpError9(
|
|
1252
1191
|
error,
|
|
@@ -1268,14 +1207,17 @@ import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
|
1268
1207
|
import { fetchPackageSchema } from "@walkeros/core";
|
|
1269
1208
|
function registerPackageSchemaResources(server2) {
|
|
1270
1209
|
const template = new ResourceTemplate("walkeros://schema/{packageName}", {
|
|
1271
|
-
list: async () =>
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1210
|
+
list: async () => {
|
|
1211
|
+
const catalog = await fetchCatalog();
|
|
1212
|
+
return {
|
|
1213
|
+
resources: catalog.map((pkg) => ({
|
|
1214
|
+
uri: `walkeros://schema/${encodeURIComponent(pkg.name)}`,
|
|
1215
|
+
name: pkg.name,
|
|
1216
|
+
description: `Schema and examples for ${pkg.name}`,
|
|
1217
|
+
mimeType: "application/json"
|
|
1218
|
+
}))
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1279
1221
|
});
|
|
1280
1222
|
server2.registerResource(
|
|
1281
1223
|
"package-schema",
|
|
@@ -1517,30 +1459,33 @@ function registerReferenceResources(server2) {
|
|
|
1517
1459
|
description: "Complete walkerOS package catalog \u2014 all sources, destinations, transformers, and stores",
|
|
1518
1460
|
mimeType: "application/json"
|
|
1519
1461
|
},
|
|
1520
|
-
async () =>
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1462
|
+
async () => {
|
|
1463
|
+
const catalog = await fetchCatalog();
|
|
1464
|
+
return {
|
|
1465
|
+
contents: [
|
|
1466
|
+
{
|
|
1467
|
+
uri: "walkeros://reference/packages",
|
|
1468
|
+
text: JSON.stringify(catalog, null, 2),
|
|
1469
|
+
mimeType: "application/json"
|
|
1470
|
+
}
|
|
1471
|
+
]
|
|
1472
|
+
};
|
|
1473
|
+
}
|
|
1529
1474
|
);
|
|
1530
1475
|
}
|
|
1531
1476
|
|
|
1532
1477
|
// src/prompts/add-step.ts
|
|
1533
|
-
import { z as
|
|
1478
|
+
import { z as z11 } from "zod";
|
|
1534
1479
|
function registerAddStepPrompt(server2) {
|
|
1535
1480
|
server2.registerPrompt(
|
|
1536
1481
|
"add-step",
|
|
1537
1482
|
{
|
|
1538
1483
|
description: "Add a source, destination, transformer, or store step to a flow configuration. Guides through package selection, config scaffolding, and wiring.",
|
|
1539
1484
|
argsSchema: {
|
|
1540
|
-
stepType:
|
|
1485
|
+
stepType: z11.string().optional().describe(
|
|
1541
1486
|
"Type of step to add: source, destination, transformer, or store"
|
|
1542
1487
|
),
|
|
1543
|
-
flowPath:
|
|
1488
|
+
flowPath: z11.string().optional().describe("Path to the flow.json file to modify")
|
|
1544
1489
|
}
|
|
1545
1490
|
},
|
|
1546
1491
|
async ({ stepType, flowPath }) => ({
|
|
@@ -1554,7 +1499,7 @@ function registerAddStepPrompt(server2) {
|
|
|
1554
1499
|
"",
|
|
1555
1500
|
"Follow these steps:",
|
|
1556
1501
|
`1. ${stepType ? "" : "Ask what type of step (source, destination, transformer, store). Then "}Use package_search to browse available packages for the selected type and platform.`,
|
|
1557
|
-
`2. Use package_get
|
|
1502
|
+
`2. Use package_get to read the package's config schema (schemas.config contains the full config shape: base fields like consent/require/logger + package-specific settings). Use section="hints" for additional guidance.`,
|
|
1558
1503
|
'3. Use package_get with section="examples" to see working configuration examples.',
|
|
1559
1504
|
"4. Scaffold the step config using the package schemas \u2014 include required settings with placeholder values.",
|
|
1560
1505
|
"5. Wire the step into the flow: add to packages section (with version if needed), connect via next/before chains if needed.",
|
|
@@ -1580,14 +1525,14 @@ function registerAddStepPrompt(server2) {
|
|
|
1580
1525
|
}
|
|
1581
1526
|
|
|
1582
1527
|
// src/prompts/setup-mapping.ts
|
|
1583
|
-
import { z as
|
|
1528
|
+
import { z as z12 } from "zod";
|
|
1584
1529
|
function registerSetupMappingPrompt(server2) {
|
|
1585
1530
|
server2.registerPrompt(
|
|
1586
1531
|
"setup-mapping",
|
|
1587
1532
|
{
|
|
1588
1533
|
description: "Set up event mapping for any step in a flow. Teaches mapping syntax and uses package examples as templates.",
|
|
1589
1534
|
argsSchema: {
|
|
1590
|
-
stepName:
|
|
1535
|
+
stepName: z12.string().optional().describe('Step name in the flow (e.g., "gtag", "meta", "express")')
|
|
1591
1536
|
}
|
|
1592
1537
|
},
|
|
1593
1538
|
async ({ stepName }) => ({
|
|
@@ -1619,14 +1564,14 @@ function registerSetupMappingPrompt(server2) {
|
|
|
1619
1564
|
}
|
|
1620
1565
|
|
|
1621
1566
|
// src/prompts/manage-contract.ts
|
|
1622
|
-
import { z as
|
|
1567
|
+
import { z as z13 } from "zod";
|
|
1623
1568
|
function registerManageContractPrompt(server2) {
|
|
1624
1569
|
server2.registerPrompt(
|
|
1625
1570
|
"manage-contract",
|
|
1626
1571
|
{
|
|
1627
1572
|
description: "Create or update event contracts for a flow. Can generate contracts from existing mappings or scaffold mappings from contracts.",
|
|
1628
1573
|
argsSchema: {
|
|
1629
|
-
direction:
|
|
1574
|
+
direction: z13.string().optional().describe(
|
|
1630
1575
|
'Direction: "from-mappings" (extract contract from existing mappings), "from-scratch" (create new contract), or "to-mappings" (scaffold mappings from contract)'
|
|
1631
1576
|
)
|
|
1632
1577
|
}
|
|
@@ -1664,14 +1609,14 @@ function registerManageContractPrompt(server2) {
|
|
|
1664
1609
|
}
|
|
1665
1610
|
|
|
1666
1611
|
// src/prompts/use-definitions.ts
|
|
1667
|
-
import { z as
|
|
1612
|
+
import { z as z14 } from "zod";
|
|
1668
1613
|
function registerUseDefinitionsPrompt(server2) {
|
|
1669
1614
|
server2.registerPrompt(
|
|
1670
1615
|
"use-definitions",
|
|
1671
1616
|
{
|
|
1672
1617
|
description: "Extract shared patterns into definitions and variables for DRY, environment-aware flow configurations.",
|
|
1673
1618
|
argsSchema: {
|
|
1674
|
-
flowPath:
|
|
1619
|
+
flowPath: z14.string().optional().describe("Path to the flow.json file to analyze")
|
|
1675
1620
|
}
|
|
1676
1621
|
},
|
|
1677
1622
|
async ({ flowPath }) => ({
|
|
@@ -1715,7 +1660,7 @@ function registerUseDefinitionsPrompt(server2) {
|
|
|
1715
1660
|
var server = new McpServer(
|
|
1716
1661
|
{
|
|
1717
1662
|
name: "walkeros-flow",
|
|
1718
|
-
version: "3.0
|
|
1663
|
+
version: "3.1.0"
|
|
1719
1664
|
},
|
|
1720
1665
|
{
|
|
1721
1666
|
instructions: `walkerOS is an open-source, privacy-first event data collection platform. Define event pipelines as code using JSON flow configurations.
|
|
@@ -1751,7 +1696,7 @@ Key rules:
|
|
|
1751
1696
|
|
|
1752
1697
|
## Getting Started
|
|
1753
1698
|
|
|
1754
|
-
1. \`flow_load({ platform: "web" })\` or \`flow_load({ source: "./flow.json" })\` \u2014 create or load a flow
|
|
1699
|
+
1. \`flow_load({ platform: "web" })\` or \`flow_load({ source: "./flow.json" })\` \u2014 create or load a flow (also accepts inline JSON strings or URLs)
|
|
1755
1700
|
2. \`package_search({ type: "destination", platform: "web" })\` \u2014 discover available packages
|
|
1756
1701
|
3. Use the \`add-step\` prompt to add sources, destinations, transformers, or stores
|
|
1757
1702
|
4. Use the \`setup-mapping\` prompt to configure event transformations
|
|
@@ -1768,7 +1713,7 @@ Read these before constructing configs manually: \`walkeros://reference/flow-sch
|
|
|
1768
1713
|
|
|
1769
1714
|
## Key Concepts
|
|
1770
1715
|
|
|
1771
|
-
- **Steps** are sources, destinations, transformers, or stores \u2014 each backed by an npm package. Use \`package_search\` to browse, \`package_get\` for schemas and examples.
|
|
1716
|
+
- **Steps** are sources, destinations, transformers, or stores \u2014 each backed by an npm package. Use \`package_search\` to browse, \`package_get\` for schemas and examples. \`package_get\` returns \`schemas.config\` \u2014 a merged JSON Schema combining base config fields (consent, require, logger, mapping, etc.) with the package's typed settings. Non-config schemas (mapping rules, utility schemas) remain as sibling keys.
|
|
1772
1717
|
- **Mapping** transforms events using data/map/loop/set/condition rules. Same syntax on sources and destinations. Mapping rules use NESTED entity \u2192 action keying: event name "product add" maps to \`{ "product": { "add": Rule } }\`. Wildcards: \`{ "*": { "view": Rule } }\`.
|
|
1773
1718
|
- **Contracts** define event schemas using entity-action keying. Can generate FROM mappings or scaffold mappings FROM contracts.
|
|
1774
1719
|
- **Variables** ($var, $env, $def, $code, $store) enable DRY, environment-aware config. Use the \`use-definitions\` prompt to extract shared patterns.
|