@productbrain/mcp 0.0.1-beta.124 → 0.0.1-beta.12402
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 +5 -1
- package/README.md +67 -0
- package/dist/chunk-3U2ECUFG.js +1764 -0
- package/dist/chunk-3U2ECUFG.js.map +1 -0
- package/dist/chunk-V2WCCCRI.js +11948 -0
- package/dist/chunk-V2WCCCRI.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +1259 -163
- package/dist/http.js.map +1 -1
- package/dist/index.js +5 -25
- package/dist/index.js.map +1 -1
- package/dist/setup-OMHPPHKE.js +204 -0
- package/dist/setup-OMHPPHKE.js.map +1 -0
- package/dist/views/src/entry-cards/index.html +85 -60
- package/dist/views/src/graph-constellation/index.html +72 -47
- package/package.json +8 -8
- package/dist/chunk-2ZWGQ6PK.js +0 -278
- package/dist/chunk-2ZWGQ6PK.js.map +0 -1
- package/dist/chunk-SDLQPEK6.js +0 -11531
- package/dist/chunk-SDLQPEK6.js.map +0 -1
- package/dist/chunk-UUI7P743.js +0 -3647
- package/dist/chunk-UUI7P743.js.map +0 -1
- package/dist/setup-2JWIZ3QO.js +0 -297
- package/dist/setup-2JWIZ3QO.js.map +0 -1
- package/dist/smart-capture-LJ6JF5DC.js +0 -41
- package/dist/smart-capture-LJ6JF5DC.js.map +0 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
AGENT_KEY_PREFIX,
|
|
4
|
+
API_KEY_FORMAT_LINE,
|
|
5
|
+
API_KEY_PREFIX,
|
|
6
|
+
DEFAULT_CLOUD_URL,
|
|
7
|
+
MCP_NPX_PACKAGE,
|
|
8
|
+
PASTE_NOW,
|
|
9
|
+
apiKeysUrl,
|
|
10
|
+
isApiKeyShaped,
|
|
11
|
+
resolveClient,
|
|
12
|
+
warnOnProdFallthrough,
|
|
13
|
+
writeClientConfig
|
|
14
|
+
} from "./chunk-3U2ECUFG.js";
|
|
15
|
+
|
|
16
|
+
// src/cli/setup.ts
|
|
17
|
+
import { execSync } from "child_process";
|
|
18
|
+
import { createInterface } from "readline";
|
|
19
|
+
function bold(s) {
|
|
20
|
+
return `\x1B[1m${s}\x1B[0m`;
|
|
21
|
+
}
|
|
22
|
+
function green(s) {
|
|
23
|
+
return `\x1B[32m${s}\x1B[0m`;
|
|
24
|
+
}
|
|
25
|
+
function dim(s) {
|
|
26
|
+
return `\x1B[2m${s}\x1B[0m`;
|
|
27
|
+
}
|
|
28
|
+
function orange(s) {
|
|
29
|
+
return `\x1B[33m${s}\x1B[0m`;
|
|
30
|
+
}
|
|
31
|
+
function log(msg) {
|
|
32
|
+
process.stdout.write(`${msg}
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
function openBrowser(url) {
|
|
36
|
+
const platform = process.platform;
|
|
37
|
+
try {
|
|
38
|
+
if (platform === "darwin") execSync(`open "${url}"`);
|
|
39
|
+
else if (platform === "win32") execSync(`start "" "${url}"`);
|
|
40
|
+
else execSync(`xdg-open "${url}"`);
|
|
41
|
+
} catch {
|
|
42
|
+
log(dim(` Could not open browser automatically.`));
|
|
43
|
+
log(` Open this URL manually: ${url}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function prompt(question) {
|
|
47
|
+
return new Promise((resolve) => {
|
|
48
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
49
|
+
rl.question(question, (answer) => {
|
|
50
|
+
rl.close();
|
|
51
|
+
resolve(answer.trim());
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function promptChoice(question, choices) {
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
log("");
|
|
58
|
+
log(bold(question));
|
|
59
|
+
choices.forEach((c, i) => log(` ${i + 1}) ${c}`));
|
|
60
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
61
|
+
rl.question(`
|
|
62
|
+
${dim("Choice [1]:")} `, (line) => {
|
|
63
|
+
rl.close();
|
|
64
|
+
const n = parseInt(line.trim(), 10);
|
|
65
|
+
if (isNaN(n) || n < 1 || n > choices.length) {
|
|
66
|
+
resolve(0);
|
|
67
|
+
} else {
|
|
68
|
+
resolve(n - 1);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function resolveSetupSiteUrl() {
|
|
74
|
+
const explicit = process.env.CONVEX_SITE_URL ?? process.env.PRODUCTBRAIN_URL;
|
|
75
|
+
const url = explicit ?? DEFAULT_CLOUD_URL;
|
|
76
|
+
warnOnProdFallthrough(url, { explicit: explicit != null });
|
|
77
|
+
return url;
|
|
78
|
+
}
|
|
79
|
+
async function verifyWorkspace(apiKey) {
|
|
80
|
+
const siteUrl = resolveSetupSiteUrl();
|
|
81
|
+
try {
|
|
82
|
+
const res = await fetch(`${siteUrl.replace(/\/$/, "")}/api/aki`, {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers: {
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
Authorization: `Bearer ${apiKey}`
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({ fn: "resolveWorkspace", args: {} })
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) return null;
|
|
91
|
+
const json = await res.json();
|
|
92
|
+
return json.data ?? null;
|
|
93
|
+
} catch {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async function runSetup() {
|
|
98
|
+
log("");
|
|
99
|
+
log(bold(` Product${orange("Brain")} Setup`));
|
|
100
|
+
log(dim(" Connect your AI assistant to your chain\n"));
|
|
101
|
+
const keysUrl = apiKeysUrl();
|
|
102
|
+
log(` ${dim("1. Get your API key from Settings \u2192 API Keys")}`);
|
|
103
|
+
log(` ${dim(keysUrl)}
|
|
104
|
+
`);
|
|
105
|
+
const openNow = await prompt(` Open this URL in your browser? [Y/n]: `);
|
|
106
|
+
if (openNow.toLowerCase() !== "n" && openNow.toLowerCase() !== "no") {
|
|
107
|
+
openBrowser(keysUrl);
|
|
108
|
+
}
|
|
109
|
+
log("");
|
|
110
|
+
log(` ${dim("2. Generate a key (if you don't have one), then copy it.\n")}`);
|
|
111
|
+
const apiKey = await prompt(` Paste your API key (${API_KEY_PREFIX} or ${AGENT_KEY_PREFIX}): `);
|
|
112
|
+
if (!apiKey || !isApiKeyShaped(apiKey)) {
|
|
113
|
+
log(` ${orange("!")} ${API_KEY_FORMAT_LINE}`);
|
|
114
|
+
log(` Get one at ${keysUrl}
|
|
115
|
+
`);
|
|
116
|
+
process.exit(1);
|
|
117
|
+
}
|
|
118
|
+
log(` ${green("\u2713")} Key received`);
|
|
119
|
+
const workspace = await verifyWorkspace(apiKey);
|
|
120
|
+
if (workspace) {
|
|
121
|
+
log(` ${green("\u2713")} Connected to workspace: ${bold(workspace.name)} ${dim(`(${workspace.slug})`)}`);
|
|
122
|
+
} else {
|
|
123
|
+
log(` ${orange("!")} Could not verify workspace. Check your key at ${keysUrl}`);
|
|
124
|
+
}
|
|
125
|
+
log("");
|
|
126
|
+
const CLIENT_NAMES = ["Cursor", "Claude Desktop"];
|
|
127
|
+
const options = [...CLIENT_NAMES, "Other"];
|
|
128
|
+
const choice = await promptChoice("Where do you want to set up Product Brain?", options);
|
|
129
|
+
if (choice === 2) {
|
|
130
|
+
printConfigSnippet(apiKey);
|
|
131
|
+
} else {
|
|
132
|
+
const client = resolveClient(CLIENT_NAMES[choice]);
|
|
133
|
+
if (client) {
|
|
134
|
+
await writeConfig(client, apiKey);
|
|
135
|
+
} else {
|
|
136
|
+
log(` ${orange("!")} ${CLIENT_NAMES[choice]} config path not available on this platform.`);
|
|
137
|
+
printConfigSnippet(apiKey);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (choice === 0) printDeeplink(apiKey);
|
|
141
|
+
log("");
|
|
142
|
+
log(
|
|
143
|
+
` ${green("\u2713")} Done! Restart your AI assistant and try: ${bold(`"${PASTE_NOW}"`)}`
|
|
144
|
+
);
|
|
145
|
+
printHelpLink();
|
|
146
|
+
}
|
|
147
|
+
async function writeConfig(client, apiKey) {
|
|
148
|
+
try {
|
|
149
|
+
const wrote = await writeClientConfig(client, apiKey);
|
|
150
|
+
if (wrote) {
|
|
151
|
+
log(` ${green("\u2713")} Wrote config to ${dim(client.configPath)}`);
|
|
152
|
+
} else {
|
|
153
|
+
log(` ${dim("\u2139")} ${client.name} already configured \u2014 skipped`);
|
|
154
|
+
}
|
|
155
|
+
} catch (err) {
|
|
156
|
+
log(` ${orange("!")} Could not write ${client.name} config: ${err.message}`);
|
|
157
|
+
printConfigSnippet(apiKey);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function printHelpLink() {
|
|
161
|
+
log(` ${dim(`Need help? See ${apiKeysUrl()}`)}`);
|
|
162
|
+
log("");
|
|
163
|
+
}
|
|
164
|
+
function printConfigSnippet(apiKey) {
|
|
165
|
+
log("");
|
|
166
|
+
log(bold(" Add this to your MCP client config:\n"));
|
|
167
|
+
const snippet = JSON.stringify(
|
|
168
|
+
{
|
|
169
|
+
mcpServers: {
|
|
170
|
+
"Product Brain": {
|
|
171
|
+
command: "npx",
|
|
172
|
+
args: ["-y", MCP_NPX_PACKAGE],
|
|
173
|
+
env: { PRODUCTBRAIN_API_KEY: apiKey }
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
null,
|
|
178
|
+
2
|
|
179
|
+
);
|
|
180
|
+
for (const line of snippet.split("\n")) {
|
|
181
|
+
log(` ${line}`);
|
|
182
|
+
}
|
|
183
|
+
log("");
|
|
184
|
+
}
|
|
185
|
+
function buildDeeplink(apiKey) {
|
|
186
|
+
const config = JSON.stringify({
|
|
187
|
+
command: "npx",
|
|
188
|
+
args: ["-y", MCP_NPX_PACKAGE],
|
|
189
|
+
env: { PRODUCTBRAIN_API_KEY: apiKey }
|
|
190
|
+
});
|
|
191
|
+
const encoded = Buffer.from(config).toString("base64url");
|
|
192
|
+
return `cursor://anysphere.cursor-deeplink/mcp/install?name=${encodeURIComponent("Product Brain")}&config=${encoded}`;
|
|
193
|
+
}
|
|
194
|
+
function printDeeplink(apiKey) {
|
|
195
|
+
const link = buildDeeplink(apiKey);
|
|
196
|
+
log("");
|
|
197
|
+
log(` ${dim("One-click install for Cursor (paste in browser):")}`);
|
|
198
|
+
log(` ${link}`);
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
resolveSetupSiteUrl,
|
|
202
|
+
runSetup
|
|
203
|
+
};
|
|
204
|
+
//# sourceMappingURL=setup-OMHPPHKE.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 { DEFAULT_CLOUD_URL } from \"../client.js\";\nimport { apiKeysUrl } from \"../lib/appUrl.js\";\nimport { warnOnProdFallthrough } from \"../prod-fallthrough.js\";\nimport { PASTE_NOW } from \"../lib/ruleListRender.js\"; // TASK-1006: the one paste sentence\nimport { AGENT_KEY_PREFIX, API_KEY_FORMAT_LINE, API_KEY_PREFIX, isApiKeyShaped } from \"../lib/tokenConstants.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 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 (${API_KEY_PREFIX} or ${AGENT_KEY_PREFIX}): `);\n\n if (!apiKey || !isApiKeyShaped(apiKey)) {\n log(` ${orange(\"!\")} ${API_KEY_FORMAT_LINE}`);\n log(` Get one at ${keysUrl}\\n`);\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 } else {\n const client = resolveClient(CLIENT_NAMES[choice]);\n if (client) {\n await writeConfig(client, apiKey);\n } else {\n log(` ${orange(\"!\")} ${CLIENT_NAMES[choice]} config path not available on this platform.`);\n printConfigSnippet(apiKey);\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(`\"${PASTE_NOW}\"`)}`,\n );\n printHelpLink();\n}\n\nasync function writeConfig(\n client: McpClientInfo,\n apiKey: string,\n): Promise<void> {\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 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":[]}
|