mcp-lab-agent 2.1.2 → 2.1.3

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/README.md CHANGED
@@ -44,6 +44,12 @@ O agente:
44
44
 
45
45
  ---
46
46
 
47
+ ## Configurações
48
+
49
+ **Primeira vez?** Veja [CONFIGURACOES.md](CONFIGURACOES.md) — lista de arquivos e onde colocar cada configuração.
50
+
51
+ ---
52
+
47
53
  ## Quick Start
48
54
 
49
55
  ### Análise Completa (CLI)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-lab-agent",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "Autonomous QA agent: executor + intelligent consultant - analyzes, predicts, recommends and learns (modular)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,37 +9,80 @@ const SLACK_BOT_DIR = path.dirname(__dirname);
9
9
 
10
10
  config({ path: path.join(SLACK_BOT_DIR, ".env") });
11
11
 
12
- function loadSlackConfig() {
13
- const configPath = process.env.QA_LAB_CONFIG || path.join(ROOT, "qa-lab-agent.config.json");
14
- if (!existsSync(configPath)) {
15
- return null;
16
- }
12
+ function getMcpJsonPath() {
13
+ const home = process.env.HOME || process.env.USERPROFILE;
14
+ if (!home) return null;
15
+ return path.join(home, ".cursor", "mcp.json");
16
+ }
17
+
18
+ function loadMcpConfig() {
19
+ const mcpPath = process.env.QA_LAB_MCP_CONFIG || getMcpJsonPath();
20
+ if (!mcpPath || !existsSync(mcpPath)) return null;
17
21
  try {
18
- const data = JSON.parse(readFileSync(configPath, "utf8"));
19
- return data.slack || data;
22
+ return JSON.parse(readFileSync(mcpPath, "utf8"));
20
23
  } catch {
21
24
  return null;
22
25
  }
23
26
  }
24
27
 
28
+ function getSlackConfigFromMcp() {
29
+ const mcp = loadMcpConfig();
30
+ const qa = mcp?.["qa-lab-agent"];
31
+ const slack = qa?.slack;
32
+ if (!slack) return null;
33
+ return {
34
+ id: slack.id || slack.channelId,
35
+ botToken: slack.botToken || slack.SLACK_BOT_TOKEN,
36
+ signingSecret: slack.signingSecret || slack.SLACK_SIGNING_SECRET,
37
+ repo: slack.repo || slack.REPO_URL,
38
+ branch: slack.branch || slack.REPO_BRANCH || "main",
39
+ };
40
+ }
41
+
42
+ function loadSlackConfig() {
43
+ const configPath = process.env.QA_LAB_CONFIG || path.join(ROOT, "qa-lab-agent.config.json");
44
+ if (existsSync(configPath)) {
45
+ try {
46
+ const data = JSON.parse(readFileSync(configPath, "utf8"));
47
+ return data.slack || data;
48
+ } catch {}
49
+ }
50
+ return null;
51
+ }
52
+
53
+ function getSlackTokens() {
54
+ const fromMcp = getSlackConfigFromMcp();
55
+ if (fromMcp?.botToken && fromMcp?.signingSecret) {
56
+ return { token: fromMcp.botToken, signingSecret: fromMcp.signingSecret };
57
+ }
58
+ return {
59
+ token: process.env.SLACK_BOT_TOKEN,
60
+ signingSecret: process.env.SLACK_SIGNING_SECRET,
61
+ };
62
+ }
63
+
25
64
  function getRepoForChannel() {
65
+ const fromMcp = getSlackConfigFromMcp();
66
+ if (fromMcp?.repo) {
67
+ return { url: fromMcp.repo, branch: fromMcp.branch || "main" };
68
+ }
26
69
  const repoUrl = process.env.REPO_URL;
27
- const repoBranch = process.env.REPO_BRANCH || "main";
28
70
  if (repoUrl) {
29
- return { url: repoUrl, branch: repoBranch };
71
+ return { url: repoUrl, branch: process.env.REPO_BRANCH || "main" };
30
72
  }
31
73
  const cfg = loadSlackConfig();
32
74
  const repo = cfg?.repo || cfg?.defaultRepo?.url;
33
75
  const branch = cfg?.branch || cfg?.defaultRepo?.branch || "main";
34
76
  if (!repo) {
35
- throw new Error("Configure REPO_URL no .env ou 'repo' no qa-lab-agent.config.json");
77
+ throw new Error("Configure 'slack.repo' no ~/.cursor/mcp.json ou em qa-lab-agent.config.json");
36
78
  }
37
79
  return { url: repo, branch };
38
80
  }
39
81
 
40
82
  function getMcpLabAgentCmd() {
83
+ const fromMcp = loadMcpConfig()?.["qa-lab-agent"]?.mcpLabAgent;
41
84
  const cfg = loadSlackConfig();
42
- const mcp = cfg?.mcpLabAgent || { command: "npx", args: ["-y", "mcp-lab-agent@latest"] };
85
+ const mcp = fromMcp || cfg?.mcpLabAgent || { command: "npx", args: ["-y", "mcp-lab-agent@latest"] };
43
86
  return { command: mcp.command, args: mcp.args || [] };
44
87
  }
45
88
 
@@ -47,4 +90,11 @@ function getCloneBaseDir() {
47
90
  return process.env.CLONE_BASE_DIR || path.join(process.cwd(), ".qa-lab-clones");
48
91
  }
49
92
 
50
- export { loadSlackConfig, getRepoForChannel, getMcpLabAgentCmd, getCloneBaseDir };
93
+ export {
94
+ loadSlackConfig,
95
+ getRepoForChannel,
96
+ getMcpLabAgentCmd,
97
+ getCloneBaseDir,
98
+ getSlackConfigFromMcp,
99
+ getSlackTokens,
100
+ };
@@ -3,23 +3,16 @@
3
3
  * QA Lab Slack Bot
4
4
  * Recebe @mentions no Slack, executa mcp-lab-agent e posta relatório.
5
5
  *
6
- * Config: qa-lab-agent.config.json (slack section)
7
- * Secrets: .env (SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET)
6
+ * Config: ~/.cursor/mcp.json (qa-lab-agent.slack) ou .env
8
7
  */
9
8
  import { App } from "@slack/bolt";
10
- import { config } from "dotenv";
11
- import path from "node:path";
12
- import { fileURLToPath } from "node:url";
9
+ import { getSlackTokens } from "./config.js";
13
10
  import { registerAppMention } from "./handlers/app-mention.js";
14
11
 
15
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
16
- config({ path: path.join(__dirname, "..", ".env") });
17
-
18
- const token = process.env.SLACK_BOT_TOKEN;
19
- const signingSecret = process.env.SLACK_SIGNING_SECRET;
12
+ const { token, signingSecret } = getSlackTokens();
20
13
 
21
14
  if (!token || !signingSecret) {
22
- console.error("Configure SLACK_BOT_TOKEN e SLACK_SIGNING_SECRET no .env");
15
+ console.error("Configure no ~/.cursor/mcp.json:\n \"qa-lab-agent\": { \"slack\": { \"botToken\": \"xoxb-...\", \"signingSecret\": \"...\" } }\n\nOu use .env (SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET)");
23
16
  process.exit(1);
24
17
  }
25
18