mcp-vitest
API

Notifications

Collect and wait on notifications a server pushes to the client.

mcp.notifications(method?) starts collecting immediately and returns a collector. Pass a method to filter.

const progress = mcp.notifications("notifications/progress");
await mcp.callTool("slow", { ms: 100 });
expect(progress.items).toHaveLength(10);

// or wait for one that matters
const collector = mcp.notifications("notifications/progress");
const halfway = collector.waitFor(
  (n) => (n.params as { progress: number }).progress >= 5,
);
await mcp.callTool("slow", { ms: 300 });
await expect(halfway).resolves.toMatchObject({
  method: "notifications/progress",
});

Each item is { method, params, at }, where at is milliseconds since the collector was created. waitFor(predicate, timeoutMs = 5000) resolves with the first match - including one already collected - and abandons pending waiters on close, so a timeout never surfaces against a later test.

A progress token is attached only when you pass onProgress or a collector is listening, so a bare callTool leaves the request untouched and your server's no-token path stays testable. Params arrive as { progress, total?, message? }; the SDK consumes the token first, so items from two concurrent calls to the same tool cannot be told apart - await one at a time when you need to attribute them.

v2 servers collect progress only. The 2026-07-28 lifecycle is stateless, so there is no persistent server to push list_changed from, and the SDK's server side does not emit it - a subscriptions/listen for it succeeds but honours nothing. A gap upstream rather than one the harness withholds; it will be wired up when the SDK sends those notifications. v1 servers collect everything the client receives.