bflabs-mcp 1.0.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.
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env node
2
+ import { select, input } from "@inquirer/prompts";
3
+ import chalk from "chalk";
4
+ import { provision, TOOLS } from "../lib/installer.js";
5
+ import { writeMcpConfig } from "../lib/config-writer.js";
6
+ import { writeSkill } from "../lib/skill-writer.js";
7
+
8
+ console.log();
9
+ console.log(chalk.bold.cyan(" ╔══════════════════════════════════════╗"));
10
+ console.log(chalk.bold.cyan(" ║ BF MCP v1.0.0 ║"));
11
+ console.log(chalk.bold.cyan(" ╚══════════════════════════════════════╝"));
12
+ console.log();
13
+
14
+ try {
15
+ const tool = await select({
16
+ message: "Which tool do you want to install?",
17
+ choices: TOOLS,
18
+ });
19
+
20
+ const email = await input({
21
+ message: "Enter your email:",
22
+ validate: (v) => v.includes("@") || "Enter a valid email",
23
+ });
24
+
25
+ process.stdout.write(chalk.dim(" ◌ Authenticating..."));
26
+
27
+ let data;
28
+ try {
29
+ data = await provision(email, tool);
30
+ process.stdout.write("\r" + chalk.green(" ✓ Authenticated") + " \n");
31
+ } catch (err) {
32
+ process.stdout.write("\r" + chalk.red(" ✗ " + err.message) + "\n");
33
+ process.exit(1);
34
+ }
35
+
36
+ // Write MCP config
37
+ const serverName = `bflabs-${tool}`;
38
+ const written = writeMcpConfig(serverName, data.mcp_url, data.api_key);
39
+ console.log(chalk.green(" ✓ MCP configured") + chalk.dim(` → ${written[0] || "~/.claude"}`));
40
+
41
+ // Write skill
42
+ const skillPath = writeSkill(tool);
43
+ console.log(chalk.green(" ✓ Skill installed") + chalk.dim(` → ${skillPath}`));
44
+
45
+ console.log();
46
+ console.log(chalk.bold(" Done! Restart Claude to activate."));
47
+ console.log();
48
+ console.log(
49
+ chalk.dim(" MCP: ") +
50
+ chalk.cyan(serverName) +
51
+ chalk.dim(" → ") +
52
+ chalk.underline(data.mcp_url)
53
+ );
54
+ console.log(chalk.dim(" User: ") + data.user_name + chalk.dim(` (${data.role})`));
55
+ console.log();
56
+ } catch (err) {
57
+ if (err.name === "ExitPromptError") {
58
+ console.log(chalk.dim("\n Cancelled."));
59
+ process.exit(0);
60
+ }
61
+ console.error(chalk.red(" Error: " + err.message));
62
+ process.exit(1);
63
+ }
@@ -0,0 +1,75 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import fs from "fs";
4
+
5
+ function getClaudeConfigPaths() {
6
+ const platform = process.platform;
7
+ const home = os.homedir();
8
+
9
+ if (platform === "darwin") {
10
+ return [
11
+ path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
12
+ ];
13
+ } else if (platform === "win32") {
14
+ return [
15
+ path.join(process.env.APPDATA || "", "Claude", "claude_desktop_config.json"),
16
+ ];
17
+ } else {
18
+ // Linux — Claude Desktop e Claude Code
19
+ return [
20
+ path.join(home, ".config", "Claude", "claude_desktop_config.json"),
21
+ path.join(home, ".claude.json"),
22
+ ];
23
+ }
24
+ }
25
+
26
+ export function writeMcpConfig(serverName, mcpUrl, apiKey) {
27
+ const configPaths = getClaudeConfigPaths();
28
+ const written = [];
29
+
30
+ for (const configPath of configPaths) {
31
+ try {
32
+ let config = {};
33
+ if (fs.existsSync(configPath)) {
34
+ const raw = fs.readFileSync(configPath, "utf-8");
35
+ config = JSON.parse(raw);
36
+ }
37
+
38
+ if (!config.mcpServers) config.mcpServers = {};
39
+
40
+ config.mcpServers[serverName] = {
41
+ url: mcpUrl,
42
+ headers: {
43
+ Authorization: `Bearer ${apiKey}`,
44
+ },
45
+ };
46
+
47
+ fs.mkdirSync(path.dirname(configPath), { recursive: true });
48
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
49
+ written.push(configPath);
50
+ } catch {
51
+ // skip if not writable
52
+ }
53
+ }
54
+
55
+ // Also write to ~/.claude/mcp_servers/ for Claude Code
56
+ const claudeCodeMcp = path.join(os.homedir(), ".claude", "mcp_servers.json");
57
+ try {
58
+ let config = {};
59
+ if (fs.existsSync(claudeCodeMcp)) {
60
+ config = JSON.parse(fs.readFileSync(claudeCodeMcp, "utf-8"));
61
+ }
62
+ if (!config.mcpServers) config.mcpServers = {};
63
+ config.mcpServers[serverName] = {
64
+ url: mcpUrl,
65
+ headers: { Authorization: `Bearer ${apiKey}` },
66
+ };
67
+ fs.mkdirSync(path.dirname(claudeCodeMcp), { recursive: true });
68
+ fs.writeFileSync(claudeCodeMcp, JSON.stringify(config, null, 2));
69
+ written.push(claudeCodeMcp);
70
+ } catch {
71
+ // skip
72
+ }
73
+
74
+ return written;
75
+ }
@@ -0,0 +1,33 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import fs from "fs";
4
+
5
+ const API_BASE = "https://adsmanager.bflabs.com.br/api/v1";
6
+
7
+ export const TOOLS = [
8
+ {
9
+ value: "ads-manager",
10
+ name: "ads-manager — Meta Ads: campanhas, ad sets, ads, criativos, insights, audiences, planos, relatórios automáticos, cohort engine, ad copies (112 tools)",
11
+ },
12
+ {
13
+ value: "catalog-manager",
14
+ name: "catalog-manager — Meta Commerce: produtos, variantes em escala, Product Sets, bulk create (catálogo integrado ao ads-manager)",
15
+ },
16
+ ];
17
+
18
+ export async function provision(email, tool) {
19
+ const res = await fetch(`${API_BASE}/installer/provision`, {
20
+ method: "POST",
21
+ headers: { "Content-Type": "application/json" },
22
+ body: JSON.stringify({ email, tool }),
23
+ });
24
+
25
+ if (!res.ok) {
26
+ const body = await res.json().catch(() => ({}));
27
+ throw new Error(body.detail || body.message || `HTTP ${res.status}`);
28
+ }
29
+
30
+ const json = await res.json();
31
+ if (!json.success) throw new Error(json.error || "Provision failed");
32
+ return json.data;
33
+ }
@@ -0,0 +1,97 @@
1
+ import os from "os";
2
+ import path from "path";
3
+ import fs from "fs";
4
+
5
+ const SKILL_CONTENTS = {
6
+ "ads-manager": `---
7
+ name: ads-manager
8
+ description: Gerencia Meta Ads (Facebook/Instagram) via MCP server. Use quando o usuário pedir para criar campanhas, analisar resultados, gerenciar ativos (páginas, audiences, pixels, catálogos) ou operar contas de anúncio.
9
+ license: proprietary
10
+ metadata:
11
+ version: 1.0.0
12
+ author: BF Labs
13
+ tags:
14
+ - meta-ads
15
+ - facebook-ads
16
+ - mcp
17
+ - bf-labs
18
+ platforms:
19
+ - Claude
20
+ ---
21
+
22
+ # Ads Manager — BF Labs
23
+
24
+ Acesse todas as operações de Meta Ads via MCP server \`bflabs-ads-manager\`.
25
+
26
+ ## MCP Server
27
+
28
+ Conectado via \`bflabs-ads-manager\` com suas credenciais pessoais.
29
+
30
+ ## Quando usar
31
+
32
+ - Criar, pausar, ativar ou duplicar campanhas/ad sets/ads
33
+ - Analisar performance (ROAS, CPL, CTR, spend)
34
+ - Gerenciar criativos e fazer upload de imagens/vídeos
35
+ - Gerar relatório de todas as contas
36
+ - Criar Custom Audiences e Lookalikes
37
+ - Planejar campanha completa e executar via agente
38
+
39
+ ## Começar
40
+
41
+ Sempre inicie com:
42
+ \`\`\`
43
+ context_list_clients() → clientes disponíveis para você
44
+ context_get_client("nome") → assets completos do cliente
45
+ \`\`\`
46
+ `,
47
+ "catalog-manager": `---
48
+ name: catalog-manager
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
+ license: proprietary
51
+ metadata:
52
+ version: 1.0.0
53
+ author: BF Labs
54
+ tags:
55
+ - meta-catalog
56
+ - commerce-manager
57
+ - mcp
58
+ - bf-labs
59
+ platforms:
60
+ - Claude
61
+ ---
62
+
63
+ # Catalog Manager — BF Labs
64
+
65
+ Operação de catálogos de produtos Meta via Commerce Manager.
66
+
67
+ ## Fluxo principal
68
+
69
+ 1 produto → 4 variantes idênticas → 1 Product Set automático
70
+
71
+ ## Quando usar
72
+
73
+ - Criar produto novo no catálogo de um cliente
74
+ - Criar variantes idênticas (fluxo de escala)
75
+ - Criar Product Set automaticamente
76
+ - Listar e atualizar produtos existentes
77
+
78
+ ## Começar
79
+
80
+ \`\`\`
81
+ context_get_client("nome-do-cliente") → business_id
82
+ catalog_list(business_id) → catalog_id
83
+ \`\`\`
84
+ `,
85
+ };
86
+
87
+ export function writeSkill(toolName) {
88
+ const skillContent = SKILL_CONTENTS[toolName];
89
+ if (!skillContent) throw new Error(`No skill content for: ${toolName}`);
90
+
91
+ const skillDir = path.join(os.homedir(), ".claude", "skills", toolName);
92
+ const skillPath = path.join(skillDir, "SKILL.md");
93
+
94
+ fs.mkdirSync(skillDir, { recursive: true });
95
+ fs.writeFileSync(skillPath, skillContent);
96
+ return skillPath;
97
+ }
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "bflabs-mcp",
3
+ "version": "1.0.0",
4
+ "description": "BF MCP — instala o MCP server e skill do ads-manager e catalog-manager em Claude Desktop/Code",
5
+ "bin": {
6
+ "bflabs-mcp": "./bin/bflabs-mcp.js"
7
+ },
8
+ "main": "./lib/installer.js",
9
+ "type": "module",
10
+ "files": [
11
+ "bin/",
12
+ "lib/"
13
+ ],
14
+ "dependencies": {
15
+ "@inquirer/prompts": "^7.0.0",
16
+ "chalk": "^5.3.0"
17
+ },
18
+ "engines": {
19
+ "node": ">=18"
20
+ },
21
+ "keywords": ["mcp", "claude", "bf-labs", "meta-ads", "installer"],
22
+ "author": "BF Labs <brunoguerrafalcao@gmail.com>",
23
+ "license": "UNLICENSED",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/BFLabsAI/bflabs-mcp"
27
+ }
28
+ }