@walkeros/mcp 3.0.0-next-1773236214827 → 3.0.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.
package/dist/index.js CHANGED
@@ -56,17 +56,9 @@ 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("Transformed payload sent"),
60
- errors: z.array(z.string()).optional().describe("Errors for this destination")
59
+ payload: z.unknown().optional().describe("Transformed payload sent")
61
60
  })
62
61
  ).optional().describe("Per-destination results"),
63
- transformers: z.record(
64
- z.string(),
65
- z.object({
66
- passed: z.boolean().describe("Whether event passed through"),
67
- modified: z.boolean().describe("Whether event was modified")
68
- })
69
- ).optional().describe("Per-transformer results"),
70
62
  exampleMatch: z.object({
71
63
  name: z.string(),
72
64
  step: z.string(),
@@ -176,10 +168,18 @@ function registerFlowValidateTool(server2) {
176
168
  "Use flow_simulate to test event flow",
177
169
  "Use flow_bundle to build"
178
170
  ]
179
- } : { next: ["Fix errors above, then run flow_validate again"] };
171
+ } : {
172
+ next: [
173
+ "Fix errors above, then run flow_validate again",
174
+ "Read walkeros://reference/flow-schema for correct structure"
175
+ ]
176
+ };
180
177
  return mcpResult(result, summary, hints);
181
178
  } catch (error) {
182
- return mcpError(error);
179
+ return mcpError(
180
+ error,
181
+ "Check the input parameter \u2014 expected a JSON string, file path, or URL"
182
+ );
183
183
  }
184
184
  }
185
185
  );
@@ -236,14 +236,23 @@ function registerFlowBundleTool(server2) {
236
236
  stats: stats ?? true,
237
237
  buildOverrides: output ? { output } : void 0
238
238
  });
239
- const output_ = result ?? {
240
- success: true,
241
- message: "Bundle created"
242
- };
239
+ if (!result) {
240
+ return mcpResult2(
241
+ { success: false, message: "Bundle produced no output" },
242
+ "Bundle produced no output",
243
+ {
244
+ warnings: [
245
+ "The build returned no result. The flow may be empty or misconfigured."
246
+ ],
247
+ next: ["Run flow_validate to check your configuration"]
248
+ }
249
+ );
250
+ }
251
+ const output_ = result;
243
252
  const size = output_.totalSize;
244
253
  const time = output_.buildTime;
245
254
  const summary = `Bundled${size ? ` (${formatBytes(size)}` : ""}${time ? `, ${time}ms)` : size ? ")" : ""}`;
