@mcp-b/global 0.0.0-beta-20260116035619 → 0.0.0-canary-20260126004552

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,8 @@
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 { jsonSchemaToZod } from "@n8n/json-schema-to-zod";
4
+ import { z } from "zod";
5
+ import { zodToJsonSchema as zodToJsonSchema$1 } from "zod-to-json-schema";
4
6
 
5
7
  //#region src/logger.ts
6
8
  /**
@@ -43,7 +45,11 @@ function isDebugEnabled(namespace) {
43
45
  if (!debugConfig) return false;
44
46
  if (debugConfig === "*") return true;
45
47
  return debugConfig.split(",").map((p) => p.trim()).some((pattern) => namespace === pattern || namespace.startsWith(`${pattern}:`));
46
- } catch {
48
+ } catch (err) {
49
+ if (typeof console !== "undefined" && console.warn) {
50
+ const message = err instanceof Error ? err.message : String(err);
51
+ console.warn(`[WebMCP] localStorage access failed, debug logging disabled: ${message}`);
52
+ }
47
53
  return false;
48
54
  }
49
55
  }
@@ -86,71 +92,101 @@ function createLogger(namespace) {
86
92
  //#endregion
87
93
  //#region src/validation.ts
88
94
  const logger$2 = createLogger("WebModelContext");
89
- /**
90
- * Detect if a schema is a Zod schema object (Record<string, ZodType>)
91
- * or a JSON Schema object.
92
- *
93
- * Uses duck-typing to detect Zod 4 schemas by checking for the `_zod` property.
94
- */
95
+ const nativeToJsonSchema = z.toJSONSchema;
96
+ const hasNativeToJSONSchema = typeof nativeToJsonSchema === "function";
97
+ const isRecord = (value) => typeof value === "object" && value !== null;
98
+ const isZod4Schema = (schema) => isRecord(schema) && "_zod" in schema;
99
+ const isZod3Schema = (schema) => isRecord(schema) && "_def" in schema && !("_zod" in schema);
100
+ const stripSchemaMeta = (schema) => {
101
+ const { $schema: _,...rest } = schema;
102
+ return rest;
103
+ };
104
+ const isOptionalSchema = (schema) => {
105
+ const typeName = schema._def?.typeName;
106
+ return typeName === "ZodOptional" || typeName === "ZodDefault";
107
+ };
95
108
  function isZodSchema(schema) {
96
- if (typeof schema !== "object" || schema === null) return false;
109
+ if (!isRecord(schema)) return false;
97
110
  if ("type" in schema && typeof schema.type === "string") return false;
98
111
  const values = Object.values(schema);
99
112
  if (values.length === 0) return false;
100
- return values.some((val) => val != null && typeof val === "object" && "_zod" in val);
113
+ return values.some((value) => isZod4Schema(value) || isZod3Schema(value));
101
114
  }
102
- /**
103
- * Convert JSON Schema to Zod validator
104
- * Uses Zod 4's native z.fromJSONSchema() for conversion
105
- */
106
- function jsonSchemaToZod(jsonSchema) {
115
+ const hasZod4Schemas = (schema) => Object.values(schema).some((value) => isZod4Schema(value));
116
+ const tryNativeZodToJsonSchema = (schema) => {
117
+ if (!hasZod4Schemas(schema) || !hasNativeToJSONSchema) return null;
107
118
  try {
108
- return z.fromJSONSchema(jsonSchema);
119
+ return stripSchemaMeta(nativeToJsonSchema(z.object(schema), { target: "draft-7" }));
109
120
  } catch (error) {
110
- logger$2.warn("Failed to convert JSON Schema to Zod:", error);
111
- return z.object({}).passthrough();
121
+ logger$2.warn("z.toJSONSchema failed, falling back to zod-to-json-schema:", error);
122
+ return null;
112
123
  }
113
- }
114
- /**
115
- * Convert Zod schema object to JSON Schema
116
- * Uses Zod 4's native z.toJSONSchema() for conversion
117
- *
118
- * @param schema - Record of Zod type definitions (e.g., { name: z.string(), age: z.number() })
119
- * @returns JSON Schema object compatible with MCP InputSchema
120
- */
124
+ };
125
+ const fallbackZodToJsonSchema = (schema) => {
126
+ const properties = {};
127
+ const required = [];
128
+ for (const [key, zodSchema] of Object.entries(schema)) {
129
+ properties[key] = stripSchemaMeta(zodToJsonSchema$1(zodSchema, {
130
+ strictUnions: true,
131
+ $refStrategy: "none"
132
+ }));
133
+ if (!isOptionalSchema(zodSchema)) required.push(key);
134
+ }
135
+ const result = {
136
+ type: "object",
137
+ properties
138
+ };
139
+ if (required.length > 0) result.required = required;
140
+ return result;
141
+ };
121
142
  function zodToJsonSchema(schema) {
122
- const zodObject = z.object(schema);
123
- const { $schema: _,...rest } = z.toJSONSchema(zodObject);
124
- return rest;
143
+ const nativeSchema = tryNativeZodToJsonSchema(schema);
144
+ if (nativeSchema) return nativeSchema;
145
+ try {
146
+ return fallbackZodToJsonSchema(schema);
147
+ } catch (error) {
148
+ logger$2.warn("zodToJsonSchema failed:", error);
149
+ return {
150
+ type: "object",
151
+ properties: {}
152
+ };
153
+ }
125
154
  }
