@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/README.md +353 -0
- package/dist/index.d.ts +3 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.iife.js +10 -8
- package/dist/index.js +107 -57
- package/dist/index.js.map +1 -1
- package/package.json +21 -6
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 {
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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 (
|
|
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((
|
|
113
|
+
return values.some((value) => isZod4Schema(value) || isZod3Schema(value));
|
|
101
114
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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.
|
|
119
|
+
return stripSchemaMeta(nativeToJsonSchema(z.object(schema), { target: "draft-7" }));
|
|
109
120
|
} catch (error) {
|
|
110
|
-
logger$2.warn("
|
|
111
|
-
return
|
|
121
|
+
logger$2.warn("z.toJSONSchema failed, falling back to zod-to-json-schema:", error);
|
|
122
|
+
return null;
|
|
112
123
|
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
|
123
|
-
|
|
124
|
-
|
|
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
|
-
|
|
128
|
-
|
|
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))
|
|
132
|
-
jsonSchema
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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(
|
|
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 (
|
|
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:
|
|
188
|
-
hasNativeTesting:
|
|
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 = /\{([^}]
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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();
|