@brainerce/mcp-server 2.6.0 → 2.7.0

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/bin/http.js CHANGED
@@ -11215,7 +11215,17 @@ async function handleGetRequiredPages(args) {
11215
11215
  var import_zod5 = require("zod");
11216
11216
 
11217
11217
  // src/utils/fetch-store-info.ts
11218
- async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com") {
11218
+ var KNOWN_API_URLS = {
11219
+ production: "https://api.brainerce.com",
11220
+ staging: "https://api-staging.brainerce.com"
11221
+ };
11222
+ var ConnectionNotFoundError = class extends Error {
11223
+ constructor(connectionId, baseUrl) {
11224
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11225
+ this.code = "NOT_FOUND";
11226
+ }
11227
+ };
11228
+ async function fetchStoreInfo(connectionId, baseUrl = KNOWN_API_URLS.production) {
11219
11229
  const url = `${baseUrl}/api/vc/${connectionId}/info`;
11220
11230
  const controller = new AbortController();
11221
11231
  const timeout = setTimeout(() => controller.abort(), 1e4);
@@ -11224,23 +11234,23 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11224
11234
  res = await fetch(url, { signal: controller.signal });
11225
11235
  } catch (err) {
11226
11236
  if (err.name === "AbortError") {
11227
- throw new Error("Request timed out");
11237
+ throw new Error(`Request to ${baseUrl} timed out`);
11228
11238
  }
11229
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11239
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11230
11240
  } finally {
11231
11241
  clearTimeout(timeout);
11232
11242
  }
11233
11243
  if (res.status === 404) {
11234
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11244
+ throw new ConnectionNotFoundError(connectionId, baseUrl);
11235
11245
  }
11236
11246
  if (!res.ok) {
11237
- throw new Error(`API returned status ${res.status}`);
11247
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11238
11248
  }
11239
11249
  let json;
11240
11250
  try {
11241
11251
  json = await res.json();
11242
11252
  } catch {
11243
- throw new Error("Invalid response from API");
11253
+ throw new Error(`Invalid response from ${baseUrl}`);
11244
11254
  }
11245
11255
  return {
11246
11256
  name: json.name || json.storeName || "My Store",
@@ -11249,6 +11259,38 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11249
11259
  ...json.i18n ? { i18n: json.i18n } : {}
11250
11260
  };
11251
11261
  }
11262
+ async function resolveStoreInfo(connectionId, candidateUrls) {
11263
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11264
+ if (urls.length === 0) {
11265
+ throw new Error("No API URLs to try");
11266
+ }
11267
+ let lastError;
11268
+ let allNotFound = true;
11269
+ for (let i = 0; i < urls.length; i++) {
11270
+ const baseUrl = urls[i];
11271
+ try {
11272
+ const info = await fetchStoreInfo(connectionId, baseUrl);
11273
+ return { info, apiBaseUrl: baseUrl, fellBack: i > 0 };
11274
+ } catch (err) {
11275
+ lastError = err;
11276
+ const isNotFound = err.code === "NOT_FOUND";
11277
+ if (!isNotFound) {
11278
+ allNotFound = false;
11279
+ }
11280
+ }
11281
+ }
11282
+ if (allNotFound) {
11283
+ throw new Error(
11284
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11285
+ );
11286
+ }
11287
+ throw lastError || new Error("Failed to resolve store info");
11288
+ }
11289
+ function getCandidateApiUrls() {
11290
+ const explicit = (process.env.BRAINERCE_API_URL || "").replace(/\/$/, "");
11291
+ if (explicit) return [explicit];
11292
+ return [KNOWN_API_URLS.production, KNOWN_API_URLS.staging];
11293
+ }
11252
11294
 
11253
11295
  // src/tools/get-store-info.ts
11254
11296
  var GET_STORE_INFO_NAME = "get-store-info";
@@ -11258,21 +11300,18 @@ var GET_STORE_INFO_SCHEMA = {
11258
11300
  };
