@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/README.md +10 -5
- package/dist/index.d.ts +28 -3
- package/dist/index.js +153 -96
- package/dist/index.js.map +1 -1
- package/dist/stdio.js +97 -40
- package/dist/stdio.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -148,11 +148,11 @@ Read these before writing a configuration by hand.
|
|
|
148
148
|
|
|
149
149
|
## Environment variables
|
|
150
150
|
|
|
151
|
-
| Variable | Required | Default | Purpose
|
|
152
|
-
| --------------------- | -------- | ------------------------- |
|
|
153
|
-
| `WALKEROS_TOKEN` | No | none | Automation token (`wos_pat_...`), an alternative to the `auth` tool login
|
|
154
|
-
| `WALKEROS_PROJECT_ID` | No | none |
|
|
155
|
-
| `WALKEROS_APP_URL` | No | `https://app.walkeros.io` | Base URL override
|
|
151
|
+
| Variable | Required | Default | Purpose |
|
|
152
|
+
| --------------------- | -------- | ------------------------- | -------------------------------------------------------------------------- |
|
|
153
|
+
| `WALKEROS_TOKEN` | No | none | Automation token (`wos_pat_...`), an alternative to the `auth` tool login |
|
|
154
|
+
| `WALKEROS_PROJECT_ID` | No | none | Project (`proj_...`) for calls without `projectId`, ahead of `set_default` |
|
|
155
|
+
| `WALKEROS_APP_URL` | No | `https://app.walkeros.io` | Base URL override |
|
|
156
156
|
|
|
157
157
|
## Programmatic usage
|
|
158
158
|
|
|
@@ -193,6 +193,11 @@ AI SDK, call `createToolHandlers(client, version, runtime)` or import
|
|
|
193
193
|
`TOOL_DEFINITIONS` and supply your own `ToolClient`. The stdio binary stays
|
|
194
194
|
available as `@walkeros/mcp/stdio` and the `walkeros-mcp` bin entry.
|
|
195
195
|
|
|
196
|
+
A `ToolClient` served inside a host that authenticates every request itself
|
|
197
|
+
returns `'host'` from `credentialSource()`. The `auth` tool then reports the
|
|
198
|
+
connection as logged in, answers `login` with "no login needed" and refuses
|
|
199
|
+
`logout`, which never reaches the client: the connection ends in the host.
|
|
200
|
+
|
|
196
201
|
A `ToolClient` may implement `checkContract()` and `openapiDocument()`. The
|
|
197
202
|
`diagnostics` tool reports the first as its contract verdict, `unknown` when it
|
|
198
203
|
is absent; the `walkeros://reference/openapi` resource serves the second.
|
package/dist/index.d.ts
CHANGED
|
@@ -370,6 +370,8 @@ interface ToolClient {
|
|
|
370
370
|
}): Promise<unknown>;
|
|
371
371
|
setDefaultProject(projectId: string): void;
|
|
372
372
|
getDefaultProject(): string | null;
|
|
373
|
+
/** Every project's flows, as an array of `{ project: { id, name }, flows }`
|
|
374
|
+
* groups whose `flows` are the rows `listFlows` answers for that project. */
|
|
373
375
|
listAllFlows(options?: {
|
|
374
376
|
sort?: string;
|
|
375
377
|
order?: 'asc' | 'desc';
|
|
@@ -524,15 +526,24 @@ interface ToolClient {
|
|
|
524
526
|
timeoutMs?: number;
|
|
525
527
|
}): Promise<DeviceLoginResult>;
|
|
526
528
|
whoami(): Promise<unknown>;
|
|
527
|
-
/**
|
|
528
|
-
|
|
529
|
+
/**
|
|
530
|
+
* Where a credential would come from, without resolving or refreshing it:
|
|
531
|
+
* `'env'` (`WALKEROS_TOKEN`), `'config'` (a stored login), `'host'` (the
|
|
532
|
+
* door is served inside a host that authenticates every request itself, so
|
|
533
|
+
* this process holds no login to start or end), or null (none).
|
|
534
|
+
*/
|
|
535
|
+
credentialSource(): 'env' | 'config' | 'host' | null;
|
|
529
536
|
/**
|
|
530
537
|
* Retire the session. Where the credential was issued to this process, that
|
|
531
538
|
* means revoking it with the server before dropping it locally; a plane
|
|
532
|
-
* holding a bearer it did not issue reports nothing deleted.
|
|
539
|
+
* holding a bearer it did not issue reports nothing deleted. `envCleared`
|
|
540
|
+
* reports that the door also dropped a `WALKEROS_TOKEN` from its own process
|
|
541
|
+
* environment, which only a door that owns its process does. The `auth`
|
|
542
|
+
* tool never calls this on a `'host'` door.
|
|
533
543
|
*/
|
|
534
544
|
logout(): Promise<{
|
|
535
545
|
deleted: boolean;
|
|
546
|
+
envCleared?: boolean;
|
|
536
547
|
}>;
|
|
537
548
|
/**
|
|
538
549
|
* The base URL of the walkerOS app this door talks to, without a trailing
|
|
@@ -762,7 +773,14 @@ declare class HttpToolClient implements ToolClient {
|
|
|
762
773
|
deleteProject(options: {
|
|
763
774
|
projectId?: string;
|
|
764
775
|
}): Promise<unknown>;
|
|
776
|
+
/** Refuses while `WALKEROS_PROJECT_ID` names another project (see the CLI). */
|
|
765
777
|
setDefaultProject(projectId: string): void;
|
|
778
|
+
/**
|
|
779
|
+
* `WALKEROS_PROJECT_ID`, then the CLI config's default, through the same
|
|
780
|
+
* resolution the CLI's own commands use. Read here, at the door that owns
|
|
781
|
+
* this process's environment, never in the shared tool layer: a hosted door
|
|
782
|
+
* runs in a server process whose variables are no person's selection.
|
|
783
|
+
*/
|
|
766
784
|
getDefaultProject(): string | null;
|
|
767
785
|
listAllFlows(options?: {
|
|
768
786
|
sort?: string;
|
|
@@ -906,8 +924,15 @@ declare class HttpToolClient implements ToolClient {
|
|
|
906
924
|
}): Promise<DeviceLoginResult>;
|
|
907
925
|
whoami(): Promise<unknown>;
|
|
908
926
|
credentialSource(): 'env' | 'config' | null;
|
|
927
|
+
/**
|
|
928
|
+
* Revoke and drop the stored session, then clear a `WALKEROS_TOKEN` from
|
|
929
|
+
* this process: the local door owns its environment, so a later call in the
|
|
930
|
+
* same session no longer authenticates with it.
|
|
931
|
+
*/
|
|
909
932
|
logout(): Promise<{
|
|
910
933
|
deleted: boolean;
|
|
934
|
+
superseded: boolean;
|
|
935
|
+
envCleared: boolean;
|
|
911
936
|
}>;
|
|
912
937
|
/**
|
|
913
938
|
* The app this local door talks to: `WALKEROS_APP_URL`, then the CLI config
|
package/dist/index.js
CHANGED
|
@@ -97,6 +97,81 @@ function createHostedRuntime(client) {
|
|
|
97
97
|
import { z as z2 } from "zod";
|
|
98
98
|
import { mcpResult, mcpError as mcpError2 } from "@walkeros/core";
|
|
99
99
|
|
|
100
|
+
// src/user-data.ts
|
|
101
|
+
function wrapUserData(s) {
|
|
102
|
+
const alreadyWrapped = s.startsWith("<user_data>") && s.endsWith("</user_data>") && s.slice(11, -12).indexOf("</user_data>") === -1;
|
|
103
|
+
if (alreadyWrapped) return s;
|
|
104
|
+
const neutralised = s.replace(/<\/user_data>/g, "</user_data_>");
|
|
105
|
+
return `<user_data>${neutralised}</user_data>`;
|
|
106
|
+
}
|
|
107
|
+
var DISPLAY_TEXT_KEYS = /* @__PURE__ */ new Set([
|
|
108
|
+
"name",
|
|
109
|
+
"flowName",
|
|
110
|
+
"summary"
|
|
111
|
+
]);
|
|
112
|
+
function wrapListedRecord(value) {
|
|
113
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
114
|
+
return value;
|
|
115
|
+
const fields = Object.entries(value);
|
|
116
|
+
const out = {};
|
|
117
|
+
for (const [key, field] of fields) {
|
|
118
|
+
out[key] = DISPLAY_TEXT_KEYS.has(key) && typeof field === "string" ? wrapUserData(field) : field;
|
|
119
|
+
}
|
|
120
|
+
return out;
|
|
121
|
+
}
|
|
122
|
+
var STRUCTURAL_KEYS = /* @__PURE__ */ new Set([
|
|
123
|
+
"id",
|
|
124
|
+
"flowId",
|
|
125
|
+
"projectId",
|
|
126
|
+
"previewId",
|
|
127
|
+
"version",
|
|
128
|
+
"slug",
|
|
129
|
+
"kind",
|
|
130
|
+
"createdAt",
|
|
131
|
+
"updatedAt",
|
|
132
|
+
"deletedAt",
|
|
133
|
+
"package",
|
|
134
|
+
"platform"
|
|
135
|
+
]);
|
|
136
|
+
var keepStructural = (key) => STRUCTURAL_KEYS.has(key);
|
|
137
|
+
function redactNestedStrings(value, opts) {
|
|
138
|
+
return walk(value, opts);
|
|
139
|
+
}
|
|
140
|
+
function redactDisplayNames(value) {
|
|
141
|
+
return walkDisplay(value);
|
|
142
|
+
}
|
|
143
|
+
function walkDisplay(value) {
|
|
144
|
+
if (Array.isArray(value)) return value.map(walkDisplay);
|
|
145
|
+
if (value && typeof value === "object") {
|
|
146
|
+
const out = {};
|
|
147
|
+
for (const [k, v] of Object.entries(value)) {
|
|
148
|
+
if (DISPLAY_TEXT_KEYS.has(k) && typeof v === "string") {
|
|
149
|
+
out[k] = wrapUserData(v);
|
|
150
|
+
} else {
|
|
151
|
+
out[k] = walkDisplay(v);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
function walk(value, opts) {
|
|
159
|
+
if (typeof value === "string") return wrapUserData(value);
|
|
160
|
+
if (Array.isArray(value)) return value.map((v) => walk(v, opts));
|
|
161
|
+
if (value && typeof value === "object") {
|
|
162
|
+
const out = {};
|
|
163
|
+
for (const [k, v] of Object.entries(value)) {
|
|
164
|
+
if (opts?.skip?.(k) && typeof v === "string") {
|
|
165
|
+
out[k] = v;
|
|
166
|
+
} else {
|
|
167
|
+
out[k] = walk(v, opts);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return out;
|
|
171
|
+
}
|
|
172
|
+
return value;
|
|
173
|
+
}
|
|
174
|
+
|
|
100
175
|
// src/tools/narrow.ts
|
|
101
176
|
import { schemas } from "@walkeros/core/dev";
|
|
102
177
|
function isRecord(value) {
|
|
@@ -150,6 +225,13 @@ function parseToolInput(shape, raw) {
|
|
|
150
225
|
// src/tools/auth.ts
|
|
151
226
|
var TITLE = "Authentication";
|
|
152
227
|
var DESCRIPTION = "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.";
|
|
228
|
+
var HOST_LOGIN_MESSAGE = "This connection is already authenticated by the host; no login needed.";
|
|
229
|
+
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.";
|
|
230
|
+
var STILL_AUTHENTICATED = {
|
|
231
|
+
config: "A newer session was stored while logging out and was kept. Call auth logout again to remove it.",
|
|
232
|
+
env: "WALKEROS_TOKEN is still set for this server process, so calls stay authenticated. Remove it from the MCP server configuration.",
|
|
233
|
+
host: HOST_LOGOUT_MESSAGE
|
|
234
|
+
};
|
|
153
235
|
var inputSchema = {
|
|
154
236
|
action: z2.enum(["status", "login", "logout"]).describe("Authentication action to perform"),
|
|
155
237
|
deviceCode: z2.string().optional().describe(
|
|
@@ -188,10 +270,20 @@ async function authHandlerBody(client, input) {
|
|
|
188
270
|
const user = await client.whoami();
|
|
189
271
|
return mcpResult({
|
|
190
272
|
authenticated: true,
|
|
191
|
-
...fieldsOf(user)
|
|
273
|
+
...redactDisplayNames(fieldsOf(user))
|
|
192
274
|
});
|
|
193
275
|
}
|
|
194
276
|
case "login": {
|
|
277
|
+
if (client.credentialSource() === "host") {
|
|
278
|
+
return mcpResult(
|
|
279
|
+
{ authenticated: true, message: HOST_LOGIN_MESSAGE },
|
|
280
|
+
{
|
|
281
|
+
next: [
|
|
282
|
+
'Use auth with action "status" to see which account you are on'
|
|
283
|
+
]
|
|
284
|
+
}
|
|
285
|
+
);
|
|
286
|
+
}
|
|
195
287
|
if (deviceCode) {
|
|
196
288
|
const poll = await client.pollForToken(deviceCode, {
|
|
197
289
|
timeoutMs: 6e4
|
|
@@ -236,15 +328,23 @@ async function authHandlerBody(client, input) {
|
|
|
236
328
|
});
|
|
237
329
|
}
|
|
238
330
|
case "logout": {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
331
|
+
if (client.credentialSource() === "host") {
|
|
332
|
+
return mcpError2(new Error(HOST_LOGOUT_MESSAGE));
|
|
333
|
+
}
|
|
334
|
+
const { deleted, envCleared } = await client.logout();
|
|
335
|
+
const remaining = client.credentialSource();
|
|
336
|
+
if (remaining !== null) {
|
|
337
|
+
return mcpResult({
|
|
338
|
+
loggedOut: false,
|
|
339
|
+
message: STILL_AUTHENTICATED[remaining]
|
|
340
|
+
});
|
|
341
|
+
}
|
|
242
342
|
let message;
|
|
243
|
-
if (deleted &&
|
|
343
|
+
if (deleted && envCleared) {
|
|
244
344
|
message = "Logged out. Config removed and WALKEROS_TOKEN cleared from process environment.";
|
|
245
345
|
} else if (deleted) {
|
|
246
346
|
message = "Logged out and config removed.";
|
|
247
|
-
} else if (
|
|
347
|
+
} else if (envCleared) {
|
|
248
348
|
message = "No config found. WALKEROS_TOKEN cleared from process environment.";
|
|
249
349
|
} else {
|
|
250
350
|
message = "No config found, already logged out.";
|
|
@@ -294,67 +394,6 @@ function isAccessRefusal(error) {
|
|
|
294
394
|
}
|
|
295
395
|
var AUTH_HINT = 'Are you logged in? Use auth(action: "status") to check.';
|
|
296
396
|
|
|
297
|
-
// src/user-data.ts
|
|
298
|
-
function wrapUserData(s) {
|
|
299
|
-
const alreadyWrapped = s.startsWith("<user_data>") && s.endsWith("</user_data>") && s.slice(11, -12).indexOf("</user_data>") === -1;
|
|
300
|
-
if (alreadyWrapped) return s;
|
|
301
|
-
const neutralised = s.replace(/<\/user_data>/g, "</user_data_>");
|
|
302
|
-
return `<user_data>${neutralised}</user_data>`;
|
|
303
|
-
}
|
|
304
|
-
var STRUCTURAL_KEYS = /* @__PURE__ */ new Set([
|
|
305
|
-
"id",
|
|
306
|
-
"flowId",
|
|
307
|
-
"projectId",
|
|
308
|
-
"previewId",
|
|
309
|
-
"version",
|
|
310
|
-
"slug",
|
|
311
|
-
"kind",
|
|
312
|
-
"createdAt",
|
|
313
|
-
"updatedAt",
|
|
314
|
-
"deletedAt",
|
|
315
|
-
"package",
|
|
316
|
-
"platform"
|
|
317
|
-
]);
|
|
318
|
-
var keepStructural = (key) => STRUCTURAL_KEYS.has(key);
|
|
319
|
-
function redactNestedStrings(value, opts) {
|
|
320
|
-
return walk(value, opts);
|
|
321
|
-
}
|
|
322
|
-
var DISPLAY_NAME_KEYS = /* @__PURE__ */ new Set(["name", "flowName"]);
|
|
323
|
-
function redactDisplayNames(value) {
|
|
324
|
-
return walkDisplay(value);
|
|
325
|
-
}
|
|
326
|
-
function walkDisplay(value) {
|
|
327
|
-
if (Array.isArray(value)) return value.map(walkDisplay);
|
|
328
|
-
if (value && typeof value === "object") {
|
|
329
|
-
const out = {};
|
|
330
|
-
for (const [k, v] of Object.entries(value)) {
|
|
331
|
-
if (DISPLAY_NAME_KEYS.has(k) && typeof v === "string") {
|
|
332
|
-
out[k] = wrapUserData(v);
|
|
333
|
-
} else {
|
|
334
|
-
out[k] = walkDisplay(v);
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
return out;
|
|
338
|
-
}
|
|
339
|
-
return value;
|
|
340
|
-
}
|
|
341
|
-
function walk(value, opts) {
|
|
342
|
-
if (typeof value === "string") return wrapUserData(value);
|
|
343
|
-
if (Array.isArray(value)) return value.map((v) => walk(v, opts));
|
|
344
|
-
if (value && typeof value === "object") {
|
|
345
|
-
const out = {};
|
|
346
|
-
for (const [k, v] of Object.entries(value)) {
|
|
347
|
-
if (opts?.skip?.(k) && typeof v === "string") {
|
|
348
|
-
out[k] = v;
|
|
349
|
-
} else {
|
|
350
|
-
out[k] = walk(v, opts);
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
return out;
|
|
354
|
-
}
|
|
355
|
-
return value;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
397
|
// src/action-requirements.ts
|
|
359
398
|
function validateActionInput(toolName, action, input, map) {
|
|
360
399
|
const rule = map[action];
|
|
@@ -474,10 +513,6 @@ var FRAME_MANAGE_REQUIREMENTS = {
|
|
|
474
513
|
};
|
|
475
514
|
|
|
476
515
|
// src/tools/project-manage.ts
|
|
477
|
-
function wrapProjectName(project) {
|
|
478
|
-
const name = stringField(project, "name");
|
|
479
|
-
return isRecord(project) && name !== void 0 ? { ...project, name: wrapUserData(name) } : project;
|
|
480
|
-
}
|
|
481
516
|
var TITLE2 = "Project Management";
|
|
482
517
|
var DESCRIPTION2 = "Manage walkerOS projects. List, create, update, delete projects, or set a default project for CLI operations.";
|
|
483
518
|
var inputSchema2 = {
|
|
@@ -535,17 +570,19 @@ async function projectManageHandlerBody(client, input) {
|
|
|
535
570
|
}
|
|
536
571
|
);
|
|
537
572
|
}
|
|
538
|
-
|
|
539
|
-
|
|
573
|
+
return mcpResult2({
|
|
574
|
+
...fieldsOf(projects),
|
|
575
|
+
projects: items.map(wrapListedRecord)
|
|
576
|
+
});
|
|
540
577
|
}
|
|
541
578
|
case "get": {
|
|
542
579
|
const project = await client.getProject({ projectId });
|
|
543
|
-
return mcpResult2(
|
|
580
|
+
return mcpResult2(wrapListedRecord(project));
|
|
544
581
|
}
|
|
545
582
|
case "create": {
|
|
546
583
|
assertParam(name, "name", "create");
|
|
547
584
|
const created = await client.createProject({ name });
|
|
548
|
-
return mcpResult2(
|
|
585
|
+
return mcpResult2(wrapListedRecord(created), {
|
|
549
586
|
next: [
|
|
550
587
|
'Use project_manage with action "set_default" to make this your active project'
|
|
551
588
|
]
|
|
@@ -554,7 +591,7 @@ async function projectManageHandlerBody(client, input) {
|
|
|
554
591
|
case "update": {
|
|
555
592
|
assertParam(name, "name", "update");
|
|
556
593
|
const updated = await client.updateProject({ projectId, name });
|
|
557
|
-
return mcpResult2(
|
|
594
|
+
return mcpResult2(wrapListedRecord(updated));
|
|
558
595
|
}
|
|
559
596
|
case "delete": {
|
|
560
597
|
const deleted = await client.deleteProject({ projectId });
|
|
@@ -725,9 +762,20 @@ function flowPageUrl(client, projectId, flowId) {
|
|
|
725
762
|
if (flowId === void 0) return void 0;
|
|
726
763
|
return links.flow({ baseUrl: client.appBaseUrl(), projectId, flowId });
|
|
727
764
|
}
|
|
728
|
-
function
|
|
729
|
-
|
|
730
|
-
|
|
765
|
+
function safeFlowPage(data) {
|
|
766
|
+
if (Array.isArray(data)) return { flows: data.map(wrapListedRecord) };
|
|
767
|
+
const flows = isRecord(data) ? data.flows : void 0;
|
|
768
|
+
return isRecord(data) && Array.isArray(flows) ? { ...data, flows: flows.map(wrapListedRecord) } : redactDisplayNames(data);
|
|
769
|
+
}
|
|
770
|
+
function safeFlowGroup(group) {
|
|
771
|
+
const safe = wrapListedRecord(group);
|
|
772
|
+
if (!isRecord(safe)) return safe;
|
|
773
|
+
const { project, flows } = safe;
|
|
774
|
+
return {
|
|
775
|
+
...safe,
|
|
776
|
+
...project !== void 0 && { project: wrapListedRecord(project) },
|
|
777
|
+
...Array.isArray(flows) && { flows: flows.map(wrapListedRecord) }
|
|
778
|
+
};
|
|
731
779
|
}
|
|
732
780
|
function safeDetail(flow) {
|
|
733
781
|
const fields = { ...fieldsOf(flow) };
|
|
@@ -912,9 +960,7 @@ async function flowManageHandlerBody(client, input) {
|
|
|
912
960
|
cursor,
|
|
913
961
|
limit
|
|
914
962
|
});
|
|
915
|
-
|
|
916
|
-
const safe2 = isRecord(data2) && Array.isArray(flows) ? { ...data2, flows: flows.map(safeSummary) } : data2;
|
|
917
|
-
return mcpResult3(safe2);
|
|
963
|
+
return mcpResult3(safeFlowPage(data2));
|
|
918
964
|
}
|
|
919
965
|
const data = await client.listAllFlows({
|
|
920
966
|
sort,
|
|
@@ -923,7 +969,7 @@ async function flowManageHandlerBody(client, input) {
|
|
|
923
969
|
cursor,
|
|
924
970
|
limit
|
|
925
971
|
});
|
|
926
|
-
const safe = Array.isArray(data) ? data.map(
|
|
972
|
+
const safe = Array.isArray(data) ? data.map(safeFlowGroup) : redactDisplayNames(data);
|
|
927
973
|
return mcpResult3(
|
|
928
974
|
{ projects: safe },
|
|
929
975
|
{
|
|
@@ -1883,10 +1929,6 @@ async function resolveSessionId(client, options) {
|
|
|
1883
1929
|
);
|
|
1884
1930
|
}
|
|
1885
1931
|
}
|
|
1886
|
-
function resolveProjectId(client, projectId) {
|
|
1887
|
-
return projectId ?? client.getDefaultProject();
|
|
1888
|
-
}
|
|
1889
|
-
var NO_DEFAULT_PROJECT_ERROR2 = "No project ID given and no default project set. Pass projectId or set one with project_manage set_default.";
|
|
1890
1932
|
function createObserveSessionToolSpec(client) {
|
|
1891
1933
|
return {
|
|
1892
1934
|
name: "observe_session",
|
|
@@ -1913,9 +1955,9 @@ async function observeSessionHandlerBody(client, input) {
|
|
|
1913
1955
|
if (!flowId) {
|
|
1914
1956
|
return mcpError8(new Error("flowId is required for observe_session."));
|
|
1915
1957
|
}
|
|
1916
|
-
const resolvedProjectId =
|
|
1958
|
+
const resolvedProjectId = resolveDefaultProject(client, projectId);
|
|
1917
1959
|
if (!resolvedProjectId) {
|
|
1918
|
-
return mcpError8(new Error(
|
|
1960
|
+
return mcpError8(new Error(NO_DEFAULT_PROJECT_ERROR));
|
|
1919
1961
|
}
|
|
1920
1962
|
try {
|
|
1921
1963
|
switch (action) {
|
|
@@ -2899,7 +2941,7 @@ async function feedbackHandlerBody(client, input) {
|
|
|
2899
2941
|
const isAnonymous = explicitAnonymous ?? anonymous ?? true;
|
|
2900
2942
|
await client.submitFeedback(text, {
|
|
2901
2943
|
anonymous: isAnonymous,
|
|
2902
|
-
version: "4.7.2
|
|
2944
|
+
version: "4.7.2"
|
|
2903
2945
|
});
|
|
2904
2946
|
return mcpResult10({ ok: true });
|
|
2905
2947
|
} catch (error) {
|
|
@@ -3691,7 +3733,7 @@ var NPM_SEARCH_URL = "https://registry.npmjs.org/-/v1/search";
|
|
|
3691
3733
|
var JSDELIVR_BASE = "https://cdn.jsdelivr.net/npm";
|
|
3692
3734
|
var WALKEROS_JSON_PATH = "dist/walkerOS.json";
|
|
3693
3735
|
var CACHE_TTL = 5 * 60 * 1e3;
|
|
3694
|
-
var CLIENT_HEADER = "walkeros-mcp/4.7.2
|
|
3736
|
+
var CLIENT_HEADER = "walkeros-mcp/4.7.2";
|
|
3695
3737
|
function getPackageBaseUrl() {
|
|
3696
3738
|
return process.env.WALKEROS_APP_URL || void 0;
|
|
3697
3739
|
}
|
|
@@ -4983,7 +5025,7 @@ Every component in a flow is a **step**: sources capture events, transformers pr
|
|
|
4983
5025
|
- **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.
|
|
4984
5026
|
- **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).
|
|
4985
5027
|
- **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\`.
|
|
4986
|
-
- **Mapping at the transformer position** uses the same \`Mapping.Config\` shape as destinations, but the semantic is event-to-event: \`policy\` and
|
|
5028
|
+
- **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\`.
|
|
4987
5029
|
- **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.
|
|
4988
5030
|
- **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.
|
|
4989
5031
|
|
|
@@ -5125,7 +5167,7 @@ import {
|
|
|
5125
5167
|
updateProject,
|
|
5126
5168
|
deleteProject,
|
|
5127
5169
|
setDefaultProject,
|
|
5128
|
-
|
|
5170
|
+
resolveProjectId,
|
|
5129
5171
|
listAllFlows,
|
|
5130
5172
|
listFlows,
|
|
5131
5173
|
getFlow,
|
|
@@ -5190,11 +5232,18 @@ var HttpToolClient = class {
|
|
|
5190
5232
|
async deleteProject(options) {
|
|
5191
5233
|
return deleteProject(options);
|
|
5192
5234
|
}
|
|
5235
|
+
/** Refuses while `WALKEROS_PROJECT_ID` names another project (see the CLI). */
|
|
5193
5236
|
setDefaultProject(projectId) {
|
|
5194
5237
|
setDefaultProject(projectId);
|
|
5195
5238
|
}
|
|
5239
|
+
/**
|
|
5240
|
+
* `WALKEROS_PROJECT_ID`, then the CLI config's default, through the same
|
|
5241
|
+
* resolution the CLI's own commands use. Read here, at the door that owns
|
|
5242
|
+
* this process's environment, never in the shared tool layer: a hosted door
|
|
5243
|
+
* runs in a server process whose variables are no person's selection.
|
|
5244
|
+
*/
|
|
5196
5245
|
getDefaultProject() {
|
|
5197
|
-
return
|
|
5246
|
+
return resolveProjectId();
|
|
5198
5247
|
}
|
|
5199
5248
|
async listAllFlows(options) {
|
|
5200
5249
|
return listAllFlows(options);
|
|
@@ -5319,8 +5368,16 @@ var HttpToolClient = class {
|
|
|
5319
5368
|
credentialSource() {
|
|
5320
5369
|
return credentialSource();
|
|
5321
5370
|
}
|
|
5371
|
+
/**
|
|
5372
|
+
* Revoke and drop the stored session, then clear a `WALKEROS_TOKEN` from
|
|
5373
|
+
* this process: the local door owns its environment, so a later call in the
|
|
5374
|
+
* same session no longer authenticates with it.
|
|
5375
|
+
*/
|
|
5322
5376
|
async logout() {
|
|
5323
|
-
|
|
5377
|
+
const result = await logout();
|
|
5378
|
+
const envCleared = Boolean(process.env.WALKEROS_TOKEN);
|
|
5379
|
+
delete process.env.WALKEROS_TOKEN;
|
|
5380
|
+
return { ...result, envCleared };
|
|
5324
5381
|
}
|
|
5325
5382
|
/**
|
|
5326
5383
|
* The app this local door talks to: `WALKEROS_APP_URL`, then the CLI config
|
|
@@ -5354,7 +5411,7 @@ var HttpToolClient = class {
|
|
|
5354
5411
|
async checkContract() {
|
|
5355
5412
|
return compareContract({
|
|
5356
5413
|
baseUrl: this.appBaseUrl(),
|
|
5357
|
-
client: { type: "mcp", version: "4.7.2
|
|
5414
|
+
client: { type: "mcp", version: "4.7.2" }
|
|
5358
5415
|
});
|
|
5359
5416
|
}
|
|
5360
5417
|
/** The live public OpenAPI document of `appBaseUrl()`, without a credential. */
|