@wakeshift/sdk 0.9.0 → 0.10.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  What changed in each release of `@wakeshift/sdk`. 0.4.0 is the first published release: to start with it, read the [README](README.md). Its notes below, and the earlier releases', are for apps that ran the preview builds.
4
4
 
5
+ ## 0.10.0 (2026-11-03)
6
+
7
+ ### Changed
8
+
9
+ - **`wakeshift_wait` is opt-in.** `attach` (and `attachMastra`) no longer serves Claude Code's wait tool unless you turn it on: `wake.attach(server, { tools: { wait: { enabled: true } } })`. While a conversation waits on it, Claude Code keeps a request open to your server for about 20 seconds at a time and sends the next about a second later, for as long as it waits, whether or not anything arrives: on a serverless host, a function invocation per waiting conversation, all the time. This changes behavior for apps on today's defaults: a recent Claude Code in the terminal whose user declines Wakeshift's plugin now waits with a background monitor, as every other Claude Code does, rather than on your server. In manual permission mode that means approving the monitor, and each restart every 25 minutes, instead of one approval of `wakeshift_wait`; and the wait no longer carries on through `claude --continue`. Users who install the plugin see no difference. To keep the wait tool, add `tools: { wait: { enabled: true } }`, on a stateless server, and on a serverless host give the function a timeout of at least 30 seconds. Without it, `server/discover` no longer offers the tasks extension, tools/list no longer lists `wakeshift_wait`, and Wakeshift's `tasks/get` and `tasks/cancel` go on to your MCP SDK.
10
+ - **`tools` takes an object, each tool `{ enabled }`**: `subscribe`, `list` and `unsubscribe` (on unless disabled, as before) and `wait` (off unless enabled). `tools: { subscribe: { enabled: false } }` replaces `tools: ["unsubscribe_events", "list_subscriptions"]`. New types: `AttachTools`, `ToolOptions`, `WaitToolOptions`.
11
+
12
+ ### Deprecated
13
+
14
+ - **`tools` as a list of names** (`BUILTIN_TOOLS`). It still works in this release, adding the tools it names and never the wait tool, and warns once through `onWarning`.
15
+
5
16
  ## 0.9.0 (2026-11-03)
6
17
 
7
18
  ### Added
