@mcp-b/global 2.0.2 → 2.0.3-canary.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/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { IframeChildTransport, TabServerTransport } from "@mcp-b/transports";
2
2
  import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, Server } from "@mcp-b/webmcp-ts-sdk";
3
- import { z } from "zod/v4";
3
+ import { z } from "zod";
4
+ import { fromJSONSchema, toJSONSchema } from "zod/v4";
4
5
 
5
6
  //#region src/logger.ts
6
7
  /**
@@ -94,42 +95,58 @@ const logger$2 = createLogger("WebModelContext");
94
95
  * Detect if a schema is a Zod schema object (Record<string, ZodType>)
95
96
  * or a JSON Schema object.
96
97
  *
97
- * Uses duck-typing to detect Zod 4 schemas by checking for the `_zod` property.
98
+ * Uses duck-typing to detect Zod schemas:
99
+ * - Zod 4 schemas have `_zod` property
100
+ * - Zod 3 schemas have `_def` property
101
+ *
102
+ * Both are supported as of Zod 3.25+ (which includes Zod 4 under the hood).
98
103
  */
99
104
  function isZodSchema(schema) {
100
105
  if (typeof schema !== "object" || schema === null) return false;
101
106
  if ("type" in schema && typeof schema.type === "string") return false;
102
107
  const values = Object.values(schema);
103
108
  if (values.length === 0) return false;
104
- return values.some((val) => val != null && typeof val === "object" && "_zod" in val);
109
+ for (const val of values) {
110
+ if (val == null || typeof val !== "object") continue;
111
+ const obj = val;
112
+ if ("_zod" in obj || "_def" in obj) return true;
113
+ }
114
+ return false;
105
115
  }
106
116
  /**
107
- * Convert JSON Schema to Zod validator
108
- * Uses Zod 4's native z.fromJSONSchema() for conversion
117
+ * Convert JSON Schema to Zod validator.
118
+ * Uses fromJSONSchema from 'zod/v4' which is available in Zod 3.25+ and Zod 4.
109
119
  */
110
120
  function jsonSchemaToZod(jsonSchema) {
111
121
  try {
112
- return z.fromJSONSchema(jsonSchema);
122
+ return fromJSONSchema(jsonSchema);
113
123
  } catch (error) {
114
124
  logger$2.warn("Failed to convert JSON Schema to Zod:", error);
115
125
  return z.object({}).passthrough();
116
126
  }
117
127
  }
118
128
  /**
119
- * Convert Zod schema object to JSON Schema
120
- * Uses Zod 4's native z.toJSONSchema() for conversion
129
+ * Convert Zod schema object to JSON Schema.
130
+ * Uses toJSONSchema from 'zod/v4' which is available in Zod 3.25+ and Zod 4.
131
+ *
132
+ * Works with schemas created from both `import { z } from 'zod'` (Zod 3.25+ compat)
133
+ * and `import { z } from 'zod/v4'` (native Zod 4).
121
134
  *
122
135
  * @param schema - Record of Zod type definitions (e.g., { name: z.string(), age: z.number() })
123
136
  * @returns JSON Schema object compatible with MCP InputSchema
124
137
  */
125
138
  function zodToJsonSchema(schema) {
126
- const zodObject = z.object(schema);
127
- const { $schema: _,...rest } = z.toJSONSchema(zodObject);
139
+ const { $schema: _,...rest } = toJSONSchema(z.object(schema));
128
140
  return rest;
129
141
  }
130
142
  /**
131
- * Normalize a schema to both JSON Schema and Zod formats
132
- * Detects which format is provided and converts to the other
143
+ * Normalize a schema to both JSON Schema and Zod formats.
144
+ * Detects which format is provided and converts to the other.
145
+ *
146
+ * Supports:
147
+ * - Zod schemas from `import { z } from 'zod'` (Zod 3.25+ compat layer)
148
+ * - Zod schemas from `import { z } from 'zod/v4'` (native Zod 4)
149
+ * - Plain JSON Schema objects
133
150
  */