11259
11301
  async function handleGetStoreInfo(args) {
11260
11302
  try {
11261
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11262
- /\/$/,
11263
- ""
11264
- );
11265
- const info = await fetchStoreInfo(args.connectionId, baseUrl);
11303
+ const resolved = await resolveStoreInfo(args.connectionId, getCandidateApiUrls());
11266
11304
  return {
11267
11305
  content: [
11268
11306
  {
11269
11307
  type: "text",
11270
11308
  text: JSON.stringify(
11271
11309
  {
11272
- name: info.name,
11273
- currency: info.currency,
11274
- language: info.language,
11275
- connectionId: args.connectionId
11310
+ name: resolved.info.name,
11311
+ currency: resolved.info.currency,
11312
+ language: resolved.info.language,
11313
+ connectionId: args.connectionId,
11314
+ apiBaseUrl: resolved.apiBaseUrl
11276
11315
  },
11277
11316
  null,
11278
11317
  2
@@ -11293,6 +11332,12 @@ async function handleGetStoreInfo(args) {
11293
11332
  var import_zod6 = require("zod");
11294
11333
 
11295
11334
  // src/utils/fetch-store-capabilities.ts
11335
+ var ConnectionNotFoundError2 = class extends Error {
11336
+ constructor(connectionId, baseUrl) {
11337
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11338
+ this.code = "NOT_FOUND";
11339
+ }
11340
+ };
11296
11341
  async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brainerce.com") {
11297
11342
  const url = `${baseUrl}/api/vc/${connectionId}/capabilities`;
11298
11343
  const controller = new AbortController();
@@ -11302,24 +11347,51 @@ async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brain
11302
11347
  res = await fetch(url, { signal: controller.signal });
11303
11348
  } catch (err) {
11304
11349
  if (err.name === "AbortError") {
11305
- throw new Error("Request timed out");
11350
+ throw new Error(`Request to ${baseUrl} timed out`);
11306
11351
  }
11307
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11352
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11308
11353
  } finally {
11309
11354
  clearTimeout(timeout);
11310
11355
  }
11311
11356
  if (res.status === 404) {
11312
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11357
+ throw new ConnectionNotFoundError2(connectionId, baseUrl);
11313
11358
  }
11314
11359
  if (!res.ok) {
11315
- throw new Error(`API returned status ${res.status}`);
11360
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11316
11361
  }
11317
11362
  try {
11318
11363
  return await res.json();
11319
11364
  } catch {
11320
- throw new Error("Invalid response from API");
11365
+ throw new Error(`Invalid response from ${baseUrl}`);
11321
11366
  }
11322
11367
  }
11368
+ async function resolveStoreCapabilities(connectionId, candidateUrls) {
11369
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11370
+ if (urls.length === 0) {
11371
+ throw new Error("No API URLs to try");
11372
+ }
11373
+ let lastError;
11374
+ let allNotFound = true;
11375
+ for (let i = 0; i < urls.length; i++) {
11376
+ const baseUrl = urls[i];
11377
+ try {
11378
+ const capabilities = await fetchStoreCapabilities(connectionId, baseUrl);
11379
+ return { capabilities, apiBaseUrl: baseUrl, fellBack: i > 0 };
11380
+ } catch (err) {
11381
+ lastError = err;
11382
+ const isNotFound = err.code === "NOT_FOUND";
11383
+ if (!isNotFound) {
11384
+ allNotFound = false;
11385
+ }
11386
+ }
11387
+ }
11388
+ if (allNotFound) {
11389
+ throw new Error(
11390
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11391
+ );
11392
+ }
11393
+ throw lastError || new Error("Failed to resolve store capabilities");
11394
+ }
11323
11395
 
11324
11396
  // src/tools/get-store-capabilities.ts
11325
11397
  var GET_STORE_CAPABILITIES_NAME = "get-store-capabilities";
@@ -11437,13 +11509,9 @@ function formatCapabilities(caps) {
11437
11509
  }
11438
11510
  async function handleGetStoreCapabilities(args) {
11439
11511
  try {
11440
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11441
- /\/$/,
11442
- ""
11443
- );
11444
- const caps = await fetchStoreCapabilities(args.connectionId, baseUrl);
11512
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11445
11513
  return {
11446
- content: [{ type: "text", text: formatCapabilities(caps) }]
11514
+ content: [{ type: "text", text: formatCapabilities(resolved.capabilities) }]
11447
11515
  };
11448
11516
  } catch (error) {
11449
11517
  const message = error instanceof Error ? error.message : "Failed to fetch store capabilities";
@@ -11706,13 +11774,10 @@ var BUILD_STORE_SCHEMA = {
11706
11774
  storeStyle: import_zod7.z.string().optional().describe('Design style (e.g., "minimalist", "luxury", "playful", "dark mode")')
11707
11775
  };
11708
11776
  async function handleBuildStore(args) {
11709
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11710
- /\/$/,
11711
- ""
11712
- );
11713
11777
  let capabilities = null;
11714
11778
  try {
11715
- capabilities = await fetchStoreCapabilities(args.connectionId, baseUrl);
11779
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11780
+ capabilities = resolved.capabilities;
11716
11781
  } catch {
11717
11782
  }
11718
11783
  const bundle = buildStoreBundle({
package/dist/bin/stdio.js CHANGED
@@ -11213,7 +11213,17 @@ async function handleGetRequiredPages(args) {
11213
11213
  var import_zod5 = require("zod");
11214
11214
 
11215
11215
  // src/utils/fetch-store-info.ts
11216
- async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com") {
11216
+ var KNOWN_API_URLS = {
11217
+ production: "https://api.brainerce.com",
11218
+ staging: "https://api-staging.brainerce.com"
11219
+ };
11220
+ var ConnectionNotFoundError = class extends Error {
11221
+ constructor(connectionId, baseUrl) {
11222
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11223
+ this.code = "NOT_FOUND";
11224
+ }
11225
+ };
11226
+ async function fetchStoreInfo(connectionId, baseUrl = KNOWN_API_URLS.production) {
11217
11227
  const url = `${baseUrl}/api/vc/${connectionId}/info`;
11218
11228
  const controller = new AbortController();
11219
11229
  const timeout = setTimeout(() => controller.abort(), 1e4);
@@ -11222,23 +11232,23 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11222
11232
  res = await fetch(url, { signal: controller.signal });
11223
11233
  } catch (err) {
11224
11234
  if (err.name === "AbortError") {
11225
- throw new Error("Request timed out");
11235
+ throw new Error(`Request to ${baseUrl} timed out`);
11226
11236
  }
11227
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11237
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11228
11238
  } finally {
11229
11239
  clearTimeout(timeout);
11230
11240
  }
11231
11241
  if (res.status === 404) {
11232
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11242
+ throw new ConnectionNotFoundError(connectionId, baseUrl);
11233
11243
  }
11234
11244
  if (!res.ok) {
11235
- throw new Error(`API returned status ${res.status}`);
11245
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11236
11246
  }
11237
11247
  let json;
11238
11248
  try {
11239
11249
  json = await res.json();
11240
11250
  } catch {
11241
- throw new Error("Invalid response from API");
11251
+ throw new Error(`Invalid response from ${baseUrl}`);
11242
11252
  }
11243
11253
  return {
11244
11254
  name: json.name || json.storeName || "My Store",
@@ -11247,6 +11257,38 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11247
11257
  ...json.i18n ? { i18n: json.i18n } : {}
11248
11258
  };
11249
11259
  }
11260
+ async function resolveStoreInfo(connectionId, candidateUrls) {
11261
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11262
+ if (urls.length === 0) {
11263
+ throw new Error("No API URLs to try");
11264
+ }
11265
+ let lastError;
11266
+ let allNotFound = true;
11267
+ for (let i = 0; i < urls.length; i++) {
11268
+ const baseUrl = urls[i];
11269
+ try {
11270
+ const info = await fetchStoreInfo(connectionId, baseUrl);
11271
+ return { info, apiBaseUrl: baseUrl, fellBack: i > 0 };
11272
+ } catch (err) {
11273
+ lastError = err;
11274
+ const isNotFound = err.code === "NOT_FOUND";
11275
+ if (!isNotFound) {
11276
+ allNotFound = false;
11277
+ }
11278
+ }
11279
+ }
11280
+ if (allNotFound) {
11281
+ throw new Error(
11282
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11283
+ );
11284
+ }
11285
+ throw lastError || new Error("Failed to resolve store info");
11286
+ }
11287
+ function getCandidateApiUrls() {
11288
+ const explicit = (process.env.BRAINERCE_API_URL || "").replace(/\/$/, "");
11289
+ if (explicit) return [explicit];
11290
+ return [KNOWN_API_URLS.production, KNOWN_API_URLS.staging];
11291
+ }
11250
11292
 
11251
11293
  // src/tools/get-store-info.ts
11252
11294
  var GET_STORE_INFO_NAME = "get-store-info";
@@ -11256,21 +11298,18 @@ var GET_STORE_INFO_SCHEMA = {
11256
11298
  };
11257
11299
  async function handleGetStoreInfo(args) {
11258
11300
  try {
11259
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11260
- /\/$/,
11261
- ""
11262
- );
11263
- const info = await fetchStoreInfo(args.connectionId, baseUrl);
11301
+ const resolved = await resolveStoreInfo(args.connectionId, getCandidateApiUrls());
11264
11302
  return {
11265
11303
  content: [
11266
11304
  {
11267
11305
  type: "text",
11268
11306
  text: JSON.stringify(
11269
11307
  {
11270
- name: info.name,
11271
- currency: info.currency,
11272
- language: info.language,
11273
- connectionId: args.connectionId
11308
+ name: resolved.info.name,
11309
+ currency: resolved.info.currency,
11310
+ language: resolved.info.language,
11311
+ connectionId: args.connectionId,
11312
+ apiBaseUrl: resolved.apiBaseUrl
11274
11313
  },
11275
11314
  null,
11276
11315
  2
@@ -11291,6 +11330,12 @@ async function handleGetStoreInfo(args) {
11291
11330
  var import_zod6 = require("zod");
11292
11331
 
11293
11332
  // src/utils/fetch-store-capabilities.ts
11333
+ var ConnectionNotFoundError2 = class extends Error {
11334
+ constructor(connectionId, baseUrl) {
11335
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11336
+ this.code = "NOT_FOUND";
11337
+ }
11338
+ };
11294
11339
  async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brainerce.com") {
11295
11340
  const url = `${baseUrl}/api/vc/${connectionId}/capabilities`;
11296
11341
  const controller = new AbortController();
@@ -11300,24 +11345,51 @@ async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brain
11300
11345
  res = await fetch(url, { signal: controller.signal });
11301
11346
  } catch (err) {
11302
11347
  if (err.name === "AbortError") {
11303
- throw new Error("Request timed out");
11348
+ throw new Error(`Request to ${baseUrl} timed out`);
11304
11349
  }
11305
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11350
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11306
11351
  } finally {
11307
11352
  clearTimeout(timeout);
11308
11353
  }
11309
11354
  if (res.status === 404) {
11310
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11355
+ throw new ConnectionNotFoundError2(connectionId, baseUrl);
11311
11356
  }
11312
11357
  if (!res.ok) {
11313
- throw new Error(`API returned status ${res.status}`);
11358
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11314
11359
  }
11315
11360
  try {
11316
11361
  return await res.json();
11317
11362
  } catch {
11318
- throw new Error("Invalid response from API");
11363
+ throw new Error(`Invalid response from ${baseUrl}`);
11319
11364
  }
11320
11365
  }
11366
+ async function resolveStoreCapabilities(connectionId, candidateUrls) {
11367
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11368
+ if (urls.length === 0) {
11369
+ throw new Error("No API URLs to try");
11370
+ }
11371
+ let lastError;
11372
+ let allNotFound = true;
11373
+ for (let i = 0; i < urls.length; i++) {
11374
+ const baseUrl = urls[i];
11375
+ try {
11376
+ const capabilities = await fetchStoreCapabilities(connectionId, baseUrl);
11377
+ return { capabilities, apiBaseUrl: baseUrl, fellBack: i > 0 };
11378
+ } catch (err) {
11379
+ lastError = err;
11380
+ const isNotFound = err.code === "NOT_FOUND";
11381
+ if (!isNotFound) {
11382
+ allNotFound = false;
11383
+ }
11384
+ }
11385
+ }
11386
+ if (allNotFound) {
11387
+ throw new Error(
11388
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11389
+ );
11390
+ }
11391
+ throw lastError || new Error("Failed to resolve store capabilities");
11392
+ }
11321
11393
 
11322
11394
  // src/tools/get-store-capabilities.ts
11323
11395
  var GET_STORE_CAPABILITIES_NAME = "get-store-capabilities";
@@ -11435,13 +11507,9 @@ function formatCapabilities(caps) {
11435
11507
  }
11436
11508
  async function handleGetStoreCapabilities(args) {
11437
11509
  try {
11438
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11439
- /\/$/,
11440
- ""
11441
- );
11442
- const caps = await fetchStoreCapabilities(args.connectionId, baseUrl);
11510
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11443
11511
  return {
11444
- content: [{ type: "text", text: formatCapabilities(caps) }]
11512
+ content: [{ type: "text", text: formatCapabilities(resolved.capabilities) }]
11445
11513
  };
11446
11514
  } catch (error) {
11447
11515
  const message = error instanceof Error ? error.message : "Failed to fetch store capabilities";
@@ -11704,13 +11772,10 @@ var BUILD_STORE_SCHEMA = {
11704
11772
  storeStyle: import_zod7.z.string().optional().describe('Design style (e.g., "minimalist", "luxury", "playful", "dark mode")')
11705
11773
  };
11706
11774
  async function handleBuildStore(args) {
11707
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11708
- /\/$/,
11709
- ""
11710
- );
11711
11775
  let capabilities = null;
11712
11776
  try {
11713
- capabilities = await fetchStoreCapabilities(args.connectionId, baseUrl);
11777
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11778
+ capabilities = resolved.capabilities;
11714
11779
  } catch {
11715
11780
  }
11716
11781
  const bundle = buildStoreBundle({
package/dist/index.js CHANGED
@@ -11242,7 +11242,17 @@ async function handleGetRequiredPages(args) {
11242
11242
  var import_zod5 = require("zod");
11243
11243
 
11244
11244
  // src/utils/fetch-store-info.ts
11245
- async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com") {
11245
+ var KNOWN_API_URLS = {
11246
+ production: "https://api.brainerce.com",
11247
+ staging: "https://api-staging.brainerce.com"
11248
+ };
11249
+ var ConnectionNotFoundError = class extends Error {
11250
+ constructor(connectionId, baseUrl) {
11251
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11252
+ this.code = "NOT_FOUND";
11253
+ }
11254
+ };
11255
+ async function fetchStoreInfo(connectionId, baseUrl = KNOWN_API_URLS.production) {
11246
11256
  const url = `${baseUrl}/api/vc/${connectionId}/info`;
11247
11257
  const controller = new AbortController();
11248
11258
  const timeout = setTimeout(() => controller.abort(), 1e4);
@@ -11251,23 +11261,23 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11251
11261
  res = await fetch(url, { signal: controller.signal });
11252
11262
  } catch (err) {
11253
11263
  if (err.name === "AbortError") {
11254
- throw new Error("Request timed out");
11264
+ throw new Error(`Request to ${baseUrl} timed out`);
11255
11265
  }
11256
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11266
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11257
11267
  } finally {
11258
11268
  clearTimeout(timeout);
11259
11269
  }
11260
11270
  if (res.status === 404) {
11261
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11271
+ throw new ConnectionNotFoundError(connectionId, baseUrl);
11262
11272
  }
11263
11273
  if (!res.ok) {
11264
- throw new Error(`API returned status ${res.status}`);
11274
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11265
11275
  }
11266
11276
  let json;
11267
11277
  try {
11268
11278
  json = await res.json();
11269
11279
  } catch {
11270
- throw new Error("Invalid response from API");
11280
+ throw new Error(`Invalid response from ${baseUrl}`);
11271
11281
  }
11272
11282
  return {
11273
11283
  name: json.name || json.storeName || "My Store",
@@ -11276,6 +11286,38 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11276
11286
  ...json.i18n ? { i18n: json.i18n } : {}
11277
11287
  };
11278
11288
  }
11289
+ async function resolveStoreInfo(connectionId, candidateUrls) {
11290
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11291
+ if (urls.length === 0) {
11292
+ throw new Error("No API URLs to try");
11293
+ }
11294
+ let lastError;
11295
+ let allNotFound = true;
11296
+ for (let i = 0; i < urls.length; i++) {
11297
+ const baseUrl = urls[i];
11298
+ try {
11299
+ const info = await fetchStoreInfo(connectionId, baseUrl);
11300
+ return { info, apiBaseUrl: baseUrl, fellBack: i > 0 };
11301
+ } catch (err) {
11302
+ lastError = err;
11303
+ const isNotFound = err.code === "NOT_FOUND";
11304
+ if (!isNotFound) {
11305
+ allNotFound = false;
11306
+ }
11307
+ }
11308
+ }
11309
+ if (allNotFound) {
11310
+ throw new Error(
11311
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11312
+ );
11313
+ }
11314
+ throw lastError || new Error("Failed to resolve store info");
11315
+ }
11316
+ function getCandidateApiUrls() {
11317
+ const explicit = (process.env.BRAINERCE_API_URL || "").replace(/\/$/, "");
11318
+ if (explicit) return [explicit];
11319
+ return [KNOWN_API_URLS.production, KNOWN_API_URLS.staging];
11320
+ }
11279
11321
 
11280
11322
  // src/tools/get-store-info.ts
11281
11323
  var GET_STORE_INFO_NAME = "get-store-info";
@@ -11285,21 +11327,18 @@ var GET_STORE_INFO_SCHEMA = {
11285
11327
  };
11286
11328
  async function handleGetStoreInfo(args) {
11287
11329
  try {
11288
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11289
- /\/$/,
11290
- ""
11291
- );
11292
- const info = await fetchStoreInfo(args.connectionId, baseUrl);
11330
+ const resolved = await resolveStoreInfo(args.connectionId, getCandidateApiUrls());
11293
11331
  return {
11294
11332
  content: [
11295
11333
  {
11296
11334
  type: "text",
11297
11335
  text: JSON.stringify(
11298
11336
  {
11299
- name: info.name,
11300
- currency: info.currency,
11301
- language: info.language,
11302
- connectionId: args.connectionId
11337
+ name: resolved.info.name,
11338
+ currency: resolved.info.currency,
11339
+ language: resolved.info.language,
11340
+ connectionId: args.connectionId,
11341
+ apiBaseUrl: resolved.apiBaseUrl
11303
11342
  },
11304
11343
  null,
11305
11344
  2
@@ -11320,6 +11359,12 @@ async function handleGetStoreInfo(args) {
11320
11359
  var import_zod6 = require("zod");
11321
11360
 
11322
11361
  // src/utils/fetch-store-capabilities.ts
11362
+ var ConnectionNotFoundError2 = class extends Error {
11363
+ constructor(connectionId, baseUrl) {
11364
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11365
+ this.code = "NOT_FOUND";
11366
+ }
11367
+ };
11323
11368
  async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brainerce.com") {
11324
11369
  const url = `${baseUrl}/api/vc/${connectionId}/capabilities`;
11325
11370
  const controller = new AbortController();
@@ -11329,24 +11374,51 @@ async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brain
11329
11374
  res = await fetch(url, { signal: controller.signal });
11330
11375
  } catch (err) {
11331
11376
  if (err.name === "AbortError") {
11332
- throw new Error("Request timed out");
11377
+ throw new Error(`Request to ${baseUrl} timed out`);
11333
11378
  }
11334
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11379
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11335
11380
  } finally {
11336
11381
  clearTimeout(timeout);
11337
11382
  }
11338
11383
  if (res.status === 404) {
11339
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11384
+ throw new ConnectionNotFoundError2(connectionId, baseUrl);
11340
11385
  }
11341
11386
  if (!res.ok) {
11342
- throw new Error(`API returned status ${res.status}`);
11387
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11343
11388
  }
11344
11389
  try {
11345
11390
  return await res.json();
11346
11391
  } catch {
11347
- throw new Error("Invalid response from API");
11392
+ throw new Error(`Invalid response from ${baseUrl}`);
11348
11393
  }
11349
11394
  }
11395
+ async function resolveStoreCapabilities(connectionId, candidateUrls) {
11396
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11397
+ if (urls.length === 0) {
11398
+ throw new Error("No API URLs to try");
11399
+ }
11400
+ let lastError;
11401
+ let allNotFound = true;
11402
+ for (let i = 0; i < urls.length; i++) {
11403
+ const baseUrl = urls[i];
11404
+ try {
11405
+ const capabilities = await fetchStoreCapabilities(connectionId, baseUrl);
11406
+ return { capabilities, apiBaseUrl: baseUrl, fellBack: i > 0 };
11407
+ } catch (err) {
11408
+ lastError = err;
11409
+ const isNotFound = err.code === "NOT_FOUND";
11410
+ if (!isNotFound) {
11411
+ allNotFound = false;
11412
+ }
11413
+ }
11414
+ }
11415
+ if (allNotFound) {
11416
+ throw new Error(
11417
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11418
+ );
11419
+ }
11420
+ throw lastError || new Error("Failed to resolve store capabilities");
11421
+ }
11350
11422
 
11351
11423
  // src/tools/get-store-capabilities.ts
11352
11424
  var GET_STORE_CAPABILITIES_NAME = "get-store-capabilities";
@@ -11464,13 +11536,9 @@ function formatCapabilities(caps) {
11464
11536
  }
11465
11537
  async function handleGetStoreCapabilities(args) {
11466
11538
  try {
11467
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11468
- /\/$/,
11469
- ""
11470
- );
11471
- const caps = await fetchStoreCapabilities(args.connectionId, baseUrl);
11539
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11472
11540
  return {
11473
- content: [{ type: "text", text: formatCapabilities(caps) }]
11541
+ content: [{ type: "text", text: formatCapabilities(resolved.capabilities) }]
11474
11542
  };
11475
11543
  } catch (error) {
11476
11544
  const message = error instanceof Error ? error.message : "Failed to fetch store capabilities";
@@ -11733,13 +11801,10 @@ var BUILD_STORE_SCHEMA = {
11733
11801
  storeStyle: import_zod7.z.string().optional().describe('Design style (e.g., "minimalist", "luxury", "playful", "dark mode")')
11734
11802
  };
11735
11803
  async function handleBuildStore(args) {
11736
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11737
- /\/$/,
11738
- ""
11739
- );
11740
11804
  let capabilities = null;
11741
11805
  try {
11742
- capabilities = await fetchStoreCapabilities(args.connectionId, baseUrl);
11806
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11807
+ capabilities = resolved.capabilities;
11743
11808
  } catch {
11744
11809
  }
11745
11810
  const bundle = buildStoreBundle({
package/dist/index.mjs CHANGED
@@ -11207,7 +11207,17 @@ async function handleGetRequiredPages(args) {
11207
11207
  import { z as z5 } from "zod";
11208
11208
 
11209
11209
  // src/utils/fetch-store-info.ts
11210
- async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com") {
11210
+ var KNOWN_API_URLS = {
11211
+ production: "https://api.brainerce.com",
11212
+ staging: "https://api-staging.brainerce.com"
11213
+ };
11214
+ var ConnectionNotFoundError = class extends Error {
11215
+ constructor(connectionId, baseUrl) {
11216
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11217
+ this.code = "NOT_FOUND";
11218
+ }
11219
+ };
11220
+ async function fetchStoreInfo(connectionId, baseUrl = KNOWN_API_URLS.production) {
11211
11221
  const url = `${baseUrl}/api/vc/${connectionId}/info`;
11212
11222
  const controller = new AbortController();
11213
11223
  const timeout = setTimeout(() => controller.abort(), 1e4);
@@ -11216,23 +11226,23 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11216
11226
  res = await fetch(url, { signal: controller.signal });
11217
11227
  } catch (err) {
11218
11228
  if (err.name === "AbortError") {
11219
- throw new Error("Request timed out");
11229
+ throw new Error(`Request to ${baseUrl} timed out`);
11220
11230
  }
11221
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11231
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11222
11232
  } finally {
11223
11233
  clearTimeout(timeout);
11224
11234
  }
11225
11235
  if (res.status === 404) {
11226
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11236
+ throw new ConnectionNotFoundError(connectionId, baseUrl);
11227
11237
  }
11228
11238
  if (!res.ok) {
11229
- throw new Error(`API returned status ${res.status}`);
11239
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11230
11240
  }
11231
11241
  let json;
11232
11242
  try {
11233
11243
  json = await res.json();
11234
11244
  } catch {
11235
- throw new Error("Invalid response from API");
11245
+ throw new Error(`Invalid response from ${baseUrl}`);
11236
11246
  }
11237
11247
  return {
11238
11248
  name: json.name || json.storeName || "My Store",
@@ -11241,6 +11251,38 @@ async function fetchStoreInfo(connectionId, baseUrl = "https://api.brainerce.com
11241
11251
  ...json.i18n ? { i18n: json.i18n } : {}
11242
11252
  };
11243
11253
  }
11254
+ async function resolveStoreInfo(connectionId, candidateUrls) {
11255
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11256
+ if (urls.length === 0) {
11257
+ throw new Error("No API URLs to try");
11258
+ }
11259
+ let lastError;
11260
+ let allNotFound = true;
11261
+ for (let i = 0; i < urls.length; i++) {
11262
+ const baseUrl = urls[i];
11263
+ try {
11264
+ const info = await fetchStoreInfo(connectionId, baseUrl);
11265
+ return { info, apiBaseUrl: baseUrl, fellBack: i > 0 };
11266
+ } catch (err) {
11267
+ lastError = err;
11268
+ const isNotFound = err.code === "NOT_FOUND";
11269
+ if (!isNotFound) {
11270
+ allNotFound = false;
11271
+ }
11272
+ }
11273
+ }
11274
+ if (allNotFound) {
11275
+ throw new Error(
11276
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11277
+ );
11278
+ }
11279
+ throw lastError || new Error("Failed to resolve store info");
11280
+ }
11281
+ function getCandidateApiUrls() {
11282
+ const explicit = (process.env.BRAINERCE_API_URL || "").replace(/\/$/, "");
11283
+ if (explicit) return [explicit];
11284
+ return [KNOWN_API_URLS.production, KNOWN_API_URLS.staging];
11285
+ }
11244
11286
 
11245
11287
  // src/tools/get-store-info.ts
11246
11288
  var GET_STORE_INFO_NAME = "get-store-info";
@@ -11250,21 +11292,18 @@ var GET_STORE_INFO_SCHEMA = {
11250
11292
  };
11251
11293
  async function handleGetStoreInfo(args) {
11252
11294
  try {
11253
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11254
- /\/$/,
11255
- ""
11256
- );
11257
- const info = await fetchStoreInfo(args.connectionId, baseUrl);
11295
+ const resolved = await resolveStoreInfo(args.connectionId, getCandidateApiUrls());
11258
11296
  return {
11259
11297
  content: [
11260
11298
  {
11261
11299
  type: "text",
11262
11300
  text: JSON.stringify(
11263
11301
  {
11264
- name: info.name,
11265
- currency: info.currency,
11266
- language: info.language,
11267
- connectionId: args.connectionId
11302
+ name: resolved.info.name,
11303
+ currency: resolved.info.currency,
11304
+ language: resolved.info.language,
11305
+ connectionId: args.connectionId,
11306
+ apiBaseUrl: resolved.apiBaseUrl
11268
11307
  },
11269
11308
  null,
11270
11309
  2
@@ -11285,6 +11324,12 @@ async function handleGetStoreInfo(args) {
11285
11324
  import { z as z6 } from "zod";
11286
11325
 
11287
11326
  // src/utils/fetch-store-capabilities.ts
11327
+ var ConnectionNotFoundError2 = class extends Error {
11328
+ constructor(connectionId, baseUrl) {
11329
+ super(`Connection "${connectionId}" not found at ${baseUrl}`);
11330
+ this.code = "NOT_FOUND";
11331
+ }
11332
+ };
11288
11333
  async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brainerce.com") {
11289
11334
  const url = `${baseUrl}/api/vc/${connectionId}/capabilities`;
11290
11335
  const controller = new AbortController();
@@ -11294,24 +11339,51 @@ async function fetchStoreCapabilities(connectionId, baseUrl = "https://api.brain
11294
11339
  res = await fetch(url, { signal: controller.signal });
11295
11340
  } catch (err) {
11296
11341
  if (err.name === "AbortError") {
11297
- throw new Error("Request timed out");
11342
+ throw new Error(`Request to ${baseUrl} timed out`);
11298
11343
  }
11299
- throw new Error(`Failed to connect to Brainerce API: ${err.message}`);
11344
+ throw new Error(`Failed to connect to ${baseUrl}: ${err.message}`);
11300
11345
  } finally {
11301
11346
  clearTimeout(timeout);
11302
11347
  }
11303
11348
  if (res.status === 404) {
11304
- throw new Error(`Connection ID "${connectionId}" not found. Check your dashboard.`);
11349
+ throw new ConnectionNotFoundError2(connectionId, baseUrl);
11305
11350
  }
11306
11351
  if (!res.ok) {
11307
- throw new Error(`API returned status ${res.status}`);
11352
+ throw new Error(`${baseUrl} returned status ${res.status}`);
11308
11353
  }
11309
11354
  try {
11310
11355
  return await res.json();
11311
11356
  } catch {
11312
- throw new Error("Invalid response from API");
11357
+ throw new Error(`Invalid response from ${baseUrl}`);
11313
11358
  }
11314
11359
  }
11360
+ async function resolveStoreCapabilities(connectionId, candidateUrls) {
11361
+ const urls = candidateUrls.filter((u, i) => u && candidateUrls.indexOf(u) === i);
11362
+ if (urls.length === 0) {
11363
+ throw new Error("No API URLs to try");
11364
+ }
11365
+ let lastError;
11366
+ let allNotFound = true;
11367
+ for (let i = 0; i < urls.length; i++) {
11368
+ const baseUrl = urls[i];
11369
+ try {
11370
+ const capabilities = await fetchStoreCapabilities(connectionId, baseUrl);
11371
+ return { capabilities, apiBaseUrl: baseUrl, fellBack: i > 0 };
11372
+ } catch (err) {
11373
+ lastError = err;
11374
+ const isNotFound = err.code === "NOT_FOUND";
11375
+ if (!isNotFound) {
11376
+ allNotFound = false;
11377
+ }
11378
+ }
11379
+ }
11380
+ if (allNotFound) {
11381
+ throw new Error(
11382
+ `Connection "${connectionId}" not found in any known environment (${urls.join(", ")}).`
11383
+ );
11384
+ }
11385
+ throw lastError || new Error("Failed to resolve store capabilities");
11386
+ }
11315
11387
 
11316
11388
  // src/tools/get-store-capabilities.ts
11317
11389
  var GET_STORE_CAPABILITIES_NAME = "get-store-capabilities";
@@ -11429,13 +11501,9 @@ function formatCapabilities(caps) {
11429
11501
  }
11430
11502
  async function handleGetStoreCapabilities(args) {
11431
11503
  try {
11432
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11433
- /\/$/,
11434
- ""
11435
- );
11436
- const caps = await fetchStoreCapabilities(args.connectionId, baseUrl);
11504
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11437
11505
  return {
11438
- content: [{ type: "text", text: formatCapabilities(caps) }]
11506
+ content: [{ type: "text", text: formatCapabilities(resolved.capabilities) }]
11439
11507
  };
11440
11508
  } catch (error) {
11441
11509
  const message = error instanceof Error ? error.message : "Failed to fetch store capabilities";
@@ -11698,13 +11766,10 @@ var BUILD_STORE_SCHEMA = {
11698
11766
  storeStyle: z7.string().optional().describe('Design style (e.g., "minimalist", "luxury", "playful", "dark mode")')
11699
11767
  };
11700
11768
  async function handleBuildStore(args) {
11701
- const baseUrl = (process.env.BRAINERCE_API_URL || "https://api.brainerce.com").replace(
11702
- /\/$/,
11703
- ""
11704
- );
11705
11769
  let capabilities = null;
11706
11770
  try {
11707
- capabilities = await fetchStoreCapabilities(args.connectionId, baseUrl);
11771
+ const resolved = await resolveStoreCapabilities(args.connectionId, getCandidateApiUrls());
11772
+ capabilities = resolved.capabilities;
11708
11773
  } catch {
11709
11774
  }
11710
11775
  const bundle = buildStoreBundle({
package/package.json CHANGED
@@ -1,53 +1,54 @@
1
- {
2
- "name": "@brainerce/mcp-server",
3
- "version": "2.6.0",
4
- "description": "MCP server for AI-powered Brainerce store building. Provides SDK docs, types, and code examples to AI tools like Lovable, Cursor, and Claude Code.",
5
- "bin": {
6
- "brainerce-mcp": "dist/bin/stdio.js"
7
- },
8
- "main": "dist/index.js",
9
- "module": "dist/index.mjs",
10
- "types": "dist/index.d.ts",
11
- "exports": {
12
- ".": {
13
- "types": "./dist/index.d.ts",
14
- "require": "./dist/index.js",
15
- "import": "./dist/index.mjs"
16
- }
17
- },
18
- "files": [
19
- "dist",
20
- "README.md"
21
- ],
22
- "scripts": {
23
- "prebuild": "node scripts/embed-templates.mjs",
24
- "build": "node scripts/embed-templates.mjs && tsup",
25
- "dev": "tsup --watch",
26
- "start:stdio": "node dist/bin/stdio.js",
27
- "start:http": "node dist/bin/http.js"
28
- },
29
- "dependencies": {
30
- "@modelcontextprotocol/sdk": "^1.27.1",
31
- "zod": "^3.24.0"
32
- },
33
- "devDependencies": {
34
- "@types/node": "^22.0.0",
35
- "tsup": "^8.0.0",
36
- "typescript": "^5.3.0"
37
- },
38
- "engines": {
39
- "node": ">=18"
40
- },
41
- "keywords": [
42
- "brainerce",
43
- "mcp",
44
- "model-context-protocol",
45
- "ai",
46
- "ecommerce",
47
- "lovable",
48
- "cursor",
49
- "claude-code",
50
- "vibe-coding"
51
- ],
52
- "license": "MIT"
53
- }
1
+ {
2
+ "name": "@brainerce/mcp-server",
3
+ "version": "2.7.0",
4
+ "description": "MCP server for AI-powered Brainerce store building. Provides SDK docs, types, and code examples to AI tools like Lovable, Cursor, and Claude Code.",
5
+ "bin": {
6
+ "brainerce-mcp": "dist/bin/stdio.js"
7
+ },
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "require": "./dist/index.js",
15
+ "import": "./dist/index.mjs"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "prebuild": "node scripts/embed-templates.mjs",
24
+ "build": "node scripts/embed-templates.mjs && tsup",
25
+ "dev": "tsup --watch",
26
+ "start:stdio": "node dist/bin/stdio.js",
27
+ "start:http": "node dist/bin/http.js",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.27.1",
32
+ "zod": "^3.24.0"
33
+ },
34
+ "devDependencies": {
35
+ "@types/node": "^22.0.0",
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.3.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=18"
41
+ },
42
+ "keywords": [
43
+ "brainerce",
44
+ "mcp",
45
+ "model-context-protocol",
46
+ "ai",
47
+ "ecommerce",
48
+ "lovable",
49
+ "cursor",
50
+ "claude-code",
51
+ "vibe-coding"
52
+ ],
53
+ "license": "MIT"
54
+ }