@mcp-b/webmcp-polyfill 2.3.2 → 3.0.0-beta.20260702171253

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/index.js CHANGED
@@ -1,61 +1,47 @@
1
- import { Validator } from "@cfworker/json-schema";
1
+ import { isPlainObject, normalizeInputSchema, toJsonValue, validateValueWithSchema } from "./schema.js";
2
2
 
3
3
  //#region src/index.ts
4
4
  const FAILED_TO_PARSE_INPUT_ARGUMENTS_MESSAGE = "Failed to parse input arguments";
5
5
  const TOOL_INVOCATION_FAILED_MESSAGE = "Tool was executed but the invocation failed. For example, the script function threw an error";
6
6
  const TOOL_CANCELLED_MESSAGE = "Tool was cancelled";
7
- const DEFAULT_INPUT_SCHEMA = {
8
- type: "object",
9
- properties: {}
10
- };
11
- const STANDARD_JSON_SCHEMA_TARGETS = ["draft-2020-12", "draft-07"];
7
+ /** WebMCP §4.2 tool name: ASCII alnum, underscore, hyphen, period; 1–128 code points. */
8
+ const VALID_TOOL_NAME_RE = /^[A-Za-z0-9_\-.]{1,128}$/u;
12
9
  const POLYFILL_MARKER_PROPERTY = "__isWebMCPPolyfill";
13
10
  const STANDARD_VALIDATOR_SYMBOL = Symbol("standardValidator");
11
+ function createAbortError() {
12
+ return new DOMException("signal is aborted without reason", "AbortError");
13
+ }
14
14
  const installState = {
15
15
  installed: false,
16
- previousModelContextDescriptor: void 0,
17
- previousModelContextTestingDescriptor: void 0
16
+ previousNavigatorModelContextDescriptor: void 0,
17
+ previousNavigatorModelContextTestingDescriptor: void 0,
18
+ previousDocumentModelContextDescriptor: void 0,
19
+ installedNavigatorModelContext: false,
20
+ installedNavigatorModelContextTesting: false,
21
+ installedDocumentModelContext: false
18
22
  };
19
23
  var StrictWebMCPContext = class extends EventTarget {
20
24
  tools = /* @__PURE__ */ new Map();
21
25
  testingShim = null;
22
26
  _ontoolchange = null;
23
- provideContextDeprecationWarned = false;
24
- clearContextDeprecationWarned = false;
25
27
  unregisterToolDeprecationWarned = false;
28
+ toolsChangedQueued = false;
26
29
  get ontoolchange() {
27
30
  return this._ontoolchange;
28
31
  }
29
32
  set ontoolchange(handler) {
30
33
  this._ontoolchange = handler;
31
34
  }
32
- provideContext(options = {}) {
33
- this.warnProvideContextDeprecationOnce();
34
- const nextTools = /* @__PURE__ */ new Map();
35
- for (const tool of options.tools ?? []) {
36
- const normalized = normalizeToolDescriptor(tool, nextTools);
37
- nextTools.set(normalized.name, normalized);
38
- }
39
- this.tools = nextTools;
40
- this.notifyToolsChanged();
41
- }
42
- clearContext() {
43
- this.warnClearContextDeprecationOnce();
44
- this.tools.clear();
45
- this.notifyToolsChanged();
46
- }
47
35
  registerTool(tool, options) {
48
36
  const signal = options?.signal;
49
- if (signal?.aborted) {
50
- console.warn(`[WebMCPPolyfill] registerTool("${tool?.name ?? "<unknown>"}") skipped: options.signal was already aborted.`);
51
- return;
52
- }
37
+ if (signal?.aborted) return Promise.reject(createAbortError());
53
38
  const normalized = normalizeToolDescriptor(tool, this.tools);
54
39
  this.tools.set(normalized.name, normalized);
55
40
  this.notifyToolsChanged();
56
41
  if (signal) signal.addEventListener("abort", () => {
57
42
  if (this.tools.delete(normalized.name)) this.notifyToolsChanged();
58
43
  }, { once: true });
44
+ return Promise.resolve();
59
45
  }
60
46
  unregisterTool(nameOrTool) {
61
47
  this.warnUnregisterToolDeprecationOnce();
@@ -63,7 +49,10 @@ var StrictWebMCPContext = class extends EventTarget {
63
49
  if (this.tools.delete(name)) this.notifyToolsChanged();
64
50
  }
65
51
  getTools() {
66
- return this.getToolInfos();
52
+ return Promise.resolve(this.getRegisteredToolInfos());
53
+ }
54
+ executeTool(tool, inputArgsJson, options) {
55
+ return this.executeToolByName(tool.name, inputArgsJson, options, false);
67
56
  }
68
57
  getTestingShim() {
69
58
  if (!this.testingShim) this.testingShim = new PolyfillTestingShim(this);
@@ -85,8 +74,23 @@ var StrictWebMCPContext = class extends EventTarget {
85
74
  };
86
75
  });
87
76
  }