246
- return mcpResult2(output_, summary, {
255
+ return mcpResult2({ success: true, ...output_ }, summary, {
247
256
  next: [
248
257
  "Use flow_simulate to test",
249
258
  "Use api({ action: 'deploy' }) to publish"
@@ -269,7 +278,7 @@ function registerFlowSimulateTool(server2) {
269
278
  "flow_simulate",
270
279
  {
271
280
  title: "Simulate Flow",
272
- description: "Simulate events through a walkerOS flow without making real API calls. Processes events through the full pipeline including transformers and destinations, returning summarized per-destination results. Use the example parameter to load event input from a step example and compare output.",
281
+ description: 'Simulate events through a walkerOS flow without making real API calls. Events must be in walkerOS format (post-source): { name: "entity action", data: {...} }. Raw source input (dataLayer pushes, HTTP requests) must first be converted to walkerOS events. Check source package examples to see what events a source outputs. Use the example parameter to load event input from a step example and compare output.',
273
282
  inputSchema: schemas3.SimulateInputShape,
274
283
  outputSchema: SimulateOutputShape,
275
284
  annotations: {
@@ -297,8 +306,7 @@ function registerFlowSimulateTool(server2) {
297
306
  destinations[name] = {
298
307
  received: calls.length > 0,
299
308
  calls: calls.length,
300
- payload: calls.length > 0 ? calls[calls.length - 1] : void 0,
301
- errors: []
309
+ payload: calls.length > 0 ? calls[calls.length - 1] : void 0
302
310
  };
303
311
  }
304
312
  }
@@ -306,6 +314,17 @@ function registerFlowSimulateTool(server2) {
306
314
  const receivedCount = Object.values(destinations).filter(
307
315
  (d) => d.received
308
316
  ).length;
317
+ const warnings = [];
318
+ if (destCount === 0) {
319
+ warnings.push(
320
+ "No destinations found in flow configuration. Check that your flow defines at least one destination."
321
+ );
322
+ }
323
+ if (destCount > 0 && receivedCount === 0) {
324
+ warnings.push(
325
+ 'No destinations received the event. Most common cause: mapping keys must be NESTED entity \u2192 action objects \u2014 event "product add" needs { "product": { "add": Rule } }, not "product.add". Also check event name match and consent settings.'
326
+ );
327
+ }
309
328
  const summary = `${receivedCount}/${destCount} destinations received the event`;
310
329
  const result = {
311
330
  success: raw.success,
@@ -316,7 +335,8 @@ function registerFlowSimulateTool(server2) {
316
335
  duration: raw.duration
317
336
  };
318
337
  return mcpResult3(result, summary, {
319
- next: ["Use flow_bundle to build for production"]
338
+ next: ["Use flow_bundle to build for production"],
339
+ ...warnings.length > 0 ? { warnings } : {}
320
340
  });
321
341
  } catch (error) {
322
342
  return mcpError3(error, "Run flow_validate for detailed error messages");
@@ -351,10 +371,19 @@ function registerFlowPushTool(server2) {
351
371
  flow,
352
372
  platform
353
373
  });
374
+ if (!result.success) {
375
+ return mcpError4(
376
+ new Error(result.error || "Push failed"),
377
+ "Check destination configuration and network connectivity. For web destinations, use flow_simulate instead."
378
+ );
379
+ }
354
380
  const summary = `Pushed event${result.duration ? ` (${result.duration}ms)` : ""}`;
355
381
  return mcpResult4(result, summary);
356
382
  } catch (error) {
357
- return mcpError4(error);
383
+ return mcpError4(
384
+ error,
385
+ "Check configPath and event format. For web destinations, use flow_simulate instead."
386
+ );
358
387
  }
359
388
  }
360
389
  );
@@ -433,12 +462,19 @@ function registerFlowExamplesTool(server2) {
433
462
  count: examples.length,
434
463
  examples
435
464
  };
436
- const summary = `${examples.length} examples across ${stepSet.size} steps`;
437
- return mcpResult5(result, summary, {
465
+ const totalExamples = examples.length;
466
+ const summary = `${totalExamples} examples across ${stepSet.size} steps`;
467
+ const hints = {
438
468
  next: ["Use flow_simulate with example parameter to test"]
439
- });
469
+ };
470
+ if (totalExamples === 0) {
471
+ hints.warnings = [
472
+ "No examples found. Add examples to step definitions in your flow config for testing."
473
+ ];
474
+ }
475
+ return mcpResult5(result, summary, hints);
440
476
  } catch (error) {
441
- return mcpError5(error);
477
+ return mcpError5(error, "Check configPath \u2014 expected a flow.json file");
442
478
  }
443
479
  }
444
480
  );
@@ -668,7 +704,7 @@ function registerPackageSearchTool(server2) {
668
704
  ),
669
705
  version: z4.string().optional().describe("Package version for detailed lookup (default: latest)")
670
706
  },
671
- outputSchema: PackageSearchOutputShape,
707
+ // No outputSchema: browse mode returns {catalog, count}, lookup returns metadata — incompatible shapes
672
708
  annotations: {
673
709
  readOnlyHint: true,
674
710
  destructiveHint: false,
@@ -679,8 +715,9 @@ function registerPackageSearchTool(server2) {
679
715
  async ({ package: packageName, type, platform, version }) => {
680
716
  if (!packageName) {
681
717
  const catalog = filterRegistry({ type, platform });
718
+ const result = { catalog, count: catalog.length };
682
719
  const summary = `${catalog.length} packages found`;
683
- return mcpResult6(catalog, summary, {
720
+ return mcpResult6(result, summary, {
684
721
  next: ["Use package_get for schemas and examples"]
685
722
  });
686
723
  }
@@ -700,7 +737,10 @@ function registerPackageSearchTool(server2) {
700
737
  next: ["Use package_get for schemas and examples"]
701
738
  });
702
739
  } catch (error) {
703
- return mcpError6(error);
740
+ return mcpError6(
741
+ error,
742
+ "Package not found. Use package_search without parameters to browse available packages."
743
+ );
704
744
  }
705
745
  }
706
746
  );
@@ -760,7 +800,10 @@ function registerGetPackageSchemaTool(server2) {
760
800
  const summary = `${info.packageName} \u2014 ${schemaCount} schemas, ${exampleCount} examples`;
761
801
  return mcpResult6(result, summary);
762
802
  } catch (error) {
763
- return mcpError6(error);
803
+ return mcpError6(
804
+ error,
805
+ "Use package_search to browse available package names."
806
+ );
764
807
  }
765
808
  }
766
809
  );