126
- /**
127
- * Normalize a schema to both JSON Schema and Zod formats
128
- * Detects which format is provided and converts to the other
129
- */
155
+ function jsonSchemaToZod$1(jsonSchema) {
156
+ try {
157
+ return jsonSchemaToZod(jsonSchema);
158
+ } catch (error) {
159
+ logger$2.warn("jsonSchemaToZod failed:", error);
160
+ return z.object({}).passthrough();
161
+ }
162
+ }
163
+ const buildZodValidator = (schema, jsonSchema) => {
164
+ if (hasZod4Schemas(schema) && hasNativeToJSONSchema) return z.object(schema);
165
+ return jsonSchemaToZod$1(jsonSchema);
166
+ };
130
167
  function normalizeSchema(schema) {
131
- if (isZodSchema(schema)) return {
132
- jsonSchema: zodToJsonSchema(schema),
133
- zodValidator: z.object(schema)
134
- };
135
- const jsonSchema = schema;
168
+ if (isZodSchema(schema)) {
169
+ const jsonSchema = zodToJsonSchema(schema);
170
+ return {
171
+ jsonSchema,
172
+ zodValidator: buildZodValidator(schema, jsonSchema)
173
+ };
174
+ }
136
175
  return {
137
- jsonSchema,
138
- zodValidator: jsonSchemaToZod(jsonSchema)
176
+ jsonSchema: schema,
177
+ zodValidator: jsonSchemaToZod$1(schema)
139
178
  };
140
179
  }
