@productbrain/mcp 0.0.1-beta.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/.env.mcp.example +32 -0
- package/README.md +238 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/cli/index.js +11 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.js +2546 -0
- package/dist/index.js.map +1 -0
- package/dist/setup-K757L5KR.js +227 -0
- package/dist/setup-K757L5KR.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
__require
|
|
4
|
+
} from "./chunk-DGUM43GV.js";
|
|
5
|
+
|
|
6
|
+
// src/cli/setup.ts
|
|
7
|
+
import { createInterface } from "readline";
|
|
8
|
+
|
|
9
|
+
// src/cli/config-writer.ts
|
|
10
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
11
|
+
import { join, dirname } from "path";
|
|
12
|
+
import { homedir, platform } from "os";
|
|
13
|
+
var SERVER_ENTRY_KEY = "productbrain";
|
|
14
|
+
function buildServerEntry(apiKey) {
|
|
15
|
+
return {
|
|
16
|
+
command: "npx",
|
|
17
|
+
args: ["-y", "productbrain"],
|
|
18
|
+
env: { PRODUCTBRAIN_API_KEY: apiKey }
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function getCursorConfigPath() {
|
|
22
|
+
return join(process.cwd(), ".cursor", "mcp.json");
|
|
23
|
+
}
|
|
24
|
+
function getClaudeDesktopConfigPath() {
|
|
25
|
+
const os = platform();
|
|
26
|
+
if (os === "darwin") {
|
|
27
|
+
return join(
|
|
28
|
+
homedir(),
|
|
29
|
+
"Library",
|
|
30
|
+
"Application Support",
|
|
31
|
+
"Claude",
|
|
32
|
+
"claude_desktop_config.json"
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
if (os === "win32") {
|
|
36
|
+
const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
|
|
37
|
+
return join(appData, "Claude", "claude_desktop_config.json");
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
function isCursorProject() {
|
|
42
|
+
return existsSync(join(process.cwd(), ".cursor")) || existsSync(join(process.cwd(), ".cursorignore"));
|
|
43
|
+
}
|
|
44
|
+
function isClaudeDesktopInstalled() {
|
|
45
|
+
const configPath = getClaudeDesktopConfigPath();
|
|
46
|
+
if (!configPath) return false;
|
|
47
|
+
return existsSync(dirname(configPath));
|
|
48
|
+
}
|
|
49
|
+
function detectClients() {
|
|
50
|
+
const clients = [];
|
|
51
|
+
if (isCursorProject()) {
|
|
52
|
+
clients.push({ name: "Cursor", configPath: getCursorConfigPath() });
|
|
53
|
+
}
|
|
54
|
+
if (isClaudeDesktopInstalled()) {
|
|
55
|
+
clients.push({
|
|
56
|
+
name: "Claude Desktop",
|
|
57
|
+
configPath: getClaudeDesktopConfigPath()
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return clients;
|
|
61
|
+
}
|
|
62
|
+
function readJsonSafe(path) {
|
|
63
|
+
if (!existsSync(path)) return {};
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
66
|
+
} catch {
|
|
67
|
+
return {};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function writeClientConfig(client, apiKey) {
|
|
71
|
+
const config = readJsonSafe(client.configPath);
|
|
72
|
+
const serversKey = "mcpServers";
|
|
73
|
+
if (!config[serversKey]) config[serversKey] = {};
|
|
74
|
+
if (config[serversKey][SERVER_ENTRY_KEY]) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
config[serversKey][SERVER_ENTRY_KEY] = buildServerEntry(apiKey);
|
|
78
|
+
const dir = dirname(client.configPath);
|
|
79
|
+
if (!existsSync(dir)) {
|
|
80
|
+
mkdirSync(dir, { recursive: true });
|
|
81
|
+
}
|
|
82
|
+
writeFileSync(client.configPath, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/cli/setup.ts
|
|
87
|
+
var SYNERGYOS_APP_URL = process.env.SYNERGYOS_APP_URL ?? process.env.PRODUCTBRAIN_APP_URL ?? "http://localhost:5173";
|
|
88
|
+
function bold(s) {
|
|
89
|
+
return `\x1B[1m${s}\x1B[0m`;
|
|
90
|
+
}
|
|
91
|
+
function green(s) {
|
|
92
|
+
return `\x1B[32m${s}\x1B[0m`;
|
|
93
|
+
}
|
|
94
|
+
function dim(s) {
|
|
95
|
+
return `\x1B[2m${s}\x1B[0m`;
|
|
96
|
+
}
|
|
97
|
+
function orange(s) {
|
|
98
|
+
return `\x1B[33m${s}\x1B[0m`;
|
|
99
|
+
}
|
|
100
|
+
function log(msg) {
|
|
101
|
+
process.stdout.write(`${msg}
|
|
102
|
+
`);
|
|
103
|
+
}
|
|
104
|
+
function openBrowser(url) {
|
|
105
|
+
const { execSync } = __require("child_process");
|
|
106
|
+
const platform2 = process.platform;
|
|
107
|
+
try {
|
|
108
|
+
if (platform2 === "darwin") execSync(`open "${url}"`);
|
|
109
|
+
else if (platform2 === "win32") execSync(`start "" "${url}"`);
|
|
110
|
+
else execSync(`xdg-open "${url}"`);
|
|
111
|
+
} catch {
|
|
112
|
+
log(dim(` Could not open browser automatically.`));
|
|
113
|
+
log(` Open this URL manually: ${url}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function prompt(question) {
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
119
|
+
rl.question(question, (answer) => {
|
|
120
|
+
rl.close();
|
|
121
|
+
resolve(answer.trim());
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
function promptChoice(question, choices) {
|
|
126
|
+
return new Promise((resolve) => {
|
|
127
|
+
log("");
|
|
128
|
+
log(bold(question));
|
|
129
|
+
choices.forEach((c, i) => log(` ${i + 1}) ${c}`));
|
|
130
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
131
|
+
rl.question(`
|
|
132
|
+
${dim("Choice [1]:")} `, (line) => {
|
|
133
|
+
rl.close();
|
|
134
|
+
const n = parseInt(line.trim(), 10);
|
|
135
|
+
if (isNaN(n) || n < 1 || n > choices.length) {
|
|
136
|
+
resolve(0);
|
|
137
|
+
} else {
|
|
138
|
+
resolve(n - 1);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async function runSetup() {
|
|
144
|
+
log("");
|
|
145
|
+
log(bold(` Product${orange("Brain")} Setup`));
|
|
146
|
+
log(dim(" Connect your AI assistant to your knowledge base\n"));
|
|
147
|
+
const apiKeysUrl = `${SYNERGYOS_APP_URL}/settings/api-keys`;
|
|
148
|
+
log(` ${dim("1. Get your API key from SynergyOS")}`);
|
|
149
|
+
log(` ${dim(apiKeysUrl)}
|
|
150
|
+
`);
|
|
151
|
+
const openNow = await prompt(` Open this URL in your browser? [Y/n]: `);
|
|
152
|
+
if (openNow.toLowerCase() !== "n" && openNow.toLowerCase() !== "no") {
|
|
153
|
+
openBrowser(apiKeysUrl);
|
|
154
|
+
}
|
|
155
|
+
log("");
|
|
156
|
+
log(` ${dim("2. Generate a key (if you don't have one), then copy it.\n")}`);
|
|
157
|
+
const apiKey = await prompt(` Paste your API key (pb_sk_...): `);
|
|
158
|
+
if (!apiKey || !apiKey.startsWith("pb_sk_")) {
|
|
159
|
+
log(` ${orange("!")} Invalid key format. Keys start with pb_sk_.`);
|
|
160
|
+
log(` Get one at ${apiKeysUrl}
|
|
161
|
+
`);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
}
|
|
164
|
+
log(` ${green("\u2713")} Key received
|
|
165
|
+
`);
|
|
166
|
+
const clients = detectClients();
|
|
167
|
+
if (clients.length === 0) {
|
|
168
|
+
log(bold(" No supported MCP clients detected.\n"));
|
|
169
|
+
printConfigSnippet(apiKey);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const clientNames = clients.map((c) => c.name);
|
|
173
|
+
const allOption = clients.length > 1 ? [...clientNames, "All of the above", "Just show me the config"] : [...clientNames, "Just show me the config"];
|
|
174
|
+
const choice = await promptChoice("Which AI assistant should I configure?", allOption);
|
|
175
|
+
if (choice === allOption.length - 1) {
|
|
176
|
+
printConfigSnippet(apiKey);
|
|
177
|
+
} else if (clients.length > 1 && choice === allOption.length - 2) {
|
|
178
|
+
for (const client of clients) {
|
|
179
|
+
await writeConfig(client, apiKey);
|
|
180
|
+
}
|
|
181
|
+
} else {
|
|
182
|
+
await writeConfig(clients[choice], apiKey);
|
|
183
|
+
}
|
|
184
|
+
log("");
|
|
185
|
+
log(
|
|
186
|
+
` ${green("\u2713")} Done! Restart your AI assistant and try: ${bold('"Use the health tool"')}`
|
|
187
|
+
);
|
|
188
|
+
log("");
|
|
189
|
+
}
|
|
190
|
+
async function writeConfig(client, apiKey) {
|
|
191
|
+
try {
|
|
192
|
+
const wrote = await writeClientConfig(client, apiKey);
|
|
193
|
+
if (wrote) {
|
|
194
|
+
log(` ${green("\u2713")} Wrote config to ${dim(client.configPath)}`);
|
|
195
|
+
} else {
|
|
196
|
+
log(` ${dim("\u2139")} ${client.name} already configured \u2014 skipped`);
|
|
197
|
+
}
|
|
198
|
+
} catch (err) {
|
|
199
|
+
log(` ${orange("!")} Could not write ${client.name} config: ${err.message}`);
|
|
200
|
+
printConfigSnippet(apiKey);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function printConfigSnippet(apiKey) {
|
|
204
|
+
log("");
|
|
205
|
+
log(bold(" Add this to your MCP client config:\n"));
|
|
206
|
+
const snippet = JSON.stringify(
|
|
207
|
+
{
|
|
208
|
+
mcpServers: {
|
|
209
|
+
productbrain: {
|
|
210
|
+
command: "npx",
|
|
211
|
+
args: ["-y", "productbrain"],
|
|
212
|
+
env: { PRODUCTBRAIN_API_KEY: apiKey }
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
null,
|
|
217
|
+
2
|
|
218
|
+
);
|
|
219
|
+
for (const line of snippet.split("\n")) {
|
|
220
|
+
log(` ${line}`);
|
|
221
|
+
}
|
|
222
|
+
log("");
|
|
223
|
+
}
|
|
224
|
+
export {
|
|
225
|
+
runSetup
|
|
226
|
+
};
|
|
227
|
+
//# sourceMappingURL=setup-K757L5KR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/setup.ts","../src/cli/config-writer.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * `npx productbrain setup`\n *\n * Guided onboarding: get API key from SynergyOS, paste it, and write MCP config.\n * No GitHub — keys come from SynergyOS → Settings → API Keys.\n */\n\nimport { createInterface } from \"node:readline\";\nimport { detectClients, writeClientConfig, type McpClientInfo } from \"./config-writer.js\";\n\nconst SYNERGYOS_APP_URL =\n process.env.SYNERGYOS_APP_URL ?? process.env.PRODUCTBRAIN_APP_URL ?? \"http://localhost:5173\";\n\n// ── Helpers ─────────────────────────────────────────────────────────────\n\nfunction bold(s: string) {\n return `\\x1b[1m${s}\\x1b[0m`;\n}\nfunction green(s: string) {\n return `\\x1b[32m${s}\\x1b[0m`;\n}\nfunction dim(s: string) {\n return `\\x1b[2m${s}\\x1b[0m`;\n}\nfunction orange(s: string) {\n return `\\x1b[33m${s}\\x1b[0m`;\n}\n\nfunction log(msg: string) {\n process.stdout.write(`${msg}\\n`);\n}\n\nfunction openBrowser(url: string) {\n const { execSync } = require(\"node:child_process\") as typeof import(\"node:child_process\");\n const platform = process.platform;\n try {\n if (platform === \"darwin\") execSync(`open \"${url}\"`);\n else if (platform === \"win32\") execSync(`start \"\" \"${url}\"`);\n else execSync(`xdg-open \"${url}\"`);\n } catch {\n log(dim(` Could not open browser automatically.`));\n log(` Open this URL manually: ${url}`);\n }\n}\n\nfunction prompt(question: string): Promise<string> {\n return new Promise((resolve) => {\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(question, (answer) => {\n rl.close();\n resolve(answer.trim());\n });\n });\n}\n\nfunction promptChoice(question: string, choices: string[]): Promise<number> {\n return new Promise((resolve) => {\n log(\"\");\n log(bold(question));\n choices.forEach((c, i) => log(` ${i + 1}) ${c}`));\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n rl.question(`\\n ${dim(\"Choice [1]:\")} `, (line) => {\n rl.close();\n const n = parseInt(line.trim(), 10);\n if (isNaN(n) || n < 1 || n > choices.length) {\n resolve(0);\n } else {\n resolve(n - 1);\n }\n });\n });\n}\n\n// ── Main ────────────────────────────────────────────────────────────────\n\nexport async function runSetup() {\n log(\"\");\n log(bold(` Product${orange(\"Brain\")} Setup`));\n log(dim(\" Connect your AI assistant to your knowledge base\\n\"));\n\n const apiKeysUrl = `${SYNERGYOS_APP_URL}/settings/api-keys`;\n\n log(` ${dim(\"1. Get your API key from SynergyOS\")}`);\n log(` ${dim(apiKeysUrl)}\\n`);\n\n const openNow = await prompt(` Open this URL in your browser? [Y/n]: `);\n if (openNow.toLowerCase() !== \"n\" && openNow.toLowerCase() !== \"no\") {\n openBrowser(apiKeysUrl);\n }\n\n log(\"\");\n log(` ${dim(\"2. Generate a key (if you don't have one), then copy it.\\n\")}`);\n\n const apiKey = await prompt(` Paste your API key (pb_sk_...): `);\n\n if (!apiKey || !apiKey.startsWith(\"pb_sk_\")) {\n log(` ${orange(\"!\")} Invalid key format. Keys start with pb_sk_.`);\n log(` Get one at ${apiKeysUrl}\\n`);\n process.exit(1);\n }\n\n log(` ${green(\"✓\")} Key received\\n`);\n\n // 3. Detect MCP clients and write config\n const clients = detectClients();\n\n if (clients.length === 0) {\n log(bold(\" No supported MCP clients detected.\\n\"));\n printConfigSnippet(apiKey);\n return;\n }\n\n const clientNames = clients.map((c) => c.name);\n const allOption =\n clients.length > 1\n ? [...clientNames, \"All of the above\", \"Just show me the config\"]\n : [...clientNames, \"Just show me the config\"];\n\n const choice = await promptChoice(\"Which AI assistant should I configure?\", allOption);\n\n if (choice === allOption.length - 1) {\n printConfigSnippet(apiKey);\n } else if (clients.length > 1 && choice === allOption.length - 2) {\n for (const client of clients) {\n await writeConfig(client, apiKey);\n }\n } else {\n await writeConfig(clients[choice], apiKey);\n }\n\n log(\"\");\n log(\n ` ${green(\"✓\")} Done! Restart your AI assistant and try: ${bold('\"Use the health tool\"')}`,\n );\n log(\"\");\n}\n\nasync function writeConfig(client: McpClientInfo, apiKey: string) {\n try {\n const wrote = await writeClientConfig(client, apiKey);\n if (wrote) {\n log(` ${green(\"✓\")} Wrote config to ${dim(client.configPath)}`);\n } else {\n log(` ${dim(\"ℹ\")} ${client.name} already configured — skipped`);\n }\n } catch (err: any) {\n log(` ${orange(\"!\")} Could not write ${client.name} config: ${err.message}`);\n printConfigSnippet(apiKey);\n }\n}\n\nfunction printConfigSnippet(apiKey: string) {\n log(\"\");\n log(bold(\" Add this to your MCP client config:\\n\"));\n const snippet = JSON.stringify(\n {\n mcpServers: {\n productbrain: {\n command: \"npx\",\n args: [\"-y\", \"productbrain\"],\n env: { PRODUCTBRAIN_API_KEY: apiKey },\n },\n },\n },\n null,\n 2,\n );\n for (const line of snippet.split(\"\\n\")) {\n log(` ${line}`);\n }\n log(\"\");\n}\n","/**\n * Multi-client MCP config detection and writer.\n *\n * Supports:\n * - Cursor: .cursor/mcp.json in cwd (project-level)\n * - Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)\n * %APPDATA%/Claude/claude_desktop_config.json (Windows)\n *\n * The writer reads existing config, merges the new server entry (never\n * overwrites existing entries), and writes back. Falls back to printing\n * a snippet for unsupported OS or unknown formats.\n */\n\nimport { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir, platform } from \"node:os\";\n\nexport interface McpClientInfo {\n name: string;\n configPath: string;\n}\n\nconst SERVER_ENTRY_KEY = \"productbrain\";\n\nfunction buildServerEntry(apiKey: string) {\n return {\n command: \"npx\",\n args: [\"-y\", \"productbrain\"],\n env: { PRODUCTBRAIN_API_KEY: apiKey },\n };\n}\n\n// ── Detection ───────────────────────────────────────────────────────────\n\nfunction getCursorConfigPath(): string {\n return join(process.cwd(), \".cursor\", \"mcp.json\");\n}\n\nfunction getClaudeDesktopConfigPath(): string | null {\n const os = platform();\n if (os === \"darwin\") {\n return join(\n homedir(),\n \"Library\",\n \"Application Support\",\n \"Claude\",\n \"claude_desktop_config.json\",\n );\n }\n if (os === \"win32\") {\n const appData = process.env.APPDATA ?? join(homedir(), \"AppData\", \"Roaming\");\n return join(appData, \"Claude\", \"claude_desktop_config.json\");\n }\n // Linux: no official Claude Desktop location yet\n return null;\n}\n\nfunction isCursorProject(): boolean {\n return existsSync(join(process.cwd(), \".cursor\")) || existsSync(join(process.cwd(), \".cursorignore\"));\n}\n\nfunction isClaudeDesktopInstalled(): boolean {\n const configPath = getClaudeDesktopConfigPath();\n if (!configPath) return false;\n // Check if the Claude directory exists (config file may not exist yet)\n return existsSync(dirname(configPath));\n}\n\nexport function detectClients(): McpClientInfo[] {\n const clients: McpClientInfo[] = [];\n\n if (isCursorProject()) {\n clients.push({ name: \"Cursor\", configPath: getCursorConfigPath() });\n }\n\n if (isClaudeDesktopInstalled()) {\n clients.push({\n name: \"Claude Desktop\",\n configPath: getClaudeDesktopConfigPath()!,\n });\n }\n\n return clients;\n}\n\n// ── Writing ─────────────────────────────────────────────────────────────\n\nfunction readJsonSafe(path: string): Record<string, any> {\n if (!existsSync(path)) return {};\n try {\n return JSON.parse(readFileSync(path, \"utf-8\"));\n } catch {\n return {};\n }\n}\n\n/**\n * Write or merge the productbrain server entry into a client config file.\n * Returns true if the config was written, false if already present.\n */\nexport async function writeClientConfig(\n client: McpClientInfo,\n apiKey: string,\n): Promise<boolean> {\n const config = readJsonSafe(client.configPath);\n\n const serversKey = \"mcpServers\";\n if (!config[serversKey]) config[serversKey] = {};\n\n // Don't overwrite an existing productbrain entry\n if (config[serversKey][SERVER_ENTRY_KEY]) {\n return false;\n }\n\n config[serversKey][SERVER_ENTRY_KEY] = buildServerEntry(apiKey);\n\n const dir = dirname(client.configPath);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n writeFileSync(client.configPath, JSON.stringify(config, null, 2) + \"\\n\", \"utf-8\");\n return true;\n}\n"],"mappings":"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","names":["platform"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@productbrain/mcp",
|
|
3
|
+
"version": "0.0.1-beta.0",
|
|
4
|
+
"description": "ProductBrain MCP server — single source of truth for product knowledge in Cursor, Claude Desktop, and any MCP-compatible AI assistant.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"productbrain": "dist/cli/index.js",
|
|
8
|
+
"synergyos-mcp": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist",
|
|
12
|
+
"README.md",
|
|
13
|
+
".env.mcp.example"
|
|
14
|
+
],
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=18.0.0"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsup",
|
|
20
|
+
"start": "node dist/index.js",
|
|
21
|
+
"dev": "tsx src/index.ts",
|
|
22
|
+
"typecheck": "tsc --noEmit",
|
|
23
|
+
"prepublishOnly": "npm run build",
|
|
24
|
+
"publish:beta": "npm publish --tag=beta --access=public",
|
|
25
|
+
"version:prerelease": "npm version prerelease"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"productbrain",
|
|
29
|
+
"synergyos",
|
|
30
|
+
"mcp",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"cursor",
|
|
33
|
+
"claude-desktop",
|
|
34
|
+
"product-management",
|
|
35
|
+
"knowledge-base",
|
|
36
|
+
"glossary",
|
|
37
|
+
"business-rules",
|
|
38
|
+
"terminology"
|
|
39
|
+
],
|
|
40
|
+
"author": "SynergyOS.ai",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/synergyai-os/productbrain.git"
|
|
45
|
+
},
|
|
46
|
+
"homepage": "https://github.com/synergyai-os/productbrain#readme",
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
49
|
+
"convex": "^1.32.0",
|
|
50
|
+
"posthog-node": "^5.24.17",
|
|
51
|
+
"zod": "^3.23.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^25.3.0",
|
|
55
|
+
"tsup": "^8.0.0",
|
|
56
|
+
"tsx": "^4.0.0",
|
|
57
|
+
"typescript": "^5.0.0"
|
|
58
|
+
}
|
|
59
|
+
}
|