@productbrain/mcp 0.0.1-beta.997 → 0.0.1-beta.9975
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 +67 -0
- package/dist/chunk-LZ4MFWIE.js +12881 -0
- package/dist/chunk-LZ4MFWIE.js.map +1 -0
- package/dist/chunk-XEKHBSS7.js +1690 -0
- package/dist/chunk-XEKHBSS7.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +504 -265
- package/dist/http.js.map +1 -1
- package/dist/index.js +8 -8
- package/dist/{setup-RYYXRDPB.js → setup-T3VRWZ4S.js} +20 -104
- package/dist/setup-T3VRWZ4S.js.map +1 -0
- package/dist/views/src/entry-cards/index.html +97 -72
- package/dist/views/src/graph-constellation/index.html +90 -65
- package/package.json +4 -3
- package/dist/chunk-CIHITLKC.js +0 -15293
- package/dist/chunk-CIHITLKC.js.map +0 -1
- package/dist/chunk-YMF3IQ5E.js +0 -465
- package/dist/chunk-YMF3IQ5E.js.map +0 -1
- package/dist/setup-RYYXRDPB.js.map +0 -1
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
DEFAULT_CLOUD_URL,
|
|
3
4
|
MCP_NPX_PACKAGE,
|
|
5
|
+
apiKeysUrl,
|
|
4
6
|
initAnalytics,
|
|
5
7
|
resolveClient,
|
|
6
8
|
shutdownAnalytics,
|
|
7
9
|
trackSetupCompleted,
|
|
8
10
|
trackSetupStarted,
|
|
11
|
+
warnOnProdFallthrough,
|
|
9
12
|
writeClientConfig
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-XEKHBSS7.js";
|
|
11
14
|
|
|
12
15
|
// src/cli/setup.ts
|
|
13
16
|
import { execSync } from "child_process";
|
|
14
17
|
import { createInterface } from "readline";
|
|
15
|
-
import { existsSync, writeFileSync, mkdirSync } from "fs";
|
|
16
|
-
import { join } from "path";
|
|
17
|
-
var APP_URL = process.env.PRODUCTBRAIN_APP_URL ?? "https://work.productbrain.io";
|
|
18
18
|
function bold(s) {
|
|
19
19
|
return `\x1B[1m${s}\x1B[0m`;
|
|
20
20
|
}
|
|
@@ -69,9 +69,14 @@ function promptChoice(question, choices) {
|
|
|
69
69
|
});
|
|
70
70
|
});
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
function resolveSetupSiteUrl() {
|
|
73
|
+
const explicit = process.env.CONVEX_SITE_URL ?? process.env.PRODUCTBRAIN_URL;
|
|
74
|
+
const url = explicit ?? DEFAULT_CLOUD_URL;
|
|
75
|
+
warnOnProdFallthrough(url, { explicit: explicit != null });
|
|
76
|
+
return url;
|
|
77
|
+
}
|
|
73
78
|
async function verifyWorkspace(apiKey) {
|
|
74
|
-
const siteUrl =
|
|
79
|
+
const siteUrl = resolveSetupSiteUrl();
|
|
75
80
|
try {
|
|
76
81
|
const res = await fetch(`${siteUrl.replace(/\/$/, "")}/api/aki`, {
|
|
77
82
|
method: "POST",
|
|
@@ -94,20 +99,20 @@ async function runSetup() {
|
|
|
94
99
|
log("");
|
|
95
100
|
log(bold(` Product${orange("Brain")} Setup`));
|
|
96
101
|
log(dim(" Connect your AI assistant to your chain\n"));
|
|
97
|
-
const
|
|
102
|
+
const keysUrl = apiKeysUrl();
|
|
98
103
|
log(` ${dim("1. Get your API key from Settings \u2192 API Keys")}`);
|
|
99
|
-
log(` ${dim(
|
|
104
|
+
log(` ${dim(keysUrl)}
|
|
100
105
|
`);
|
|
101
106
|
const openNow = await prompt(` Open this URL in your browser? [Y/n]: `);
|
|
102
107
|
if (openNow.toLowerCase() !== "n" && openNow.toLowerCase() !== "no") {
|
|
103
|
-
openBrowser(
|
|
108
|
+
openBrowser(keysUrl);
|
|
104
109
|
}
|
|
105
110
|
log("");
|
|
106
111
|
log(` ${dim("2. Generate a key (if you don't have one), then copy it.\n")}`);
|
|
107
112
|
const apiKey = await prompt(` Paste your API key (pb_sk_...): `);
|
|
108
113
|
if (!apiKey || !apiKey.startsWith("pb_sk_")) {
|
|
109
114
|
log(` ${orange("!")} Invalid key format. Keys start with pb_sk_.`);
|
|
110
|
-
log(` Get one at ${
|
|
115
|
+
log(` Get one at ${keysUrl}
|
|
111
116
|
`);
|
|
112
117
|
await shutdownAnalytics();
|
|
113
118
|
process.exit(1);
|
|
@@ -117,7 +122,7 @@ async function runSetup() {
|
|
|
117
122
|
if (workspace) {
|
|
118
123
|
log(` ${green("\u2713")} Connected to workspace: ${bold(workspace.name)} ${dim(`(${workspace.slug})`)}`);
|
|
119
124
|
} else {
|
|
120
|
-
log(` ${orange("!")} Could not verify workspace. Check your key at ${
|
|
125
|
+
log(` ${orange("!")} Could not verify workspace. Check your key at ${keysUrl}`);
|
|
121
126
|
}
|
|
122
127
|
log("");
|
|
123
128
|
const CLIENT_NAMES = ["Cursor", "Claude Desktop"];
|
|
@@ -137,13 +142,7 @@ async function runSetup() {
|
|
|
137
142
|
trackSetupCompleted(CLIENT_NAMES[choice], "write_error");
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
|
-
if (choice === 0)
|
|
141
|
-
await offerCursorRulesInstall();
|
|
142
|
-
printDeeplink(apiKey);
|
|
143
|
-
}
|
|
144
|
-
if (choice === 1) {
|
|
145
|
-
printClaudeSnippet();
|
|
146
|
-
}
|
|
145
|
+
if (choice === 0) printDeeplink(apiKey);
|
|
147
146
|
log("");
|
|
148
147
|
log(
|
|
149
148
|
` ${green("\u2713")} Done! Restart your AI assistant and try: ${bold('"Start PB"')}`
|
|
@@ -168,7 +167,7 @@ async function writeConfig(client, apiKey) {
|
|
|
168
167
|
}
|
|
169
168
|
}
|
|
170
169
|
function printHelpLink() {
|
|
171
|
-
log(` ${dim(`Need help? See ${
|
|
170
|
+
log(` ${dim(`Need help? See ${apiKeysUrl()}`)}`);
|
|
172
171
|
log("");
|
|
173
172
|
}
|
|
174
173
|
function printConfigSnippet(apiKey) {
|
|
@@ -192,79 +191,6 @@ function printConfigSnippet(apiKey) {
|
|
|
192
191
|
}
|
|
193
192
|
log("");
|
|
194
193
|
}
|
|
195
|
-
var CURSOR_RULE_FILENAME = "product-brain.mdc";
|
|
196
|
-
var CURSOR_RULE_CONTENT = `---
|
|
197
|
-
description: Product Brain MCP \u2014 single source of truth for product knowledge
|
|
198
|
-
globs:
|
|
199
|
-
alwaysApply: true
|
|
200
|
-
---
|
|
201
|
-
|
|
202
|
-
# Product Brain MCP
|
|
203
|
-
|
|
204
|
-
Product Brain is your product knowledge base. The Chain is the single source of truth.
|
|
205
|
-
|
|
206
|
-
Every entry is either a **draft** (captured but not committed) or **committed** (on the Chain, SSOT).
|
|
207
|
-
Committing to the Chain is the compounding act.
|
|
208
|
-
|
|
209
|
-
## Quick Start
|
|
210
|
-
|
|
211
|
-
Say **"Start PB"** or **"Start Product Brain"** to begin. This single call:
|
|
212
|
-
- Orients you to the workspace (readiness, gaps, planned work)
|
|
213
|
-
- Unlocks write tools for the session
|
|
214
|
-
- Surfaces your next recommended action
|
|
215
|
-
|
|
216
|
-
## Tool Workflow
|
|
217
|
-
|
|
218
|
-
1. **Start here**: \`start\` \u2014 workspace context + next action
|
|
219
|
-
2. **Search**: \`entries action=search\` \u2014 find entries across all collections
|
|
220
|
-
3. **Drill in**: \`entries action=get\` \u2014 full record with data, labels, relations
|
|
221
|
-
4. **Context**: \`context action=gather\` \u2014 related knowledge around an entry or task
|
|
222
|
-
5. **Capture**: \`capture\` \u2014 create knowledge with auto-linking + quality score
|
|
223
|
-
6. **Commit**: \`commit-entry\` \u2014 promote drafts to SSOT when confirmation is still required
|
|
224
|
-
7. **Connect**: \`graph action=suggest\` then \`relations action=create\` to build the graph
|
|
225
|
-
|
|
226
|
-
## Bulk Knowledge Input
|
|
227
|
-
|
|
228
|
-
When given a document or batch of knowledge to capture:
|
|
229
|
-
1. Scan the input \u2014 identify all collections needed
|
|
230
|
-
2. Call \`collections action=list\` \u2014 compare against what exists
|
|
231
|
-
3. Propose missing collections to the user for confirmation
|
|
232
|
-
4. Call \`collections action=create\` for each confirmed collection
|
|
233
|
-
5. Then capture entries into the correct collections
|
|
234
|
-
|
|
235
|
-
Never stuff entries into the wrong collection. Never silently skip knowledge.
|
|
236
|
-
|
|
237
|
-
## Rules
|
|
238
|
-
|
|
239
|
-
- In Open mode, user-authored captures can commit immediately unless the user asks to keep them as drafts.
|
|
240
|
-
- In consensus/role modes, only call \`commit-entry\` when the user confirms.
|
|
241
|
-
- Use \`graph action=suggest\` after capturing to discover and create relations.
|
|
242
|
-
- Collections are dynamic \u2014 use \`collections action=create\` when the workspace needs new ones.
|
|
243
|
-
- When lost, fetch \`productbrain://orientation\` for the full system map.
|
|
244
|
-
`;
|
|
245
|
-
function isCursorProject() {
|
|
246
|
-
return existsSync(join(process.cwd(), ".cursor")) || existsSync(join(process.cwd(), ".cursorignore"));
|
|
247
|
-
}
|
|
248
|
-
async function offerCursorRulesInstall() {
|
|
249
|
-
if (!isCursorProject()) return;
|
|
250
|
-
const answer = await prompt(`
|
|
251
|
-
Install Product Brain rule for Cursor? [Y/n]: `);
|
|
252
|
-
if (answer.toLowerCase() === "n" || answer.toLowerCase() === "no") {
|
|
253
|
-
log(dim(" Skipped rule install."));
|
|
254
|
-
return;
|
|
255
|
-
}
|
|
256
|
-
const rulesDir = join(process.cwd(), ".cursor", "rules");
|
|
257
|
-
const rulePath = join(rulesDir, CURSOR_RULE_FILENAME);
|
|
258
|
-
if (existsSync(rulePath)) {
|
|
259
|
-
log(` ${dim("\u2139")} Rule already exists at ${dim(rulePath)} \u2014 skipped`);
|
|
260
|
-
return;
|
|
261
|
-
}
|
|
262
|
-
if (!existsSync(rulesDir)) {
|
|
263
|
-
mkdirSync(rulesDir, { recursive: true });
|
|
264
|
-
}
|
|
265
|
-
writeFileSync(rulePath, CURSOR_RULE_CONTENT, "utf-8");
|
|
266
|
-
log(` ${green("\u2713")} Installed rule at ${dim(rulePath)}`);
|
|
267
|
-
}
|
|
268
194
|
function buildDeeplink(apiKey) {
|
|
269
195
|
const config = JSON.stringify({
|
|
270
196
|
command: "npx",
|
|
@@ -280,18 +206,8 @@ function printDeeplink(apiKey) {
|
|
|
280
206
|
log(` ${dim("One-click install for Cursor (paste in browser):")}`);
|
|
281
207
|
log(` ${link}`);
|
|
282
208
|
}
|
|
283
|
-
function printClaudeSnippet() {
|
|
284
|
-
log("");
|
|
285
|
-
log(bold(" For Claude Code / CLAUDE.md:"));
|
|
286
|
-
log(dim(" Add this line to your ~/.claude/CLAUDE.md:"));
|
|
287
|
-
log("");
|
|
288
|
-
log(` When Product Brain MCP is available, say "Start PB" at the beginning`);
|
|
289
|
-
log(` of each session to orient to the workspace and unlock write tools.`);
|
|
290
|
-
log(` In Open mode, user-authored captures can commit immediately unless the user asks to keep drafts.`);
|
|
291
|
-
log(` In consensus/role modes, only commit when the user confirms.`);
|
|
292
|
-
log("");
|
|
293
|
-
}
|
|
294
209
|
export {
|
|
210
|
+
resolveSetupSiteUrl,
|
|
295
211
|
runSetup
|
|
296
212
|
};
|
|
297
|
-
//# sourceMappingURL=setup-
|
|
213
|
+
//# sourceMappingURL=setup-T3VRWZ4S.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/setup.ts"],"sourcesContent":["#!/usr/bin/env node\n\n/**\n * `npx @productbrain/mcp@beta setup`\n *\n * Guided onboarding: get API key from the app, paste it, write MCP config.\n */\n\nimport { execSync } from \"node:child_process\";\nimport { createInterface } from \"node:readline\";\nimport { resolveClient, writeClientConfig, MCP_NPX_PACKAGE, type McpClientInfo } from \"./config-writer.js\";\nimport { initAnalytics, trackSetupStarted, trackSetupCompleted, shutdownAnalytics } from \"../analytics.js\";\nimport { DEFAULT_CLOUD_URL } from \"../client.js\";\nimport { apiKeysUrl } from \"../lib/appUrl.js\";\nimport { warnOnProdFallthrough } from \"../prod-fallthrough.js\";\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 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// ── Workspace Verification ───────────────────────────────────────────────\n\n/**\n * Resolve the gateway URL the setup flow probes. TEN-2382: setup is an\n * independent entry point (no bootstrap), so it warns on silent prod\n * fall-through here. DEFAULT_CLOUD_URL is imported from client.ts (the\n * in-package SSOT) — no local re-declare.\n */\nexport function resolveSetupSiteUrl(): string {\n const explicit = process.env.CONVEX_SITE_URL ?? process.env.PRODUCTBRAIN_URL;\n const url = explicit ?? DEFAULT_CLOUD_URL;\n warnOnProdFallthrough(url, { explicit: explicit != null });\n return url;\n}\n\nasync function verifyWorkspace(\n apiKey: string,\n): Promise<{ name: string; slug: string } | null> {\n const siteUrl = resolveSetupSiteUrl();\n\n try {\n const res = await fetch(`${siteUrl.replace(/\\/$/, \"\")}/api/aki`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ fn: \"resolveWorkspace\", args: {} }),\n });\n\n if (!res.ok) return null;\n const json = (await res.json()) as {\n data?: { name: string; slug: string } | null;\n error?: string;\n };\n return json.data ?? null;\n } catch {\n return null;\n }\n}\n\n// ── Main ────────────────────────────────────────────────────────────────\n\nexport async function runSetup() {\n initAnalytics();\n trackSetupStarted();\n\n log(\"\");\n log(bold(` Product${orange(\"Brain\")} Setup`));\n log(dim(\" Connect your AI assistant to your chain\\n\"));\n\n const keysUrl = apiKeysUrl();\n\n log(` ${dim(\"1. Get your API key from Settings → API Keys\")}`);\n log(` ${dim(keysUrl)}\\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(keysUrl);\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 ${keysUrl}\\n`);\n await shutdownAnalytics();\n process.exit(1);\n }\n\n log(` ${green(\"✓\")} Key received`);\n\n const workspace = await verifyWorkspace(apiKey);\n if (workspace) {\n log(` ${green(\"✓\")} Connected to workspace: ${bold(workspace.name)} ${dim(`(${workspace.slug})`)}`);\n } else {\n log(` ${orange(\"!\")} Could not verify workspace. Check your key at ${keysUrl}`);\n }\n log(\"\");\n\n const CLIENT_NAMES = [\"Cursor\", \"Claude Desktop\"] as const;\n const options = [...CLIENT_NAMES, \"Other\"];\n\n const choice = await promptChoice(\"Where do you want to set up Product Brain?\", options);\n\n if (choice === 2) {\n printConfigSnippet(apiKey);\n trackSetupCompleted(\"Other\", \"snippet_shown\");\n } else {\n const client = resolveClient(CLIENT_NAMES[choice]);\n if (client) {\n const outcome = await writeConfig(client, apiKey);\n trackSetupCompleted(CLIENT_NAMES[choice], outcome);\n } else {\n log(` ${orange(\"!\")} ${CLIENT_NAMES[choice]} config path not available on this platform.`);\n printConfigSnippet(apiKey);\n trackSetupCompleted(CLIENT_NAMES[choice], \"write_error\");\n }\n }\n\n // TASK-670 (WP-820, DEC-1863): no Cursor rule file and no CLAUDE.md snippet; the connector's\n // session start teaches the agent how to work here, one source.\n if (choice === 0) printDeeplink(apiKey);\n\n log(\"\");\n log(\n ` ${green(\"✓\")} Done! Restart your AI assistant and try: ${bold('\"Start PB\"')}`,\n );\n printHelpLink();\n await shutdownAnalytics();\n}\n\nasync function writeConfig(\n client: McpClientInfo,\n apiKey: string,\n): Promise<\"config_written\" | \"config_existed\" | \"write_error\"> {\n try {\n const wrote = await writeClientConfig(client, apiKey);\n if (wrote) {\n log(` ${green(\"✓\")} Wrote config to ${dim(client.configPath)}`);\n return \"config_written\";\n } else {\n log(` ${dim(\"ℹ\")} ${client.name} already configured — skipped`);\n return \"config_existed\";\n }\n } catch (err: any) {\n log(` ${orange(\"!\")} Could not write ${client.name} config: ${err.message}`);\n printConfigSnippet(apiKey);\n return \"write_error\";\n }\n}\n\nfunction printHelpLink() {\n log(` ${dim(`Need help? See ${apiKeysUrl()}`)}`);\n log(\"\");\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 \"Product Brain\": {\n command: \"npx\",\n args: [\"-y\", MCP_NPX_PACKAGE],\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\nfunction buildDeeplink(apiKey: string): string {\n const config = JSON.stringify({\n command: \"npx\",\n args: [\"-y\", MCP_NPX_PACKAGE],\n env: { PRODUCTBRAIN_API_KEY: apiKey },\n });\n const encoded = Buffer.from(config).toString(\"base64url\");\n return `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent(\"Product Brain\")}&config=${encoded}`;\n}\n\nfunction printDeeplink(apiKey: string): void {\n const link = buildDeeplink(apiKey);\n log(\"\");\n log(` ${dim(\"One-click install for Cursor (paste in browser):\")}`);\n log(` ${link}`);\n}\n\n"],"mappings":"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","names":[]}
|