77
+ /** @internal Used by getTools() */
78
+ getRegisteredToolInfos() {
79
+ return this.getToolInfos().map((toolInfo) => {
80
+ const tool = this.tools.get(toolInfo.name);
81
+ return {
82
+ ...toolInfo,
83
+ title: tool?.title ?? "",
84
+ origin: globalThis.location?.origin ?? "",
85
+ window: globalThis.window
86
+ };
87
+ });
88
+ }
88
89
  /** @internal Used by PolyfillTestingShim */
89
90
  async executeToolForTesting(toolName, inputArgsJson, options) {
91
+ return this.executeToolByName(toolName, inputArgsJson, options, true);
92
+ }
93
+ async executeToolByName(toolName, inputArgsJson, options, normalizeResult) {
90
94
  if (options?.signal?.aborted) throw createUnknownError(TOOL_CANCELLED_MESSAGE);
91
95
  const tool = this.tools.get(toolName);
92
96
  if (!tool) throw createUnknownError(`Tool not found: ${toolName}`);
@@ -101,7 +105,13 @@ var StrictWebMCPContext = class extends EventTarget {
101
105
  } };
102
106
  try {
103
107
  const execution = tool.execute(args, client);
104
- return toSerializedTestingResult(normalizeToolResponse(await withAbortSignal(Promise.resolve(execution), options?.signal)));
108
+ const rawResult = await withAbortSignal(Promise.resolve(execution), options?.signal);
109
+ const normalizedResult = normalizeToolResponse(rawResult);
110
+ const outputValidationError = validateOutputForTool(normalizedResult, tool);
111
+ if (outputValidationError) throw new Error(outputValidationError);
112
+ if (normalizeResult) return toSerializedTestingResult(normalizedResult);
113
+ const serialized = JSON.stringify(rawResult);
114
+ return serialized === void 0 ? null : serialized;
105
115
  } catch (error) {
106
116
  throw createUnknownError(error instanceof Error ? `${TOOL_INVOCATION_FAILED_MESSAGE}: ${error.message}` : TOOL_INVOCATION_FAILED_MESSAGE);
107
117
  } finally {
@@ -109,7 +119,10 @@ var StrictWebMCPContext = class extends EventTarget {
109
119
  }
110
120
  }
