@walkeros/mcp 4.6.0 → 4.6.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
@@ -1,3 +1,98 @@
1
+ // src/cloud-flow.ts
2
+ import { isObject } from "@walkeros/core";
3
+ var CLOUD_ID_PATTERN = /^(flow|cfg)_[A-Za-z0-9_-]+$/;
4
+ function isCloudId(input) {
5
+ return CLOUD_ID_PATTERN.test(input);
6
+ }
7
+ function flowConfigOf(flow) {
8
+ return isObject(flow) && isObject(flow.config) ? flow.config : {};
9
+ }
10
+
11
+ // src/runtime/types.ts
12
+ var RuntimeRefusal = class extends Error {
13
+ hint;
14
+ constructor(message, hint) {
15
+ super(message);
16
+ this.name = "RuntimeRefusal";
17
+ this.hint = hint;
18
+ }
19
+ };
20
+ function refusalHint(error, fallback) {
21
+ return error instanceof RuntimeRefusal ? error.hint : fallback;
22
+ }
23
+ var HINT_OUT_OF_PROCESS = "Build and deploy through the app with deploy_manage, or simulate the flow in the app. On your own machine, use the walkerOS CLI.";
24
+ function unavailableOperation(operation) {
25
+ const verb = operation === "bundle" ? "Bundling" : operation === "simulate" ? "Simulating" : "Running";
26
+ return new RuntimeRefusal(
27
+ `${verb} a flow is not available on the hosted walkerOS MCP server.`,
28
+ HINT_OUT_OF_PROCESS
29
+ );
30
+ }
31
+
32
+ // src/runtime/hosted.ts
33
+ function isHttpUrl(value) {
34
+ try {
35
+ const url = new URL(value);
36
+ return url.protocol === "http:" || url.protocol === "https:";
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+ function looksLikePath(value) {
42
+ return /[\\/]/.test(value) || value.startsWith(".") || /\.[A-Za-z0-9]+$/.test(value);
43
+ }
44
+ function classifyConfigInput(input) {
45
+ const trimmed = input.trim();
46
+ if (isHttpUrl(trimmed)) return "url";
47
+ if (isCloudId(trimmed)) return "cloud-id";
48
+ if (trimmed.startsWith("{") || trimmed.startsWith("[")) return "inline-json";
49
+ if (looksLikePath(trimmed)) return "local-path";
50
+ return "bare-string";
51
+ }
52
+ var HINT_INLINE_OR_ID = "Pass the flow inline as JSON, or reference a saved flow by its flow_ or cfg_ id.";
53
+ function refuseLocalPath() {
54
+ return new RuntimeRefusal(
55
+ "Local file paths are not available on the hosted walkerOS MCP server.",
56
+ HINT_INLINE_OR_ID
57
+ );
58
+ }
59
+ function refuseUrl() {
60
+ return new RuntimeRefusal(
61
+ "Fetching URLs is not available on the hosted walkerOS MCP server.",
62
+ HINT_INLINE_OR_ID
63
+ );
64
+ }
65
+ function parseInline(trimmed) {
66
+ try {
67
+ return JSON.parse(trimmed);
68
+ } catch (error) {
69
+ const message = error instanceof Error ? error.message : String(error);
70
+ throw new Error(`Input appears to be JSON but contains errors: ${message}`);
71
+ }
72
+ }
73
+ function createHostedRuntime(client) {
74
+ return {
75
+ async load(input) {
76
+ const trimmed = input.trim();
77
+ if (trimmed === "") throw new Error("Input is required");
78
+ switch (classifyConfigInput(trimmed)) {
79
+ case "url":
80
+ throw refuseUrl();
81
+ case "cloud-id":
82
+ return flowConfigOf(await client.getFlow({ flowId: trimmed }));
83
+ case "inline-json":
84
+ return parseInline(trimmed);
85
+ case "local-path":
86
+ throw refuseLocalPath();
87
+ case "bare-string":
88
+ throw new Error(
89
+ `Cannot resolve "${trimmed}" on the hosted walkerOS MCP server. ${HINT_INLINE_OR_ID}`
90
+ );
91
+ }
92
+ }
93
+ };
94
+ }
95
+
1
96
  // src/tools/auth.ts
2
97
  import { z } from "zod";
3
98
  import { mcpResult, mcpError } from "@walkeros/core";
@@ -2738,7 +2833,7 @@ async function feedbackHandlerBody(client, input) {
2738
2833
  const isAnonymous = explicitAnonymous ?? anonymous ?? true;
2739
2834
  await client.submitFeedback(text, {
2740
2835
  anonymous: isAnonymous,
2741
- version: "4.6.0"
2836
+ version: "4.6.1"
2742
2837
  });
2743
2838
  return mcpResult10({ ok: true });
2744
2839
  } catch (error) {
@@ -2762,7 +2857,7 @@ function registerFeedbackTool(server, client) {
2762
2857
  }
2763
2858
 
2764
2859
  // src/tools/validate.ts
2765
- import { validate, loadJsonConfig } from "@walkeros/cli";
2860
+ import { validate } from "@walkeros/cli";
2766
2861
  import { schemas } from "@walkeros/cli/dev";
2767
2862
  import { mcpResult as mcpResult11, mcpError as mcpError11 } from "@walkeros/core";
2768
2863
 
@@ -2857,6 +2952,22 @@ var ExamplesListOutputShape = {
2857
2952
  };
2858
2953
 
2859
2954
  // src/tools/validate.ts
2955
+ async function loadValidateInput(runtime, input, type) {
2956
+ if (!input || input.trim() === "") throw new Error(`${type} is required`);
2957
+ const trimmed = input.trim();
2958
+ const looksLikeJson = trimmed.startsWith("{") || trimmed.startsWith("[");
2959
+ try {
2960
+ return await runtime.load(input);
2961
+ } catch (error) {
2962
+ if (error instanceof RuntimeRefusal || isCloudId(trimmed)) throw error;
2963
+ if (looksLikeJson) {
2964
+ const message = error instanceof Error ? error.message : String(error);
2965
+ throw new Error(`Failed to parse ${type}. ${message}`);
2966
+ }
2967
+ if (type === "event") return { name: trimmed };
2968
+ throw error;
2969
+ }
2970
+ }
2860
2971
  var DEPRECATED_STORE_PACKAGE = "@walkeros/store-memory";
2861
2972
  function detectDeprecatedStorePackages(config) {
2862
2973
  const errors = [];
@@ -2886,7 +2997,7 @@ function detectDeprecatedStorePackages(config) {
2886
2997
  return errors;
2887
2998
  }
2888
2999
  var TITLE11 = "Validate Flow";
2889
- var DESCRIPTION9 = "Validate walkerOS events, flow configurations, mapping rules, or data contracts. Accepts JSON strings, file paths, or URLs as input. Returns validation results with errors, warnings, and details.";
3000
+ var DESCRIPTION9 = "Validate walkerOS events, flow configurations, mapping rules, or data contracts. Accepts JSON strings, file paths, or URLs as input; on the hosted server only inline JSON or a saved flow id (flow_ or cfg_), no file paths or URLs. Returns validation results with errors, warnings, and details.";
2890
3001
  var inputSchema9 = schemas.ValidateInputShape;
2891
3002
  var annotations11 = {
2892
3003
  readOnlyHint: true,
@@ -2894,17 +3005,17 @@ var annotations11 = {
2894
3005
  idempotentHint: true,
2895
3006
  openWorldHint: false
2896
3007
  };
2897
- function createFlowValidateToolSpec() {
3008
+ function createFlowValidateToolSpec(runtime) {
2898
3009
  return {
2899
3010
  name: "flow_validate",
2900
3011
  title: TITLE11,
2901
3012
  description: DESCRIPTION9,
2902
3013
  inputSchema: inputSchema9,
2903
3014
  annotations: annotations11,
2904
- handler: (input) => flowValidateHandlerBody(input)
3015
+ handler: (input) => flowValidateHandlerBody(runtime, input)
2905
3016
  };
2906
3017
  }
2907
- async function flowValidateHandlerBody(input) {
3018
+ async function flowValidateHandlerBody(runtime, input) {
2908
3019
  const {
2909
3020
  type,
2910
3021
  input: validateInput,
@@ -2912,30 +3023,27 @@ async function flowValidateHandlerBody(input) {
2912
3023
  path: path2
2913
3024
  } = input ?? {};
2914
3025
  try {
2915
- const result = await validate(type, validateInput, {
3026
+ const resolved = await loadValidateInput(runtime, validateInput, type);
3027
+ const result = await validate(type, resolved, {
2916
3028
  flow,
2917
3029
  path: path2
2918
3030
  });
2919
3031
  let augmented = result;
2920
- if (type === "flow" && typeof validateInput === "string") {
2921
- try {
2922
- const config = await loadJsonConfig(validateInput);
2923
- const deprecatedErrors = detectDeprecatedStorePackages(config);
2924
- if (deprecatedErrors.length > 0) {
2925
- augmented = {
2926
- ...result,
2927
- valid: false,
2928
- errors: [...result.errors, ...deprecatedErrors]
2929
- };
2930
- }
2931
- } catch {
3032
+ if (type === "flow") {
3033
+ const deprecatedErrors = detectDeprecatedStorePackages(resolved);
3034
+ if (deprecatedErrors.length > 0) {
3035
+ augmented = {
3036
+ ...result,
3037
+ valid: false,
3038
+ errors: [...result.errors, ...deprecatedErrors]
3039
+ };
2932
3040
  }
2933
3041
  }
2934
3042
  const hints = augmented.valid ? {
2935
- next: [
3043
+ next: runtime.simulate ? [
2936
3044
  "Use flow_simulate to test event flow",
2937
3045
  "Use flow_bundle to build"
2938
- ]
3046
+ ] : [HINT_OUT_OF_PROCESS]
2939
3047
  } : {
2940
3048
  next: [
2941
3049
  "Fix errors above, then run flow_validate again",
@@ -2946,12 +3054,15 @@ async function flowValidateHandlerBody(input) {
2946
3054
  } catch (error) {
2947
3055
  return mcpError11(
2948
3056
  error,
2949
- "Check the input parameter \u2014 expected a JSON string, file path, or URL"
3057
+ refusalHint(
3058
+ error,
3059
+ "Check the input parameter \u2014 expected a JSON string, file path, or URL"
3060
+ )
2950
3061
  );
2951
3062
  }
2952
3063
  }
2953
- function registerFlowValidateTool(server) {
2954
- const spec = createFlowValidateToolSpec();
3064
+ function registerFlowValidateTool(server, runtime) {
3065
+ const spec = createFlowValidateToolSpec(runtime);
2955
3066
  server.registerTool(
2956
3067
  spec.name,
2957
3068
  {
@@ -2969,17 +3080,14 @@ function registerFlowValidateTool(server) {
2969
3080
  }
2970
3081
 
2971
3082
  // src/tools/bundle.ts
2972
- import { bundle } from "@walkeros/cli";
2973
3083
  import { schemas as schemas2 } from "@walkeros/cli/dev";
2974
3084
  import { mcpResult as mcpResult12, mcpError as mcpError12 } from "@walkeros/core";
2975
3085
 
2976
3086
  // src/tools/resolve-config-path.ts
2977
- var API_ID_PREFIX = /^(flow|cfg)_/;
2978
3087
  async function resolveConfigPath(client, configPath) {
2979
- if (!API_ID_PREFIX.test(configPath)) return configPath;
3088
+ if (!isCloudId(configPath)) return configPath;
2980
3089
  const flow = await client.getFlow({ flowId: configPath });
2981
- const config = flow.config;
2982
- return JSON.stringify(config ?? {});
3090
+ return JSON.stringify(flowConfigOf(flow));
2983
3091
  }
2984
3092
 
2985
3093
  // src/tools/bundle.ts
@@ -2994,24 +3102,28 @@ var annotations12 = {
2994
3102
  idempotentHint: false,
2995
3103
  openWorldHint: true
2996
3104
  };
2997
- function createFlowBundleToolSpec(client) {
3105
+ function createFlowBundleToolSpec(client, runtime) {
2998
3106
  return {
2999
3107
  name: "flow_bundle",
3000
3108
  title: TITLE12,
3001
3109
  description: DESCRIPTION10,
3002
3110
  inputSchema: inputSchema10,
3003
3111
  annotations: annotations12,
3004
- handler: (input) => flowBundleHandlerBody(client, input)
3112
+ handler: (input) => flowBundleHandlerBody(client, runtime, input)
3005
3113
  };
3006
3114
  }
3007
- async function flowBundleHandlerBody(client, input) {
3115
+ async function flowBundleHandlerBody(client, runtime, input) {
3008
3116
  const { configPath, flow, stats, output } = input ?? {};
3117
+ if (!runtime.bundle) {
3118
+ const refusal = unavailableOperation("bundle");
3119
+ return mcpError12(refusal, refusal.hint);
3120
+ }
3009
3121
  try {
3010
3122
  const resolvedConfigPath = await resolveConfigPath(client, configPath);
3011
- const result = await bundle(resolvedConfigPath, {
3123
+ const result = await runtime.bundle(resolvedConfigPath, {
3012
3124
  flowName: flow,
3013
3125
  stats: stats ?? true,
3014
- buildOverrides: output ? { output } : void 0
3126
+ output
3015
3127
  });
3016
3128
  if (!result) {
3017
3129
  return mcpResult12(
@@ -3035,11 +3147,14 @@ async function flowBundleHandlerBody(client, input) {
3035
3147
  }
3036
3148
  );
3037
3149
  } catch (error) {
3038
- return mcpError12(error, "Run flow_validate for detailed error messages");
3150
+ return mcpError12(
3151
+ error,
3152
+ refusalHint(error, "Run flow_validate for detailed error messages")
3153
+ );
3039
3154
  }
3040
3155
  }
3041
- function registerFlowBundleTool(server, client) {
3042
- const spec = createFlowBundleToolSpec(client);
3156
+ function registerFlowBundleTool(server, client, runtime) {
3157
+ const spec = createFlowBundleToolSpec(client, runtime);
3043
3158
  server.registerTool(
3044
3159
  spec.name,
3045
3160
  {
@@ -3058,101 +3173,17 @@ function registerFlowBundleTool(server, client) {
3058
3173
 
3059
3174
  // src/tools/simulate.ts
3060
3175
  import { z as z12 } from "zod";
3061
- import {
3062
- simulateSource,
3063
- simulateTransformer,
3064
- simulateDestination,
3065
- simulateCollector
3066
- } from "@walkeros/cli";
3067
3176
  import { schemas as schemas3 } from "@walkeros/cli/dev";
3068
3177
  import { mcpResult as mcpResult13, mcpError as mcpError13 } from "@walkeros/core";
3069
-
3070
- // src/tools/bundle-cache.ts
3071
- import { createHash } from "crypto";
3072
- import os from "os";
3073
- import path from "path";
3074
- import { mkdir, rm, writeFile } from "fs/promises";
3075
- import { rmSync } from "fs";
3076
- import { bundle as bundle2 } from "@walkeros/cli";
3077
- var MAX_ENTRIES = 8;
3078
- var cache = /* @__PURE__ */ new Map();
3079
- var inFlight = /* @__PURE__ */ new Map();
3080
- var cleanupRegistered = false;
3081
- function hashConfig(resolvedConfig) {
3082
- return createHash("sha256").update(resolvedConfig).digest("hex");
3083
- }
3084
- function isInlineJsonConfig(resolvedConfig) {
3085
- const trimmed = resolvedConfig.trimStart();
3086
- if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return false;
3087
- try {
3088
- JSON.parse(resolvedConfig);
3089
- return true;
3090
- } catch {
3091
- return false;
3092
- }
3093
- }
3094
- function registerProcessCleanup() {
3095
- if (cleanupRegistered) return;
3096
- cleanupRegistered = true;
3097
- const cleanup = () => {
3098
- for (const entry of cache.values()) {
3099
- try {
3100
- rmSync(entry.dir, { recursive: true, force: true });
3101
- } catch {
3102
- }
3103
- }
3104
- cache.clear();
3105
- };
3106
- process.once("exit", cleanup);
3107
- }
3108
- async function evictIfNeeded() {
3109
- while (cache.size > MAX_ENTRIES) {
3110
- const oldestKey = cache.keys().next().value;
3111
- if (oldestKey === void 0) break;
3112
- const evicted = cache.get(oldestKey);
3113
- cache.delete(oldestKey);
3114
- if (evicted) await rm(evicted.dir, { recursive: true, force: true });
3115
- }
3116
- }
3117
- async function getOrBuildBundle(resolvedConfig) {
3118
- if (!isInlineJsonConfig(resolvedConfig)) return void 0;
3119
- registerProcessCleanup();
3120
- const key = hashConfig(resolvedConfig);
3121
- const cached = cache.get(key);
3122
- if (cached) {
3123
- cache.delete(key);
3124
- cache.set(key, cached);
3125
- return cached.bundlePath;
3126
- }
3127
- const pending = inFlight.get(key);
3128
- if (pending) return pending;
3129
- const build = (async () => {
3130
- const dir = path.join(
3131
- os.tmpdir(),
3132
- `walkeros-mcp-bundle-${key.slice(0, 16)}`
3133
- );
3134
- await rm(dir, { recursive: true, force: true });
3135
- await mkdir(dir, { recursive: true });
3136
- const bundlePath = path.join(dir, "flow.mjs");
3137
- await writeFile(bundlePath, "", "utf-8");
3138
- await bundle2(resolvedConfig, {
3139
- target: "simulate",
3140
- silent: true,
3141
- buildOverrides: { output: bundlePath, format: "esm", minify: false }
3142
- });
3143
- cache.set(key, { bundlePath, dir });
3144
- await evictIfNeeded();
3145
- return bundlePath;
3146
- })();
3147
- inFlight.set(key, build);
3148
- try {
3149
- return await build;
3150
- } finally {
3151
- inFlight.delete(key);
3152
- }
3178
+ var STEP_TYPES = [
3179
+ "source",
3180
+ "transformer",
3181
+ "collector",
3182
+ "destination"
3183
+ ];
3184
+ function isStepType(value) {
3185
+ return STEP_TYPES.some((t) => t === value);
3153
3186
  }
3154
-
3155
- // src/tools/simulate.ts
3156
3187
  var TITLE13 = "Simulate Flow";
3157
3188
  var DESCRIPTION11 = '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? } }, where content is the walkerOS event { name: "entity action", data: {...} }. step (required) targets the step to simulate, e.g. "destination.gtag". Use flow_examples to discover available test data. IMPORTANT: Destinations with require (e.g. require: ["consent"]) stay pending until that collector event fires \u2014 simulation will error "not found" if require is not satisfied. Remove require from config or provide consent/user events before simulating. Separately, destinations with consent (e.g. consent: { marketing: true }) only receive events where the event includes matching consent. Mapping transforms event names and data at the destination level. Policy redacts or injects fields before mapping runs.';
3158
3189
  var inputSchema11 = {
@@ -3181,23 +3212,31 @@ var inputSchema11 = {
3181
3212
  )
3182
3213
  };
3183
3214
  var annotations13 = {
3184
- readOnlyHint: true,
3185
- destructiveHint: false,
3186
- idempotentHint: true,
3187
- openWorldHint: false
3215
+ // Simulation downloads the packages a config names and runs caller-controlled
3216
+ // flow code in process. Destinations are mocked, but that code is not, so the
3217
+ // hints stay conservative: side effects possible, repeat calls not assumed
3218
+ // safe, external systems reachable.
3219
+ readOnlyHint: false,
3220
+ destructiveHint: true,
3221
+ idempotentHint: false,
3222
+ openWorldHint: true
3188
3223
  };
3189
- function createFlowSimulateToolSpec(client) {
3224
+ function createFlowSimulateToolSpec(client, runtime) {
3190
3225
  return {
3191
3226
  name: "flow_simulate",
3192
3227
  title: TITLE13,
3193
3228
  description: DESCRIPTION11,
3194
3229
  inputSchema: inputSchema11,
3195
3230
  annotations: annotations13,
3196
- handler: (input) => flowSimulateHandlerBody(client, input)
3231
+ handler: (input) => flowSimulateHandlerBody(client, runtime, input)
3197
3232
  };
3198
3233
  }
3199
- async function flowSimulateHandlerBody(client, input) {
3234
+ async function flowSimulateHandlerBody(client, runtime, input) {
3200
3235
  const { configPath, event, flow, platform, step, verbose, ingest, state } = input ?? {};
3236
+ if (!runtime.simulate) {
3237
+ const refusal = unavailableOperation("simulate");
3238
+ return mcpError13(refusal, refusal.hint);
3239
+ }
3201
3240
  try {
3202
3241
  if (!event) {
3203
3242
  throw new Error(
@@ -3227,66 +3266,16 @@ async function flowSimulateHandlerBody(client, input) {
3227
3266
  }
3228
3267
  const stepType = step.substring(0, dotIndex);
3229
3268
  const stepId = step.substring(dotIndex + 1);
3230
- const resolvedConfigPath = await resolveConfigPath(client, configPath);
3231
- let bundlePath;
3232
- try {
3233
- bundlePath = await getOrBuildBundle(resolvedConfigPath);
3234
- } catch {
3235
- bundlePath = void 0;
3236
- }
3237
- let result;
3238
- switch (stepType) {
3239
- case "source":
3240
- result = await simulateSource(resolvedConfigPath, resolvedEvent, {
3241
- sourceId: stepId,
3242
- bundlePath,
3243
- flow,
3244
- silent: true
3245
- });
3246
- break;
3247
- case "transformer":
3248
- result = await simulateTransformer(
3249
- resolvedConfigPath,
3250
- resolvedEvent,
3251
- {
3252
- transformerId: stepId,
3253
- bundlePath,
3254
- flow,
3255
- silent: true,
3256
- ingest
3257
- }
3258
- );
3259
- break;
3260
- case "collector":
3261
- result = await simulateCollector(
3262
- resolvedConfigPath,
3263
- resolvedEvent,
3264
- {
3265
- collectorName: stepId,
3266
- bundlePath,
3267
- flow,
3268
- silent: true,
3269
- state
3270
- }
3271
- );
3272
- break;
3273
- case "destination":
3274
- result = await simulateDestination(
3275
- resolvedConfigPath,
3276
- resolvedEvent,
3277
- {
3278
- destinationId: stepId,
3279
- bundlePath,
3280
- flow,
3281
- silent: true
3282
- }
3283
- );
3284
- break;
3285
- default:
3286
- throw new Error(
3287
- `Unknown step type "${stepType}". Use "source", "collector", "transformer", or "destination".`
3288
- );
3269
+ if (!isStepType(stepType)) {
3270
+ throw new Error(
3271
+ `Unknown step type "${stepType}". Use "source", "collector", "transformer", or "destination".`
3272
+ );
3289
3273
  }
3274
+ const resolvedConfigPath = await resolveConfigPath(client, configPath);
3275
+ const result = await runtime.simulate(
3276
+ resolvedConfigPath,
3277
+ { stepType, stepId, event: resolvedEvent, flow, ingest, state }
3278
+ );
3290
3279
  const success = !result.error;
3291
3280
  const errorMessage = result.error?.message;
3292
3281
  if (result.step === "source") {
@@ -3374,11 +3363,11 @@ async function flowSimulateHandlerBody(client, input) {
3374
3363
  if (msg.includes("not found in collector")) {
3375
3364
  hint = 'If this destination has require: ["consent"] or require: ["user"], it stays pending until that event fires. For simulation, either remove require from the config or simulate with a flow that omits require on the target destination.';
3376
3365
  }
3377
- return mcpError13(error, hint);
3366
+ return mcpError13(error, refusalHint(error, hint));
3378
3367
  }
3379
3368
  }
3380
- function registerFlowSimulateTool(server, client) {
3381
- const spec = createFlowSimulateToolSpec(client);
3369
+ function registerFlowSimulateTool(server, client, runtime) {
3370
+ const spec = createFlowSimulateToolSpec(client, runtime);
3382
3371
  server.registerTool(
3383
3372
  spec.name,
3384
3373
  {
@@ -3397,7 +3386,6 @@ function registerFlowSimulateTool(server, client) {
3397
3386
 
3398
3387
  // src/tools/push.ts
3399
3388
  import { z as z13 } from "zod";
3400
- import { push } from "@walkeros/cli";
3401
3389
  import { schemas as schemas4 } from "@walkeros/cli/dev";
3402
3390
  import { mcpResult as mcpResult14, mcpError as mcpError14 } from "@walkeros/core";
3403
3391
  var TITLE14 = "Push Events";
@@ -3416,21 +3404,24 @@ var annotations14 = {
3416
3404
  idempotentHint: false,
3417
3405
  openWorldHint: true
3418
3406
  };
3419
- function createFlowPushToolSpec() {
3407
+ function createFlowPushToolSpec(runtime) {
3420
3408
  return {
3421
3409
  name: "flow_push",
3422
3410
  title: TITLE14,
3423
3411
  description: DESCRIPTION12,
3424
3412
  inputSchema: inputSchema12,
3425
3413
  annotations: annotations14,
3426
- handler: (input) => flowPushHandlerBody(input)
3414
+ handler: (input) => flowPushHandlerBody(runtime, input)
3427
3415
  };
3428
3416
  }
3429
- async function flowPushHandlerBody(input) {
3417
+ async function flowPushHandlerBody(runtime, input) {
3430
3418
  const { configPath, event, flow, platform } = input ?? {};
3419
+ if (!runtime.push) {
3420
+ const refusal = unavailableOperation("push");
3421
+ return mcpError14(refusal, refusal.hint);
3422
+ }
3431
3423
  try {
3432
- const result = await push(configPath, event, {
3433
- json: true,
3424
+ const result = await runtime.push(configPath, event, {
3434
3425
  flow,
3435
3426
  platform
3436
3427
  });
@@ -3444,12 +3435,15 @@ async function flowPushHandlerBody(input) {
3444
3435
  } catch (error) {
3445
3436
  return mcpError14(
3446
3437
  error,
3447
- "Check configPath and event format. For web flows, use flow_simulate."
3438
+ refusalHint(
3439
+ error,
3440
+ "Check configPath and event format. For web flows, use flow_simulate."
3441
+ )
3448
3442
  );
3449
3443
  }
3450
3444
  }
3451
- function registerFlowPushTool(server) {
3452
- const spec = createFlowPushToolSpec();
3445
+ function registerFlowPushTool(server, runtime) {
3446
+ const spec = createFlowPushToolSpec(runtime);
3453
3447
  server.registerTool(
3454
3448
  spec.name,
3455
3449
  {
@@ -3468,7 +3462,6 @@ function registerFlowPushTool(server) {
3468
3462
 
3469
3463
  // src/tools/examples.ts
3470
3464
  import { z as z14 } from "zod";
3471
- import { loadJsonConfig as loadJsonConfig2 } from "@walkeros/cli";
3472
3465
  import { fetchPackage, mcpResult as mcpResult15, mcpError as mcpError15 } from "@walkeros/core";
3473
3466
 
3474
3467
  // src/catalog.ts
@@ -3476,7 +3469,7 @@ var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
3476
3469
  var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
3477
3470
  var WALKEROS_JSON_PATH = "dist/walkerOS.json";
3478
3471
  var CACHE_TTL = 5 * 60 * 1e3;
3479
- var CLIENT_HEADER = "walkeros-mcp/4.6.0";
3472
+ var CLIENT_HEADER = "walkeros-mcp/4.6.1";
3480
3473
  function getPackageBaseUrl() {
3481
3474
  return process.env.WALKEROS_APP_URL || void 0;
3482
3475
  }
@@ -3484,7 +3477,7 @@ var lastFetchInfo;
3484
3477
  function getLastCatalogSource() {
3485
3478
  return lastFetchInfo;
3486
3479
  }
3487
- var cache2 = /* @__PURE__ */ new Map();
3480
+ var cache = /* @__PURE__ */ new Map();
3488
3481
  function normalizePlatform(platform) {
3489
3482
  if (platform == null) return [];
3490
3483
  if (typeof platform === "string") {
@@ -3498,7 +3491,7 @@ function normalizePlatform(platform) {
3498
3491
  async function fetchCatalog(filters) {
3499
3492
  const sourceKey = filters?.baseUrl ?? "npm";
3500
3493
  const warnings = [];
3501
- const cached = cache2.get(sourceKey);
3494
+ const cached = cache.get(sourceKey);
3502
3495
  if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
3503
3496
  lastFetchInfo = {
3504
3497
  source: filters?.baseUrl ? "app" : "npm",
@@ -3556,7 +3549,7 @@ async function fetchCatalog(filters) {
3556
3549
  timestamp: Date.now()
3557
3550
  };
3558
3551
  if (result.entries.length > 0 && result.complete) {
3559
- cache2.set(sourceKey, { entries: result.entries, timestamp: Date.now() });
3552
+ cache.set(sourceKey, { entries: result.entries, timestamp: Date.now() });
3560
3553
  }
3561
3554
  return { entries: applyFilters(result.entries, filters), warnings };
3562
3555
  }
@@ -3629,10 +3622,13 @@ function applyFilters(entries, filters) {
3629
3622
  }
3630
3623
 
3631
3624
  // src/tools/examples.ts
3625
+ var MAX_PACKAGE_LOOKUPS = 25;
3632
3626
  var TITLE15 = "Flow Examples";
3633
- var DESCRIPTION13 = 'List all step examples in a walkerOS flow configuration. Shows example names, step locations, and in/out shapes. Inline examples on a step take precedence; steps without inline examples fall back to the examples shipped by their referenced package. Each result is tagged with its source ("inline" or "package"). Use this to discover available test fixtures and simulation data.';
3627
+ var DESCRIPTION13 = 'List all step examples in a walkerOS flow configuration. Shows example names, step locations, and in/out shapes. Inline examples on a step take precedence; steps without inline examples fall back to the examples shipped by their referenced package. Each result is tagged with its source ("inline" or "package"). On the hosted server configPath accepts only inline JSON or a saved flow id (flow_ or cfg_), no file paths or URLs. Use this to discover available test fixtures and simulation data.';
3634
3628
  var inputSchema13 = {
3635
- configPath: z14.string().min(1).describe("Path to flow configuration file, URL, or inline JSON string"),
3629
+ configPath: z14.string().min(1).describe(
3630
+ "Inline JSON string, file path, or URL of a flow configuration (hosted server: inline JSON or a saved flow id only)"
3631
+ ),
3636
3632
  flow: z14.string().optional().describe("Flow name for multi-flow configs"),
3637
3633
  step: z14.string().optional().describe('Filter to a specific step (e.g., "destination.gtag")'),
3638
3634
  full: z14.boolean().optional().describe(
@@ -3648,20 +3644,20 @@ var annotations15 = {
3648
3644
  idempotentHint: true,
3649
3645
  openWorldHint: false
3650
3646
  };
3651
- function createFlowExamplesToolSpec() {
3647
+ function createFlowExamplesToolSpec(runtime) {
3652
3648
  return {
3653
3649
  name: "flow_examples",
3654
3650
  title: TITLE15,
3655
3651
  description: DESCRIPTION13,
3656
3652
  inputSchema: inputSchema13,
3657
3653
  annotations: annotations15,
3658
- handler: (input) => flowExamplesHandlerBody(input)
3654
+ handler: (input) => flowExamplesHandlerBody(runtime, input)
3659
3655
  };
3660
3656
  }
3661
- async function flowExamplesHandlerBody(input) {
3657
+ async function flowExamplesHandlerBody(runtime, input) {
3662
3658
  const { configPath, flow, step, full, includeHidden } = input ?? {};
3663
3659
  try {
3664
- const rawConfig = await loadJsonConfig2(configPath);
3660
+ const rawConfig = await runtime.load(configPath);
3665
3661
  const flowNames = Object.keys(rawConfig.flows || {});
3666
3662
  const flowName = flow || (flowNames.length === 1 ? flowNames[0] : void 0);
3667
3663
  if (!flowName) {
@@ -3715,6 +3711,19 @@ async function flowExamplesHandlerBody(input) {
3715
3711
  }
3716
3712
  return void 0;
3717
3713
  };
3714
+ const packageLookups = /* @__PURE__ */ new Map();
3715
+ let skippedPackages = false;
3716
+ const examplesForPackage = (packageName) => {
3717
+ const existing = packageLookups.get(packageName);
3718
+ if (existing) return existing;
3719
+ if (packageLookups.size >= MAX_PACKAGE_LOOKUPS) {
3720
+ skippedPackages = true;
3721
+ return Promise.resolve(void 0);
3722
+ }
3723
+ const lookup = loadPackageExamples(packageName);
3724
+ packageLookups.set(packageName, lookup);
3725
+ return lookup;
3726
+ };
3718
3727
  const stepTypes = [
3719
3728
  { key: "sources", type: "source" },
3720
3729
  { key: "transformers", type: "transformer" },
@@ -3731,7 +3740,7 @@ async function flowExamplesHandlerBody(input) {
3731
3740
  continue;
3732
3741
  }
3733
3742
  if (!ref.package) continue;
3734
- const packageExamples = await loadPackageExamples(ref.package);
3743
+ const packageExamples = await examplesForPackage(ref.package);
3735
3744
  if (packageExamples)
3736
3745
  examples.push(...toItems(packageExamples, type, name, "package"));
3737
3746
  }
@@ -3741,21 +3750,33 @@ async function flowExamplesHandlerBody(input) {
3741
3750
  count: examples.length,
3742
3751
  examples
3743
3752
  };
3744
- const hints = {
3745
- next: ["Use flow_simulate with step and event to simulate"]
3746
- };
3753
+ const warnings = [];
3747
3754
  if (examples.length === 0) {
3748
- hints.warnings = [
3755
+ warnings.push(
3749
3756
  "No examples found. Add examples to step entries, or reference a package that ships examples (see package_get)."
3750
- ];
3757
+ );
3758
+ }
3759
+ if (skippedPackages) {
3760
+ warnings.push(
3761
+ `Package examples were looked up for the first ${MAX_PACKAGE_LOOKUPS} packages only. Use step to narrow the result.`
3762
+ );
3751
3763
  }
3764
+ const hints = {
3765
+ next: [
3766
+ runtime.simulate ? "Use flow_simulate with step and event to simulate" : HINT_OUT_OF_PROCESS
3767
+ ],
3768
+ ...warnings.length > 0 ? { warnings } : {}
3769
+ };
3752
3770
  return mcpResult15(result, hints);
3753
3771
  } catch (error) {
3754
- return mcpError15(error, "Check configPath \u2014 expected a flow.json file");
3772
+ return mcpError15(
3773
+ error,
3774
+ refusalHint(error, "Check configPath \u2014 expected a flow.json file")
3775
+ );
3755
3776
  }
3756
3777
  }
3757
- function registerFlowExamplesTool(server) {
3758
- const spec = createFlowExamplesToolSpec();
3778
+ function registerFlowExamplesTool(server, runtime) {
3779
+ const spec = createFlowExamplesToolSpec(runtime);
3759
3780
  server.registerTool(
3760
3781
  spec.name,
3761
3782
  {
@@ -3774,9 +3795,7 @@ function registerFlowExamplesTool(server) {
3774
3795
 
3775
3796
  // src/tools/flow-load.ts
3776
3797
  import { z as z15 } from "zod";
3777
- import { loadJsonConfig as loadJsonConfig3 } from "@walkeros/cli";
3778
3798
  import { mcpResult as mcpResult16, mcpError as mcpError16 } from "@walkeros/core";
3779
- var API_ID_PREFIX2 = /^(flow|cfg)_/;
3780
3799
  var WEB_SKELETON = {
3781
3800
  version: 4,
3782
3801
  flows: {
@@ -3798,7 +3817,7 @@ var SERVER_SKELETON = {
3798
3817
  }
3799
3818
  };
3800
3819
  var TITLE16 = "Load or Create Flow";
3801
- var DESCRIPTION14 = "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.";
3820
+ var DESCRIPTION14 = "Load an existing flow configuration from a local file path, URL, or walkerOS API (by flow ID). On the hosted server only inline JSON or a saved flow id is accepted, no file paths or URLs. 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.";
3802
3821
  var inputSchema14 = {
3803
3822
  source: z15.string().optional().describe(
3804
3823
  "Flow source: local file path (./flow.json), URL (https://...), inline JSON string, or API flow ID (cfg_...). Omit to create a new flow."
@@ -3817,19 +3836,19 @@ var annotations16 = {
3817
3836
  idempotentHint: true,
3818
3837
  openWorldHint: true
3819
3838
  };
3820
- function createFlowLoadToolSpec(client) {
3839
+ function createFlowLoadToolSpec(client, runtime) {
3821
3840
  return {
3822
3841
  name: "flow_load",
3823
3842
  title: TITLE16,
3824
3843
  description: DESCRIPTION14,
3825
3844
  inputSchema: inputSchema14,
3826
3845
  annotations: annotations16,
3827
- handler: (input) => flowLoadHandlerBody(client, input)
3846
+ handler: (input) => flowLoadHandlerBody(client, runtime, input)
3828
3847
  };
3829
3848
  }
3830
- async function flowLoadHandlerBody(client, input) {
3849
+ async function flowLoadHandlerBody(client, runtime, input) {
3831
3850
  const { source, platform } = input ?? {};
3832
- if (source && API_ID_PREFIX2.test(source)) {
3851
+ if (source && isCloudId(source)) {
3833
3852
  const resolvedProjectId = resolveDefaultProject(client, void 0);
3834
3853
  if (!resolvedProjectId) {
3835
3854
  return mcpError16(new Error(NO_DEFAULT_PROJECT_ERROR));
@@ -3839,9 +3858,8 @@ async function flowLoadHandlerBody(client, input) {
3839
3858
  flowId: source,
3840
3859
  projectId: resolvedProjectId
3841
3860
  });
3842
- const config = flow.config;
3843
3861
  return mcpResult16(
3844
- redactNestedStrings(config ?? {}, { skip: keepStructural }),
3862
+ redactNestedStrings(flowConfigOf(flow), { skip: keepStructural }),
3845
3863
  {
3846
3864
  next: ["Use flow_validate to check", "Use add-step prompt to modify"]
3847
3865
  }
@@ -3852,7 +3870,7 @@ async function flowLoadHandlerBody(client, input) {
3852
3870
  }
3853
3871
  try {
3854
3872
  if (source) {
3855
- const config = await loadJsonConfig3(source);
3873
+ const config = await runtime.load(source);
3856
3874
  return mcpResult16(redactNestedStrings(config, { skip: keepStructural }), {
3857
3875
  next: ["Use flow_validate to check", "Use add-step prompt to modify"]
3858
3876
  });
@@ -3872,14 +3890,15 @@ async function flowLoadHandlerBody(client, input) {
3872
3890
  ]
3873
3891
  });
3874
3892
  } catch (error) {
3893
+ if (error instanceof RuntimeRefusal) return mcpError16(error, error.hint);
3875
3894
  const msg = error instanceof Error ? error.message : "";
3876
3895
  if (msg.includes("not found") || msg.includes("ENOENT"))
3877
3896
  return mcpError16(error, "Check configPath \u2014 expected a flow.json file");
3878
3897
  return mcpError16(error);
3879
3898
  }
3880
3899
  }
3881
- function registerFlowLoadTool(server, client) {
3882
- const spec = createFlowLoadToolSpec(client);
3900
+ function registerFlowLoadTool(server, client, runtime) {
3901
+ const spec = createFlowLoadToolSpec(client, runtime);
3883
3902
  server.registerTool(
3884
3903
  spec.name,
3885
3904
  {
@@ -24517,6 +24536,7 @@ function wrapRegisteredToolsWithTelemetry(server) {
24517
24536
  }
24518
24537
  function createWalkerOSMcpServer(opts) {
24519
24538
  const packageVersion = opts.version ?? "0.0.0";
24539
+ const runtime = opts.runtime ?? createHostedRuntime(opts.client);
24520
24540
  const server = new McpServer(
24521
24541
  {
24522
24542
  name: "walkeros-flow",
@@ -24535,12 +24555,12 @@ function createWalkerOSMcpServer(opts) {
24535
24555
  registerFrameManageTool(server, opts.client);
24536
24556
  registerFeedbackTool(server, opts.client);
24537
24557
  registerDiagnosticsTool(server, opts.client, packageVersion);
24538
- registerFlowValidateTool(server);
24539
- registerFlowBundleTool(server, opts.client);
24540
- registerFlowSimulateTool(server, opts.client);
24541
- registerFlowPushTool(server);
24542
- registerFlowExamplesTool(server);
24543
- registerFlowLoadTool(server, opts.client);
24558
+ registerFlowValidateTool(server, runtime);
24559
+ registerFlowBundleTool(server, opts.client, runtime);
24560
+ registerFlowSimulateTool(server, opts.client, runtime);
24561
+ registerFlowPushTool(server, runtime);
24562
+ registerFlowExamplesTool(server, runtime);
24563
+ registerFlowLoadTool(server, opts.client, runtime);
24544
24564
  registerPackageSearchTool(server);
24545
24565
  registerGetPackageSchemaTool(server);
24546
24566
  registerPackageSchemaResources(server);
@@ -24835,6 +24855,153 @@ function createStreamableHttpHandler(server, opts = {}) {
24835
24855
  };
24836
24856
  }
24837
24857
 
24858
+ // src/runtime/local.ts
24859
+ import {
24860
+ loadJsonConfig,
24861
+ bundle as bundle2,
24862
+ push,
24863
+ simulateSource,
24864
+ simulateTransformer,
24865
+ simulateCollector,
24866
+ simulateDestination
24867
+ } from "@walkeros/cli";
24868
+
24869
+ // src/runtime/bundle-cache.ts
24870
+ import { createHash } from "crypto";
24871
+ import os from "os";
24872
+ import path from "path";
24873
+ import { mkdir, rm, writeFile } from "fs/promises";
24874
+ import { rmSync } from "fs";
24875
+ import { bundle } from "@walkeros/cli";
24876
+ var MAX_ENTRIES = 8;
24877
+ var cache2 = /* @__PURE__ */ new Map();
24878
+ var inFlight = /* @__PURE__ */ new Map();
24879
+ var cleanupRegistered = false;
24880
+ function hashConfig(resolvedConfig) {
24881
+ return createHash("sha256").update(resolvedConfig).digest("hex");
24882
+ }
24883
+ function isInlineJsonConfig(resolvedConfig) {
24884
+ const trimmed = resolvedConfig.trimStart();
24885
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return false;
24886
+ try {
24887
+ JSON.parse(resolvedConfig);
24888
+ return true;
24889
+ } catch {
24890
+ return false;
24891
+ }
24892
+ }
24893
+ function registerProcessCleanup() {
24894
+ if (cleanupRegistered) return;
24895
+ cleanupRegistered = true;
24896
+ const cleanup = () => {
24897
+ for (const entry of cache2.values()) {
24898
+ try {
24899
+ rmSync(entry.dir, { recursive: true, force: true });
24900
+ } catch {
24901
+ }
24902
+ }
24903
+ cache2.clear();
24904
+ };
24905
+ process.once("exit", cleanup);
24906
+ }
24907
+ async function evictIfNeeded() {
24908
+ while (cache2.size > MAX_ENTRIES) {
24909
+ const oldestKey = cache2.keys().next().value;
24910
+ if (oldestKey === void 0) break;
24911
+ const evicted = cache2.get(oldestKey);
24912
+ cache2.delete(oldestKey);
24913
+ if (evicted) await rm(evicted.dir, { recursive: true, force: true });
24914
+ }
24915
+ }
24916
+ async function getOrBuildBundle(resolvedConfig) {
24917
+ if (!isInlineJsonConfig(resolvedConfig)) return void 0;
24918
+ registerProcessCleanup();
24919
+ const key = hashConfig(resolvedConfig);
24920
+ const cached = cache2.get(key);
24921
+ if (cached) {
24922
+ cache2.delete(key);
24923
+ cache2.set(key, cached);
24924
+ return cached.bundlePath;
24925
+ }
24926
+ const pending = inFlight.get(key);
24927
+ if (pending) return pending;
24928
+ const build = (async () => {
24929
+ const dir = path.join(
24930
+ os.tmpdir(),
24931
+ `walkeros-mcp-bundle-${key.slice(0, 16)}`
24932
+ );
24933
+ await rm(dir, { recursive: true, force: true });
24934
+ await mkdir(dir, { recursive: true });
24935
+ const bundlePath = path.join(dir, "flow.mjs");
24936
+ await writeFile(bundlePath, "", "utf-8");
24937
+ await bundle(resolvedConfig, {
24938
+ target: "simulate",
24939
+ silent: true,
24940
+ buildOverrides: { output: bundlePath, format: "esm", minify: false }
24941
+ });
24942
+ cache2.set(key, { bundlePath, dir });
24943
+ await evictIfNeeded();
24944
+ return bundlePath;
24945
+ })();
24946
+ inFlight.set(key, build);
24947
+ try {
24948
+ return await build;
24949
+ } finally {
24950
+ inFlight.delete(key);
24951
+ }
24952
+ }
24953
+
24954
+ // src/runtime/local.ts
24955
+ function createLocalRuntime() {
24956
+ return {
24957
+ load: (input) => loadJsonConfig(input),
24958
+ bundle: (input, opts) => bundle2(input, {
24959
+ flowName: opts.flowName,
24960
+ stats: opts.stats,
24961
+ buildOverrides: opts.output ? { output: opts.output } : void 0
24962
+ }),
24963
+ async simulate(input, opts) {
24964
+ let bundlePath;
24965
+ try {
24966
+ bundlePath = await getOrBuildBundle(input);
24967
+ } catch {
24968
+ bundlePath = void 0;
24969
+ }
24970
+ const common = { bundlePath, flow: opts.flow, silent: true };
24971
+ switch (opts.stepType) {
24972
+ case "source":
24973
+ return simulateSource(input, opts.event, {
24974
+ sourceId: opts.stepId,
24975
+ ...common
24976
+ });
24977
+ case "transformer":
24978
+ return simulateTransformer(
24979
+ input,
24980
+ opts.event,
24981
+ { transformerId: opts.stepId, ...common, ingest: opts.ingest }
24982
+ );
24983
+ case "collector":
24984
+ return simulateCollector(
24985
+ input,
24986
+ opts.event,
24987
+ { collectorName: opts.stepId, ...common, state: opts.state }
24988
+ );
24989
+ case "destination":
24990
+ return simulateDestination(
24991
+ input,
24992
+ opts.event,
24993
+ { destinationId: opts.stepId, ...common }
24994
+ );
24995
+ }
24996
+ },
24997
+ push: (input, event, opts) => push(input, event, {
24998
+ json: true,
24999
+ flow: opts.flow,
25000
+ platform: opts.platform
25001
+ })
25002
+ };
25003
+ }
25004
+
24838
25005
  // src/tool-definitions.ts
24839
25006
  import { z as z20 } from "zod";
24840
25007
  import { schemas as schemas6 } from "@walkeros/cli/dev";
@@ -24999,7 +25166,7 @@ var TOOL_DEFINITIONS = [
24999
25166
  {
25000
25167
  name: "flow_validate",
25001
25168
  title: "Validate Flow",
25002
- description: "Validate walkerOS events, flow configurations, mapping rules, or data contracts. Accepts JSON strings, file paths, or URLs as input. Returns validation results with errors, warnings, and details.",
25169
+ description: "Validate walkerOS events, flow configurations, mapping rules, or data contracts. Accepts JSON strings, file paths, or URLs as input; on the hosted server only inline JSON or a saved flow id (flow_ or cfg_), no file paths or URLs. Returns validation results with errors, warnings, and details.",
25003
25170
  inputSchema: schemas6.ValidateInputShape,
25004
25171
  annotations: {
25005
25172
  readOnlyHint: true,
@@ -25037,10 +25204,11 @@ var TOOL_DEFINITIONS = [
25037
25204
  verbose: z20.boolean().optional()
25038
25205
  },
25039
25206
  annotations: {
25040
- readOnlyHint: true,
25041
- destructiveHint: false,
25042
- idempotentHint: true,
25043
- openWorldHint: false
25207
+ // Not read-only: simulation compiles and runs the flow in process.
25208
+ readOnlyHint: false,
25209
+ destructiveHint: true,
25210
+ idempotentHint: false,
25211
+ openWorldHint: true
25044
25212
  }
25045
25213
  },
25046
25214
  {
@@ -25063,7 +25231,7 @@ var TOOL_DEFINITIONS = [
25063
25231
  {
25064
25232
  name: "flow_examples",
25065
25233
  title: "Flow Examples",
25066
- 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.",
25234
+ description: "List all step examples in a walkerOS flow configuration. Shows example names, step locations, and in/out shapes. On the hosted server configPath accepts only inline JSON or a saved flow id (flow_ or cfg_), no file paths or URLs. Use this to discover available test fixtures and simulation data.",
25067
25235
  inputSchema: {
25068
25236
  configPath: z20.string().min(1),
25069
25237
  flow: z20.string().optional(),
@@ -25081,7 +25249,7 @@ var TOOL_DEFINITIONS = [
25081
25249
  {
25082
25250
  name: "flow_load",
25083
25251
  title: "Load or Create Flow",
25084
- 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.",
25252
+ description: "Load an existing flow configuration from a local file path, URL, or walkerOS API (by flow ID). On the hosted server only inline JSON or a saved flow id is accepted, no file paths or URLs. 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.",
25085
25253
  inputSchema: {
25086
25254
  source: z20.string().optional(),
25087
25255
  platform: z20.enum(["web", "server"]).optional()
@@ -25172,7 +25340,7 @@ var TOOL_DEFINITIONS = [
25172
25340
  ];
25173
25341
 
25174
25342
  // src/index.ts
25175
- function createToolHandlers(client, packageVersion = "0.0.0") {
25343
+ function createToolHandlers(client, packageVersion = "0.0.0", runtime = createHostedRuntime(client)) {
25176
25344
  const specs = [
25177
25345
  createAuthToolSpec(client),
25178
25346
  createProjectManageToolSpec(client),
@@ -25184,12 +25352,12 @@ function createToolHandlers(client, packageVersion = "0.0.0") {
25184
25352
  createHubManageToolSpec(client),
25185
25353
  createFrameManageToolSpec(client),
25186
25354
  createFeedbackToolSpec(client),
25187
- createFlowValidateToolSpec(),
25188
- createFlowBundleToolSpec(client),
25189
- createFlowSimulateToolSpec(client),
25190
- createFlowPushToolSpec(),
25191
- createFlowExamplesToolSpec(),
25192
- createFlowLoadToolSpec(client),
25355
+ createFlowValidateToolSpec(runtime),
25356
+ createFlowBundleToolSpec(client, runtime),
25357
+ createFlowSimulateToolSpec(client, runtime),
25358
+ createFlowPushToolSpec(runtime),
25359
+ createFlowExamplesToolSpec(runtime),
25360
+ createFlowLoadToolSpec(client, runtime),
25193
25361
  createPackageSearchToolSpec(),
25194
25362
  createPackageGetToolSpec(),
25195
25363
  createDiagnosticsToolSpec(client, packageVersion)
@@ -25249,7 +25417,10 @@ export {
25249
25417
  HUB_NOT_FOUND_HINT,
25250
25418
  HttpToolClient,
25251
25419
  DESCRIPTION7 as OBSERVE_SESSION_DESCRIPTION,
25420
+ RuntimeRefusal,
25252
25421
  TOOL_DEFINITIONS,
25422
+ createHostedRuntime,
25423
+ createLocalRuntime,
25253
25424
  createStreamableHttpHandler,
25254
25425
  createToolHandlers,
25255
25426
  createWalkerOSMcpServer,