brilliant-directories-mcp 6.58.607 → 6.58.608
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/index.js +15 -3
- package/openapi/bd-api.json +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -327,7 +327,8 @@ async function _takenSlugsFor(config, slugs) {
|
|
|
327
327
|
// front, and reused.
|
|
328
328
|
// Mirrored in the Worker — keep in step.
|
|
329
329
|
function aicSlugify(name) {
|
|
330
|
-
|
|
330
|
+
// Fold diacritics first: stripping them outright turns "Cafés" into "caf-s".
|
|
331
|
+
const ascii = String(name).normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60);
|
|
331
332
|
if (ascii) return ascii;
|
|
332
333
|
// A name with no Latin characters percent-encodes, which is what BD itself stores
|
|
333
334
|
// for sub-category slugs — a shared generic fallback would collide across every name.
|
|
@@ -400,8 +401,14 @@ async function buildCategoryTree(config, args) {
|
|
|
400
401
|
return { status: "error", message: "Could not read the site's existing top categories; nothing was created. Retry." };
|
|
401
402
|
}
|
|
402
403
|
// Cross-namespace collision check for the tops we may have to create.
|
|
404
|
+
// Probe the suffix variants too: a collision is resolved by appending -1..-3, and those
|
|
405
|
+
// variants can themselves be taken by a web page, plan or member profile.
|
|
403
406
|
const candidateSlugs = [];
|
|
404
|
-
for (const step of plan)
|
|
407
|
+
for (const step of plan) {
|
|
408
|
+
if (idByName[step.top.toLowerCase()] !== undefined) continue;
|
|
409
|
+
const base = step.wantSlug || aicSlugify(step.top);
|
|
410
|
+
candidateSlugs.push(base, base + "-1", base + "-2", base + "-3");
|
|
411
|
+
}
|
|
405
412
|
if (candidateSlugs.length) {
|
|
406
413
|
const foreign = await _takenSlugsFor(config, candidateSlugs);
|
|
407
414
|
for (const k in foreign) takenSlugs[k] = true;
|
|
@@ -417,7 +424,11 @@ async function buildCategoryTree(config, args) {
|
|
|
417
424
|
let slug = step.wantSlug || aicSlugify(step.top);
|
|
418
425
|
if (takenSlugs[slug]) {
|
|
419
426
|
let n = 1;
|
|
420
|
-
while (n <=
|
|
427
|
+
while (n <= 3 && takenSlugs[slug + "-" + n]) n++;
|
|
428
|
+
if (n > 3) {
|
|
429
|
+
results.push({ top_category: step.top, sub_categories: step.subs, top_status: "error", message: `the URL slug "${slug}" and its -1, -2 and -3 variants are all in use elsewhere on this site. Give this category a more distinct name, or pass a filename for it.` });
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
421
432
|
slug = slug + "-" + n;
|
|
422
433
|
}
|
|
423
434
|
const resp = await makeRequest(config, "POST", "/api/v2/list_professions/create", null, { name: step.top, filename: slug });
|
|
@@ -491,6 +502,7 @@ async function buildCategoryTree(config, args) {
|
|
|
491
502
|
message: {
|
|
492
503
|
groups_requested: plan.length,
|
|
493
504
|
groups_completed: results.length - failed.length,
|
|
505
|
+
sub_categories_created: results.reduce((n, r) => n + (r.sub_status === "created" ? r.sub_categories.length : 0), 0),
|
|
494
506
|
temp_member: cleanup || (needSubs.length ? "no temporary member was created" : "not needed (no sub-categories requested)"),
|
|
495
507
|
groups: results.map((r) => ({
|
|
496
508
|
top_category: r.top_category,
|
package/openapi/bd-api.json
CHANGED
|
@@ -11752,7 +11752,7 @@
|
|
|
11752
11752
|
"post": {
|
|
11753
11753
|
"operationId": "createCategoryTree",
|
|
11754
11754
|
"summary": "Create a full category taxonomy (tops + subs + sub-subs) in one call.",
|
|
11755
|
-
"description": "Wrapper-native synthetic tool. Creates member categories — top categories, their sub-categories, and third-tier sub-sub-categories — in one call.\n\n**Use when:** creating a category at any level, including adding to a structure that already exists. Use `createTopCategory` or `createSubCategory` only for a single category that needs `desc`, `keywords`, `icon`, `sort_order`, `lead_price`, `image`, `master_id`, or a `filename` other than the default slug set at create time. For every other category create, use `createCategoryTree`.\n\n**Required:** `groups` — an array of `{ top_category, sub_categories }`, 25 entries maximum per call.\n\n**Send the whole taxonomy in one call.** A top category named again is matched by name and reused, so a later call adds to it. Never issue two calls concurrently: a top category named in both is created twice, because BD's category list does not reflect a row written by a call still in flight. A second call is safe once the first call's response has returned.\n\n**The three shapes, all the same input:**\n\n- New top plus its subs: `{ top_category: \"Surf Shops\", sub_categories: [\"Surfboards\", \"Wetsuits\"] }`\n\n- Subs under a top that already exists: the same shape, naming that top. It is reused; only the listed subs are added, and existing subs are left alone.\n\n- Top only: omit `sub_categories` or pass `[]`.\n\n**Third tier — `Parent=>Child`:** a `sub_categories` entry containing `=>` creates `Child` under `Parent`, and `Parent` under the group's `top_category`. An existing `Parent` is reused. Exactly one `=>` per entry: `\"Surf Camps=>Kids Camps\"`. `A=>B=>C` is rejected — send `A=>B` in this call, then `\"B=>C\"` in a second call naming the same `top_category` once this call's response has returned.\n\n**Sub-category names must not contain commas** — this tool writes them through BD's comma-separated `services` field, which would split one name into several. Replace the comma with a hyphen. To create the parts as separate categories instead, send each as its own `sub_categories` entry. One comma anywhere in `sub_categories` rejects the call. Top category names may contain commas.\n\n**Nothing is written until every name validates.** Writing itself is not atomic: a failure part-way leaves earlier groups created. `groups_completed` and each group's `top_status` / `sub_status` name exactly what landed — read them before retrying. Re-send a group only when its `top_status` is `error`, or its `sub_status` is `error` or `not attempted`; `created`, `existing`, and `none requested` all mean that part landed.\n\nBuilding sub-categories requires a temporary member, which this tool creates and deletes for you. `temp_member` reports what happened to it; the categories are unaffected either way.\n\n**See also:** `createTopCategory`, `createSubCategory`, `listTopCategories`, `listSubCategories`.\n\n**Returns:** `{ status, message: { groups_requested, groups_completed, temp_member, groups: [{ top_category, profession_id, top_status, sub_categories, sub_status }] } }`. `top_status` is `created`, `existing`, or `error`. `sub_status` is `created`, `error`, `none requested`, or `not attempted`. `temp_member` is one of: `temporary member deleted` — cleanup succeeded; `not needed (no sub-categories requested)`; `no temporary member was created` — no sub-category was written and every `sub_status` is `error`; or a `user_id` — sub-categories were written but cleanup failed, so pass that id to `deleteUser`. Each group carries the resolved `profession_id`, ready for `updateUser.profession_id`. Sub-category ids are not returned — read them with `listSubCategories` filtered on that `profession_id` before assigning members via `updateUser.services` or `createMemberSubCategoryLink`.",
|
|
11755
|
+
"description": "Wrapper-native synthetic tool. Creates member categories — top categories, their sub-categories, and third-tier sub-sub-categories — in one call.\n\n**Use when:** creating a category at any level, including adding to a structure that already exists. Use `createTopCategory` or `createSubCategory` only for a single category that needs `desc`, `keywords`, `icon`, `sort_order`, `lead_price`, `image`, `master_id`, or a `filename` other than the default slug set at create time. For every other category create, use `createCategoryTree`.\n\n**Required:** `groups` — an array of `{ top_category, sub_categories }`, 25 entries maximum per call.\n\n**Send the whole taxonomy in one call.** A top category named again is matched by name and reused, so a later call adds to it. Never issue two calls concurrently: a top category named in both is created twice, because BD's category list does not reflect a row written by a call still in flight. A second call is safe once the first call's response has returned.\n\n**The three shapes, all the same input:**\n\n- New top plus its subs: `{ top_category: \"Surf Shops\", sub_categories: [\"Surfboards\", \"Wetsuits\"] }`\n\n- Subs under a top that already exists: the same shape, naming that top. It is reused; only the listed subs are added, and existing subs are left alone.\n\n- Top only: omit `sub_categories` or pass `[]`.\n\n**Third tier — `Parent=>Child`:** a `sub_categories` entry containing `=>` creates `Child` under `Parent`, and `Parent` under the group's `top_category`. An existing `Parent` is reused. Exactly one `=>` per entry: `\"Surf Camps=>Kids Camps\"`. `A=>B=>C` is rejected — send `A=>B` in this call, then `\"B=>C\"` in a second call naming the same `top_category` once this call's response has returned.\n\n**Sub-category names must not contain commas** — this tool writes them through BD's comma-separated `services` field, which would split one name into several. Replace the comma with a hyphen. To create the parts as separate categories instead, send each as its own `sub_categories` entry. One comma anywhere in `sub_categories` rejects the call. Top category names may contain commas.\n\n**Nothing is written until every name validates.** Writing itself is not atomic: a failure part-way leaves earlier groups created. `groups_completed` and each group's `top_status` / `sub_status` name exactly what landed — read them before retrying. Re-send a group only when its `top_status` is `error`, or its `sub_status` is `error` or `not attempted`; `created`, `existing`, and `none requested` all mean that part landed.\n\nBuilding sub-categories requires a temporary member, which this tool creates and deletes for you. `temp_member` reports what happened to it; the categories are unaffected either way.\n\n**See also:** `createTopCategory`, `createSubCategory`, `listTopCategories`, `listSubCategories`.\n\n**Returns:** `{ status, message: { groups_requested, groups_completed, sub_categories_created, temp_member, groups: [{ top_category, profession_id, top_status, sub_categories, sub_status }] } }`. `top_status` is `created`, `existing`, or `error`. `sub_status` is `created`, `error`, `none requested`, or `not attempted`. `sub_categories_created` is the total across all groups — report it rather than counting names. `temp_member` is one of: `temporary member deleted` — cleanup succeeded; `not needed (no sub-categories requested)`; `no temporary member was created` — no sub-category was written and every `sub_status` is `error`; or a `user_id` — sub-categories were written but cleanup failed, so pass that id to `deleteUser`. Each group carries the resolved `profession_id`, ready for `updateUser.profession_id`. Sub-category ids are not returned — read them with `listSubCategories` filtered on that `profession_id` before assigning members via `updateUser.services` or `createMemberSubCategoryLink`.",
|
|
11756
11756
|
"tags": [
|
|
11757
11757
|
"Categories"
|
|
11758
11758
|
],
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brilliant-directories-mcp",
|
|
3
3
|
"mcpName": "io.github.brilliantdirectories/brilliant-directories-mcp",
|
|
4
|
-
"version": "6.58.
|
|
4
|
+
"version": "6.58.608",
|
|
5
5
|
"description": "Official MCP server for Brilliant Directories — manage members, posts, leads, reviews, and more.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|