@walkeros/mcp 4.7.2-next-1791147139360 → 4.7.2

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
@@ -826,7 +826,7 @@ var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
826
826
  var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
827
827
  var WALKEROS_JSON_PATH = "dist/walkerOS.json";
828
828
  var CACHE_TTL = 5 * 60 * 1e3;
829
- var CLIENT_HEADER = "walkeros-mcp/4.7.2-next-1791147139360";
829
+ var CLIENT_HEADER = "walkeros-mcp/4.7.2";
830
830
  function getPackageBaseUrl() {
831
831
  return process.env.WALKEROS_APP_URL || void 0;
832
832
  }
@@ -1432,6 +1432,21 @@ function wrapUserData(s) {
1432
1432
  const neutralised = s.replace(/<\/user_data>/g, "</user_data_>");
1433
1433
  return `<user_data>${neutralised}</user_data>`;
1434
1434
  }
1435
+ var DISPLAY_TEXT_KEYS = /* @__PURE__ */ new Set([
1436
+ "name",
1437
+ "flowName",
1438
+ "summary"
1439
+ ]);
1440
+ function wrapListedRecord(value) {
1441
+ if (typeof value !== "object" || value === null || Array.isArray(value))
1442
+ return value;
1443
+ const fields = Object.entries(value);
1444
+ const out = {};
1445
+ for (const [key, field] of fields) {
1446
+ out[key] = DISPLAY_TEXT_KEYS.has(key) && typeof field === "string" ? wrapUserData(field) : field;
1447
+ }
1448
+ return out;
1449
+ }
1435
1450
  var STRUCTURAL_KEYS = /* @__PURE__ */ new Set([
1436
1451
  "id",
1437
1452
  "flowId",
@@ -1450,7 +1465,6 @@ var keepStructural = (key) => STRUCTURAL_KEYS.has(key);
1450
1465
  function redactNestedStrings(value, opts) {
1451
1466
  return walk(value, opts);
1452
1467
  }
1453
- var DISPLAY_NAME_KEYS = /* @__PURE__ */ new Set(["name", "flowName"]);
1454
1468
  function redactDisplayNames(value) {
1455
1469
  return walkDisplay(value);
1456
1470
  }
@@ -1459,7 +1473,7 @@ function walkDisplay(value) {
1459
1473
  if (value && typeof value === "object") {
1460
1474
  const out = {};
1461
1475
  for (const [k, v] of Object.entries(value)) {
1462
- if (DISPLAY_NAME_KEYS.has(k) && typeof v === "string") {
1476
+ if (DISPLAY_TEXT_KEYS.has(k) && typeof v === "string") {
1463
1477
  out[k] = wrapUserData(v);
1464
1478
  } else {
1465
1479
  out[k] = walkDisplay(v);
@@ -1666,7 +1680,7 @@ async function feedbackHandlerBody(client, input) {
1666
1680
  const isAnonymous = explicitAnonymous ?? anonymous ?? true;
1667
1681
  await client.submitFeedback(text, {
1668
1682
  anonymous: isAnonymous,
1669
- version: "4.7.2-next-1791147139360"
1683
+ version: "4.7.2"
1670
1684
  });
1671
1685
  return mcpResult8({ ok: true });
1672
1686
  } catch (error) {
@@ -1816,6 +1830,13 @@ import { z as z9 } from "zod";
1816
1830
  import { mcpResult as mcpResult10, mcpError as mcpError11 } from "@walkeros/core";
1817
1831
  var TITLE9 = "Authentication";
1818
1832
  var DESCRIPTION8 = "Manage walkerOS authentication. Check login status, log in via the device authorization grant, or log out. No terminal or browser required, the MCP client handles the authorization URL.";
1833
+ var HOST_LOGIN_MESSAGE = "This connection is already authenticated by the host; no login needed.";
1834
+ var HOST_LOGOUT_MESSAGE = "This connection is authorized by the host, so there is no session here to log out of. To end it, disconnect walkerOS in your MCP client, or revoke it in the walkerOS app under Account, Connected apps.";
1835
+ var STILL_AUTHENTICATED = {
1836
+ config: "A newer session was stored while logging out and was kept. Call auth logout again to remove it.",
1837
+ env: "WALKEROS_TOKEN is still set for this server process, so calls stay authenticated. Remove it from the MCP server configuration.",
1838
+ host: HOST_LOGOUT_MESSAGE
1839
+ };
1819
1840
  var inputSchema9 = {
1820
1841
  action: z9.enum(["status", "login", "logout"]).describe("Authentication action to perform"),
1821
1842
  deviceCode: z9.string().optional().describe(
@@ -1854,10 +1875,20 @@ async function authHandlerBody(client, input) {
1854
1875
  const user = await client.whoami();
1855
1876
  return mcpResult10({
1856
1877
  authenticated: true,
1857
- ...fieldsOf(user)
1878
+ ...redactDisplayNames(fieldsOf(user))
1858
1879
  });
1859
1880
  }
1860
1881
  case "login": {
1882
+ if (client.credentialSource() === "host") {
1883
+ return mcpResult10(
1884
+ { authenticated: true, message: HOST_LOGIN_MESSAGE },
1885
+ {
1886
+ next: [
1887
+ 'Use auth with action "status" to see which account you are on'
1888
+ ]
1889
+ }
1890
+ );
1891
+ }
1861
1892
  if (deviceCode) {
1862
1893
  const poll = await client.pollForToken(deviceCode, {
1863
1894
  timeoutMs: 6e4
@@ -1902,15 +1933,23 @@ async function authHandlerBody(client, input) {
1902
1933
  });
1903
1934
  }
1904
1935
  case "logout": {
1905
- const { deleted } = await client.logout();
1906
- const hadEnvToken = typeof process.env.WALKEROS_TOKEN === "string" && process.env.WALKEROS_TOKEN.length > 0;
1907
- delete process.env.WALKEROS_TOKEN;
1936
+ if (client.credentialSource() === "host") {
1937
+ return mcpError11(new Error(HOST_LOGOUT_MESSAGE));
1938
+ }
1939
+ const { deleted, envCleared } = await client.logout();
1940
+ const remaining = client.credentialSource();
1941
+ if (remaining !== null) {
1942
+ return mcpResult10({
1943
+ loggedOut: false,
1944
+ message: STILL_AUTHENTICATED[remaining]
1945
+ });
1946
+ }
1908
1947
  let message;
1909
- if (deleted && hadEnvToken) {
1948
+ if (deleted && envCleared) {
1910
1949
  message = "Logged out. Config removed and WALKEROS_TOKEN cleared from process environment.";
1911
1950
  } else if (deleted) {
1912
1951
  message = "Logged out and config removed.";
1913
- } else if (hadEnvToken) {
1952
+ } else if (envCleared) {
1914
1953
  message = "No config found. WALKEROS_TOKEN cleared from process environment.";
1915
1954
  } else {
1916
1955
  message = "No config found, already logged out.";
@@ -2066,10 +2105,6 @@ var FRAME_MANAGE_REQUIREMENTS = {
2066
2105
  };
2067
2106
 
2068
2107
  // src/tools/project-manage.ts
2069
- function wrapProjectName(project) {
2070
- const name = stringField(project, "name");
2071
- return isRecord(project) && name !== void 0 ? { ...project, name: wrapUserData(name) } : project;
2072
- }
2073
2108
  var TITLE10 = "Project Management";
2074
2109
  var DESCRIPTION9 = "Manage walkerOS projects. List, create, update, delete projects, or set a default project for CLI operations.";
2075
2110
  var inputSchema10 = {
@@ -2127,17 +2162,19 @@ async function projectManageHandlerBody(client, input) {
2127
2162
  }
2128
2163
  );
2129
2164
  }
2130
- const safe = Array.isArray(projects) ? items.map(wrapProjectName) : { ...fieldsOf(projects), projects: items.map(wrapProjectName) };
2131
- return mcpResult11(safe);
2165
+ return mcpResult11({
2166
+ ...fieldsOf(projects),
2167
+ projects: items.map(wrapListedRecord)
2168
+ });
2132
2169
  }
2133
2170
  case "get": {
2134
2171
  const project = await client.getProject({ projectId });
2135
- return mcpResult11(wrapProjectName(project));
2172
+ return mcpResult11(wrapListedRecord(project));
2136
2173
  }
2137
2174
  case "create": {
2138
2175
  assertParam(name, "name", "create");
2139
2176
  const created = await client.createProject({ name });
2140
- return mcpResult11(wrapProjectName(created), {
2177
+ return mcpResult11(wrapListedRecord(created), {
2141
2178
  next: [
2142
2179
  'Use project_manage with action "set_default" to make this your active project'
2143
2180
  ]
@@ -2146,7 +2183,7 @@ async function projectManageHandlerBody(client, input) {
2146
2183
  case "update": {
2147
2184
  assertParam(name, "name", "update");
2148
2185
  const updated = await client.updateProject({ projectId, name });
2149
- return mcpResult11(wrapProjectName(updated));
2186
+ return mcpResult11(wrapListedRecord(updated));
2150
2187
  }
2151
2188
  case "delete": {
2152
2189
  const deleted = await client.deleteProject({ projectId });
@@ -2308,9 +2345,20 @@ function flowPageUrl(client, projectId, flowId) {
2308
2345
  if (flowId === void 0) return void 0;
2309
2346
  return links.flow({ baseUrl: client.appBaseUrl(), projectId, flowId });
2310
2347
  }
2311
- function safeSummary(flow) {
2312
- const name = stringField(flow, "name");
2313
- return isRecord(flow) && name !== void 0 ? { ...flow, name: wrapUserData(name) } : flow;
2348
+ function safeFlowPage(data) {
2349
+ if (Array.isArray(data)) return { flows: data.map(wrapListedRecord) };
2350
+ const flows = isRecord(data) ? data.flows : void 0;
2351
+ return isRecord(data) && Array.isArray(flows) ? { ...data, flows: flows.map(wrapListedRecord) } : redactDisplayNames(data);
2352
+ }
2353
+ function safeFlowGroup(group) {
2354
+ const safe = wrapListedRecord(group);
2355
+ if (!isRecord(safe)) return safe;
2356
+ const { project, flows } = safe;
2357
+ return {
2358
+ ...safe,
2359
+ ...project !== void 0 && { project: wrapListedRecord(project) },
2360
+ ...Array.isArray(flows) && { flows: flows.map(wrapListedRecord) }
2361
+ };
2314
2362
  }
2315
2363
  function safeDetail(flow) {
2316
2364
  const fields = { ...fieldsOf(flow) };
@@ -2495,9 +2543,7 @@ async function flowManageHandlerBody(client, input) {
2495
2543
  cursor,
2496
2544
  limit
2497
2545
  });
2498
- const flows = isRecord(data2) ? data2.flows : void 0;
2499
- const safe2 = isRecord(data2) && Array.isArray(flows) ? { ...data2, flows: flows.map(safeSummary) } : data2;
2500
- return mcpResult12(safe2);
2546
+ return mcpResult12(safeFlowPage(data2));
2501
2547
  }
2502
2548
  const data = await client.listAllFlows({
2503
2549
  sort,
@@ -2506,7 +2552,7 @@ async function flowManageHandlerBody(client, input) {
2506
2552
  cursor,
2507
2553
  limit
2508
2554
  });
2509
- const safe = Array.isArray(data) ? data.map(safeSummary) : data;
2555
+ const safe = Array.isArray(data) ? data.map(safeFlowGroup) : redactDisplayNames(data);
2510
2556
  return mcpResult12(
2511
2557
  { projects: safe },
2512
2558
  {
@@ -3466,10 +3512,6 @@ async function resolveSessionId(client, options) {
3466
3512
  );
3467
3513
  }
3468
3514
  }
3469
- function resolveProjectId(client, projectId) {
3470
- return projectId ?? client.getDefaultProject();
3471
- }
3472
- var NO_DEFAULT_PROJECT_ERROR2 = "No project ID given and no default project set. Pass projectId or set one with project_manage set_default.";
3473
3515
  function createObserveSessionToolSpec(client) {
3474
3516
  return {
3475
3517
  name: "observe_session",
@@ -3496,9 +3538,9 @@ async function observeSessionHandlerBody(client, input) {
3496
3538
  if (!flowId) {
3497
3539
  return mcpError17(new Error("flowId is required for observe_session."));
3498
3540
  }
3499
- const resolvedProjectId = resolveProjectId(client, projectId);
3541
+ const resolvedProjectId = resolveDefaultProject(client, projectId);
3500
3542
  if (!resolvedProjectId) {
3501
- return mcpError17(new Error(NO_DEFAULT_PROJECT_ERROR2));
3543
+ return mcpError17(new Error(NO_DEFAULT_PROJECT_ERROR));
3502
3544
  }
3503
3545
  try {
3504
3546
  switch (action) {
@@ -4922,7 +4964,7 @@ Every component in a flow is a **step**: sources capture events, transformers pr
4922
4964
  - **Consent** gates destinations (\`config.consent\`) and individual fields (a value's \`consent\`). A mapping rule's \`consent\` is not enforced yet. Privacy-first by design.
4923
4965
  - **Routing** uses one grammar in every chain field (\`source.before\`, \`source.next\`, \`transformer.before\`, \`transformer.next\`, \`collector.next\`, \`destination.before\`, \`destination.next\`). A route is a string ID, a sequence (\`["a", "b"]\`), or a RouteConfig: \`{ match?, next }\`, \`{ match?, one: [...] }\` (first match wins), \`{ match?, many: [...] }\` (every match becomes its own copy of the event with its own id and finishes the rest of the path on its own, never merged), or \`{ match?, stop: true }\` (ends that copy). In a sequence, a member's own \`next\` runs right after it, then the sequence continues. \`match\` reads \`{ ingest, event }\` and each route is evaluated when the event reaches it. A \`stop\` in \`collector.next\` drops the event for every destination; per-destination filtering belongs in \`destination.before\`. An array of only route configs is an implicit \`one\`. The optional \`match\` field is omitted to mean always-match (no wildcard literal).
4924
4966
  - **Pass-through steps** are transformer entries with no \`code\` and no \`package\`. The runtime synthesizes the push for them automatically. Three flavors share this shape: a \`before\` / \`next\`-only step (named hop reusable across destinations), a \`cache\`-only step (dedup, rate-limit), and a \`mapping\`-only step (declarative event-to-event transform). A pass-through must declare at least one of \`before\`, \`next\`, \`cache\`, or \`mapping\`.
4925
- - **Mapping at the transformer position** uses the same \`Mapping.Config\` shape as destinations, but the semantic is event-to-event: \`policy\` and per-rule \`policy\`, \`mapping[].name\` (rename), \`mapping[].ignore\` (drop from chain), and \`include\` apply. \`consent\` is not enforced at this position. Vendor-payload fields (\`data\`, \`silent\`, \`mapping[].data\`) are no-ops at this position.
4967
+ - **Mapping at the transformer position** uses the same \`Mapping.Config\` shape as destinations, but the semantic is event-to-event: only config-level \`policy\` and a rule's \`condition\`, \`policy\`, \`name\` (rename) and \`ignore\` (drop from chain) apply. Everything that shapes a vendor payload or gates a destination is a no-op there: config-level \`consent\`, \`include\`, \`data\`, and a rule's \`consent\`, \`include\`, \`remove\`, \`batch\`, \`settings\`, \`extend\`, \`data\`, \`silent\`; validation warns about them (\`TRANSFORMER_MAPPING_NO_OP\`). A \`config.mapping\` wins over a step-level \`mapping\`.
4926
4968
  - **Closed-schema rule on transformer entries:** known keys only. Operative keys are \`code\`, \`package\`, \`before\`, \`next\`, \`cache\`, \`mapping\`. Combined with structural keys (\`config\`, \`env\`, \`validate\`, \`disabled\`, \`id\`, etc.). Unknown top-level keys on a transformer step are errors (catches typos like \`dedup: {}\` instead of nested under \`cache\`). \`code\` + \`package\` together is a conflict.
4927
4969
  - **Cache** memoizes step output on a configured store. Set \`cache.stop: true\` to short-circuit the chain on HIT (sources default to stop-on-HIT); in a source chain or \`collector.next\` that halts the event for all destinations. Set \`cache.namespace\` to prefix keys; omit it to write keys directly. \`CacheRule.match\` is optional, omit for always-match.
4928
4970
 
@@ -5131,7 +5173,7 @@ import {
5131
5173
  updateProject,
5132
5174
  deleteProject,
5133
5175
  setDefaultProject,
5134
- getDefaultProject,
5176
+ resolveProjectId,
5135
5177
  listAllFlows,
5136
5178
  listFlows,
5137
5179
  getFlow,
@@ -5196,11 +5238,18 @@ var HttpToolClient = class {
5196
5238
  async deleteProject(options) {
5197
5239
  return deleteProject(options);
5198
5240
  }
5241
+ /** Refuses while `WALKEROS_PROJECT_ID` names another project (see the CLI). */
5199
5242
  setDefaultProject(projectId) {
5200
5243
  setDefaultProject(projectId);
5201
5244
  }
5245
+ /**
5246
+ * `WALKEROS_PROJECT_ID`, then the CLI config's default, through the same
5247
+ * resolution the CLI's own commands use. Read here, at the door that owns
5248
+ * this process's environment, never in the shared tool layer: a hosted door
5249
+ * runs in a server process whose variables are no person's selection.
5250
+ */
5202
5251
  getDefaultProject() {
5203
- return getDefaultProject();
5252
+ return resolveProjectId();
5204
5253
  }
5205
5254
  async listAllFlows(options) {
5206
5255
  return listAllFlows(options);
@@ -5325,8 +5374,16 @@ var HttpToolClient = class {
5325
5374
  credentialSource() {
5326
5375
  return credentialSource();
5327
5376
  }
5377
+ /**
5378
+ * Revoke and drop the stored session, then clear a `WALKEROS_TOKEN` from
5379
+ * this process: the local door owns its environment, so a later call in the
5380
+ * same session no longer authenticates with it.
5381
+ */
5328
5382
  async logout() {
5329
- return logout();
5383
+ const result = await logout();
5384
+ const envCleared = Boolean(process.env.WALKEROS_TOKEN);
5385
+ delete process.env.WALKEROS_TOKEN;
5386
+ return { ...result, envCleared };
5330
5387
  }
5331
5388
  /**
5332
5389
  * The app this local door talks to: `WALKEROS_APP_URL`, then the CLI config
@@ -5360,7 +5417,7 @@ var HttpToolClient = class {
5360
5417
  async checkContract() {
5361
5418
  return compareContract({
5362
5419
  baseUrl: this.appBaseUrl(),
5363
- client: { type: "mcp", version: "4.7.2-next-1791147139360" }
5420
+ client: { type: "mcp", version: "4.7.2" }
5364
5421
  });
5365
5422
  }
5366
5423
  /** The live public OpenAPI document of `appBaseUrl()`, without a credential. */
@@ -5571,7 +5628,7 @@ function parseJson(content) {
5571
5628
  }
5572
5629
 
5573
5630
  // src/stdio.ts
5574
- setClientContext({ type: "mcp", version: "4.7.2-next-1791147139360" });
5631
+ setClientContext({ type: "mcp", version: "4.7.2" });
5575
5632
  process.on("uncaughtException", (err) => {
5576
5633
  const emitter = getMcpEmitterSingleton();
5577
5634
  if (emitter) {
@@ -5591,7 +5648,7 @@ process.on("unhandledRejection", (reason) => {
5591
5648
  async function main() {
5592
5649
  const server = createWalkerOSMcpServer({
5593
5650
  client: new HttpToolClient(),
5594
- version: "4.7.2-next-1791147139360",
5651
+ version: "4.7.2",
5595
5652
  runtime: createLocalRuntime()
5596
5653
  });
5597
5654
  const transport = new StdioServerTransport();
@@ -5602,7 +5659,7 @@ main().catch(async (error) => {
5602
5659
  try {
5603
5660
  const emitter = await createMcpEmitter({
5604
5661
  clientInfo: void 0,
5605
- packageVersion: "4.7.2-next-1791147139360"
5662
+ packageVersion: "4.7.2"
5606
5663
  });
5607
5664
  await emitter.emitError("startup");
5608
5665
  } catch {