@@ -771,7 +814,7 @@ import { z as z5 } from "zod";
771
814
  import { loadJsonConfig as loadJsonConfig2 } from "@walkeros/cli";
772
815
  import { mcpResult as mcpResult7, mcpError as mcpError7 } from "@walkeros/core";
773
816
  var WEB_SKELETON = {
774
- version: 1,
817
+ version: 3,
775
818
  flows: {
776
819
  default: {
777
820
  web: {},
@@ -782,7 +825,7 @@ var WEB_SKELETON = {
782
825
  }
783
826
  };
784
827
  var SERVER_SKELETON = {
785
- version: 1,
828
+ version: 3,
786
829
  flows: {
787
830
  default: {
788
831
  server: {},
@@ -806,6 +849,10 @@ function registerFlowLoadTool(server2) {
806
849
  "Platform for new flows. Required when source is omitted. web = browser tracking, server = Node.js HTTP."
807
850
  )
808
851
  },
852
+ outputSchema: {
853
+ version: z5.number().describe("Flow config version"),
854
+ flows: z5.record(z5.string(), z5.unknown()).describe("Flow definitions")
855
+ },
809
856
  annotations: {
810
857
  readOnlyHint: true,
811
858
  destructiveHint: false,
@@ -839,7 +886,12 @@ function registerFlowLoadTool(server2) {
839
886
  return mcpResult7(
840
887
  skeleton,
841
888
  `Created empty ${platform} flow. Use the add-step prompt to add sources, destinations, and transformers.`,
842
- { next: ["Use add-step prompt to add sources and destinations"] }
889
+ {
890
+ next: [
891
+ "Read walkeros://reference/flow-schema for config structure",
892
+ "Use add-step prompt to add sources and destinations"
893
+ ]
894
+ }
843
895
  );
844
896
  } catch (error) {
845
897
  const msg = error instanceof Error ? error.message : "";
@@ -1068,7 +1120,10 @@ function registerApiTool(server2) {
1068
1120
  const st = data.status;
1069
1121
  const deployData = data;
1070
1122
  if (st === "failed") {
1071
- summary = `Deploy failed: ${deployData.errorMessage ?? "unknown error"}`;
1123
+ const msg = `Deploy failed: ${deployData.errorMessage ?? "unknown error"}`;
1124
+ return mcpResult8({ action, ok: false, data }, msg, {
1125
+ next: ["Run flow_validate to check your configuration"]
1126
+ });
1072
1127
  } else {
1073
1128
  summary = `Deployed flow ${id} \u2014 status: ${st}`;
1074
1129
  const publicUrl = deployData.publicUrl;
@@ -1193,70 +1248,20 @@ function registerPackageSchemaResources(server2) {
1193
1248
  }
1194
1249
 
1195
1250
  // src/resources/references.ts
1196
- var FLOW_SCHEMA_REFERENCE = {
1197
- structure: {
1198
- version: "1 (required, use 1 for new flows)",
1199
- flows: {
1200
- "<flowName>": {
1201
- "web: {} | server: {}": "Platform marker (exactly one, use empty object as value)",
1202
- packages: "Record<packageName, {} | { path?, imports? }> \u2014 all referenced packages",
1203
- sources: "Record<name, { package, config?, env?, next? }> \u2014 event capture",
1204
- destinations: "Record<name, { package, config?, env?, mapping?, before? }> \u2014 event delivery",
1205
- transformers: "Record<name, { package, config?, env?, next? }> \u2014 event processing",
1206
- stores: "Record<name, { package, config?, env? }> \u2014 key-value storage",
1207
- collector: "{ consent?, globals? } \u2014 collector settings (optional)"
1208
- }
1209
- },
1210
- variables: "Record<string, string> \u2014 shared variables (optional)",
1211
- definitions: "Record<string, object> \u2014 reusable definitions (optional)",
1212
- contract: "Event contract for validation (optional)"
1213
- },
1214
- connectionRules: [
1215
- 'Sources have `next` \u2192 links to pre-collector transformer chain (e.g., next: "transformerName")',
1216
- 'Destinations have `before` \u2192 links to post-collector transformer chain (e.g., before: "transformerName")',
1217
- 'Transformers have `next` \u2192 chains to next transformer (e.g., next: "anotherTransformer")',
1218
- "Stores are passive \u2014 injected via `env` values using `$store:storeName` syntax",
1219
- "Mapping on destinations transforms vendor-agnostic events into vendor-specific formats"
1220
- ],
1221
- platformOptions: {
1222
- web: "Browser environment \u2014 uses @walkeros/web-source-browser as default source",
1223
- server: "Node.js environment \u2014 uses @walkeros/server-source-express as default source"
1224
- },
1225
- minimalExample: {
1226
- version: 1,
1227
- flows: {
1228
- default: {
1229
- web: {},
1230
- packages: {
1231
- "@walkeros/web-source-browser": {},
1232
- "@walkeros/web-destination-gtag": {}
1233
- },
1234
- sources: {
1235
- browser: { package: "@walkeros/web-source-browser", config: {} }
1236
- },
1237
- destinations: {
1238
- gtag: {
1239
- package: "@walkeros/web-destination-gtag",
1240
- config: { measurementId: "G-XXXXXXXXXX" }
1241
- }
1242
- }
1243
- }
1244
- }
1245
- }
1246
- };
1251
+ import { schemas as schemas5 } from "@walkeros/core/dev";
1247
1252
  function registerReferenceResources(server2) {
1248
1253
  server2.resource(
1249
1254
  "flow-schema",
1250
1255
  "walkeros://reference/flow-schema",
1251
1256
  {
1252
- description: "Annotated Flow.Config structure reference with connection rules and minimal example",
1257
+ description: "JSON Schema for Flow.Config \u2014 the complete flow configuration structure",
1253
1258
  mimeType: "application/json"
1254
1259
  },
1255
1260
  async () => ({
1256
1261
  contents: [
1257
1262
  {
1258
1263
  uri: "walkeros://reference/flow-schema",
1259
- text: JSON.stringify(FLOW_SCHEMA_REFERENCE, null, 2),
1264
+ text: JSON.stringify(schemas5.configJsonSchema, null, 2),
1260
1265
  mimeType: "application/json"
1261
1266
  }
1262
1267
  ]
@@ -1266,40 +1271,14 @@ function registerReferenceResources(server2) {
1266
1271
  "event-model",
1267
1272
  "walkeros://reference/event-model",
1268
1273
  {
1269
- description: "walkerOS event structure: entity-action naming, properties (data, context, globals, nested, consent, user)",
1274
+ description: "JSON Schema for walkerOS events: entity-action naming, data, context, globals, user, consent",
1270
1275
  mimeType: "application/json"
1271
1276
  },
1272
1277
  async () => ({
1273
1278
  contents: [
1274
1279
  {
1275
1280
  uri: "walkeros://reference/event-model",
1276
- text: JSON.stringify(
1277
- {
1278
- naming: 'Events use "entity action" format: "page view", "product add", "order complete"',
1279
- minimalEvent: { name: "page view", data: { title: "Home" } },
1280
- properties: {
1281
- data: "Entity-specific properties (product name, price, etc.)",
1282
- context: "State/environment info (page type, test group)",
1283
- globals: "Cross-event properties set once (language, currency)",
1284
- nested: "Nested entities (products inside an order)",
1285
- user: "User identifiers (id, device, session, hash)",
1286
- consent: "Granted permissions (functional, analytics, marketing)",
1287
- custom: "Application-specific data"
1288
- },
1289
- autoPopulated: [
1290
- "timestamp",
1291
- "timing",
1292
- "group",
1293
- "count",
1294
- "version",
1295
- "source",
1296
- "entity",
1297
- "action"
1298
- ]
1299
- },
1300
- null,
1301
- 2
1302
- ),
1281
+ text: JSON.stringify(schemas5.eventJsonSchema, null, 2),
1303
1282
  mimeType: "application/json"
1304
1283
  }
1305
1284
  ]
@@ -1309,7 +1288,7 @@ function registerReferenceResources(server2) {
1309
1288
  "mapping",
1310
1289
  "walkeros://reference/mapping",
1311
1290
  {
1312
- description: "walkerOS mapping syntax: data/map/loop/set/condition/consent/policy rules for event transformation",
1291
+ description: "JSON Schemas for walkerOS mapping: rules, valueConfig, rule, policy",
1313
1292
  mimeType: "application/json"
1314
1293
  },
1315
1294
  async () => ({
@@ -1318,46 +1297,10 @@ function registerReferenceResources(server2) {
1318
1297
  uri: "walkeros://reference/mapping",
1319
1298
  text: JSON.stringify(
1320
1299
  {
1321
- overview: "Mapping transforms walkerOS events into vendor-specific formats. Same syntax on sources (input normalization) and destinations (output transformation).",
1322
- config: {
1323
- consent: "Record<string, boolean> \u2014 destination-level consent requirements",
1324
- data: "Mapping.ValueConfig[] \u2014 field extraction rules",
1325
- policy: "Pre-processing rules applied before mapping",
1326
- mapping: "Record<entityAction, Mapping.Rule[]> \u2014 per-event mapping rules"
1327
- },
1328
- rules: {
1329
- keying: 'entity.action format with wildcards: "product.add", "*.view", "order.*", "*.*"',
1330
- priority: "Exact match > entity wildcard > action wildcard > global wildcard",
1331
- example: {
1332
- "product.add": [
1333
- {
1334
- name: "add_to_cart",
1335
- data: { map: { value: "data.price" } }
1336
- }
1337
- ],
1338
- "*.view": [{ name: "page_view" }]
1339
- }
1340
- },
1341
- valueConfig: {
1342
- key: 'Source property path (e.g., "data.title", "context.page")',
1343
- value: "Static value or fallback",
1344
- fn: "$code:(event) => event.data.price * 100 \u2014 inline function",
1345
- map: "Record<string, ValueConfig> \u2014 object transformation",
1346
- loop: "Array iteration (e.g., loop nested entities)",
1347
- set: "Create array from multiple values",
1348
- condition: 'Conditional inclusion: { if: "data.price", value: "paid" }',
1349
- consent: 'Field-level consent: { key: "user.email", consent: { marketing: true } }',
1350
- validate: "Schema validation for the value"
1351
- },
1352
- codeFunction: "$code:(event, mapping, options) => expression \u2014 inline JavaScript. Access event data, mapping context, and options.",
1353
- policyRules: {
1354
- overview: "Pre-processing rules applied before mapping transforms events",
1355
- types: [
1356
- "consent \u2014 require specific consent before processing",
1357
- "ignore \u2014 skip events matching conditions",
1358
- "redact \u2014 remove sensitive fields"
1359
- ]
1360
- }
1300
+ rules: schemas5.rulesJsonSchema,
1301
+ valueConfig: schemas5.valueConfigJsonSchema,
1302
+ rule: schemas5.ruleJsonSchema,
1303
+ policy: schemas5.policyJsonSchema
1361
1304
  },
1362
1305
  null,
1363
1306
  2
@@ -1371,43 +1314,14 @@ function registerReferenceResources(server2) {
1371
1314
  "consent",
1372
1315
  "walkeros://reference/consent",
1373
1316
  {
1374
- description: "walkerOS consent model: destination-level, rule-level, and field-level consent gating",
1317
+ description: "JSON Schema for walkerOS consent: destination-level, rule-level, and field-level consent gating",
1375
1318
  mimeType: "application/json"
1376
1319
  },
1377
1320
  async () => ({
1378
1321
  contents: [
1379
1322
  {
1380
1323
  uri: "walkeros://reference/consent",
1381
- text: JSON.stringify(
1382
- {
1383
- levels: {
1384
- destination: "config.consent: { marketing: true } \u2014 entire destination requires consent",
1385
- rule: "mapping.product.add.consent: { analytics: true } \u2014 specific mapping rule requires consent",
1386
- field: 'data.map.email: { key: "user.email", consent: { marketing: true } } \u2014 individual field requires consent'
1387
- },
1388
- deferredInit: {
1389
- require: '["consent"] \u2014 destination waits for consent before initializing',
1390
- queue: "true (default) \u2014 events are queued while waiting for consent, replayed when granted"
1391
- },
1392
- collectorDefault: "Collector starts with empty consent state. Sources (CMP) push consent updates.",
1393
- example: {
1394
- destinations: {
1395
- gtag: {
1396
- package: "@walkeros/web-destination-gtag",
1397
- config: { measurementId: "G-XXX" },
1398
- consent: { analytics: true }
1399
- },
1400
- meta: {
1401
- package: "@walkeros/web-destination-meta",
1402
- config: { pixelId: "123" },
1403
- consent: { marketing: true }
1404
- }
1405
- }
1406
- }
1407
- },
1408
- null,
1409
- 2
1410
- ),
1324
+ text: JSON.stringify(schemas5.consentJsonSchema, null, 2),
1411
1325
  mimeType: "application/json"
1412
1326
  }
1413
1327
  ]
@@ -1470,79 +1384,48 @@ function registerReferenceResources(server2) {
1470
1384
  "contract",
1471
1385
  "walkeros://reference/contract",
1472
1386
  {
1473
- description: "walkerOS contracts: event schema validation with entity-action keying, wildcards, and inheritance",
1387
+ description: "JSON Schema for walkerOS contracts: event schema validation with entity-action keying",
1474
1388
  mimeType: "application/json"
1475
1389
  },
1476
1390
  async () => ({
1477
1391
  contents: [
1478
1392
  {
1479
1393
  uri: "walkeros://reference/contract",
1480
- text: JSON.stringify(
1481
- {
1482
- overview: "Contracts define event schemas using entity-action keying. Used by the validator transformer to enforce data quality.",
1483
- structure: {
1484
- $tagging: "1 \u2014 contract format version (required)",
1485
- namedContracts: "Top-level keys are contract names with extends support",
1486
- entityAction: 'Keys use entity.action format: "product.add", "order.*", "*.*"',
1487
- wildcards: {
1488
- "*.*": "Matches all events",
1489
- "*.action": "Matches any entity with specific action",
1490
- "entity.*": "Matches all actions of specific entity"
1491
- }
1492
- },
1493
- inheritance: {
1494
- extends: 'Named contracts can extend other contracts: { extends: "base" }',
1495
- merging: "Child properties merge with parent. Child overrides take precedence."
1496
- },
1497
- schema: {
1498
- properties: {
1499
- data: "JSON Schema for entity data properties",
1500
- globals: "JSON Schema for global properties",
1501
- context: "JSON Schema for context properties",
1502
- custom: "JSON Schema for custom properties",
1503
- user: "JSON Schema for user identifiers",
1504
- consent: "Required consent state"
1505
- }
1506
- },
1507
- reference: "$contract.name \u2014 use in flow config to reference a named contract",
1508
- example: {
1509
- $tagging: 1,
1510
- ecommerce: {
1511
- "product.*": {
1512
- properties: {
1513
- data: {
1514
- type: "object",
1515
- properties: {
1516
- name: { type: "string" },
1517
- price: { type: "number" }
1518
- },
1519
- required: ["name"]
1520
- }
1521
- }
1522
- },
1523
- "order.complete": {
1524
- properties: {
1525
- data: {
1526
- type: "object",
1527
- properties: {
1528
- total: { type: "number" },
1529
- orderId: { type: "string" }
1530
- },
1531
- required: ["total", "orderId"]
1532
- }
1533
- }
1534
- }
1535
- }
1536
- }
1537
- },
1538
- null,
1539
- 2
1540
- ),
1394
+ text: JSON.stringify(schemas5.contractJsonSchema, null, 2),
1541
1395
  mimeType: "application/json"
1542
1396
  }
1543
1397
  ]
1544
1398
  })
1545
1399
  );
1400
+ server2.resource(
1401
+ "examples",
1402
+ "walkeros://reference/examples",
1403
+ {
1404
+ description: "Complete flow config example: web + server flows, mapping, contracts, step examples",
1405
+ mimeType: "application/json"
1406
+ },
1407
+ async () => {
1408
+ let example;
1409
+ try {
1410
+ const { readFileSync } = await import("fs");
1411
+ const { createRequire } = await import("module");
1412
+ const require2 = createRequire(import.meta.url);
1413
+ const examplePath = require2.resolve("@walkeros/cli/examples/flow-complete.json");
1414
+ example = readFileSync(examplePath, "utf-8");
1415
+ } catch {
1416
+ example = JSON.stringify({ error: "Example not found" });
1417
+ }
1418
+ return {
1419
+ contents: [
1420
+ {
1421
+ uri: "walkeros://reference/examples",
1422
+ text: example,
1423
+ mimeType: "application/json"
1424
+ }
1425
+ ]
1426
+ };
1427
+ }
1428
+ );
1546
1429
  server2.resource(
1547
1430
  "api",
1548
1431
  "walkeros://reference/api",
@@ -1619,15 +1502,18 @@ function registerAddStepPrompt(server2) {
1619
1502
  `2. Use package_get with section="hints" to read the selected package's configuration guidance.`,
1620
1503
  '3. Use package_get with section="examples" to see working configuration examples.',
1621
1504
  "4. Scaffold the step config using the package schemas \u2014 include required settings with placeholder values.",
1622
- "5. Wire the step into the flow: add to packages section, connect via next/before chains if needed.",
1623
- "6. Use flow_validate to verify the result.",
1505
+ "5. Wire the step into the flow: add to packages section (with version if needed), connect via next/before chains if needed.",
1506
+ '6. For destinations: configure mapping using nested entity \u2192 action keys. Event "product add" maps to `{ "product": { "add": { name: "AddToCart" } } }`. Use the setup-mapping prompt for guidance.',
1507
+ "7. Use flow_validate to verify the result.",
1624
1508
  "",
1625
1509
  "Important:",
1626
1510
  "- Read the walkeros://reference/flow-schema resource to understand connection rules.",
1627
1511
  "- Sources connect to pre-collector transformers via `next`.",
1628
1512
  "- Destinations connect to post-collector transformers via `before`.",
1629
1513
  "- Stores are passive \u2014 referenced via `$store:storeName` in env values.",
1630
- "- Use variables ($var) for values that change between environments."
1514
+ "- Use variables ($var) for values that change between environments.",
1515
+ "- For required settings without defaults in the package schema, ask the user which value to use. Do not guess credentials, IDs, or environment-specific values.",
1516
+ "- If $meta.exports lists named exports, set the `code` field on the step to the chosen export name. If only one export exists, use it automatically."
1631
1517
  ].join("\n")
1632
1518
  }
1633
1519
  }
@@ -1656,8 +1542,14 @@ function registerSetupMappingPrompt(server2) {
1656
1542
  text: [
1657
1543
  `Help me set up mapping${stepName ? ` for the "${stepName}" step` : ""}.`,
1658
1544
  "",
1545
+ "IMPORTANT \u2014 Mapping key structure:",
1546
+ "Mapping uses NESTED entity \u2192 action keys, NOT dot-separated strings.",
1547
+ 'Event name "product add" splits into entity "product" and action "add".',
1548
+ 'Config structure: `{ "mapping": { "product": { "add": { name: "AddToCart", data: { ... } } } } }`',
1549
+ 'Wildcards: `{ "*": { "view": Rule } }` matches any entity with action "view".',
1550
+ "",
1659
1551
  "Follow these steps:",
1660
- "1. Read the walkeros://reference/mapping resource to understand mapping syntax.",
1552
+ "1. Read the walkeros://reference/mapping resource for full syntax reference.",
1661
1553
  `2. ${stepName ? `Identify the package for "${stepName}" in the flow, then u` : "U"}se package_get with section="examples" to see how events are mapped for this package.`,
1662
1554
  '3. Ask which events I want to map (e.g., "product view", "order complete").',
1663
1555
  "4. Generate mapping rules using the package examples as templates.",
@@ -1774,7 +1666,7 @@ function registerUseDefinitionsPrompt(server2) {
1774
1666
  var server = new McpServer(
1775
1667
  {
1776
1668
  name: "walkeros-flow",
1777
- version: "3.0.0-next-1773236214827"
1669
+ version: "3.0.1"
1778
1670
  },
1779
1671
  {
1780
1672
  instructions: `walkerOS is an open-source, privacy-first event data collection platform. Define event pipelines as code using JSON flow configurations.
@@ -1783,24 +1675,52 @@ var server = new McpServer(
1783
1675
 
1784
1676
  Every component in a flow is a **step**: sources capture events, transformers process them, destinations deliver them, stores provide shared state. Steps connect via \`next\` (pre-collector) and \`before\` (post-collector) chains.
1785
1677
 
1678
+ ## Flow Config Structure
1679
+
1680
+ Every flow config follows this shape:
1681
+
1682
+ \`\`\`json
1683
+ {
1684
+ "version": 3,
1685
+ "flows": {
1686
+ "default": {
1687
+ "web": {},
1688
+ "sources": { "<name>": { "package": "<npm-package>", "config": {} } },
1689
+ "destinations": { "<name>": { "package": "<npm-package>", "config": { "settings": {} } } }
1690
+ }
1691
+ }
1692
+ }
1693
+ \`\`\`
1694
+
1695
+ Event format: \`{ name: "entity action", data: {...}, entity: "...", action: "..." }\`. Sources convert raw input into this format.
1696
+
1697
+ Key rules:
1698
+ - \`version: 3\` is required
1699
+ - Each flow must have exactly one of \`web: {}\` or \`server: {}\`
1700
+ - Destination settings go inside \`config.settings\`, not directly on the destination
1701
+ - Read \`walkeros://reference/flow-schema\` for the full annotated structure
1702
+
1786
1703
  ## Getting Started
1787
1704
 
1788
1705
  1. \`flow_load({ platform: "web" })\` or \`flow_load({ source: "./flow.json" })\` \u2014 create or load a flow
1789
- 2. Use the \`add-step\` prompt to add sources, destinations, transformers, or stores
1790
- 3. Use the \`setup-mapping\` prompt to configure event transformations
1791
- 4. \`flow_validate({ type: "flow", input: "flow.json" })\` \u2014 verify configuration
1792
- 5. \`flow_simulate({ configPath: "flow.json", event: "..." })\` \u2014 test with mocked API calls
1793
- 6. \`flow_bundle({ configPath: "flow.json" })\` \u2014 build deployable JavaScript
1794
- 7. \`api({ action: "deploy", id: "cfg_..." })\` \u2014 deploy to walkerOS cloud (requires WALKEROS_TOKEN)
1706
+ 2. \`package_search({ type: "destination", platform: "web" })\` \u2014 discover available packages
1707
+ 3. Use the \`add-step\` prompt to add sources, destinations, transformers, or stores
1708
+ 4. Use the \`setup-mapping\` prompt to configure event transformations
1709
+ 5. \`flow_validate({ type: "flow", input: "flow.json" })\` \u2014 verify configuration
1710
+ 6. \`flow_simulate({ configPath: "flow.json", event: "..." })\` \u2014 test with mocked API calls
1711
+ 7. \`flow_bundle({ configPath: "flow.json" })\` \u2014 build deployable JavaScript
1712
+ 8. \`api({ action: "deploy", id: "cfg_..." })\` \u2014 deploy to walkerOS cloud (requires WALKEROS_TOKEN env var; unavailable without it)
1713
+
1714
+ If validation fails, fix the reported errors and re-validate. Do not skip validation.
1795
1715
 
1796
1716
  ## Reference Resources
1797
1717
 
1798
- Attach these for context: \`walkeros://reference/flow-schema\`, \`walkeros://reference/mapping\`, \`walkeros://reference/event-model\`, \`walkeros://reference/consent\`, \`walkeros://reference/variables\`, \`walkeros://reference/contract\`.
1718
+ Read these before constructing configs manually: \`walkeros://reference/flow-schema\`, \`walkeros://reference/mapping\`, \`walkeros://reference/event-model\`, \`walkeros://reference/consent\`, \`walkeros://reference/variables\`, \`walkeros://reference/contract\`, \`walkeros://reference/examples\`.
1799
1719
 
1800
1720
  ## Key Concepts
1801
1721
 
1802
- - **Steps** are sources, destinations, transformers, or stores \u2014 each backed by an npm package with schemas, hints, and examples.
1803
- - **Mapping** transforms events using data/map/loop/set/condition rules. Same syntax on sources and destinations.
1722
+ - **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.
1723
+ - **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 } }\`.
1804
1724
  - **Contracts** define event schemas using entity-action keying. Can generate FROM mappings or scaffold mappings FROM contracts.
1805
1725
  - **Variables** ($var, $env, $def, $code, $store) enable DRY, environment-aware config. Use the \`use-definitions\` prompt to extract shared patterns.
1806
1726
  - **Consent** gates destinations, mapping rules, and individual fields. Privacy-first by design.`