package/README.md CHANGED
@@ -106,7 +106,7 @@ await turn.emit({ table: "juniper" }, { hole: ["As", "Kd"], toCall: 2 }, { to: "
106
106
 
107
107
  - **`wake.defineEvent(name, { description, args, payload, text, authorize?, personal?, deleteOnDelivery? })`** returns the event. `args` is what a subscriber picks; its required string, integer and boolean fields route occurrences, so their values are lowercase IDs (a-z 0-9 . _ -), and an optional one filters on the payload field of the same name. `authorize(subscriber, args)` decides who may subscribe. With `deleteOnDelivery: true`, Wakeshift deletes each occurrence's text and payload once it's delivered. Define every event before `attach`, which throws with none.
108
108
  - **`event.emit(args, payload, { id?, to? })`** checks the payload against its schema and sends it to everyone subscribed with those arguments. A personal event goes to its recipients, `to`: users (the `user` attach's `identify` gives for them), `{ user, subscription }` (exactly one conversation's subscription, the `id` `call.subscribe` returned) and `{ native: user }` (only that user's own MCP Events subscriptions), mixable, up to 1,000. It returns `{ matched, duplicate, unmatched, ended }`: `matched` counts the conversations reached, `unmatched` the users with nothing subscribed, `ended` the subscriptions no longer live (forget them). `id` makes retries emit once: a retry of the same emit returns the first's result with `duplicate: true`, and the same `id` on a different emit (other arguments, recipients or payload) throws `IdReusedError` (`id_reused`) and sends nothing.
109
- - **`wake.attach(server, { identify?, tools?, events? })`** attaches Wakeshift to your MCP server and returns the handle your own tools use (below). It serves `events/list`, `events/subscribe` and `events/unsubscribe` to clients that speak MCP Events, and adds `subscribe_events` (for everyone else), `unsubscribe_events` and `list_subscriptions` (for every client, so a person can always see and stop what they're subscribed to); `tools` names fewer of them (`BUILTIN_TOOLS`; `[]` for none). `identify(ctx)` says who is behind a request, as `{ user, client? }`: `user` is your app's ID for the person, from your own sign-in; without it, requests have no user, so personal events and `list_subscriptions` refuse. On a stateless server, which never sees `initialize` (`createMcpHandler`'s is one), `client` is the MCP client's name as your sign-in knows it (an OAuth registration's `client_name`, say): Wakeshift reads it to tell which program the agent runs in. A name the request carries wins. On a stateless server it also serves `wakeshift_wait` to clients that take MCP tasks (a recent Claude Code in the terminal): Wakeshift tells those conversations to call it, and it wakes them when your events arrive, with nothing to install; other clients don't see it. Once it has run, the first call about events sends your app's manifest, with your events: it adds them and never removes one. An emit before `attach` has run (`createMcpHandler` runs it on the first request), or from a separate process that only emits, sends the manifest only if Wakeshift answers with `unknown_event`, then emits again (see [emitting before any agent connects](#emitting-before-any-agent-connects)).
109
+ - **`wake.attach(server, { identify?, tools?, events? })`** attaches Wakeshift to your MCP server and returns the handle your own tools use (below). It serves `events/list`, `events/subscribe` and `events/unsubscribe` to clients that speak MCP Events, and adds `subscribe_events` (for everyone else), `unsubscribe_events` and `list_subscriptions` (for every client, so a person can always see and stop what they're subscribed to). `tools` picks them, each `{ enabled }`: `subscribe`, `list` and `unsubscribe` are on unless disabled (`tools: { subscribe: { enabled: false } }`); a list of names (`BUILTIN_TOOLS`) still works, but is deprecated. `identify(ctx)` says who is behind a request, as `{ user, client? }`: `user` is your app's ID for the person, from your own sign-in; without it, requests have no user, so personal events and `list_subscriptions` refuse. On a stateless server, which never sees `initialize` (`createMcpHandler`'s is one), `client` is the MCP client's name as your sign-in knows it (an OAuth registration's `client_name`, say): Wakeshift reads it to tell which program the agent runs in. A name the request carries wins. With `tools: { wait: { enabled: true } }`, on a stateless server, it also serves `wakeshift_wait` to clients that take MCP tasks (a recent Claude Code in the terminal): Wakeshift tells those conversations to call it, after the user declines Wakeshift's plugin, instead of starting a background monitor; other clients don't see it. It's off by default, because each waiting conversation then keeps a request open to your server (about 20 seconds at a time, the next a second later, for as long as it waits): on a serverless host, that's a function invocation per waiting conversation, which needs a timeout of at least 30 seconds. Once it has run, the first call about events sends your app's manifest, with your events: it adds them and never removes one. An emit before `attach` has run (`createMcpHandler` runs it on the first request), or from a separate process that only emits, sends the manifest only if Wakeshift answers with `unknown_event`, then emits again (see [emitting before any agent connects](#emitting-before-any-agent-connects)).
110
110
  - **`event.end(user, id)`** ends one of a user's subscriptions by its ID, outside a tool (a player who timed out, a member removed).
111
111
  - **`event.status(args, { to? })`** counts the conversations subscribed with those arguments (a personal event: one user's), how many are connected now, and how: `{ subscriptions, connected, via: { stream, poll, hooks, webhook } }`. **`event.statusOf([{ user, subscription }, …])`** reads up to 1,000 subscriptions by ID: `[{ id, user, live, connected, via? }]`. Both only read.
112
112
  - **`event.publishUrl(args, { to? })`** returns `{ id, event, url }`, a capability URL that emits the event with those arguments (a personal event: to one user) for services that only send webhooks. A POST's JSON body is the payload, checked against the event's schema. `wake.revokePublishUrl(id)` stops it.
@@ -255,7 +255,7 @@ const watchCi = createTool({
255
255
  const server = attached.serve(new MCPServer({ id: "ci-bot", name: "CI bot", version: "1.0.0", tools: { watch_ci: watchCi } }))
256
256
  ```
257
257
 
258
- Serve it as Mastra's docs do (`server.startHTTP`, `server.startStdio`, or registered on your `Mastra` instance). It gets everything `attach` gives: the built-in tools, MCP Events for clients that speak it, Claude Code's `wakeshift_wait`, and Wakeshift's addition in your wrapped tools' results.
258
+ Serve it as Mastra's docs do (`server.startHTTP`, `server.startStdio`, or registered on your `Mastra` instance). It gets everything `attach` gives: the built-in tools, MCP Events for clients that speak it, Claude Code's `wakeshift_wait` (with `tools: { wait: { enabled: true } }`), and Wakeshift's addition in your wrapped tools' results.
259
259
 
260
260
  - `attached.events(name, { subscribes }, handler)` wraps a tool's `execute` for the tool your `MCPServer` serves under `name` (its key in `tools`); `subscribes` is as on `attach`'s handle. `handler(args, call, context)` returns what a Mastra tool returns: a string, or your output. Run outside an MCP client's call (by an agent, a workflow or Studio), `call.subscribe` throws.
261
261
  - Wrapped tools answer in one call: a Mastra task or a request for input from one ends what it subscribed.
package/dist/events.d.ts CHANGED
@@ -194,19 +194,53 @@ export interface AttachOptions<C = any> {
194
194
  */
195
195
  identify?(extra: C): Identity | undefined;
196
196
  /**
197
- * Which of attach's own tools it adds (BUILTIN_TOOLS): subscribe_events,
198
- * unsubscribe_events and list_subscriptions. Default: all three; `[]`
199
- * adds none. Leave out unsubscribe_events or list_subscriptions only if
200
- * your own tools let a person see and stop their subscriptions.
197
+ * Which of attach's own tools it adds, each `{ enabled }` (AttachTools):
198
+ * `subscribe` (subscribe_events), `list` (list_subscriptions) and
199
+ * `unsubscribe` (unsubscribe_events), on unless disabled, and `wait`
200
+ * (wakeshift_wait, Claude Code's wait tool), off unless enabled:
201
+ * `tools: { wait: { enabled: true } }`. Disable `list` or `unsubscribe`
202
+ * only if your own tools let a person see and stop their subscriptions.
203
+ *
204
+ * Deprecated: a list of names (BUILTIN_TOOLS) still works for now, adding
205
+ * only the tools it names, and never the wait tool.
201
206
  */
202
- tools?: readonly BuiltinTool[];
207
+ tools?: AttachTools | readonly BuiltinTool[];
203
208
  /** The event features' options: events.native overrides native detection for wrapped tools (attached.events). */
204
209
  events?: EventsOptions<C>;
205
210
  }
206
- /** The tools attach adds, unless AttachOptions.tools names fewer. */
211
+ /** The tools attach adds by default (deprecated as AttachOptions.tools' list form). */
207
212
  export declare const BUILTIN_TOOLS: readonly ["subscribe_events", "unsubscribe_events", "list_subscriptions"];
208
- /** One of attach's own tools. */
213
+ /** One of attach's own tools, by name (AttachOptions.tools' deprecated list form). */
209
214
  export type BuiltinTool = (typeof BUILTIN_TOOLS)[number];
215
+ /** One of attach's own tools' options (AttachTools). */
216
+ export interface ToolOptions {
217
+ /** Whether attach adds it. Default: on, except the wait tool. */
218
+ enabled?: boolean;
219
+ }
220
+ /**
221
+ * The wait tool's options (AttachTools.wait): Wakeshift's wait tool,
222
+ * wakeshift_wait, Claude Code's wake path with nothing installed, where
223
+ * its client takes MCP tasks (protocol 2026-07-28, on a stateless server).
224
+ * Off by default: Claude Code is then woken by its plugin or, after a no, a
225
+ * background Monitor, as every other server's is. On, a waiting
226
+ * conversation's Claude Code holds a request to this server (tasks/get,
227
+ * about 20 seconds) and sends the next about a second later, for as long as
228
+ * it waits: on a serverless host, give the function a timeout of at least
229
+ * 30 seconds, and expect one held invocation per waiting conversation.
230
+ */
231
+ export interface WaitToolOptions extends ToolOptions {
232
+ }
233
+ /** Which of attach's own tools it adds (AttachOptions.tools). */
234
+ export interface AttachTools {
235
+ /** wakeshift_wait, Claude Code's wait tool: off unless enabled. */
236
+ wait?: WaitToolOptions;
237
+ /** subscribe_events, for clients that don't speak MCP Events: on unless disabled. */
238
+ subscribe?: ToolOptions;
239
+ /** list_subscriptions: on unless disabled. */
240
+ list?: ToolOptions;
241
+ /** unsubscribe_events: on unless disabled. */
242
+ unsubscribe?: ToolOptions;
243
+ }
210
244
  export declare const EVENT_TOOL_TEXT: {
211
245
  readonly a_webhook: "a webhook";
212
246
  readonly arguments_argument: "The event's arguments, as an object: see the event's list above";
package/dist/events.js CHANGED
@@ -326,8 +326,51 @@ export class ArgsError extends WakeshiftError {
326
326
  this.name = "ArgsError";
327
327
  }
328
328
  }
329
- /** The tools attach adds, unless AttachOptions.tools names fewer. */
329
+ /** The tools attach adds by default (deprecated as AttachOptions.tools' list form). */
330
330
  export const BUILTIN_TOOLS = ["subscribe_events", "unsubscribe_events", "list_subscriptions"];
331
+ const TOOL_KEYS = { subscribe: "subscribe_events", list: "list_subscriptions", unsubscribe: "unsubscribe_events" };
332
+ /**
333
+ * @internal AttachOptions.tools as the tools to add: each `{ enabled }` of
334
+ * the object form, or the names of the deprecated list form (never the
335
+ * wait tool). Throws on a key, name or value it doesn't know.
336
+ */
337
+ export function toolChoice(tools, what = "attach") {
338
+ if (tools === undefined)
339
+ return { builtin: new Set(BUILTIN_TOOLS), wait: false };
340
+ if (Array.isArray(tools)) {
341
+ for (const t of tools) {
342
+ if (!BUILTIN_TOOLS.includes(t))
343
+ throw new Error(`wakeshift: ${what}'s tools names "${t}": its own tools are ${BUILTIN_TOOLS.join(", ")}`);
344
+ }
345
+ return { builtin: new Set(tools), wait: false };
346
+ }
347
+ if (!tools || typeof tools !== "object")
348
+ throw new Error(`wakeshift: ${what}'s tools is { wait, subscribe, list, unsubscribe }, each { enabled }`);
349
+ const o = tools;
350
+ for (const [k, v] of Object.entries(o)) {
351
+ if (k !== "wait" && !(k in TOOL_KEYS))
352
+ throw new Error(`wakeshift: ${what}'s tools has "${k}": its own tools are wait, subscribe, list and unsubscribe`);
353
+ if (v === undefined)
354
+ continue;
355
+ if (!v || typeof v !== "object" || Array.isArray(v))
356
+ throw new Error(`wakeshift: ${what}'s tools.${k} is an object, { enabled }`);
357
+ for (const [ok, ov] of Object.entries(v)) {
358
+ if (ok !== "enabled")
359
+ throw new Error(`wakeshift: ${what}'s tools.${k} has "${ok}": its options are { enabled }`);
360
+ if (ov !== undefined && typeof ov !== "boolean")
361
+ throw new Error(`wakeshift: ${what}'s tools.${k}.enabled is true or false`);
362
+ }
363
+ }
364
+ const builtin = new Set();
365
+ for (const [k, name] of Object.entries(TOOL_KEYS))
366
+ if (o[k]?.enabled !== false)
367
+ builtin.add(name);
368
+ return { builtin, wait: o.wait?.enabled === true };
369
+ }
370
+ /** @internal The warning for AttachOptions.tools' deprecated list form. */
371
+ export function toolsListWarning(what = "attach") {
372
+ return `wakeshift: ${what}'s tools as a list of names is deprecated: pass { subscribe, list, unsubscribe }, each { enabled } (and wait: { enabled: true } for Claude Code's wait tool)`;
373
+ }
331
374
  // What a client says about itself on initialize (2.x: or the request's
332
375
  // envelope), or a request's _meta; else the name identify gave (identified).
333
376
  function clientInfoName(host, meta, identified) {
@@ -484,18 +527,21 @@ export function attachEvents(wake, server, events, opts = {}) {
484
527
  checkAttach(events, opts);
485
528
  return attachHost(wake, hostOf(server), events, opts);
486
529
  }
487
- /** @internal What attach refuses before it touches a server: no events, or an own tool it doesn't have. */
530
+ /** @internal What attach refuses before it touches a server: no events, or tools it doesn't know. */
488
531
  export function checkAttach(events, opts, what = "attach") {
489
532
  if (events.length === 0)
490
533
  throw new Error(`wakeshift: ${what} needs at least one event (wake.defineEvent) defined first`);
491
- for (const t of opts.tools ?? []) {
492
- if (!BUILTIN_TOOLS.includes(t))
493
- throw new Error(`wakeshift: ${what}'s tools names "${t}": its own tools are ${BUILTIN_TOOLS.join(", ")}`);
494
- }
534
+ toolChoice(opts.tools, what);
495
535
  }
496
536
  /** @internal attach on a Host: an McpServer's, or a framework adapter's (mastra.ts, xmcp.ts). */
497
537
  export function attachHost(wake, host, events, opts = {}) {
498
- const tools = new Set(opts.tools ?? BUILTIN_TOOLS);
538
+ const choice = toolChoice(opts.tools);
539
+ if (Array.isArray(opts.tools))
540
+ wake.warnOnce("tools-list", toolsListWarning());
541
+ const tools = choice.builtin;
542
+ // The wait tool, only if the app turns it on and the MCP SDK's request
543
+ // handlers can be reached (tasks.ts): otherwise no call says it takes tasks.
544
+ const wait = choice.wait && !!host.handlers();
499
545
  // raw is the MCP SDK's own request context (1.x's extra, 2.x's ctx): what identify gets.
500
546
  const identityOf = (raw) => opts.identify?.(raw) ?? undefined;
501
547
  // Who's calling: the user, and the client's name (the request's, else identify's).
@@ -510,6 +556,7 @@ export function attachHost(wake, host, events, opts = {}) {
510
556
  clientOf: (meta, identified) => clientInfoName(host, meta, identified),
511
557
  events: opts.events ?? {},
512
558
  warnOnce: (key, message) => wake.warnOnce(key, message),
559
+ wait,
513
560
  });
514
561
  const byName = new Map(events.map((e) => [e.name, e]));
515
562
  try {
@@ -521,15 +568,16 @@ export function attachHost(wake, host, events, opts = {}) {
521
568
  if (!host.handlers() && !host.framework) {
522
569
  // An MCP SDK release that keeps its request handlers elsewhere: the native
523
570
  // events and the built-in tools still work, but not what wraps the SDK's own methods.
524
- wake.warnOnce("handlers", "wakeshift: this MCP SDK keeps its request handlers where Wakeshift can't reach them, so wakeshift_wait, the 2026-07-28 tools/list changes and wrapped tools' output schemas are off: check for a newer @wakeshift/sdk");
571
+ wake.warnOnce("handlers", `wakeshift: this MCP SDK keeps its request handlers where Wakeshift can't reach them, so ${choice.wait ? "wakeshift_wait, " : ""}the 2026-07-28 tools/list changes and wrapped tools' output schemas are off: check for a newer @wakeshift/sdk`);
525
572
  }
526
573
  // Clients that speak only protocol 2026-07-28 (OpenClaw): on the MCP SDK
527
574
  // 1.x, on a stateless transport, server/discover and resultType
528
575
  // (discover.ts); on 2.x, its own.
529
576
  serveStateless(host, { bridgedOnly: ["subscribe_events"] });
530
577
  // Clients that take MCP tasks there (Claude Code): Wakeshift's wait tool,
531
- // answered with a task (tasks.ts).
532
- serveTasks(wake, host, callerOf);
578
+ // answered with a task (tasks.ts), if the app turns it on (wait).
579
+ if (wait)
580
+ serveTasks(wake, host, callerOf);
533
581
  // tools/list: a wrapped tool's output schema names wakeshift, which its
534
582
  // structured results carry (toolcall.ts).
535
583
  attached.amendToolsList();
@@ -665,7 +713,7 @@ export function attachHost(wake, host, events, opts = {}) {
665
713
  }
666
714
  try {
667
715
  const out = await wake.requestApp("POST", "/event-subscriptions", {
668
- call: toolCallOf(host.req(raw), client, user, rest, "subscribe_events"),
716
+ call: toolCallOf(host.req(raw), client, user, rest, "subscribe_events", wait),
669
717
  name: ev.name,
670
718
  arguments: args,
671
719
  });
@@ -700,7 +748,7 @@ export function attachHost(wake, host, events, opts = {}) {
700
748
  return fail(fill("need"));
701
749
  const args = ev.parseArgs(rawArgs ?? {});
702
750
  const out = await wake.requestApp("POST", "/event-subscriptions/unsubscribe", {
703
- call: toolCallOf(host.req(raw), client, user, rest, "unsubscribe_events"),
751
+ call: toolCallOf(host.req(raw), client, user, rest, "unsubscribe_events", wait),
704
752
  name: ev.name,
705
753
  arguments: args,
706
754
  });
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { Wakeshift, DEFAULT_CORE, SESSION_ARG, HARNESS_ARG, CONVERSATION_ARG, ty
2
2
  export { harnessAgent } from "./harness.js";
3
3
  export { IdReusedError, WakeshiftError, isCode } from "./errors.js";
4
4
  export { parseKey, signAssertion, type AppKey } from "./key.js";
5
- export { WakeEvent, ArgsError, EVENT_TOOL_TEXT, notifies, type NotifiesOptions, SUBSCRIBE_TOOL_DESCRIPTION, UNSUBSCRIBE_TOOL_DESCRIPTION, LIST_TOOL_DESCRIPTION, BUILTIN_TOOLS, type BuiltinTool, type EventOptions, type EmitOptions, type EventStatus, type EventSubscriptionStatus, MAX_STATUS_SUBSCRIPTIONS, type EventTypeManifest, type AttachOptions, type Identity, type Subscriber, } from "./events.js";
5
+ export { WakeEvent, ArgsError, EVENT_TOOL_TEXT, notifies, type NotifiesOptions, SUBSCRIBE_TOOL_DESCRIPTION, UNSUBSCRIBE_TOOL_DESCRIPTION, LIST_TOOL_DESCRIPTION, BUILTIN_TOOLS, type BuiltinTool, type EventOptions, type EmitOptions, type EventStatus, type EventSubscriptionStatus, MAX_STATUS_SUBSCRIPTIONS, type EventTypeManifest, type AttachOptions, type AttachTools, type ToolOptions, type WaitToolOptions, type Identity, type Subscriber, } from "./events.js";
6
6
  export { CallEnded, type AnyWakeEvent, type EventArgs, type ToolCallBase, type ToolCallSubscribe, type ToolEventsOptions, type Attached, type AppArgs, type EventsOptions, type Subscription, type ToolCall, type ToolCallExtra, type ToolSubscribeOptions, type WakeArgs, type WakeInputs, type WakeInputsV3, type WakeInputsV4, type WakeKey, type WakeOutputShape, type WakeOutputV3, type WakeOutputV4, type WakeShape, type WrappedCallback, type WrappedResult, } from "./toolcall.js";
7
7
  export type { AuthInfo, CallToolResult, ContentBlock, HostContext, McpServerLike } from "./mcp.js";
8
8
  export { EXTENSION_KEY, TEXT_META, REVISION as EVENTS_REVISION } from "./spec.js";
package/dist/mastra.d.ts CHANGED
@@ -2,7 +2,7 @@ import type * as z3 from "zod/v3";
2
2
  import type * as z4 from "zod/v4";
3
3
  import type { ToolCallExtra } from "./mcp.js";
4
4
  import type { ZodRawShapeCompat } from "./zod.js";
5
- import { type AttachOptions, type BuiltinTool, type Identity } from "./events.js";
5
+ import { type AttachOptions, type AttachTools, type BuiltinTool, type Identity } from "./events.js";
6
6
  import { CallEnded, type AnyWakeEvent, type ToolCall, type ToolEventsOptions, type WakeArgs, type WakeInputs, type WakeInputsV3, type WakeInputsV4, type WakeOutputShape, type WakeOutputV3, type WakeOutputV4 } from "./toolcall.js";
7
7
  import type { Wakeshift } from "./wakeshift.js";
8
8
  /** The @mastra/mcp releases serve() is built for: 2.x, from 2.7. */
@@ -83,4 +83,4 @@ export declare class MastraAttached {
83
83
  * ctx.http?.authInfo).
84
84
  */
85
85
  export declare function attachMastra(wake: Wakeshift, opts?: MastraAttachOptions): MastraAttached;
86
- export { CallEnded, type BuiltinTool, type Identity, type ToolCall, type WakeArgs };
86
+ export { CallEnded, type AttachTools, type BuiltinTool, type Identity, type ToolCall, type WakeArgs };
package/dist/tasks.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // MCP Tasks as a wake path (docs/harnesses.md, "Claude Code: MCP tasks as a
2
2
  // wake path"): for a client that takes MCP tasks, on protocol 2026-07-28
3
- // (discover.ts), attach serves Wakeshift's wait tool, wakeshift_wait. Its
3
+ // (discover.ts), attach with wait: true serves Wakeshift's wait tool,
4
+ // wakeshift_wait (off by default: AttachOptions.wait). Its
4
5
  // call is answered with a task that completes when the conversation's next
5
6
  // Wakeshift messages arrive; the client follows it in the background
6
7
  // (tasks/get), and a completed task wakes an idle conversation. Wakeshift
@@ -58,7 +59,7 @@ export function serveTasks(wake, host, callerOf) {
58
59
  }
59
60
  const call = (raw, args) => {
60
61
  const { user, client } = callerOf(raw);
61
- return toolCallOf(host.req(raw), client, user, args, WAIT_TOOL);
62
+ return toolCallOf(host.req(raw), client, user, args, WAIT_TOOL, true);
62
63
  };
63
64
  const takes = (raw) => {
64
65
  const req = host.req(raw);
package/dist/toolcall.js CHANGED
@@ -300,7 +300,7 @@ export class CallScope {
300
300
  harness: this.args.harness,
301
301
  conversation: this.args.conversation,
302
302
  tool: this.tool,
303
- tasks: takesTasks(meta, req),
303
+ tasks: !!this.at.wait && takesTasks(meta, req),
304
304
  });
305
305
  }
306
306
  // request runs one request of the call to Wakeshift, after any before it
package/dist/wakeshift.js CHANGED
@@ -64,7 +64,7 @@ export function packCall(c) {
64
64
  * others): its _meta and User-Agent, the client's name, the user, and
65
65
  * session_key, harness and conversation_id from its arguments.
66
66
  */
67
- export function toolCallOf(extra, client, user, args, tool) {
67
+ export function toolCallOf(extra, client, user, args, tool, wait) {
68
68
  const req = v1Req(extra); // a request already read passes through
69
69
  return packCall({
70
70
  meta: req.meta,
@@ -75,7 +75,7 @@ export function toolCallOf(extra, client, user, args, tool) {
75
75
  harness: str(args, HARNESS_ARG),
76
76
  conversation: str(args, CONVERSATION_ARG),
77
77
  tool,
78
- tasks: takesTasks(req.meta, req),
78
+ tasks: wait && takesTasks(req.meta, req),
79
79
  });
80
80
  }
81
81
  // str is a tool argument's value if it's a string.
package/dist/xmcp.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { AuthInfo, CallToolResult } from "./mcp.js";
2
2
  import type { ZodRawShapeCompat } from "./zod.js";
3
- import { BUILTIN_TOOLS, type BuiltinTool, type Identity } from "./events.js";
3
+ import { BUILTIN_TOOLS, type AttachTools, type BuiltinTool, type Identity } from "./events.js";
4
4
  import { type AnyWakeEvent, type ToolCall, type ToolEventsOptions, type WakeArgs, type WakeInputs, type WrappedResult } from "./toolcall.js";
5
5
  import type { Wakeshift } from "./wakeshift.js";
6
6
  /** The request context xmcp passes a tool's handler, its second argument: what Wakeshift reads of it. */
@@ -27,8 +27,12 @@ export interface XmcpAttachOptions {
27
27
  * have no user, so personal events and list_subscriptions refuse.
28
28
  */
29
29
  identify?(extra: XmcpExtra): Identity | undefined;
30
- /** Which of attach's own tools attached.tool gives (default: all three). */
31
- tools?: readonly BuiltinTool[];
30
+ /**
31
+ * Which of attach's own tools attached.tool gives, each `{ enabled }`
32
+ * (default: all three). xmcp can't serve the wait tool. Deprecated: a
33
+ * list of names.
34
+ */
35
+ tools?: Omit<AttachTools, "wait"> | readonly BuiltinTool[];
32
36
  }
33
37
  /** One of attach's own tools as an xmcp tool file exports it. */
34
38
  export interface XmcpTool {
@@ -88,4 +92,4 @@ export declare class XmcpAttached {
88
92
  * own tools that subscribe, and attached.tool for attach's own three.
89
93
  */
90
94
  export declare function attachXmcp(wake: Wakeshift, opts?: XmcpAttachOptions): XmcpAttached;
91
- export { BUILTIN_TOOLS, type BuiltinTool, type Identity, type ToolCall, type WakeArgs, type WrappedResult };
95
+ export { BUILTIN_TOOLS, type AttachTools, type BuiltinTool, type Identity, type ToolCall, type WakeArgs, type WrappedResult };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wakeshift/sdk",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Let agents subscribe to things in your app: Wakeshift wakes them when you emit an event.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Clawvisor Inc. <support@wakeshift.ai>",