134
151
  function normalizeSchema(schema) {
135
152
  if (isZodSchema(schema)) return {
@@ -181,6 +198,7 @@ const POLYFILL_MARKER_PROPERTY = "__isWebMCPPolyfill";
181
198
  * @returns Detection result with flags for native context and testing API availability
182
199
  */
183
200
  function detectNativeAPI() {
201
+ /* c8 ignore next 2 */
184
202
  if (typeof window === "undefined" || typeof navigator === "undefined") return {
185
203
  hasNativeContext: false,
186
204
  hasNativeTesting: false
@@ -188,8 +206,8 @@ function detectNativeAPI() {
188
206
  const modelContext = navigator.modelContext;
189
207
  const modelContextTesting = navigator.modelContextTesting;
190
208
  if (!modelContext || !modelContextTesting) return {
191
- hasNativeContext: false,
192
- hasNativeTesting: false
209
+ hasNativeContext: Boolean(modelContext),
210
+ hasNativeTesting: Boolean(modelContextTesting)
193
211
  };
194
212
  if (POLYFILL_MARKER_PROPERTY in modelContextTesting && modelContextTesting[POLYFILL_MARKER_PROPERTY] === true) return {
195
213
  hasNativeContext: false,
@@ -898,11 +916,11 @@ var WebModelContext = class {
898
916
  * @private
899
917
  */
900
918
  validateResource(resource) {
901
- const templateParamRegex = /\{([^}]+)\}/g;
919
+ const templateParamRegex = /\{([^}]{1,100})\}/g;
902
920
  const templateParams = [];
903
921
  for (const match of resource.uri.matchAll(templateParamRegex)) {
904
922
  const paramName = match[1];
905
- if (paramName) templateParams.push(paramName);
923
+ templateParams.push(paramName);
906
924
  }
907
925
  return {
908
926
  uri: resource.uri,
@@ -1318,7 +1336,13 @@ var WebModelContext = class {
1318
1336
  async readResource(uri) {
1319
1337
  const staticResource = this.bridge.resources.get(uri);
1320
1338
  if (staticResource && !staticResource.isTemplate) try {
1321
- const parsedUri = new URL(uri);
1339
+ let parsedUri;
1340
+ try {
1341
+ parsedUri = new URL(uri);
1342
+ } catch {
1343
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1344
+ parsedUri.originalUri = uri;
1345
+ }
1322
1346
  return await staticResource.read(parsedUri);
1323
1347
  } catch (error) {
1324
1348
  logger$1.error(`Error reading resource ${uri}:`, error);
@@ -1328,7 +1352,13 @@ var WebModelContext = class {
1328
1352
  if (!resource.isTemplate) continue;
1329
1353
  const params = this.matchUriTemplate(resource.uri, uri);
1330
1354
  if (params) try {
1331
- const parsedUri = new URL(uri);
1355
+ let parsedUri;
1356
+ try {
1357
+ parsedUri = new URL(uri);
1358
+ } catch {
1359
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1360
+ parsedUri.originalUri = uri;
1361
+ }
1332
1362
  return await resource.read(parsedUri, params);
1333
1363
  } catch (error) {
1334
1364
  logger$1.error(`Error reading resource ${uri}:`, error);
@@ -1361,8 +1391,7 @@ var WebModelContext = class {
1361
1391
  const params = {};
1362
1392
  for (let i = 0; i < paramNames.length; i++) {
1363
1393
  const paramName = paramNames[i];
1364
- const paramValue = match[i + 1];
1365
- if (paramName !== void 0 && paramValue !== void 0) params[paramName] = paramValue;
1394
+ params[paramName] = match[i + 1];
1366
1395
  }
1367
1396
  return params;
1368
1397
  }
@@ -1640,6 +1669,7 @@ function initializeMCPBridge(options) {
1640
1669
  * ```
1641
1670
  */
1642
1671
  function initializeWebModelContext(options) {
1672
+ /* c8 ignore next 4 */
1643
1673
  if (typeof window === "undefined") {
1644
1674
  logger$1.warn("Not in browser environment, skipping initialization");
1645
1675
  return;
@@ -1733,6 +1763,7 @@ function initializeWebModelContext(options) {
1733
1763
  * ```
1734
1764
  */
1735
1765
  function cleanupWebModelContext() {
1766
+ /* c8 ignore next */
1736
1767
  if (typeof window === "undefined") return;
1737
1768
  if (window.__mcpBridge) try {
1738
1769
  window.__mcpBridge.tabServer.close();