141
- /**
142
- * Validate data with Zod schema and return formatted result
143
- */
144
180
  function validateWithZod(data, validator) {
145
181
  const result = validator.safeParse(data);
146
- if (!result.success) return {
147
- success: false,
148
- error: `Validation failed:\n${result.error.issues.map((err) => ` - ${err.path.join(".") || "root"}: ${err.message}`).join("\n")}`
149
- };
150
- return {
182
+ if (result.success) return {
151
183
  success: true,
152
184
  data: result.data
153
185
  };
186
+ return {
187
+ success: false,
188
+ error: `Validation failed:\n${result.error.issues.map((err) => ` - ${err.path.join(".") || "root"}: ${err.message}`).join("\n")}`
189
+ };
154
190
  }
155
191
 
156
192
  //#endregion
@@ -177,6 +213,7 @@ const POLYFILL_MARKER_PROPERTY = "__isWebMCPPolyfill";
177
213
  * @returns Detection result with flags for native context and testing API availability
178
214
  */
179
215
  function detectNativeAPI() {
216
+ /* c8 ignore next 2 */
180
217
  if (typeof window === "undefined" || typeof navigator === "undefined") return {
181
218
  hasNativeContext: false,
182
219
  hasNativeTesting: false
@@ -184,8 +221,8 @@ function detectNativeAPI() {
184
221
  const modelContext = navigator.modelContext;
185
222
  const modelContextTesting = navigator.modelContextTesting;
186
223
  if (!modelContext || !modelContextTesting) return {
187
- hasNativeContext: false,
188
- hasNativeTesting: false
224
+ hasNativeContext: Boolean(modelContext),
225
+ hasNativeTesting: Boolean(modelContextTesting)
189
226
  };
190
227
  if (POLYFILL_MARKER_PROPERTY in modelContextTesting && modelContextTesting[POLYFILL_MARKER_PROPERTY] === true) return {
191
228
  hasNativeContext: false,
@@ -254,7 +291,7 @@ var NativeModelContextAdapter = class {
254
291
  const result = await this.nativeTesting.executeTool(toolInfo.name, JSON.stringify(args));
255
292
  return this.convertToToolResponse(result);
256
293
  },
257
- inputValidator: jsonSchemaToZod(inputSchema)
294
+ inputValidator: jsonSchemaToZod$1(inputSchema)
258
295
  };
259
296
  this.bridge.tools.set(toolInfo.name, validatedTool);
260
297
  } catch (error) {
@@ -894,11 +931,11 @@ var WebModelContext = class {
894
931
  * @private
895
932
  */
896
933
  validateResource(resource) {
897
- const templateParamRegex = /\{([^}]+)\}/g;
934
+ const templateParamRegex = /\{([^}]{1,100})\}/g;
898
935
  const templateParams = [];
899
936
  for (const match of resource.uri.matchAll(templateParamRegex)) {
900
937
  const paramName = match[1];
901
- if (paramName) templateParams.push(paramName);
938
+ templateParams.push(paramName);
902
939
  }
903
940
  return {
904
941
  uri: resource.uri,
@@ -1314,7 +1351,13 @@ var WebModelContext = class {
1314
1351
  async readResource(uri) {
1315
1352
  const staticResource = this.bridge.resources.get(uri);
1316
1353
  if (staticResource && !staticResource.isTemplate) try {
1317
- const parsedUri = new URL(uri);
1354
+ let parsedUri;
1355
+ try {
1356
+ parsedUri = new URL(uri);
1357
+ } catch {
1358
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1359
+ parsedUri.originalUri = uri;
1360
+ }
1318
1361
  return await staticResource.read(parsedUri);
1319
1362
  } catch (error) {
1320
1363
  logger$1.error(`Error reading resource ${uri}:`, error);
@@ -1324,7 +1367,13 @@ var WebModelContext = class {
1324
1367
  if (!resource.isTemplate) continue;
1325
1368
  const params = this.matchUriTemplate(resource.uri, uri);
1326
1369
  if (params) try {
1327
- const parsedUri = new URL(uri);
1370
+ let parsedUri;
1371
+ try {
1372
+ parsedUri = new URL(uri);
1373
+ } catch {
1374
+ parsedUri = new URL(`custom-scheme:///${encodeURIComponent(uri)}`);
1375
+ parsedUri.originalUri = uri;
1376
+ }
1328
1377
  return await resource.read(parsedUri, params);
1329
1378
  } catch (error) {
1330
1379
  logger$1.error(`Error reading resource ${uri}:`, error);
@@ -1357,8 +1406,7 @@ var WebModelContext = class {
1357
1406
  const params = {};
1358
1407
  for (let i = 0; i < paramNames.length; i++) {
1359
1408
  const paramName = paramNames[i];
1360
- const paramValue = match[i + 1];
1361
- if (paramName !== void 0 && paramValue !== void 0) params[paramName] = paramValue;
1409
+ params[paramName] = match[i + 1];
1362
1410
  }
1363
1411
  return params;
1364
1412
  }
@@ -1636,6 +1684,7 @@ function initializeMCPBridge(options) {
1636
1684
  * ```
1637
1685
  */
1638
1686
  function initializeWebModelContext(options) {
1687
+ /* c8 ignore next 4 */
1639
1688
  if (typeof window === "undefined") {
1640
1689
  logger$1.warn("Not in browser environment, skipping initialization");
1641
1690
  return;
@@ -1729,6 +1778,7 @@ function initializeWebModelContext(options) {
1729
1778
  * ```
1730
1779
  */
1731
1780
  function cleanupWebModelContext() {
1781
+ /* c8 ignore next */
1732
1782
  if (typeof window === "undefined") return;
1733
1783
  if (window.__mcpBridge) try {
1734
1784
  window.__mcpBridge.tabServer.close();