111
121
  notifyToolsChanged() {
122
+ if (this.toolsChangedQueued) return;
123
+ this.toolsChangedQueued = true;
112
124
  queueMicrotask(() => {
125
+ this.toolsChangedQueued = false;
113
126
  const event = new Event("toolchange");
114
127
  try {
115
128
  this._ontoolchange?.call(this, event);
@@ -120,16 +133,6 @@ var StrictWebMCPContext = class extends EventTarget {
120
133
  this.testingShim?.dispatchToolChange();
121
134
  });
122
135
  }
123
- warnProvideContextDeprecationOnce() {
124
- if (this.provideContextDeprecationWarned) return;
125
- this.provideContextDeprecationWarned = true;
126
- console.warn("[WebMCPPolyfill] navigator.modelContext.provideContext() is deprecated and will be removed in the next major version. Register tools individually with registerTool() instead.");
127
- }
128
- warnClearContextDeprecationOnce() {
129
- if (this.clearContextDeprecationWarned) return;
130
- this.clearContextDeprecationWarned = true;
131
- console.warn("[WebMCPPolyfill] navigator.modelContext.clearContext() is deprecated and will be removed in the next major version. Unregister individual tools instead.");
132
- }
133
136
  warnUnregisterToolDeprecationOnce() {
134
137
  if (this.unregisterToolDeprecationWarned) return;
135
138
  this.unregisterToolDeprecationWarned = true;
@@ -194,6 +197,15 @@ function createUnknownError(message) {
194
197
  return error;
195
198
  }
196
199
  }
200
+ function createInvalidStateError(message) {
201
+ try {
202
+ return new DOMException(message, "InvalidStateError");
203
+ } catch {
204
+ const error = new Error(message);
205
+ error.name = "InvalidStateError";
206
+ return error;
207
+ }
208
+ }
197
209
  function parseInputArgsJson(inputArgsJson) {
198
210
  let parsed;
199
211
  try {
@@ -209,131 +221,11 @@ function getToolNameForUnregister(nameOrTool) {
209
221
  if (isPlainObject(nameOrTool) && typeof nameOrTool.name === "string") return nameOrTool.name;
210
222
  throw new TypeError("Failed to execute 'unregisterTool' on 'ModelContext': parameter 1 must be a string or an object with a string name.");
211
223
  }
212
- function isPlainObject(value) {
213
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
214
- }
215
- function getStandardProps(value) {
216
- if (!isPlainObject(value)) return null;
217
- const standard = value["~standard"];
218
- if (!isPlainObject(standard)) return null;
219
- return standard;
220
- }
221
- function isStandardInputValidatorSchema(value) {
222
- const standard = getStandardProps(value);
223
- return Boolean(standard && standard.version === 1 && typeof standard.validate === "function");
224
- }
225
- function isStandardInputJsonSchema(value) {
226
- const standard = getStandardProps(value);
227
- if (!standard || standard.version !== 1 || !isPlainObject(standard.jsonSchema)) return false;
228
- return typeof standard.jsonSchema.input === "function";
229
- }
230
- function createStandardValidatorFromJsonSchema(schema) {
231
- return { "~standard": {
232
- version: 1,
233
- vendor: "@mcp-b/webmcp-polyfill-json-schema",
234
- validate(value) {
235
- if (!isPlainObject(value)) return { issues: [{ message: "expected object arguments" }] };
236
- const issue = validateArgsWithSchema(value, schema);
237
- if (issue) return { issues: [issue] };
238
- return { value };
239
- }
240
- } };
241
- }
242
- function convertStandardInputSchema(schema) {
243
- for (const target of STANDARD_JSON_SCHEMA_TARGETS) try {
244
- const converted = schema["~standard"].jsonSchema.input({ target });
245
- validateInputSchema(converted);
246
- return converted;
247
- } catch (error) {
248
- console.warn(`[WebMCPPolyfill] Standard JSON Schema conversion failed for target "${target}":`, error);
249
- }
250
- throw new Error("Failed to convert Standard JSON Schema inputSchema to a JSON Schema object");
251
- }
252
- function normalizeInputSchema(inputSchema) {
253
- if (inputSchema === void 0) {
254
- const normalized = DEFAULT_INPUT_SCHEMA;
255
- return {
256
- inputSchema: normalized,
257
- standardValidator: createStandardValidatorFromJsonSchema(normalized)
258
- };
259
- }
260
- if (isStandardInputJsonSchema(inputSchema)) {
261
- const converted = convertStandardInputSchema(inputSchema);
262
- return {
263
- inputSchema: converted,
264
- standardValidator: createStandardValidatorFromJsonSchema(converted)
265
- };
266
- }
267
- if (isStandardInputValidatorSchema(inputSchema)) return {
268
- inputSchema: DEFAULT_INPUT_SCHEMA,
269
- standardValidator: inputSchema
270
- };
271
- validateInputSchema(inputSchema);
272
- if (Object.keys(inputSchema).length === 0) return {
273
- inputSchema: DEFAULT_INPUT_SCHEMA,
274
- standardValidator: createStandardValidatorFromJsonSchema(DEFAULT_INPUT_SCHEMA)
275
- };
276
- const normalizedSchema = inputSchema.type === void 0 ? {
277
- type: "object",
278
- ...inputSchema
279
- } : inputSchema;
280
- return {
281
- inputSchema: normalizedSchema,
282
- standardValidator: createStandardValidatorFromJsonSchema(normalizedSchema)
283
- };
284
- }
285
- function validateInputSchema(schema) {
286
- if (!isPlainObject(schema)) throw new Error("inputSchema must be a JSON Schema object");
287
- validateJsonSchemaNode(schema, "$");
288
- }
289
- function validateJsonSchemaNode(node, path) {
290
- const typeValue = node.type;
291
- if (typeValue !== void 0 && typeof typeValue !== "string" && !(Array.isArray(typeValue) && typeValue.every((entry) => typeof entry === "string" && entry.length > 0))) throw new Error(`Invalid JSON Schema at ${path}: "type" must be a string or string[]`);
292
- const requiredValue = node.required;
293
- if (requiredValue !== void 0 && !(Array.isArray(requiredValue) && requiredValue.every((entry) => typeof entry === "string"))) throw new Error(`Invalid JSON Schema at ${path}: "required" must be an array of strings`);
294
- const propertiesValue = node.properties;
295
- if (propertiesValue !== void 0) {
296
- if (!isPlainObject(propertiesValue)) throw new Error(`Invalid JSON Schema at ${path}: "properties" must be an object`);
297
- for (const [key, value] of Object.entries(propertiesValue)) {
298
- if (!isPlainObject(value)) throw new Error(`Invalid JSON Schema at ${path}.properties.${key}: expected object schema`);
299
- validateJsonSchemaNode(value, `${path}.properties.${key}`);
300
- }
301
- }
302
- const itemsValue = node.items;
303
- if (itemsValue !== void 0) if (Array.isArray(itemsValue)) for (const [index, value] of itemsValue.entries()) {
304
- if (!isPlainObject(value)) throw new Error(`Invalid JSON Schema at ${path}.items[${index}]: expected object schema`);
305
- validateJsonSchemaNode(value, `${path}.items[${index}]`);
306
- }
307
- else if (isPlainObject(itemsValue)) validateJsonSchemaNode(itemsValue, `${path}.items`);
308
- else throw new Error(`Invalid JSON Schema at ${path}: "items" must be an object or object[]`);
309
- for (const keyword of [
310
- "allOf",
311
- "anyOf",
312
- "oneOf"
313
- ]) {
314
- const value = node[keyword];
315
- if (value === void 0) continue;
316
- if (!Array.isArray(value)) throw new Error(`Invalid JSON Schema at ${path}: "${keyword}" must be an array`);
317
- for (const [index, entry] of value.entries()) {
318
- if (!isPlainObject(entry)) throw new Error(`Invalid JSON Schema at ${path}.${keyword}[${index}]: expected object schema`);
319
- validateJsonSchemaNode(entry, `${path}.${keyword}[${index}]`);
320
- }
321
- }
322
- const notValue = node.not;
323
- if (notValue !== void 0) {
324
- if (!isPlainObject(notValue)) throw new Error(`Invalid JSON Schema at ${path}: "not" must be an object schema`);
325
- validateJsonSchemaNode(notValue, `${path}.not`);
326
- }
327
- try {
328
- JSON.stringify(node);
329
- } catch {
330
- throw new Error(`Invalid JSON Schema at ${path}: schema must be JSON-serializable`);
331
- }
332
- }
333
224
  function normalizeToolDescriptor(tool, existing) {
334
225
  if (!tool || typeof tool !== "object") throw new TypeError("registerTool(tool) requires a tool object");
335
- if (typeof tool.name !== "string" || tool.name.length === 0) throw new TypeError("Tool \"name\" must be a non-empty string");
336
- if (typeof tool.description !== "string" || tool.description.length === 0) throw new TypeError("Tool \"description\" must be a non-empty string");
226
+ if (typeof tool.name !== "string" || tool.name.length === 0) throw createInvalidStateError("Tool \"name\" must be a non-empty string");
227
+ if (!VALID_TOOL_NAME_RE.test(tool.name) || Array.from(tool.name).length > 128) throw createInvalidStateError("Tool \"name\" must be 1–128 characters and contain only ASCII alphanumeric, underscore, hyphen, or period");
228
+ if (typeof tool.description !== "string" || tool.description.length === 0) throw createInvalidStateError("Tool \"description\" must be a non-empty string");
337
229
  if (typeof tool.execute !== "function") throw new TypeError("Tool \"execute\" must be a function");
338
230
  if (existing.has(tool.name)) throw new Error(`Tool already registered: ${tool.name}`);
339
231
  const normalizedInputSchema = normalizeInputSchema(tool.inputSchema);
@@ -352,13 +244,6 @@ function normalizeToolDescriptor(tool, existing) {
352
244
  [STANDARD_VALIDATOR_SYMBOL]: normalizedInputSchema.standardValidator
353
245
  };
354
246
  }
355
- function validateArgsWithSchema(args, schema) {
356
- const result = new Validator(schema, "2020-12", true).validate(args);
357
- if (result.valid) return null;
358
- const error = result.errors[result.errors.length - 1];
359
- if (!error) return { message: "Input validation failed" };
360
- return { message: error.error };
361
- }
362
247
  function formatStandardIssuePath(path) {
363
248
  if (!path || path.length === 0) return null;
364
249
  const segments = path.map((segment) => {
@@ -387,22 +272,15 @@ async function validateArgsWithStandardSchema(args, schema) {
387
272
  async function validateArgsForTool(args, tool) {
388
273
  return validateArgsWithStandardSchema(args, tool[STANDARD_VALIDATOR_SYMBOL]);
389
274
  }
275
+ function validateOutputForTool(result, tool) {
276
+ if (!tool.outputSchema || result.isError) return null;
277
+ if (result.structuredContent === void 0) return `Output validation error: Tool ${tool.name} has an output schema but no structured content was provided`;
278
+ const issue = validateValueWithSchema(result.structuredContent, tool.outputSchema);
279
+ return issue ? `Output validation error: ${issue.message}` : null;
280
+ }
390
281
  function isCallToolResult(value) {
391
282
  return isPlainObject(value) && Array.isArray(value.content);
392
283
  }
393
- function isJsonPrimitive(value) {
394
- return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean";
395
- }
396
- function isJsonValue(value) {
397
- if (isJsonPrimitive(value)) return Number.isFinite(value) || typeof value !== "number";
398
- if (Array.isArray(value)) return value.every((entry) => isJsonValue(entry));
399
- if (!isPlainObject(value)) return false;
400
- return Object.values(value).every((entry) => isJsonValue(entry));
401
- }
402
- function toStructuredContent(value) {
403
- if (!isPlainObject(value) || !isJsonValue(value)) return;
404
- return value;
405
- }
406
284
  function serializeTextContent(value) {
407
285
  if (typeof value === "string") return value;
408
286
  try {
@@ -413,13 +291,13 @@ function serializeTextContent(value) {
413
291
  }
414
292
  function normalizeToolResponse(value) {
415
293
  if (isCallToolResult(value)) return value;
416
- const structuredContent = toStructuredContent(value);
294
+ const structuredContent = toJsonValue(value);
417
295
  return {
418
296
  content: [{
419
297
  type: "text",
420
298
  text: serializeTextContent(value)
421
299
  }],
422
- ...structuredContent ? { structuredContent } : {},
300
+ ...structuredContent !== void 0 ? { structuredContent } : {},
423
301
  isError: false
424
302
  };
425
303
  }
@@ -462,6 +340,10 @@ function getNavigator() {
462
340
  if (typeof navigator !== "undefined") return navigator;
463
341
  return null;
464
342
  }
343
+ function getDocument() {
344
+ if (typeof document !== "undefined") return document;
345
+ return null;
346
+ }
465
347
  function defineNavigatorProperty(target, key, value) {
466
348
  Object.defineProperty(target, key, {
467
349
  configurable: true,
@@ -470,37 +352,90 @@ function defineNavigatorProperty(target, key, value) {
470
352
  value
471
353
  });
472
354
  }
355
+ function defineDocumentModelContextProperty(target, value) {
356
+ Object.defineProperty(target, "modelContext", {
357
+ configurable: true,
358
+ enumerable: true,
359
+ writable: false,
360
+ value
361
+ });
362
+ }
363
+ let navigatorModelContextDeprecationWarned = false;
364
+ function defineDeprecatedNavigatorModelContext(target, value) {
365
+ Object.defineProperty(target, "modelContext", {
366
+ configurable: true,
367
+ enumerable: true,
368
+ get() {
369
+ if (!navigatorModelContextDeprecationWarned) {
370
+ navigatorModelContextDeprecationWarned = true;
371
+ console.warn("[WebMCPPolyfill] navigator.modelContext is deprecated. The May 27, 2026 WebMCP draft moved the modelContext getter from Navigator to Document — use document.modelContext instead. See https://github.com/webmachinelearning/webmcp/pull/184.");
372
+ }
373
+ return value;
374
+ }
375
+ });
376
+ }
473
377
  function initializeWebMCPPolyfill(options) {
474
378
  const nav = getNavigator();
475
- if (!nav) return;
476
- if (Boolean(nav.modelContext)) return;
379
+ const doc = getDocument();
380
+ if (!nav && !doc) return;
381
+ const documentModelContext = doc?.modelContext;
382
+ if (Boolean(documentModelContext)) return;
383
+ const navigatorModelContext = nav?.modelContext;
384
+ const hasNavigatorModelContext = Boolean(navigatorModelContext);
477
385
  if (installState.installed) cleanupWebMCPPolyfill();
386
+ if (doc && navigatorModelContext) {
387
+ installState.previousDocumentModelContextDescriptor = Object.getOwnPropertyDescriptor(doc, "modelContext");
388
+ defineDocumentModelContextProperty(doc, navigatorModelContext);
389
+ installState.installedDocumentModelContext = true;
390
+ installState.installed = true;
391
+ return;
392
+ }
393
+ if (hasNavigatorModelContext) return;
478
394
  const context = new StrictWebMCPContext();
479
395
  const modelContext = context;
480
396
  modelContext[POLYFILL_MARKER_PROPERTY] = true;
481
- installState.previousModelContextDescriptor = Object.getOwnPropertyDescriptor(nav, "modelContext");
482
- installState.previousModelContextTestingDescriptor = Object.getOwnPropertyDescriptor(nav, "modelContextTesting");
483
- defineNavigatorProperty(nav, "modelContext", modelContext);
484
- const installTestingShim = options?.installTestingShim ?? "if-missing";
485
- const hasModelContextTesting = Boolean(nav.modelContextTesting);
486
- if (installTestingShim === "always" || (installTestingShim === true || installTestingShim === "if-missing") && !hasModelContextTesting) defineNavigatorProperty(nav, "modelContextTesting", context.getTestingShim());
397
+ if (doc) {
398
+ installState.previousDocumentModelContextDescriptor = Object.getOwnPropertyDescriptor(doc, "modelContext");
399
+ defineDocumentModelContextProperty(doc, modelContext);
400
+ installState.installedDocumentModelContext = true;
401
+ }
402
+ if (nav) {
403
+ installState.previousNavigatorModelContextDescriptor = Object.getOwnPropertyDescriptor(nav, "modelContext");
404
+ installState.previousNavigatorModelContextTestingDescriptor = Object.getOwnPropertyDescriptor(nav, "modelContextTesting");
405
+ navigatorModelContextDeprecationWarned = false;
406
+ defineDeprecatedNavigatorModelContext(nav, modelContext);
407
+ installState.installedNavigatorModelContext = true;
408
+ const installTestingShim = options?.installTestingShim ?? "if-missing";
409
+ const hasModelContextTesting = Boolean(nav.modelContextTesting);
410
+ if (installTestingShim === "always" || (installTestingShim === true || installTestingShim === "if-missing") && !hasModelContextTesting) {
411
+ defineNavigatorProperty(nav, "modelContextTesting", context.getTestingShim());
412
+ installState.installedNavigatorModelContextTesting = true;
413
+ }
414
+ }
487
415
  installState.installed = true;
488
416
  }
489
417
  function cleanupWebMCPPolyfill() {
490
- const nav = getNavigator();
491
- if (!nav || !installState.installed) return;
492
- const restore = (key, previousDescriptor) => {
418
+ if (!installState.installed) return;
419
+ const restore = (target, key, previousDescriptor) => {
493
420
  if (previousDescriptor) {
494
- Object.defineProperty(nav, key, previousDescriptor);
421
+ Object.defineProperty(target, key, previousDescriptor);
495
422
  return;
496
423
  }
497
- delete nav[key];
424
+ delete target[key];
498
425
  };
499
- restore("modelContext", installState.previousModelContextDescriptor);
500
- restore("modelContextTesting", installState.previousModelContextTestingDescriptor);
426
+ const nav = getNavigator();
427
+ const doc = getDocument();
428
+ if (doc && installState.installedDocumentModelContext) restore(doc, "modelContext", installState.previousDocumentModelContextDescriptor);
429
+ if (nav && installState.installedNavigatorModelContext) restore(nav, "modelContext", installState.previousNavigatorModelContextDescriptor);
430
+ if (nav && installState.installedNavigatorModelContextTesting) restore(nav, "modelContextTesting", installState.previousNavigatorModelContextTestingDescriptor);
501
431
  installState.installed = false;
502
- installState.previousModelContextDescriptor = void 0;
503
- installState.previousModelContextTestingDescriptor = void 0;
432
+ installState.previousDocumentModelContextDescriptor = void 0;
433
+ installState.previousNavigatorModelContextDescriptor = void 0;
434
+ installState.previousNavigatorModelContextTestingDescriptor = void 0;
435
+ installState.installedDocumentModelContext = false;
436
+ installState.installedNavigatorModelContext = false;
437
+ installState.installedNavigatorModelContextTesting = false;
438
+ navigatorModelContextDeprecationWarned = false;
504
439
  }
505
440
  if (typeof window !== "undefined" && typeof document !== "undefined") {
506
441
  const options = window.__webMCPPolyfillOptions;
@@ -512,5 +447,5 @@ if (typeof window !== "undefined" && typeof document !== "undefined") {
512
447
  }
513
448
 
514
449
  //#endregion
515
- export { cleanupWebMCPPolyfill, initializeWebMCPPolyfill, initializeWebMCPPolyfill as initializeWebModelContextPolyfill, isPlainObject, validateArgsWithSchema };
450
+ export { cleanupWebMCPPolyfill, initializeWebMCPPolyfill, initializeWebMCPPolyfill as initializeWebModelContextPolyfill, isPlainObject, normalizeInputSchema, toJsonValue, validateValueWithSchema };
516
451
  //# sourceMappingURL=index.js.map