bflabs-mcp 1.0.2 → 1.0.4
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/bin/bflabs-mcp.js +88 -24
- package/lib/config-writer.js +4 -0
- package/lib/skill-writer.js +13 -4
- package/package.json +1 -1
package/bin/bflabs-mcp.js
CHANGED
|
@@ -5,22 +5,41 @@ import { provision, TOOLS } from "../lib/installer.js";
|
|
|
5
5
|
import { writeMcpConfig } from "../lib/config-writer.js";
|
|
6
6
|
import { writeSkill } from "../lib/skill-writer.js";
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
console.log(chalk.bold.cyan(" ║ BF MCP v1.0.0 ║"));
|
|
11
|
-
console.log(chalk.bold.cyan(" ╚══════════════════════════════════════╝"));
|
|
12
|
-
console.log();
|
|
8
|
+
const VERSION = "1.0.3";
|
|
9
|
+
const MCP_SERVER_NAME = "bflabs-ads-manager";
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
function printBanner() {
|
|
12
|
+
console.log();
|
|
13
|
+
console.log(chalk.bold.cyan(" ╔══════════════════════════════════════╗"));
|
|
14
|
+
console.log(chalk.bold.cyan(` ║ BF MCP v${VERSION} ║`));
|
|
15
|
+
console.log(chalk.bold.cyan(" ╚══════════════════════════════════════╝"));
|
|
16
|
+
console.log();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function install() {
|
|
20
|
+
printBanner();
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
let tool;
|
|
23
|
+
try {
|
|
24
|
+
tool = await select({
|
|
25
|
+
message: "Which tool do you want to install?",
|
|
26
|
+
choices: TOOLS,
|
|
27
|
+
});
|
|
28
|
+
} catch (err) {
|
|
29
|
+
if (err.name === "ExitPromptError") { console.log(chalk.dim("\n Cancelled.")); process.exit(0); }
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let email;
|
|
34
|
+
try {
|
|
35
|
+
email = await input({
|
|
36
|
+
message: "Enter your email:",
|
|
37
|
+
validate: (v) => v.includes("@") || "Enter a valid email",
|
|
38
|
+
});
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err.name === "ExitPromptError") { console.log(chalk.dim("\n Cancelled.")); process.exit(0); }
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
24
43
|
|
|
25
44
|
process.stdout.write(chalk.dim(" ◌ Authenticating..."));
|
|
26
45
|
|
|
@@ -33,26 +52,71 @@ try {
|
|
|
33
52
|
process.exit(1);
|
|
34
53
|
}
|
|
35
54
|
|
|
36
|
-
//
|
|
37
|
-
const
|
|
38
|
-
const written = writeMcpConfig(serverName, data.mcp_url, data.api_key);
|
|
55
|
+
// Always use single server name regardless of tool
|
|
56
|
+
const written = writeMcpConfig(MCP_SERVER_NAME, data.mcp_url, data.api_key);
|
|
39
57
|
console.log(chalk.green(" ✓ MCP configured") + chalk.dim(` → ${written[0] || "~/.claude"}`));
|
|
40
58
|
|
|
41
|
-
// Write skill
|
|
42
59
|
const skillPath = writeSkill(tool);
|
|
43
60
|
console.log(chalk.green(" ✓ Skill installed") + chalk.dim(` → ${skillPath}`));
|
|
44
61
|
|
|
45
62
|
console.log();
|
|
46
63
|
console.log(chalk.bold(" Done! Restart Claude to activate."));
|
|
47
64
|
console.log();
|
|
48
|
-
console.log(
|
|
49
|
-
chalk.dim(" MCP: ") +
|
|
50
|
-
chalk.cyan(serverName) +
|
|
51
|
-
chalk.dim(" → ") +
|
|
52
|
-
chalk.underline(data.mcp_url)
|
|
53
|
-
);
|
|
65
|
+
console.log(chalk.dim(" MCP: ") + chalk.cyan(MCP_SERVER_NAME) + chalk.dim(" → ") + chalk.underline(data.mcp_url));
|
|
54
66
|
console.log(chalk.dim(" User: ") + data.user_name + chalk.dim(` (${data.role})`));
|
|
67
|
+
if (data.scope && data.scope !== "full") {
|
|
68
|
+
console.log(chalk.dim(" Scope: ") + chalk.yellow(data.scope));
|
|
69
|
+
}
|
|
55
70
|
console.log();
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async function update() {
|
|
74
|
+
printBanner();
|
|
75
|
+
console.log(chalk.dim(" Refreshing your API key and permissions...\n"));
|
|
76
|
+
|
|
77
|
+
let email;
|
|
78
|
+
try {
|
|
79
|
+
email = await input({
|
|
80
|
+
message: "Enter your email:",
|
|
81
|
+
validate: (v) => v.includes("@") || "Enter a valid email",
|
|
82
|
+
});
|
|
83
|
+
} catch (err) {
|
|
84
|
+
if (err.name === "ExitPromptError") { console.log(chalk.dim("\n Cancelled.")); process.exit(0); }
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
process.stdout.write(chalk.dim(" ◌ Refreshing credentials..."));
|
|
89
|
+
|
|
90
|
+
let data;
|
|
91
|
+
try {
|
|
92
|
+
data = await provision(email, "ads-manager");
|
|
93
|
+
process.stdout.write("\r" + chalk.green(" ✓ Credentials refreshed") + " \n");
|
|
94
|
+
} catch (err) {
|
|
95
|
+
process.stdout.write("\r" + chalk.red(" ✗ " + err.message) + "\n");
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const written = writeMcpConfig(MCP_SERVER_NAME, data.mcp_url, data.api_key);
|
|
100
|
+
console.log(chalk.green(" ✓ MCP config updated") + chalk.dim(` → ${written[0] || "~/.claude"}`));
|
|
101
|
+
|
|
102
|
+
console.log();
|
|
103
|
+
console.log(chalk.bold(" Updated! Restart Claude to apply new permissions."));
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(chalk.dim(" User: ") + data.user_name + chalk.dim(` (${data.role})`));
|
|
106
|
+
if (data.scope && data.scope !== "full") {
|
|
107
|
+
console.log(chalk.dim(" Scope: ") + chalk.yellow(data.scope));
|
|
108
|
+
}
|
|
109
|
+
console.log();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const cmd = process.argv[2];
|
|
113
|
+
|
|
114
|
+
try {
|
|
115
|
+
if (cmd === "update") {
|
|
116
|
+
await update();
|
|
117
|
+
} else {
|
|
118
|
+
await install();
|
|
119
|
+
}
|
|
56
120
|
} catch (err) {
|
|
57
121
|
if (err.name === "ExitPromptError") {
|
|
58
122
|
console.log(chalk.dim("\n Cancelled."));
|
package/lib/config-writer.js
CHANGED
|
@@ -37,6 +37,9 @@ export function writeMcpConfig(serverName, mcpUrl, apiKey) {
|
|
|
37
37
|
|
|
38
38
|
if (!config.mcpServers) config.mcpServers = {};
|
|
39
39
|
|
|
40
|
+
// Remove legacy separate catalog-manager entry if present
|
|
41
|
+
delete config.mcpServers["bflabs-catalog-manager"];
|
|
42
|
+
|
|
40
43
|
config.mcpServers[serverName] = {
|
|
41
44
|
type: "http",
|
|
42
45
|
url: mcpUrl,
|
|
@@ -61,6 +64,7 @@ export function writeMcpConfig(serverName, mcpUrl, apiKey) {
|
|
|
61
64
|
config = JSON.parse(fs.readFileSync(claudeCodeMcp, "utf-8"));
|
|
62
65
|
}
|
|
63
66
|
if (!config.mcpServers) config.mcpServers = {};
|
|
67
|
+
delete config.mcpServers["bflabs-catalog-manager"];
|
|
64
68
|
config.mcpServers[serverName] = {
|
|
65
69
|
type: "http",
|
|
66
70
|
url: mcpUrl,
|
package/lib/skill-writer.js
CHANGED
|
@@ -49,7 +49,7 @@ name: catalog-manager
|
|
|
49
49
|
description: Gerencia catálogos de produtos Meta (Commerce Manager) via MCP. Use quando o usuário pedir para criar produtos, variantes, conjuntos de produtos (Product Sets) ou executar criação em massa.
|
|
50
50
|
license: proprietary
|
|
51
51
|
metadata:
|
|
52
|
-
version: 1.0.
|
|
52
|
+
version: 1.0.1
|
|
53
53
|
author: BF Labs
|
|
54
54
|
tags:
|
|
55
55
|
- meta-catalog
|
|
@@ -64,22 +64,31 @@ metadata:
|
|
|
64
64
|
|
|
65
65
|
Operação de catálogos de produtos Meta via Commerce Manager.
|
|
66
66
|
|
|
67
|
-
## Fluxo principal
|
|
67
|
+
## Fluxo principal (escala BF Labs)
|
|
68
|
+
|
|
69
|
+
1 produto base → N variantes (mesmo \`item_group_id\`) → 1 Product Set automático
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
As variantes aparecem agrupadas no Commerce Manager como um único item com múltiplas cópias.
|
|
70
72
|
|
|
71
73
|
## Quando usar
|
|
72
74
|
|
|
73
75
|
- Criar produto novo no catálogo de um cliente
|
|
74
|
-
- Criar variantes idênticas (fluxo de escala)
|
|
76
|
+
- Criar variantes idênticas (fluxo de escala) com \`catalog_bulk_create_product\`
|
|
75
77
|
- Criar Product Set automaticamente
|
|
76
78
|
- Listar e atualizar produtos existentes
|
|
77
79
|
|
|
80
|
+
## Comportamento importante
|
|
81
|
+
|
|
82
|
+
- \`additional_image_urls\`: lista de URLs de imagens extras — enviada automaticamente como JSON string para a API Meta
|
|
83
|
+
- \`item_group_id\`: no bulk create, todas as variantes recebem o \`retailer_id_base\` como \`item_group_id\`, agrupando-as como variantes do mesmo produto no Commerce Manager
|
|
84
|
+
- Campos \`None\` são removidos automaticamente antes do envio
|
|
85
|
+
|
|
78
86
|
## Começar
|
|
79
87
|
|
|
80
88
|
\`\`\`
|
|
81
89
|
context_get_client("nome-do-cliente") → business_id
|
|
82
90
|
catalog_list(business_id) → catalog_id
|
|
91
|
+
catalog_bulk_create_product(catalog_id, name, retailer_id_base, ...)
|
|
83
92
|
\`\`\`
|
|
84
93
|
`,
|
|
85
94
|
};
|