@walkeros/mcp 4.7.2 → 4.8.0-next-1791496487198

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/stdio.js CHANGED
@@ -281,8 +281,9 @@ import { mcpError as mcpError2 } from "@walkeros/core";
281
281
  function inputIssuesMessage(error) {
282
282
  return error.issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`).join("; ");
283
283
  }
284
- function parseToolInput(shape, raw) {
285
- const parsed = z2.object(shape).safeParse(raw ?? {});
284
+ function parseToolInput(shape, raw, options = {}) {
285
+ const schema = options.strict ? z2.strictObject(shape) : z2.object(shape);
286
+ const parsed = schema.safeParse(raw ?? {});
286
287
  if (!parsed.success) {
287
288
  return {
288
289
  ok: false,
@@ -826,7 +827,7 @@ var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
826
827
  var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
827
828
  var WALKEROS_JSON_PATH = "dist/walkerOS.json";
828
829
  var CACHE_TTL = 5 * 60 * 1e3;
829
- var CLIENT_HEADER = "walkeros-mcp/4.7.2";
830
+ var CLIENT_HEADER = "walkeros-mcp/4.8.0-next-1791496487198";
830
831
  function getPackageBaseUrl() {
831
832
  return process.env.WALKEROS_APP_URL || void 0;
832
833
  }
@@ -1680,7 +1681,7 @@ async function feedbackHandlerBody(client, input) {
1680
1681
  const isAnonymous = explicitAnonymous ?? anonymous ?? true;
1681
1682
  await client.submitFeedback(text, {
1682
1683
  anonymous: isAnonymous,
1683
- version: "4.7.2"
1684
+ version: "4.8.0-next-1791496487198"
1684
1685
  });
1685
1686
  return mcpResult8({ ok: true });
1686
1687
  } catch (error) {
@@ -2037,7 +2038,7 @@ var FLOW_MANAGE_REQUIREMENTS = {
2037
2038
  preview_get: { required: ["flowId", "previewId"] },
2038
2039
  preview_create: {
2039
2040
  required: ["flowId"],
2040
- oneOf: [["flowName", "flowSettingsId"]]
2041
+ oneOf: [["settingsName", "flowSettingsId"]]
2041
2042
  },
2042
2043
  preview_delete: { required: ["flowId", "previewId"] },
2043
2044
  preview_regrant: { required: ["flowId", "previewId"] }
@@ -2094,13 +2095,17 @@ var PROJECT_MANAGE_REQUIREMENTS = {
2094
2095
  create: { required: ["name"] }
2095
2096
  };
2096
2097
  var FRAME_MANAGE_REQUIREMENTS = {
2098
+ list: {
2099
+ required: ["flowId"],
2100
+ hint: 'Use flow_manage action "list" to find the flow the frames belong to.'
2101
+ },
2097
2102
  page: {
2098
- required: ["pageKey"],
2099
- hint: 'Use action "list" to see the source keys of the project\u2019s frames.'
2103
+ required: ["flowId", "pageKey"],
2104
+ hint: 'Use flow_manage action "list" to find the flow, and action "list" to see the source keys of its frames.'
2100
2105
  },
2101
2106
  get: {
2102
- required: ["frameId"],
2103
- hint: 'Use action "list" or "page" to find a frameId.'
2107
+ required: ["flowId", "frameId"],
2108
+ hint: 'Use flow_manage action "list" to find the flow, and action "list" or "page" to find a frameId.'
2104
2109
  }
2105
2110
  };
2106
2111
 
@@ -2377,7 +2382,7 @@ function safeDetail(flow) {
2377
2382
  };
2378
2383
  }
2379
2384
  var TITLE11 = "Flow Management";
2380
- var DESCRIPTION10 = "Manage walkerOS flows and their previews. List/get/create/update/delete/duplicate flows, or create/inspect/delete preview bundles and mint activation grants (preview_regrant) for testing flow changes on live sites.";
2385
+ var DESCRIPTION10 = "Manage walkerOS flows and their previews. List/get/create/update/delete/duplicate flows (deleting a flow deletes its frames too), or create/inspect/delete preview bundles and mint activation grants (preview_regrant) for testing flow changes on live sites.";
2381
2386
  var inputSchema11 = {
2382
2387
  action: z11.enum([
2383
2388
  "list",
@@ -2416,11 +2421,11 @@ var inputSchema11 = {
2416
2421
  previewId: z11.string().optional().describe(
2417
2422
  "Preview ID (prv_...). Required for preview_get, preview_delete, and preview_regrant (all also require flowId)."
2418
2423
  ),
2419
- flowName: z11.string().optional().describe(
2420
- "Used by preview_create \u2014 provide one of flowName or flowSettingsId (preview_create also requires flowId)."
2424
+ settingsName: z11.string().optional().describe(
2425
+ "Settings name of a multi-settings flow (the `settings[].name` from flow_manage list). Used by preview_create: provide one of settingsName or flowSettingsId (preview_create also requires flowId)."
2421
2426
  ),
2422
2427
  flowSettingsId: z11.string().optional().describe(
2423
- "Used by preview_create \u2014 provide one of flowName or flowSettingsId (preview_create also requires flowId)."
2428
+ "Used by preview_create: provide one of settingsName or flowSettingsId (preview_create also requires flowId)."
2424
2429
  ),
2425
2430
  source: z11.discriminatedUnion("kind", [
2426
2431
  z11.object({ kind: z11.literal("draft") }),
@@ -2501,7 +2506,7 @@ function createFlowManageToolSpec(client) {
2501
2506
  };
2502
2507
  }
2503
2508
  async function flowManageHandlerBody(client, input) {
2504
- const parsed = parseToolInput(inputSchema11, input);
2509
+ const parsed = parseToolInput(inputSchema11, input, { strict: true });
2505
2510
  if (!parsed.ok) return parsed.error;
2506
2511
  const {
2507
2512
  action,
@@ -2517,7 +2522,7 @@ async function flowManageHandlerBody(client, input) {
2517
2522
  cursor,
2518
2523
  limit,
2519
2524
  previewId,
2520
- flowName,
2525
+ settingsName,
2521
2526
  flowSettingsId,
2522
2527
  source,
2523
2528
  siteUrl,
@@ -2527,7 +2532,7 @@ async function flowManageHandlerBody(client, input) {
2527
2532
  const validationError = validateActionInput(
2528
2533
  "flow_manage",
2529
2534
  action ?? "",
2530
- { flowId, projectId, name, previewId, flowName, flowSettingsId },
2535
+ { flowId, projectId, name, previewId, settingsName, flowSettingsId },
2531
2536
  FLOW_MANAGE_REQUIREMENTS
2532
2537
  );
2533
2538
  if (validationError) return mcpError13(new Error(validationError));
@@ -2723,7 +2728,7 @@ async function flowManageHandlerBody(client, input) {
2723
2728
  const preview = await client.createPreview({
2724
2729
  projectId: resolvedProjectId,
2725
2730
  flowId,
2726
- flowName,
2731
+ flowName: settingsName,
2727
2732
  flowSettingsId,
2728
2733
  ...source ? { source } : {},
2729
2734
  ...siteUrl ? { siteUrl } : {}
@@ -2796,7 +2801,9 @@ function registerFlowManageTool(server, client) {
2796
2801
  {
2797
2802
  title: spec.title,
2798
2803
  description: spec.description,
2799
- inputSchema: spec.inputSchema,
2804
+ // Strict, so a key the tool does not take is an input error naming that
2805
+ // key rather than a key dropped without a word.
2806
+ inputSchema: z11.strictObject(spec.inputSchema),
2800
2807
  annotations: spec.annotations
2801
2808
  },
2802
2809
  (args) => flowManageHandlerBody(client, args)
@@ -2859,7 +2866,7 @@ async function resolveDeploymentSlug(args) {
2859
2866
 
2860
2867
  // src/tools/deploy-manage.ts
2861
2868
  var TITLE12 = "Deploy Management";
2862
- var DESCRIPTION11 = "Deploy walkerOS flows and manage deployments. deploy waits for the deployment to reach a terminal status by default (wait=true), with a 12-minute budget; pass wait=false to return immediately with the deployment id. A finished deployment carries its status and, on failure, an errorMessage with the user-facing reason; use the get action to re-read it. list supports cursor and limit for pagination. delete removes an active deployment. For get and delete pass flowId (required) plus optional slug to disambiguate when a flow has multiple active deployments. If a flow has >=2 active deployments and no slug is supplied, the tool returns a MULTIPLE_DEPLOYMENTS error with a details[] list showing each deployment's slug, type, status, and updatedAt.";
2869
+ var DESCRIPTION11 = "Deploy walkerOS flows and manage deployments. deploy waits for the deployment to reach a terminal status by default (wait=true), up to 12 minutes on the local door and up to 10 minutes on the hosted door; pass wait=false to return immediately with the deployment id. A finished deployment carries its status and, on failure, an errorMessage with the user-facing reason; use the get action to re-read it. list supports cursor and limit for pagination. delete removes an active deployment. For get and delete pass flowId (required) plus optional slug to disambiguate when a flow has multiple active deployments. If a flow has >=2 active deployments and no slug is supplied, the tool returns a MULTIPLE_DEPLOYMENTS error with a details[] list showing each deployment's slug, type, status, and updatedAt.";
2863
2870
  var DEPLOYMENT_STATUSES = {
2864
2871
  idle: true,
2865
2872
  deploying: true,
@@ -2887,10 +2894,10 @@ var inputSchema12 = {
2887
2894
  type: z12.enum(membersOf(DEPLOYMENT_TYPES)).optional().describe("Deployment type filter for list."),
2888
2895
  status: z12.enum(membersOf(DEPLOYMENT_STATUSES)).optional().describe("Status filter for list."),
2889
2896
  wait: z12.boolean().optional().describe(
2890
- "Wait for the deployment to reach a terminal status (default true), with a 12-minute budget. Set false to return the deployment id immediately. Only used with deploy action."
2897
+ "Wait for the deployment to reach a terminal status (default true): up to 12 minutes on the local door, up to 10 minutes on the hosted door. Set false to return the deployment id immediately. Only used with deploy action."
2891
2898
  ),
2892
- flowName: z12.string().optional().describe(
2893
- "Flow name for multi-settings flows. Only used with deploy action."
2899
+ settingsName: z12.string().optional().describe(
2900
+ "Settings name of a multi-settings flow (the `settings[].name` from flow_manage list). Only used with deploy action."
2894
2901
  ),
2895
2902
  cursor: z12.string().optional().describe(
2896
2903
  "Pagination cursor from a previous list response. Only used with the list action."
@@ -2959,7 +2966,7 @@ function createDeployManageToolSpec(client) {
2959
2966
  };
2960
2967
  }
2961
2968
  async function deployManageHandlerBody(client, input) {
2962
- const parsed = parseToolInput(inputSchema12, input);
2969
+ const parsed = parseToolInput(inputSchema12, input, { strict: true });
2963
2970
  if (!parsed.ok) return parsed.error;
2964
2971
  const {
2965
2972
  action,
@@ -2969,7 +2976,7 @@ async function deployManageHandlerBody(client, input) {
2969
2976
  type,
2970
2977
  status,
2971
2978
  wait,
2972
- flowName,
2979
+ settingsName,
2973
2980
  cursor,
2974
2981
  limit
2975
2982
  } = parsed.data;
@@ -2988,7 +2995,7 @@ async function deployManageHandlerBody(client, input) {
2988
2995
  flowId,
2989
2996
  projectId,
2990
2997
  wait: wait ?? true,
2991
- flowName
2998
+ flowName: settingsName
2992
2999
  });
2993
3000
  const appUrl = deploymentUrl(client, projectId, result);
2994
3001
  return mcpResult13(withAppUrl(redactDisplayNames(result), appUrl), {
@@ -3061,7 +3068,9 @@ function registerDeployTool(server, client) {
3061
3068
  {
3062
3069
  title: spec.title,
3063
3070
  description: spec.description,
3064
- inputSchema: spec.inputSchema,
3071
+ // Strict, so a key the tool does not take is an input error naming that
3072
+ // key: a dropped settings key would deploy as if no settings were named.
3073
+ inputSchema: z12.strictObject(spec.inputSchema),
3065
3074
  annotations: spec.annotations
3066
3075
  },
3067
3076
  (args) => deployManageHandlerBody(client, args)
@@ -4263,14 +4272,17 @@ import { mcpResult as mcpResult18, mcpError as mcpError19 } from "@walkeros/core
4263
4272
  var FRAME_ID_PATTERN2 = /^frm_[A-Za-z0-9_-]{21}$/;
4264
4273
  var MAX_PAGE_KEY_CHARS = 1024;
4265
4274
  var TITLE17 = "Frames";
4266
- var FRAME_MANAGE_DESCRIPTION = 'Read the frames of a measurement plan: named rectangles with marks inside them, drawn in Tag Mode or in the app. Actions: list (every frame of the project, without marks), page (the frames of one page at any depth, with marks), get (one frame with its marks). Read-only: frames are drawn and edited in Tag Mode or the app, never here. A frame name is documentation; the marks inside it carry the meaning. A frame that extends another stores only what it adds, so its tags may carry only the fields they change. Marks are { tags, note }: tags is one flat list of tags, each with an id, a kind such as entity, property or action, a name, and a parentId naming the tag it sits under; note is the frame\u2019s own description and thread. Use hub_manage action "knowledge" with a frameId or markId to read what people wrote on a frame. A markId is a tag id: a tag\u2019s id, parentId and threadRef come back literal when they have the shape the app mints, so they can be passed straight back; every other string value in the marks is wrapped as data, and so is an object key that is not a plain identifier.';
4275
+ var FRAME_MANAGE_DESCRIPTION = 'Read the frames of a measurement plan: named rectangles with marks inside them, drawn in Tag Mode or in the app. Frames belong to a flow: every action takes the flowId of the flow they live in; use flow_manage action "list" to find one. Actions: list (every frame of the flow, without marks), page (the flow\u2019s frames on one page at any depth, with marks), get (one frame with its marks). Read-only: frames are drawn and edited in Tag Mode or the app, never here. A frame name is documentation; the marks inside it carry the meaning. A frame that extends another stores only what it adds, so its tags may carry only the fields they change. Marks are { tags, note }: tags is one flat list of tags, each with an id, a kind such as entity, property or action, a name, and a parentId naming the tag it sits under; note is the frame\u2019s own description and thread. Use hub_manage action "knowledge" with a frameId or markId to read what people wrote on a frame. A markId is a tag id: a tag\u2019s id, parentId and threadRef come back literal when they have the shape the app mints, so they can be passed straight back; every other string value in the marks is wrapped as data, and so is an object key that is not a plain identifier.';
4267
4276
  var FRAME_MANAGE_INPUT_SCHEMA = {
4268
4277
  action: z17.enum(["list", "page", "get"]).describe(
4269
- "list the project\u2019s frames, read one page with marks, or read one frame"
4278
+ "list the flow\u2019s frames, read one page with marks, or read one frame"
4270
4279
  ),
4271
4280
  projectId: z17.string().optional().describe(
4272
4281
  "Project ID. Optional: falls back to the default project when omitted."
4273
4282
  ),
4283
+ flowId: z17.string().optional().describe(
4284
+ 'Flow ID (flow_...). Required for list, page and get: frames belong to a flow. Use flow_manage action "list" to find one.'
4285
+ ),
4274
4286
  pageKey: z17.string().min(1).max(MAX_PAGE_KEY_CHARS).optional().describe(
4275
4287
  "The page as its frames address it (the `source.key` of a page frame, usually the page URL without query). Required for page."
4276
4288
  ),
@@ -4286,12 +4298,23 @@ var annotations17 = {
4286
4298
  };
4287
4299
  var FRAME_HINT_OPEN_PAGE_OR_GET = 'Use action "page" with a pageKey (a frame\u2019s source.key) to read a page with marks, or action "get" with a frameId.';
4288
4300
  var FRAME_HINT_NAMES_ARE_DOCUMENTATION = "Frame names are documentation; the marks inside a frame carry the meaning.";
4289
- var FRAME_HINT_NONE_YET = "This project has no frames yet. Frames are drawn in Tag Mode or the app, not through this tool.";
4301
+ var FRAME_HINT_NONE_YET = "This flow has no frames yet. Frames are drawn in Tag Mode or the app, not through this tool.";
4290
4302
  var FRAME_HINT_MARK_SPACE = "Tag geometry is fractional: a rect is 0..1 of its frame, and an at is 0..1 of its parent tag\u2019s box, or of the frame for a root tag; a child frame sits inside its parent through placements[].rect.";
4291
4303
  var FRAME_HINT_READ_KNOWLEDGE = 'Use hub_manage action "knowledge" with frameId (and markId) to read what people wrote here. A markId is a tag id from these marks, and a tag\u2019s threadRef is the id of its thread entry there.';
4292
4304
  var FRAME_HINT_NONE_ON_PAGE = 'No frames on this page. Check the pageKey against the source.key values from action "list".';
4293
4305
  var FRAME_HINT_EXTENDS_BASE = "This frame extends another and stores only what it adds; read the base frame (extends) for the rest.";
4294
4306
  var FRAME_NOT_FOUND_HINT = 'Use action "list" or "page" to find frame ids.';
4307
+ var FRAME_FLOW_NOT_FOUND_HINT = 'Use flow_manage action "list" to find a live flow of the project.';
4308
+ function frameRefusalHint(error) {
4309
+ switch (codeOf(error)) {
4310
+ case "FLOW_NOT_FOUND":
4311
+ return FRAME_FLOW_NOT_FOUND_HINT;
4312
+ case "FRAME_NOT_FOUND":
4313
+ return FRAME_NOT_FOUND_HINT;
4314
+ default:
4315
+ return errorHint(error, "frames", FRAME_NOT_FOUND_HINT);
4316
+ }
4317
+ }
4295
4318
  var keepSourceAddress = (key) => key === "kind" || key === "key";
4296
4319
  function serializeLean(frame) {
4297
4320
  return {
@@ -4301,7 +4324,6 @@ function serializeLean(frame) {
4301
4324
  extends: frame.extends,
4302
4325
  source: redactNestedStrings(frame.source, { skip: keepSourceAddress }),
4303
4326
  origin: frame.origin,
4304
- flowId: frame.flowId,
4305
4327
  placements: frame.placements.map((placement) => ({
4306
4328
  id: placement.id,
4307
4329
  rect: placement.rect
@@ -4390,11 +4412,11 @@ async function frameManageHandler(client, rawInput) {
4390
4412
  if (!parsed.success) {
4391
4413
  return mcpError19(new Error(inputIssuesMessage(parsed.error)));
4392
4414
  }
4393
- const { action, projectId, pageKey, frameId } = parsed.data;
4415
+ const { action, projectId, flowId, pageKey, frameId } = parsed.data;
4394
4416
  const validationError = validateActionInput(
4395
4417
  "frame_manage",
4396
4418
  action,
4397
- { pageKey, frameId },
4419
+ { flowId, pageKey, frameId },
4398
4420
  FRAME_MANAGE_REQUIREMENTS
4399
4421
  );
4400
4422
  if (validationError) return mcpError19(new Error(validationError));
@@ -4405,8 +4427,10 @@ async function frameManageHandler(client, rawInput) {
4405
4427
  }
4406
4428
  switch (action) {
4407
4429
  case "list": {
4430
+ assertParam(flowId, "flowId", "list");
4408
4431
  const { frames } = await client.listFrames({
4409
- projectId: resolvedProjectId
4432
+ projectId: resolvedProjectId,
4433
+ flowId
4410
4434
  });
4411
4435
  return mcpResult18(
4412
4436
  { frames: frames.map(serializeLean) },
@@ -4419,9 +4443,11 @@ async function frameManageHandler(client, rawInput) {
4419
4443
  );
4420
4444
  }
4421
4445
  case "page": {
4446
+ assertParam(flowId, "flowId", "page");
4422
4447
  assertParam(pageKey, "pageKey", "page");
4423
4448
  const { frames } = await client.listPageFrames({
4424
4449
  projectId: resolvedProjectId,
4450
+ flowId,
4425
4451
  pageKey
4426
4452
  });
4427
4453
  return mcpResult18(
@@ -4432,9 +4458,11 @@ async function frameManageHandler(client, rawInput) {
4432
4458
  );
4433
4459
  }
4434
4460
  case "get": {
4461
+ assertParam(flowId, "flowId", "get");
4435
4462
  assertParam(frameId, "frameId", "get");
4436
4463
  const frame = await client.getFrame({
4437
4464
  projectId: resolvedProjectId,
4465
+ flowId,
4438
4466
  frameId
4439
4467
  });
4440
4468
  return mcpResult18(
@@ -4446,7 +4474,7 @@ async function frameManageHandler(client, rawInput) {
4446
4474
  }
4447
4475
  }
4448
4476
  } catch (error) {
4449
- return mcpError19(error, errorHint(error, "frames", FRAME_NOT_FOUND_HINT));
4477
+ return mcpError19(error, frameRefusalHint(error));
4450
4478
  }
4451
4479
  }
4452
4480
  function createFrameManageToolSpec(client) {
@@ -4930,7 +4958,7 @@ var SERVER_INSTRUCTIONS = `walkerOS is an open-source, privacy-first event data
4930
4958
  14. \`flow_manage({ action: "preview_regrant", flowId: "...", previewId: "...", origins: [...] })\` - mint an activation link; minted while the flow is observed, it pairs with that Observe session automatically, so the previewed page streams into the same feed
4931
4959
  15. \`observe_journeys({ flowId: "..." })\` - read what arrived; it is the only read, and it never judges whether events are correct
4932
4960
  16. \`hub_manage({ action: "releases", flowId: "..." })\` - read what changed across releases and why; \`release_get\` carries a server-computed diff, \`rationale_set\` records why
4933
- 17. \`frame_manage({ action: "page", pageKey: "..." })\` - read the frames of a page with their marks; read-only, edited in Tag Mode or the app
4961
+ 17. \`frame_manage({ action: "page", flowId: "...", pageKey: "..." })\` - read the frames of a flow on one page with their marks; read-only, edited in Tag Mode or the app
4934
4962
 
4935
4963
  ## Architecture: Source \u2192 Collector \u2192 Destination(s)
4936
4964
 
@@ -5417,7 +5445,7 @@ var HttpToolClient = class {
5417
5445
  async checkContract() {
5418
5446
  return compareContract({
5419
5447
  baseUrl: this.appBaseUrl(),
5420
- client: { type: "mcp", version: "4.7.2" }
5448
+ client: { type: "mcp", version: "4.8.0-next-1791496487198" }
5421
5449
  });
5422
5450
  }
5423
5451
  /** The live public OpenAPI document of `appBaseUrl()`, without a credential. */
@@ -5628,7 +5656,7 @@ function parseJson(content) {
5628
5656
  }
5629
5657
 
5630
5658
  // src/stdio.ts
5631
- setClientContext({ type: "mcp", version: "4.7.2" });
5659
+ setClientContext({ type: "mcp", version: "4.8.0-next-1791496487198" });
5632
5660
  process.on("uncaughtException", (err) => {
5633
5661
  const emitter = getMcpEmitterSingleton();
5634
5662
  if (emitter) {
@@ -5648,7 +5676,7 @@ process.on("unhandledRejection", (reason) => {
5648
5676
  async function main() {
5649
5677
  const server = createWalkerOSMcpServer({
5650
5678
  client: new HttpToolClient(),
5651
- version: "4.7.2",
5679
+ version: "4.8.0-next-1791496487198",
5652
5680
  runtime: createLocalRuntime()
5653
5681
  });
5654
5682
  const transport = new StdioServerTransport();
@@ -5659,7 +5687,7 @@ main().catch(async (error) => {
5659
5687
  try {
5660
5688
  const emitter = await createMcpEmitter({
5661
5689
  clientInfo: void 0,
5662
- packageVersion: "4.7.2"
5690
+ packageVersion: "4.8.0-next-1791496487198"
5663
5691
  });
5664
5692
  await emitter.emitError("startup");
5665
5693
  } catch {