@aiwerk/mcp-bridge 3.0.1 → 3.0.2

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.
@@ -64,7 +64,12 @@ export interface CatalogRecipe {
64
64
  [key: string]: unknown;
65
65
  };
66
66
  signature?: RecipeSignature;
67
- localOnly?: boolean;
67
+ /**
68
+ * Local-only marker. Boolean form (true) blocks hosted install entirely;
69
+ * string[] form lists tool names the hosted bridge hides from tools/list
70
+ * (standalone ignores the array — all tools run locally).
71
+ */
72
+ localOnly?: boolean | string[];
68
73
  [key: string]: unknown;
69
74
  }
70
75
  export declare class CatalogError extends Error {
@@ -280,10 +280,30 @@ export function validateRecipe(recipe) {
280
280
  // hosted bridge use them; the standalone runtime mostly informs the user
281
281
  // and does not enforce hosted-only semantics (e.g. localOnly is not a
282
282
  // gate locally — every recipe runs on the user's machine anyway).
283
- // localOnly: top-level boolean. Hosted bridge refuses these recipes;
284
- // standalone accepts them and lets the user spawn locally.
285
- if (recipe.localOnly !== undefined && typeof recipe.localOnly !== "boolean") {
286
- errors.push(`localOnly must be boolean, got ${typeof recipe.localOnly}`);
283
+ // localOnly: two accepted forms.
284
+ // - boolean true → hosted bridge refuses install entirely (chrome-devtools);
285
+ // standalone accepts and spawns locally
286
+ // - string[] → per-tool hosted-bridge filter (the listed names are
287
+ // stripped from tools/list on hosted); standalone IGNORES
288
+ // the array — every tool runs locally regardless.
289
+ // Standalone runtime accepts both forms; we only validate the shape here so
290
+ // a typo (`"yes"`, number, object) is caught at recipe-load time.
291
+ if (recipe.localOnly !== undefined) {
292
+ const lo = recipe.localOnly;
293
+ if (typeof lo === "boolean") {
294
+ // OK
295
+ }
296
+ else if (Array.isArray(lo)) {
297
+ if (lo.length === 0) {
298
+ errors.push("localOnly array must be non-empty (use false or omit instead)");
299
+ }
300
+ else if (lo.some((t) => typeof t !== "string" || t.trim().length === 0)) {
301
+ errors.push("localOnly array must contain only non-empty tool-name strings");
302
+ }
303
+ }
304
+ else {
305
+ errors.push(`localOnly must be boolean or string[], got ${typeof lo}`);
306
+ }
287
307
  }
288
308
  // multiInstance + instanceNameHint: hosted-only semantics today. Standalone
289
309
  // accepts the fields without enforcing multi-instance install behavior.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiwerk/mcp-bridge",
3
- "version": "3.0.1",
3
+ "version": "3.0.2",
4
4
  "description": "Standalone MCP server that multiplexes multiple MCP servers into one interface",
5
5
  "type": "module",
6
6
  "main": "./dist/src/index.js",