@emseepea/testing 0.9.14 → 0.11.1

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 CHANGED
@@ -75,6 +75,22 @@ const running = await startEmseepea(t, await createApp({
75
75
  const client = await running.connect();
76
76
  ```
77
77
 
78
+ The test context is optional. Use explicit cleanup with Vitest, Jest, another
79
+ runner, or a plain script:
80
+
81
+ ```js
82
+ const running = await startEmseepea(await createApp());
83
+ try {
84
+ const client = await running.connect();
85
+ // assertions
86
+ } finally {
87
+ await running.close();
88
+ }
89
+ ```
90
+
91
+ Passing a test context with an `after` hook, as in the first example, registers
92
+ that same idempotent `close()` operation automatically.
93
+
78
94
  Set `protocolVersion` on `startEmseepea` or `startMcpServer` to test one of the
79
95
  server's documented protocol revisions. Omitting it keeps the `2026-07-28`
80
96
  default; for example, `{ protocolVersion: "2025-11-25" }` exercises the legacy
@@ -93,6 +109,62 @@ For ordinary integration tests, `startMcpServer(...).output()` returns the
93
109
  server's captured `stdout` and `stderr`. Use it to prove that logs do not expose
94
110
  credentials or provider details.
95
111
 
112
+ ## Simulate an MCP Apps Host
113
+
114
+ Use `createMcpAppHostSimulator` to test an app controller without creating a
115
+ fake parent window or JSON-RPC dispatcher. The simulator has no React, Svelte,
116
+ or test-runner dependency.
117
+
118
+ ```js
119
+ import assert from "node:assert/strict";
120
+ import { createMcpAppController } from "@emseepea/server/ui";
121
+ import { createMcpAppHostSimulator } from "@emseepea/testing";
122
+
123
+ const host = createMcpAppHostSimulator({
124
+ hostContext: { theme: "light", displayMode: "inline" },
125
+ });
126
+ const controller = createMcpAppController({
127
+ name: "Order result",
128
+ version: "1.0.0",
129
+ parseResult: parseOrderResult,
130
+ });
131
+
132
+ controller.connect(host.channel);
133
+ host.deliverToolResult({ orderId: "example-123", status: "ready" });
134
+ host.changeHostContext({ theme: "dark" });
135
+
136
+ const sent = controller.sendMessage("Show the delivery details.");
137
+ host.messageRequests()[0].succeed();
138
+ await sent;
139
+
140
+ const rejected = controller.sendMessage("Change the delivery address.");
141
+ host.messageRequests()[1].reject("The action needs confirmation.");
142
+ await assert.rejects(rejected, /host rejected/i);
143
+
144
+ host.cancel("user cancelled");
145
+ await host.teardown("test complete");
146
+
147
+ function parseOrderResult(value) {
148
+ if (!value || typeof value !== "object" ||
149
+ typeof value.orderId !== "string" || value.status !== "ready") {
150
+ throw new TypeError("Invalid order result");
151
+ }
152
+ return { orderId: value.orderId, status: value.status };
153
+ }
154
+ ```
155
+
156
+ Initialization is automatic. `initialized()` shows whether the controller sent
157
+ `ui/notifications/initialized`. The app's `parseResult` function remains the
158
+ validation boundary for delivered structured content. Use `dispatch()` for a
159
+ malformed trusted-parent message and `dispatchUntrusted()` for a message from a
160
+ different source when testing that the controller ignores unsafe input.
161
+
162
+ This deterministic simulation proves the lifecycle behavior that the test
163
+ drives, including initialization, result validation, context changes, message
164
+ responses, cancellation, and teardown. It does not prove behavior in ChatGPT,
165
+ Claude, or another exact host. Qualify each supported host separately through
166
+ its real public journey before making a host-specific production claim.
167
+
96
168
  ## Diagnose Failures
97
169
 
98
170
  The evidence file contains readable test prompts, assistant responses,
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Client } from "@modelcontextprotocol/client";
2
2
  import { serveEmseepea, type AuthenticationOptions } from "@emseepea/server";
3
+ export { createMcpAppHostSimulator, type McpAppHostSimulator, type McpAppHostSimulatorOptions, type McpAppMessageRequest, } from "./mcp-app-host.js";
3
4
  export type SupportedProtocolVersion = "2026-07-28" | "2025-11-25" | "2025-06-18" | "2025-03-26" | "2024-11-05" | "2024-10-07";
4
5
  export interface TestCleanup {
5
6
  after(cleanup: () => Promise<void>): void;
@@ -12,6 +13,7 @@ export interface StartMcpServerOptions {
12
13
  token?: string;
13
14
  }
14
15
  export interface RunningMcpServer {
16
+ close(): Promise<void>;
15
17
  connect(token?: string): Promise<Client>;
16
18
  output(): Readonly<{
17
19
  stdout: string;
@@ -21,6 +23,10 @@ export interface RunningMcpServer {
21
23
  }
22
24
  /** Test-only verifier. Never use it in a deployed server. */
23
25
  export declare function insecureTestAuthentication(permissions: readonly string[], discovery?: "public" | "protected"): AuthenticationOptions;
24
- export declare function startEmseepea(test: TestCleanup, app: Parameters<typeof serveEmseepea>[0], options?: Pick<StartMcpServerOptions, "clientName" | "protocolVersion" | "token">): Promise<RunningMcpServer>;
26
+ type StartEmseepeaOptions = Pick<StartMcpServerOptions, "clientName" | "protocolVersion" | "token">;
27
+ type EmseepeaApp = Parameters<typeof serveEmseepea>[0];
28
+ export declare function startEmseepea(app: EmseepeaApp, options?: StartEmseepeaOptions): Promise<RunningMcpServer>;
29
+ export declare function startEmseepea(test: TestCleanup, app: EmseepeaApp, options?: StartEmseepeaOptions): Promise<RunningMcpServer>;
30
+ export declare function startMcpServer(serverUrl: URL, options?: StartMcpServerOptions): Promise<RunningMcpServer>;
25
31
  export declare function startMcpServer(test: TestCleanup, serverUrl: URL, options?: StartMcpServerOptions): Promise<RunningMcpServer>;
26
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAiC,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,MAAM,wBAAwB,GAChC,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,GAAG,EAAE,GAAG,CAAC;CACV;AAED,6DAA6D;AAC7D,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,SAAS,GAAE,QAAQ,GAAG,WAAyB,GAC9C,qBAAqB,CAyBvB;AAED,wBAAsB,aAAa,CACjC,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,EACxC,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAM,GACpF,OAAO,CAAC,gBAAgB,CAAC,CAkB3B;AAED,wBAAsB,cAAc,CAClC,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,GAAG,EACd,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,gBAAgB,CAAC,CA4D3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAiC,MAAM,8BAA8B,CAAC;AACrF,OAAO,EAAE,aAAa,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,EAC/B,KAAK,oBAAoB,GAC1B,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,wBAAwB,GAChC,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,GACZ,YAAY,CAAC;AAEjB,MAAM,WAAW,WAAW;IAC1B,KAAK,CAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,eAAe,CAAC,EAAE,wBAAwB,CAAC;IAC3C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvD,GAAG,EAAE,GAAG,CAAC;CACV;AAED,6DAA6D;AAC7D,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,SAAS,GAAE,QAAQ,GAAG,WAAyB,GAC9C,qBAAqB,CAyBvB;AAED,KAAK,oBAAoB,GAAG,IAAI,CAAC,qBAAqB,EAAE,YAAY,GAAG,iBAAiB,GAAG,OAAO,CAAC,CAAC;AACpG,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;AAEvD,wBAAgB,aAAa,CAC3B,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC7B,wBAAgB,aAAa,CAC3B,IAAI,EAAE,WAAW,EACjB,GAAG,EAAE,WAAW,EAChB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AA4B7B,wBAAgB,cAAc,CAC5B,SAAS,EAAE,GAAG,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAC7B,wBAAgB,cAAc,CAC5B,IAAI,EAAE,WAAW,EACjB,SAAS,EAAE,GAAG,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,gBAAgB,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
2
2
  import { fileURLToPath } from "node:url";
3
3
  import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
4
4
  import { serveEmseepea } from "@emseepea/server";
5
+ export { createMcpAppHostSimulator, } from "./mcp-app-host.js";
5
6
  /** Test-only verifier. Never use it in a deployed server. */
6
7
  export function insecureTestAuthentication(permissions, discovery = "protected") {
7
8
  const resourceServerUrl = new URL("https://test.example/mcp");
@@ -29,20 +30,27 @@ export function insecureTestAuthentication(permissions, discovery = "protected")
29
30
  },
30
31
  };
31
32
  }
32
- export async function startEmseepea(test, app, options = {}) {
33
+ export async function startEmseepea(testOrApp, appOrOptions = {}, explicitOptions = {}) {
34
+ const usesTestHook = typeof appOrOptions.listen === "function";
35
+ const test = usesTestHook ? testOrApp : undefined;
36
+ const app = usesTestHook ? appOrOptions : testOrApp;
37
+ const options = usesTestHook ? explicitOptions : appOrOptions;
33
38
  const running = await serveEmseepea(app, { port: 0 });
34
39
  const clients = [];
35
- test.after(async () => {
36
- await Promise.allSettled(clients.map((client) => client.close()));
37
- await running.close();
38
- });
40
+ const close = closeServer(clients, running.close);
41
+ test?.after(close);
39
42
  return {
40
43
  ...running,
44
+ close,
41
45
  output: () => Object.freeze({ stdout: "", stderr: "" }),
42
46
  connect: (token = options.token) => connect(running.url, clients, options.clientName, token, options.protocolVersion),
43
47
  };
44
48
  }
45
- export async function startMcpServer(test, serverUrl, options = {}) {
49
+ export async function startMcpServer(testOrServerUrl, serverUrlOrOptions = {}, explicitOptions = {}) {
50
+ const usesTestHook = !(testOrServerUrl instanceof URL);
51
+ const test = usesTestHook ? testOrServerUrl : undefined;
52
+ const serverUrl = usesTestHook ? serverUrlOrOptions : testOrServerUrl;
53
+ const options = usesTestHook ? explicitOptions : serverUrlOrOptions;
46
54
  const child = spawn(process.execPath, [fileURLToPath(serverUrl)], {
47
55
  env: {
48
56
  ...process.env,
@@ -84,11 +92,10 @@ export async function startMcpServer(test, serverUrl, options = {}) {
84
92
  await stopProcess(child);
85
93
  throw error;
86
94
  });
87
- test.after(async () => {
88
- await Promise.allSettled(clients.map((client) => client.close()));
89
- await stopProcess(child);
90
- });
95
+ const close = closeServer(clients, () => stopProcess(child));
96
+ test?.after(close);
91
97
  return {
98
+ close,
92
99
  url,
93
100
  output: () => Object.freeze({ stdout: output, stderr: errors }),
94
101
  connect: (token = options.token) => connect(url, clients, options.clientName, token, options.protocolVersion),
@@ -98,9 +105,22 @@ async function connect(url, clients, clientName = "emseepea-test", token, protoc
98
105
  const client = new Client({ name: clientName, version: "0.0.0" }, protocolVersion === "2026-07-28"
99
106
  ? { versionNegotiation: { mode: { pin: protocolVersion } } }
100
107
  : { supportedProtocolVersions: [protocolVersion], versionNegotiation: { mode: "legacy" } });
101
- await client.connect(new StreamableHTTPClientTransport(url, token ? { authProvider: { token: async () => token } } : undefined));
102
108
  clients.push(client);
103
- return client;
109
+ try {
110
+ await client.connect(new StreamableHTTPClientTransport(url, token ? { authProvider: { token: async () => token } } : undefined));
111
+ return client;
112
+ }
113
+ catch (error) {
114
+ await client.close().catch(() => undefined);
115
+ throw error;
116
+ }
117
+ }
118
+ function closeServer(clients, stop) {
119
+ let closing;
120
+ return () => closing ??= (async () => {
121
+ await Promise.allSettled(clients.map((client) => client.close()));
122
+ await stop();
123
+ })();
104
124
  }
105
125
  async function stopProcess(child) {
106
126
  if (child.exitCode !== null)
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { McpAppHostContext } from "@emseepea/server/ui";
2
+ export interface McpAppHostSimulatorOptions {
3
+ readonly hostContext?: McpAppHostContext;
4
+ }
5
+ export interface McpAppMessageRequest {
6
+ readonly id: string | number;
7
+ readonly text: string;
8
+ succeed(): void;
9
+ reject(message?: string): void;
10
+ }
11
+ export interface McpAppHostSimulator {
12
+ /** Pass this window-compatible channel to `createMcpAppController().connect()`. */
13
+ readonly channel: Window;
14
+ initialized(): boolean;
15
+ messageRequests(): readonly McpAppMessageRequest[];
16
+ deliverToolResult(structuredContent: unknown): void;
17
+ changeHostContext(context: Partial<McpAppHostContext>): void;
18
+ cancel(reason?: string): void;
19
+ teardown(reason?: string): Promise<void>;
20
+ /** Deliver an arbitrary message from the trusted parent for negative tests. */
21
+ dispatch(message: unknown): void;
22
+ /** Deliver an arbitrary message from a different source for trust-boundary tests. */
23
+ dispatchUntrusted(message: unknown): void;
24
+ }
25
+ /** Deterministic, framework-neutral simulation of the MCP Apps browser host lifecycle. */
26
+ export declare function createMcpAppHostSimulator(options?: McpAppHostSimulatorOptions): McpAppHostSimulator;
27
+ //# sourceMappingURL=mcp-app-host.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-host.d.ts","sourceRoot":"","sources":["../src/mcp-app-host.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC;CAC1C;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,OAAO,IAAI,IAAI,CAAC;IAChB,MAAM,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,mBAAmB;IAClC,mFAAmF;IACnF,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,WAAW,IAAI,OAAO,CAAC;IACvB,eAAe,IAAI,SAAS,oBAAoB,EAAE,CAAC;IACnD,iBAAiB,CAAC,iBAAiB,EAAE,OAAO,GAAG,IAAI,CAAC;IACpD,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAAC;IAC7D,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,+EAA+E;IAC/E,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,qFAAqF;IACrF,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAC3C;AAOD,0FAA0F;AAC1F,wBAAgB,yBAAyB,CACvC,OAAO,GAAE,0BAA+B,GACvC,mBAAmB,CAgHrB"}
@@ -0,0 +1,119 @@
1
+ /** Deterministic, framework-neutral simulation of the MCP Apps browser host lifecycle. */
2
+ export function createMcpAppHostSimulator(options = {}) {
3
+ const events = new EventTarget();
4
+ const requests = [];
5
+ const responses = new Map();
6
+ let initialized = false;
7
+ let sequence = 0;
8
+ const parent = {
9
+ postMessage(message) {
10
+ if (!record(message) || message.jsonrpc !== "2.0")
11
+ return;
12
+ if ((typeof message.id === "string" || typeof message.id === "number") &&
13
+ (record(message.result) || record(message.error))) {
14
+ responses.set(message.id, {
15
+ ...(message.result !== undefined ? { result: message.result } : {}),
16
+ ...(message.error !== undefined ? { error: message.error } : {}),
17
+ });
18
+ return;
19
+ }
20
+ if (message.method === "ui/initialize" &&
21
+ (typeof message.id === "string" || typeof message.id === "number")) {
22
+ dispatch({
23
+ jsonrpc: "2.0",
24
+ id: message.id,
25
+ result: {
26
+ protocolVersion: "2026-01-26",
27
+ hostInfo: { name: "emseepea-test-host", version: "0.0.0" },
28
+ hostCapabilities: {},
29
+ hostContext: options.hostContext ?? {},
30
+ },
31
+ }, parent);
32
+ return;
33
+ }
34
+ if (message.method === "ui/notifications/initialized") {
35
+ initialized = true;
36
+ return;
37
+ }
38
+ if (message.method !== "ui/message" ||
39
+ (typeof message.id !== "string" && typeof message.id !== "number") ||
40
+ !record(message.params) || message.params.role !== "user" ||
41
+ !Array.isArray(message.params.content) || message.params.content.length !== 1 ||
42
+ !record(message.params.content[0]) || message.params.content[0].type !== "text" ||
43
+ typeof message.params.content[0].text !== "string")
44
+ return;
45
+ const id = message.id;
46
+ let settled = false;
47
+ const answer = (response) => {
48
+ if (settled)
49
+ throw new Error("The ui/message request has already been answered.");
50
+ settled = true;
51
+ dispatch({ jsonrpc: "2.0", id, ...response }, parent);
52
+ };
53
+ requests.push(Object.freeze({
54
+ id,
55
+ text: message.params.content[0].text,
56
+ succeed: () => answer({ result: {} }),
57
+ reject: (reason = "The test host rejected the message.") => answer({
58
+ error: { code: -32_000, message: reason },
59
+ }),
60
+ }));
61
+ },
62
+ };
63
+ const untrusted = {};
64
+ const channel = {
65
+ parent,
66
+ addEventListener: events.addEventListener.bind(events),
67
+ removeEventListener: events.removeEventListener.bind(events),
68
+ };
69
+ function dispatch(message, source = parent) {
70
+ const event = new Event("message");
71
+ Object.defineProperties(event, {
72
+ data: { value: message },
73
+ source: { value: source },
74
+ });
75
+ events.dispatchEvent(event);
76
+ }
77
+ return {
78
+ channel,
79
+ initialized: () => initialized,
80
+ messageRequests: () => Object.freeze([...requests]),
81
+ deliverToolResult: (structuredContent) => dispatch({
82
+ jsonrpc: "2.0",
83
+ method: "ui/notifications/tool-result",
84
+ params: { structuredContent },
85
+ }),
86
+ changeHostContext: (context) => dispatch({
87
+ jsonrpc: "2.0",
88
+ method: "ui/notifications/host-context-changed",
89
+ params: context,
90
+ }),
91
+ cancel: (reason) => dispatch({
92
+ jsonrpc: "2.0",
93
+ method: "ui/notifications/tool-cancelled",
94
+ ...(reason === undefined ? {} : { params: { reason } }),
95
+ }),
96
+ teardown: async (reason) => {
97
+ const id = `emseepea-host-teardown-${++sequence}`;
98
+ responses.delete(id);
99
+ dispatch({
100
+ jsonrpc: "2.0",
101
+ id,
102
+ method: "ui/resource-teardown",
103
+ params: reason === undefined ? {} : { reason },
104
+ });
105
+ const response = responses.get(id);
106
+ responses.delete(id);
107
+ if (!response)
108
+ throw new Error("The app did not answer resource teardown.");
109
+ if (response.error !== undefined)
110
+ throw new Error("The app rejected resource teardown.");
111
+ },
112
+ dispatch: (message) => dispatch(message),
113
+ dispatchUntrusted: (message) => dispatch(message, untrusted),
114
+ };
115
+ }
116
+ function record(value) {
117
+ return typeof value === "object" && value !== null;
118
+ }
119
+ //# sourceMappingURL=mcp-app-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-app-host.js","sourceRoot":"","sources":["../src/mcp-app-host.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@emseepea/testing",
3
- "version": "0.9.14",
3
+ "version": "0.11.1",
4
4
  "description": "MCP integration and semantic testing helpers",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,7 +41,7 @@
41
41
  "test:built": "node --test test/*.test.mjs"
42
42
  },
43
43
  "dependencies": {
44
- "@emseepea/server": "0.11.0",
44
+ "@emseepea/server": "0.11.1",
45
45
  "@modelcontextprotocol/client": "2.0.0"
46
46
  },
47
47
  "engines": {