@brainmcp/brainmcp 0.1.12 → 0.1.14
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 +79 -5
- package/dist/agent-config.js +155 -24
- package/dist/commands/auth.d.ts +47 -0
- package/dist/commands/auth.js +392 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/capture.d.ts +34 -0
- package/dist/commands/capture.js +349 -0
- package/dist/commands/capture.js.map +1 -0
- package/dist/commands/dispatch.d.ts +43 -0
- package/dist/commands/dispatch.js +287 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +198 -36
- package/dist/commands/index.js.map +1 -1
- package/dist/hooks/adapters.d.ts +14 -0
- package/dist/hooks/adapters.js +41 -0
- package/dist/hooks/adapters.js.map +1 -0
- package/dist/hooks/claude.d.ts +24 -0
- package/dist/hooks/claude.js +36 -0
- package/dist/hooks/claude.js.map +1 -0
- package/dist/hooks/codex.d.ts +18 -0
- package/dist/hooks/codex.js +36 -0
- package/dist/hooks/codex.js.map +1 -0
- package/dist/hooks/cursor.d.ts +22 -0
- package/dist/hooks/cursor.js +26 -0
- package/dist/hooks/cursor.js.map +1 -0
- package/dist/hooks/managed-hooks.d.ts +30 -0
- package/dist/hooks/managed-hooks.js +189 -0
- package/dist/hooks/managed-hooks.js.map +1 -0
- package/dist/hooks/vscode.d.ts +22 -0
- package/dist/hooks/vscode.js +27 -0
- package/dist/hooks/vscode.js.map +1 -0
- package/dist/index.js +7 -102
- package/dist/index.js.map +1 -1
- package/dist/lib/api-client.d.ts +32 -0
- package/dist/lib/api-client.js +207 -0
- package/dist/lib/api-client.js.map +1 -0
- package/dist/lib/callback-server.d.ts +17 -0
- package/dist/lib/callback-server.js +145 -0
- package/dist/lib/callback-server.js.map +1 -0
- package/dist/lib/cli-contracts.d.ts +193 -0
- package/dist/lib/cli-contracts.js +242 -0
- package/dist/lib/cli-contracts.js.map +1 -0
- package/dist/lib/config.d.ts +2 -0
- package/dist/lib/config.js +11 -0
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/credentials.d.ts +89 -0
- package/dist/lib/credentials.js +304 -0
- package/dist/lib/credentials.js.map +1 -0
- package/dist/lib/endpoints.d.ts +5 -0
- package/dist/lib/endpoints.js +31 -0
- package/dist/lib/endpoints.js.map +1 -0
- package/dist/lib/http.d.ts +3 -0
- package/dist/lib/http.js +51 -0
- package/dist/lib/http.js.map +1 -0
- package/dist/lib/managed.d.ts +8 -0
- package/dist/lib/managed.js +72 -6
- package/dist/lib/managed.js.map +1 -1
- package/dist/lib/oauth-client.d.ts +55 -0
- package/dist/lib/oauth-client.js +155 -0
- package/dist/lib/oauth-client.js.map +1 -0
- package/dist/lib/pkce.d.ts +14 -0
- package/dist/lib/pkce.js +33 -0
- package/dist/lib/pkce.js.map +1 -0
- package/dist/lib/vault.d.ts +26 -0
- package/dist/lib/vault.js +221 -0
- package/dist/lib/vault.js.map +1 -0
- package/dist/runtime/brainmcp-hook-runtime.mjs +3243 -0
- package/dist/runtime/capture.d.ts +83 -0
- package/dist/runtime/capture.js +332 -0
- package/dist/runtime/capture.js.map +1 -0
- package/dist/runtime/diagnostics.d.ts +7 -0
- package/dist/runtime/diagnostics.js +75 -0
- package/dist/runtime/diagnostics.js.map +1 -0
- package/dist/runtime/doctor-checks.d.ts +15 -0
- package/dist/runtime/doctor-checks.js +233 -0
- package/dist/runtime/doctor-checks.js.map +1 -0
- package/dist/runtime/flush.d.ts +30 -0
- package/dist/runtime/flush.js +193 -0
- package/dist/runtime/flush.js.map +1 -0
- package/dist/runtime/hook-dispatcher.d.ts +31 -0
- package/dist/runtime/hook-dispatcher.js +381 -0
- package/dist/runtime/hook-dispatcher.js.map +1 -0
- package/dist/runtime/index.d.ts +12 -0
- package/dist/runtime/index.js +69 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/installer.d.ts +26 -0
- package/dist/runtime/installer.js +134 -0
- package/dist/runtime/installer.js.map +1 -0
- package/dist/runtime/lock.d.ts +19 -0
- package/dist/runtime/lock.js +116 -0
- package/dist/runtime/lock.js.map +1 -0
- package/dist/runtime/orient.d.ts +55 -0
- package/dist/runtime/orient.js +256 -0
- package/dist/runtime/orient.js.map +1 -0
- package/dist/runtime/queue.d.ts +7 -0
- package/dist/runtime/queue.js +80 -0
- package/dist/runtime/queue.js.map +1 -0
- package/dist/runtime/retention.d.ts +26 -0
- package/dist/runtime/retention.js +175 -0
- package/dist/runtime/retention.js.map +1 -0
- package/dist/runtime/session.d.ts +68 -0
- package/dist/runtime/session.js +283 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/runtime/storage.d.ts +32 -0
- package/dist/runtime/storage.js +236 -0
- package/dist/runtime/storage.js.map +1 -0
- package/package.json +3 -2
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import { cwd, stdin, stdout } from 'node:process';
|
|
2
|
+
import { createInterface } from 'node:readline/promises';
|
|
3
|
+
import { BRAINMCP_CLI_PACKAGE_SPEC, BRAINMCP_GLOBAL_CLIENTS } from '../agent-config.js';
|
|
4
|
+
import { CLI_EXIT_CODES } from '../lib/cli-contracts.js';
|
|
5
|
+
import { assertClientId, CLIENT_IDS, clientLabel } from '../lib/config.js';
|
|
6
|
+
import { doctor, init, initAll, printConfig, remove, } from './index.js';
|
|
7
|
+
import { login, logout, whoami } from './auth.js';
|
|
8
|
+
import { runHookRuntimeCli } from '../runtime/index.js';
|
|
9
|
+
import { captureStatus, captureEnable, captureDisable, captureNow, capturePurgeLocal, capturePurgePreview, } from './capture.js';
|
|
10
|
+
export const HELP = `brainmcp — configure BrainMCP for agent projects and authenticate companion CLI
|
|
11
|
+
|
|
12
|
+
Recommended setup (supported agents, all projects):
|
|
13
|
+
npx --yes ${BRAINMCP_CLI_PACKAGE_SPEC} init --all --scope user
|
|
14
|
+
|
|
15
|
+
Usage:
|
|
16
|
+
brainmcp init [--client <client>] [--workspace <id>] [--scope project|user] [--no-hooks] [--write-back-nudge] [--yes]
|
|
17
|
+
brainmcp init --all [--workspace <id>] [--scope project|user] [--no-hooks] [--write-back-nudge] [--yes]
|
|
18
|
+
brainmcp doctor [--client <client>] [--workspace <id>] [--scope project|user]
|
|
19
|
+
brainmcp print [--client <client>] [--workspace <id>] [--scope project|user]
|
|
20
|
+
brainmcp remove [--client <client>] [--scope project|user] [--yes]
|
|
21
|
+
brainmcp login [--capture-digests] [--allow-file-credentials] [--service-token-stdin] [--store-service-token] [--force] [--json]
|
|
22
|
+
brainmcp logout [--json]
|
|
23
|
+
brainmcp whoami [--json]
|
|
24
|
+
brainmcp hook <client> <event>
|
|
25
|
+
brainmcp capture [enable|disable|status|now|purge-local] [--dry-run] [--workspace <id>] [--include-prompts] [--yes] [--json]
|
|
26
|
+
|
|
27
|
+
Clients: ${CLIENT_IDS.join(', ')}
|
|
28
|
+
--all configures ${BRAINMCP_GLOBAL_CLIENTS.map(clientLabel).join(', ')} (generic is client-specific).
|
|
29
|
+
Project scope is the default. User scope writes to each host's supported per-user locations.
|
|
30
|
+
Every mutation previews a diff and needs confirmation unless a trailing CLI --yes is supplied.
|
|
31
|
+
The leading npx --yes above accepts npm's package download; it does not skip the file preview.`;
|
|
32
|
+
export function parseCliArgs(args) {
|
|
33
|
+
const [command, ...rawOptions] = args;
|
|
34
|
+
const result = {
|
|
35
|
+
command,
|
|
36
|
+
yes: false,
|
|
37
|
+
all: false,
|
|
38
|
+
captureDigests: false,
|
|
39
|
+
force: false,
|
|
40
|
+
json: false,
|
|
41
|
+
noHooks: false,
|
|
42
|
+
writeBackNudge: false,
|
|
43
|
+
enable: false,
|
|
44
|
+
disable: false,
|
|
45
|
+
status: false,
|
|
46
|
+
dryRun: false,
|
|
47
|
+
purge: false,
|
|
48
|
+
includePrompts: false,
|
|
49
|
+
now: false,
|
|
50
|
+
allowFileCredentials: false,
|
|
51
|
+
serviceTokenStdin: false,
|
|
52
|
+
storeServiceToken: false,
|
|
53
|
+
};
|
|
54
|
+
for (let index = 0; index < rawOptions.length; index += 1) {
|
|
55
|
+
const option = rawOptions[index];
|
|
56
|
+
if (option === '--yes' || option === '-y')
|
|
57
|
+
result.yes = true;
|
|
58
|
+
else if (option === '--all')
|
|
59
|
+
result.all = true;
|
|
60
|
+
else if (option === '--capture-digests')
|
|
61
|
+
result.captureDigests = true;
|
|
62
|
+
else if (option === '--force')
|
|
63
|
+
result.force = true;
|
|
64
|
+
else if (option === '--json')
|
|
65
|
+
result.json = true;
|
|
66
|
+
else if (option === '--enable' || option === 'enable')
|
|
67
|
+
result.enable = true;
|
|
68
|
+
else if (option === '--disable' || option === 'disable')
|
|
69
|
+
result.disable = true;
|
|
70
|
+
else if (option === '--status' || option === 'status')
|
|
71
|
+
result.status = true;
|
|
72
|
+
else if (option === '--dry-run')
|
|
73
|
+
result.dryRun = true;
|
|
74
|
+
else if (option === '--purge' || option === 'purge-local')
|
|
75
|
+
result.purge = true;
|
|
76
|
+
else if (option === '--include-prompts')
|
|
77
|
+
result.includePrompts = true;
|
|
78
|
+
else if (option === '--now' || option === 'now')
|
|
79
|
+
result.now = true;
|
|
80
|
+
else if (option === '--allow-file-credentials')
|
|
81
|
+
result.allowFileCredentials = true;
|
|
82
|
+
else if (option === '--service-token-stdin')
|
|
83
|
+
result.serviceTokenStdin = true;
|
|
84
|
+
else if (option === '--store-service-token')
|
|
85
|
+
result.storeServiceToken = true;
|
|
86
|
+
else if (option === '--no-hooks')
|
|
87
|
+
result.noHooks = true;
|
|
88
|
+
else if (option === '--write-back-nudge')
|
|
89
|
+
result.writeBackNudge = true;
|
|
90
|
+
else if (option === '--client')
|
|
91
|
+
result.client = assertClientId(readValue(rawOptions, ++index, option));
|
|
92
|
+
else if (option === '--workspace')
|
|
93
|
+
result.workspace = readValue(rawOptions, ++index, option);
|
|
94
|
+
else if (option === '--scope') {
|
|
95
|
+
const scope = readValue(rawOptions, ++index, option);
|
|
96
|
+
if (scope !== 'project' && scope !== 'user')
|
|
97
|
+
throw new Error('--scope must be project or user.');
|
|
98
|
+
result.scope = scope;
|
|
99
|
+
}
|
|
100
|
+
else if (option === '--root')
|
|
101
|
+
result.root = readValue(rawOptions, ++index, option);
|
|
102
|
+
else
|
|
103
|
+
throw new Error(`Unknown option: ${option}`);
|
|
104
|
+
}
|
|
105
|
+
if (command === 'capture') {
|
|
106
|
+
const actions = [result.enable, result.disable, result.status, result.now, result.purge].filter(Boolean);
|
|
107
|
+
if (actions.length > 1) {
|
|
108
|
+
throw new Error('Choose exactly one capture action: enable, disable, status, now, or purge-local.');
|
|
109
|
+
}
|
|
110
|
+
const effectiveNow = result.now || (actions.length === 0 && result.dryRun);
|
|
111
|
+
if (result.dryRun && !effectiveNow) {
|
|
112
|
+
throw new Error('--dry-run is valid only with `capture now`.');
|
|
113
|
+
}
|
|
114
|
+
if (result.includePrompts && !result.enable) {
|
|
115
|
+
throw new Error('--include-prompts is valid only with `capture enable`.');
|
|
116
|
+
}
|
|
117
|
+
if (result.workspace && !result.enable && !effectiveNow) {
|
|
118
|
+
throw new Error('--workspace is valid only with `capture enable` or `capture now`.');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
function readValue(args, index, option) {
|
|
124
|
+
const value = args[index];
|
|
125
|
+
if (!value || value.startsWith('-'))
|
|
126
|
+
throw new Error(`${option} requires a value.`);
|
|
127
|
+
return value;
|
|
128
|
+
}
|
|
129
|
+
export async function defaultConfirm(message) {
|
|
130
|
+
if (!stdin.isTTY || !stdout.isTTY)
|
|
131
|
+
return false;
|
|
132
|
+
const readline = createInterface({ input: stdin, output: stdout });
|
|
133
|
+
try {
|
|
134
|
+
return (await readline.question(`${message} [y/N] `)).trim().toLowerCase() === 'y';
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
readline.close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export async function dispatch(rawArgs, context = {}) {
|
|
141
|
+
const output = context.output ?? console.log;
|
|
142
|
+
const confirmFn = context.confirm ?? defaultConfirm;
|
|
143
|
+
const currentRoot = context.cwd ?? cwd();
|
|
144
|
+
const [command] = rawArgs;
|
|
145
|
+
if (!command || command === '--help' || command === '-h' || command === 'help') {
|
|
146
|
+
output(HELP);
|
|
147
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
148
|
+
}
|
|
149
|
+
if (command === 'hook') {
|
|
150
|
+
await runHookRuntimeCli(rawArgs.slice(1));
|
|
151
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
152
|
+
}
|
|
153
|
+
let parsed;
|
|
154
|
+
try {
|
|
155
|
+
parsed = parseCliArgs(rawArgs);
|
|
156
|
+
}
|
|
157
|
+
catch (err) {
|
|
158
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
159
|
+
return CLI_EXIT_CODES.USAGE_ERROR;
|
|
160
|
+
}
|
|
161
|
+
if (parsed.all && parsed.client) {
|
|
162
|
+
console.error('Use either --all or --client, not both.');
|
|
163
|
+
return CLI_EXIT_CODES.USAGE_ERROR;
|
|
164
|
+
}
|
|
165
|
+
if (parsed.all && parsed.command !== 'init') {
|
|
166
|
+
console.error('--all is currently supported only by init.');
|
|
167
|
+
return CLI_EXIT_CODES.USAGE_ERROR;
|
|
168
|
+
}
|
|
169
|
+
const legacyOptions = {
|
|
170
|
+
root: parsed.root ?? currentRoot,
|
|
171
|
+
client: parsed.client,
|
|
172
|
+
workspace: parsed.workspace,
|
|
173
|
+
scope: parsed.scope ?? 'project',
|
|
174
|
+
yes: parsed.yes,
|
|
175
|
+
noHooks: parsed.noHooks,
|
|
176
|
+
writeBackNudge: parsed.writeBackNudge,
|
|
177
|
+
output,
|
|
178
|
+
confirm: confirmFn,
|
|
179
|
+
};
|
|
180
|
+
try {
|
|
181
|
+
switch (parsed.command) {
|
|
182
|
+
case 'init':
|
|
183
|
+
await (parsed.all ? initAll(legacyOptions) : init(legacyOptions));
|
|
184
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
185
|
+
case 'doctor':
|
|
186
|
+
await doctor(legacyOptions);
|
|
187
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
188
|
+
case 'print':
|
|
189
|
+
await printConfig(legacyOptions);
|
|
190
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
191
|
+
case 'remove':
|
|
192
|
+
await remove(legacyOptions);
|
|
193
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
194
|
+
case 'login':
|
|
195
|
+
if (parsed.serviceTokenStdin && parsed.captureDigests) {
|
|
196
|
+
console.error('Service credential login cannot be mixed with --capture-digests.');
|
|
197
|
+
return CLI_EXIT_CODES.USAGE_ERROR;
|
|
198
|
+
}
|
|
199
|
+
await login({
|
|
200
|
+
captureDigests: parsed.captureDigests,
|
|
201
|
+
force: parsed.force,
|
|
202
|
+
json: parsed.json,
|
|
203
|
+
allowFileCredentials: parsed.allowFileCredentials,
|
|
204
|
+
serviceTokenStdin: parsed.serviceTokenStdin,
|
|
205
|
+
storeServiceToken: parsed.storeServiceToken,
|
|
206
|
+
output,
|
|
207
|
+
openBrowser: context.openBrowser,
|
|
208
|
+
store: context.store,
|
|
209
|
+
oauthClient: context.oauthClient,
|
|
210
|
+
});
|
|
211
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
212
|
+
case 'logout':
|
|
213
|
+
await logout({
|
|
214
|
+
json: parsed.json,
|
|
215
|
+
output,
|
|
216
|
+
store: context.store,
|
|
217
|
+
oauthClient: context.oauthClient,
|
|
218
|
+
});
|
|
219
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
220
|
+
case 'whoami':
|
|
221
|
+
await whoami({
|
|
222
|
+
json: parsed.json,
|
|
223
|
+
output,
|
|
224
|
+
store: context.store,
|
|
225
|
+
apiClient: context.apiClient,
|
|
226
|
+
});
|
|
227
|
+
return CLI_EXIT_CODES.SUCCESS;
|
|
228
|
+
case 'capture': {
|
|
229
|
+
let result;
|
|
230
|
+
if (parsed.enable) {
|
|
231
|
+
result = await captureEnable({
|
|
232
|
+
baseDir: context.baseDir,
|
|
233
|
+
includePrompts: parsed.includePrompts,
|
|
234
|
+
workspace: parsed.workspace,
|
|
235
|
+
apiClient: context.apiClient,
|
|
236
|
+
store: context.store,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
else if (parsed.disable) {
|
|
240
|
+
result = captureDisable({ baseDir: context.baseDir });
|
|
241
|
+
}
|
|
242
|
+
else if (parsed.purge) {
|
|
243
|
+
const preview = capturePurgePreview({ baseDir: context.baseDir });
|
|
244
|
+
const previewText = `${preview.queueItems} queue item(s), ${preview.sessionLedgers} session ledger(s), and ${preview.orientationCacheFiles} orientation cache file(s)`;
|
|
245
|
+
const confirmed = parsed.yes || await confirmFn(`Delete ${previewText}? Credentials, preferences, and host configuration will be preserved.`);
|
|
246
|
+
result = confirmed
|
|
247
|
+
? capturePurgeLocal({ baseDir: context.baseDir })
|
|
248
|
+
: {
|
|
249
|
+
exitCode: CLI_EXIT_CODES.SUCCESS,
|
|
250
|
+
data: { purged: false, preview, message: 'Local capture purge cancelled; no files were deleted.' },
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
else if (parsed.now || parsed.dryRun) {
|
|
254
|
+
result = await captureNow({
|
|
255
|
+
dryRun: parsed.dryRun,
|
|
256
|
+
baseDir: context.baseDir,
|
|
257
|
+
cwd: currentRoot,
|
|
258
|
+
workspace: parsed.workspace,
|
|
259
|
+
apiClient: context.apiClient,
|
|
260
|
+
store: context.store,
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
result = captureStatus({ baseDir: context.baseDir, json: parsed.json });
|
|
265
|
+
}
|
|
266
|
+
if (parsed.json) {
|
|
267
|
+
output(JSON.stringify(result.data, null, 2));
|
|
268
|
+
}
|
|
269
|
+
else if (typeof result.data === 'object' && result.data !== null && 'message' in result.data) {
|
|
270
|
+
output(String(result.data.message));
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
output(JSON.stringify(result.data, null, 2));
|
|
274
|
+
}
|
|
275
|
+
return result.exitCode;
|
|
276
|
+
}
|
|
277
|
+
default:
|
|
278
|
+
console.error(`Unknown command: ${parsed.command}\n\n${HELP}`);
|
|
279
|
+
return CLI_EXIT_CODES.USAGE_ERROR;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
284
|
+
return CLI_EXIT_CODES.GENERAL_ERROR;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/commands/dispatch.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/index.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export type CommandOptions = {
|
|
|
5
5
|
workspace?: string;
|
|
6
6
|
scope: Scope;
|
|
7
7
|
yes: boolean;
|
|
8
|
+
noHooks?: boolean;
|
|
9
|
+
writeBackNudge?: boolean;
|
|
8
10
|
/** Test/embedding override. The CLI defaults to `os.homedir()`. */
|
|
9
11
|
home?: string;
|
|
10
12
|
/** Test/embedding override. The CLI defaults to `process.env`. */
|
|
@@ -22,3 +24,5 @@ export declare function initAll(options: CommandOptions): Promise<void>;
|
|
|
22
24
|
export declare function remove(options: CommandOptions): Promise<void>;
|
|
23
25
|
export declare function printConfig(options: CommandOptions): Promise<void>;
|
|
24
26
|
export declare function doctor(options: CommandOptions): Promise<void>;
|
|
27
|
+
export * from './auth.js';
|
|
28
|
+
export * from './dispatch.js';
|
package/dist/commands/index.js
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import { homedir } from 'node:os';
|
|
2
2
|
import { join, resolve } from 'node:path';
|
|
3
|
-
import { BRAIN_BOOTSTRAP_PROMPT, BRAIN_DOCS_URL, BRAIN_MCP_ENDPOINT, BRAIN_MCP_INITIAL_SCOPES, BRAIN_OAUTH_AUTH_METADATA_CANONICAL_URL, BRAIN_OAUTH_AUTH_METADATA_URL, BRAIN_OAUTH_ISSUER, BRAIN_OAUTH_RESOURCE_METADATA_COMPAT_URL, BRAIN_OAUTH_RESOURCE_METADATA_URL, BRAINMCP_CLI_CLIENTS, BRAINMCP_GLOBAL_CLIENTS, MCP_OAUTH_CLIENT_IDS, buildBrainmcpDoctorCommand, } from '../agent-config.js';
|
|
3
|
+
import { BRAIN_BOOTSTRAP_PROMPT, BRAIN_DOCS_URL, BRAIN_MCP_ENDPOINT, BRAIN_MCP_INITIAL_SCOPES, BRAIN_OAUTH_AUTH_METADATA_CANONICAL_URL, BRAIN_OAUTH_AUTH_METADATA_URL, BRAIN_OAUTH_ISSUER, BRAIN_OAUTH_RESOURCE_METADATA_COMPAT_URL, BRAIN_OAUTH_RESOURCE_METADATA_URL, BRAINMCP_CLI_CLIENTS, BRAINMCP_GLOBAL_CLIENTS, MCP_OAUTH_CLIENT_IDS, buildBrainmcpDoctorCommand, buildBrainmcpInitCommand, buildBrainVerificationPrompt, GUIDANCE_VERSION, } from '../agent-config.js';
|
|
4
4
|
import { clientLabel, guidancePreamble, renderGuidance, resolveWorkspace, targetFor, describeAntigravityServerConfig, } from '../lib/config.js';
|
|
5
5
|
import { applyChanges, exists, readText, renderDiff, toAbsolute } from '../lib/files.js';
|
|
6
|
-
import { parseJsonc, removeJsonServer, removeMarkdownBlock, removeTomlBlock, upsertJsonServer, upsertMarkdownBlock, upsertTomlBlock } from '../lib/managed.js';
|
|
6
|
+
import { parseJsonc, removeJsoncPath, removeJsonServer, removeMarkdownBlock, removeTomlBlock, upsertJsoncPath, upsertJsonServer, upsertMarkdownBlock, upsertTomlBlock } from '../lib/managed.js';
|
|
7
|
+
import { checkCredentialHealth, checkRuntimeDrift, checkConsentPreferences, checkQueueStatus, checkCompanionApiTarget } from '../runtime/doctor-checks.js';
|
|
8
|
+
import { companionWorkspacesUrl } from '../lib/endpoints.js';
|
|
9
|
+
import { getBrainHome } from '../runtime/storage.js';
|
|
10
|
+
import { cliPackageVersion, getVersionedRuntimePath, loadPackagedRuntimeBundle, } from '../runtime/installer.js';
|
|
11
|
+
import { removeClaudeManagedHooks, removeCodexManagedHooks, removeCursorManagedHooks, removeVsCodeManagedHooks, upsertClaudeManagedHooks, upsertCodexManagedHooks, upsertCursorManagedHooks, upsertVsCodeManagedHooks, } from '../hooks/managed-hooks.js';
|
|
7
12
|
export async function detectClients(root) {
|
|
8
13
|
const candidates = [
|
|
9
14
|
['cursor', ['.cursor', '.cursor/mcp.json']],
|
|
@@ -32,6 +37,7 @@ export async function chooseClient(options) {
|
|
|
32
37
|
}
|
|
33
38
|
export async function init(options) {
|
|
34
39
|
const client = await chooseClient(options);
|
|
40
|
+
await assertSingleMcpConfigScope(options, [client]);
|
|
35
41
|
const workspace = resolveWorkspace(options.workspace);
|
|
36
42
|
const changes = await plannedChanges(options, client, workspace, 'init');
|
|
37
43
|
await previewAndApply(changes, options);
|
|
@@ -40,6 +46,7 @@ export async function init(options) {
|
|
|
40
46
|
}
|
|
41
47
|
export async function initAll(options) {
|
|
42
48
|
const workspace = resolveWorkspace(options.workspace);
|
|
49
|
+
await assertSingleMcpConfigScope(options, BRAINMCP_GLOBAL_CLIENTS);
|
|
43
50
|
const groups = await Promise.all(BRAINMCP_GLOBAL_CLIENTS.map((client) => plannedChanges(options, client, workspace, 'init')));
|
|
44
51
|
await previewAndApply(mergeFileChanges(groups.flat()), options);
|
|
45
52
|
options.output(`BrainMCP configured for ${BRAINMCP_GLOBAL_CLIENTS.map(clientLabel).join(', ')}.`);
|
|
@@ -74,7 +81,9 @@ function renderSetupNextSteps(clients, scope, workspace) {
|
|
|
74
81
|
'3. Log in to brain from every client you plan to use:',
|
|
75
82
|
...authorizationSteps,
|
|
76
83
|
'4. In browser consent, review the scopes, select the workspace(s) this client may reach, and choose its default workspace.',
|
|
77
|
-
|
|
84
|
+
`5. Verify with a read-only agent prompt (guidance ${GUIDANCE_VERSION}):`,
|
|
85
|
+
` ${buildBrainVerificationPrompt({ workspaceId: workspace })}`,
|
|
86
|
+
' Confirm the dashboard Connect view shows Agent seen after a successful authenticated tool call.',
|
|
78
87
|
'6. If the workspace is empty, copy and paste this bootstrap command into the connected agent:',
|
|
79
88
|
...BRAIN_BOOTSTRAP_PROMPT.split('\n').map((line) => ` ${line}`),
|
|
80
89
|
'7. Follow the proposal status the agent reports. If it awaits Review, approve, edit, or reject it in the dashboard. The workspace is not populated until the proposal is applied.',
|
|
@@ -136,7 +145,20 @@ export async function doctor(options) {
|
|
|
136
145
|
}
|
|
137
146
|
if (guidance !== undefined) {
|
|
138
147
|
const occurrences = (guidance.match(/brainmcp:managed:start/g) ?? []).length;
|
|
139
|
-
|
|
148
|
+
const normalizedGuidance = guidance.replace(/\r\n/g, '\n');
|
|
149
|
+
const ends = (guidance.match(/brainmcp:managed:end/g) ?? []).length;
|
|
150
|
+
const blocks = normalizedGuidance.match(/<!-- brainmcp:managed:start[^\n]*-->[\s\S]*?<!-- brainmcp:managed:end -->/g) ?? [];
|
|
151
|
+
const validMarkers = occurrences === 1 && ends === 1 && blocks.length === 1;
|
|
152
|
+
checks.push(['managed guidance markers', validMarkers, validMarkers ? 'one complete managed block' : `${occurrences} starts, ${ends} ends, ${blocks.length} complete blocks`]);
|
|
153
|
+
const installedWorkspace = blocks[0]?.match(/^Workspace id: (.+)$/m)?.[1]?.trim();
|
|
154
|
+
const expectedWorkspace = resolveWorkspace(options.workspace) ?? installedWorkspace;
|
|
155
|
+
const expectedGuidance = renderGuidance(client, expectedWorkspace).trim();
|
|
156
|
+
const currentGuidance = validMarkers && blocks[0] === expectedGuidance;
|
|
157
|
+
checks.push([
|
|
158
|
+
'managed guidance content', currentGuidance,
|
|
159
|
+
currentGuidance ? `matches bundled guidance ${GUIDANCE_VERSION}` :
|
|
160
|
+
`outdated or modified; preview repair with ${buildBrainmcpInitCommand({ client, scope: options.scope, workspaceId: expectedWorkspace })}`,
|
|
161
|
+
]);
|
|
140
162
|
checks.push(['workspace binding', !options.workspace || guidance.includes(`Workspace id: ${resolveWorkspace(options.workspace)}`), options.workspace ? 'requested workspace binding' : 'no workspace requested']);
|
|
141
163
|
if ((client === 'vscode' || client === 'copilot') && options.scope === 'user') {
|
|
142
164
|
checks.push([
|
|
@@ -157,38 +179,18 @@ export async function doctor(options) {
|
|
|
157
179
|
]);
|
|
158
180
|
}
|
|
159
181
|
}
|
|
160
|
-
if (client
|
|
161
|
-
const otherScope = options.scope
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
`
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
else {
|
|
173
|
-
try {
|
|
174
|
-
const duplicated = hasBrainServerConfig(otherConfig, otherTarget);
|
|
175
|
-
checks.push([
|
|
176
|
-
'single MCP configuration scope',
|
|
177
|
-
!duplicated,
|
|
178
|
-
duplicated
|
|
179
|
-
? `brain is also configured at ${otherTarget.configPath}; keep it in only one scope`
|
|
180
|
-
: `no ${otherScope}-scope brain entry`,
|
|
181
|
-
]);
|
|
182
|
-
}
|
|
183
|
-
catch (error) {
|
|
184
|
-
checks.push([
|
|
185
|
-
'single MCP configuration scope',
|
|
186
|
-
false,
|
|
187
|
-
`cannot inspect ${otherTarget.configPath}: ${error instanceof Error ? error.message : String(error)}`,
|
|
188
|
-
]);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
}
|
|
182
|
+
if (requiresSingleMcpConfigScope(client)) {
|
|
183
|
+
const otherScope = oppositeScope(options.scope);
|
|
184
|
+
const duplicate = await inspectOtherMcpConfigScope(options, client);
|
|
185
|
+
checks.push([
|
|
186
|
+
'single MCP configuration scope',
|
|
187
|
+
duplicate.status === 'absent',
|
|
188
|
+
duplicate.status === 'present'
|
|
189
|
+
? `brain is also configured at ${duplicate.path}; keep it in only one scope`
|
|
190
|
+
: duplicate.status === 'invalid'
|
|
191
|
+
? `cannot inspect ${duplicate.path}: ${duplicate.error}`
|
|
192
|
+
: `no ${otherScope}-scope brain entry`,
|
|
193
|
+
]);
|
|
192
194
|
}
|
|
193
195
|
const fetchImpl = options.fetch ?? fetch;
|
|
194
196
|
for (const [name, url] of [
|
|
@@ -253,11 +255,90 @@ export async function doctor(options) {
|
|
|
253
255
|
catch (error) {
|
|
254
256
|
checks.push(['endpoint challenge', false, error instanceof Error ? error.message : String(error)]);
|
|
255
257
|
}
|
|
258
|
+
const apiOriginCheck = checkCompanionApiTarget();
|
|
259
|
+
checks.push([apiOriginCheck.name, apiOriginCheck.passed, apiOriginCheck.detail]);
|
|
260
|
+
try {
|
|
261
|
+
const workspacesUrl = companionWorkspacesUrl();
|
|
262
|
+
const workspaces = await fetchImpl(workspacesUrl, { headers: { accept: 'application/json' } });
|
|
263
|
+
const valid = workspaces.status === 401 || workspaces.status === 403;
|
|
264
|
+
checks.push([
|
|
265
|
+
'companion workspaces endpoint',
|
|
266
|
+
valid,
|
|
267
|
+
valid
|
|
268
|
+
? `HTTP ${workspaces.status} at ${workspacesUrl}`
|
|
269
|
+
: `HTTP ${workspaces.status} at ${workspacesUrl}; companion REST belongs on the API origin, not MCP`,
|
|
270
|
+
]);
|
|
271
|
+
}
|
|
272
|
+
catch (error) {
|
|
273
|
+
checks.push(['companion workspaces endpoint', false, error instanceof Error ? error.message : String(error)]);
|
|
274
|
+
}
|
|
275
|
+
const brainHome = options.home ? join(options.home, '.brainmcp') : getBrainHome();
|
|
276
|
+
const credCheck = await checkCredentialHealth(brainHome, { probeVault: !options.home });
|
|
277
|
+
checks.push([credCheck.name, credCheck.passed, credCheck.detail]);
|
|
278
|
+
const driftCheck = checkRuntimeDrift(cliPackageVersion(), brainHome);
|
|
279
|
+
checks.push([driftCheck.name, driftCheck.passed, driftCheck.detail]);
|
|
280
|
+
const consentCheck = checkConsentPreferences(brainHome);
|
|
281
|
+
checks.push([consentCheck.name, consentCheck.passed, consentCheck.detail]);
|
|
282
|
+
const queueCheck = checkQueueStatus(brainHome);
|
|
283
|
+
checks.push([queueCheck.name, queueCheck.passed, queueCheck.detail]);
|
|
256
284
|
for (const [name, passed, detail] of checks)
|
|
257
285
|
options.output(`${passed ? '✓' : '✗'} ${name}: ${detail}`);
|
|
258
286
|
if (checks.some(([, passed]) => !passed))
|
|
259
287
|
throw new Error('BrainMCP doctor found configuration issues.');
|
|
260
288
|
}
|
|
289
|
+
const SINGLE_SCOPE_MCP_CLIENTS = new Set([
|
|
290
|
+
'antigravity',
|
|
291
|
+
'codex',
|
|
292
|
+
'copilot',
|
|
293
|
+
'cursor',
|
|
294
|
+
'vscode',
|
|
295
|
+
]);
|
|
296
|
+
function requiresSingleMcpConfigScope(client) {
|
|
297
|
+
return SINGLE_SCOPE_MCP_CLIENTS.has(client);
|
|
298
|
+
}
|
|
299
|
+
function oppositeScope(scope) {
|
|
300
|
+
return scope === 'project' ? 'user' : 'project';
|
|
301
|
+
}
|
|
302
|
+
async function inspectOtherMcpConfigScope(options, client) {
|
|
303
|
+
const otherScope = oppositeScope(options.scope);
|
|
304
|
+
const currentTarget = resolveTarget(options, targetFor(client, options.scope));
|
|
305
|
+
const otherTarget = resolveTarget({ ...options, scope: otherScope }, targetFor(client, otherScope));
|
|
306
|
+
if (otherTarget.configPath === currentTarget.configPath) {
|
|
307
|
+
return { path: otherTarget.configPath, status: 'absent' };
|
|
308
|
+
}
|
|
309
|
+
const otherConfig = await readText(otherTarget.configPath);
|
|
310
|
+
if (otherConfig === undefined) {
|
|
311
|
+
return { path: otherTarget.configPath, status: 'absent' };
|
|
312
|
+
}
|
|
313
|
+
try {
|
|
314
|
+
return {
|
|
315
|
+
path: otherTarget.configPath,
|
|
316
|
+
status: hasBrainServerConfig(otherConfig, otherTarget) ? 'present' : 'absent',
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
return {
|
|
321
|
+
error: error instanceof Error ? error.message : String(error),
|
|
322
|
+
path: otherTarget.configPath,
|
|
323
|
+
status: 'invalid',
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
async function assertSingleMcpConfigScope(options, clients) {
|
|
328
|
+
for (const client of clients) {
|
|
329
|
+
if (!requiresSingleMcpConfigScope(client))
|
|
330
|
+
continue;
|
|
331
|
+
const duplicate = await inspectOtherMcpConfigScope(options, client);
|
|
332
|
+
if (duplicate.status === 'absent')
|
|
333
|
+
continue;
|
|
334
|
+
const otherScope = oppositeScope(options.scope);
|
|
335
|
+
if (duplicate.status === 'invalid') {
|
|
336
|
+
throw new Error(`Cannot inspect the existing ${clientLabel(client)} ${otherScope}-scope configuration at ${duplicate.path}: ${duplicate.error}`);
|
|
337
|
+
}
|
|
338
|
+
throw new Error(`Brain is already configured for ${clientLabel(client)} at ${duplicate.path} (${otherScope} scope). ` +
|
|
339
|
+
`Keep it in exactly one scope: run \`brainmcp remove --client ${client} --scope ${otherScope} --yes\`, then retry.`);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
261
342
|
function hasBrainServerConfig(config, target) {
|
|
262
343
|
if (target.format === 'toml') {
|
|
263
344
|
return /\[mcp_servers\.brain\]/.test(config);
|
|
@@ -411,6 +492,84 @@ async function plannedChanges(options, client, workspace, mode) {
|
|
|
411
492
|
}
|
|
412
493
|
}
|
|
413
494
|
}
|
|
495
|
+
const hookChanges = await plannedHookChanges(options, client, target, mode);
|
|
496
|
+
changes.push(...hookChanges);
|
|
497
|
+
return changes;
|
|
498
|
+
}
|
|
499
|
+
async function plannedHookChanges(options, client, target, mode) {
|
|
500
|
+
if (!target.supportsHooks || !target.hookPath)
|
|
501
|
+
return [];
|
|
502
|
+
if (mode === 'init' && options.noHooks)
|
|
503
|
+
return [];
|
|
504
|
+
const bundle = loadPackagedRuntimeBundle();
|
|
505
|
+
if (mode === 'init' && !bundle) {
|
|
506
|
+
throw new Error('The packaged BrainMCP hook runtime is missing. Reinstall or rebuild the CLI before enabling hooks.');
|
|
507
|
+
}
|
|
508
|
+
const home = options.home ?? homedir();
|
|
509
|
+
const brainHome = options.home ? join(options.home, '.brainmcp') : getBrainHome();
|
|
510
|
+
const version = cliPackageVersion();
|
|
511
|
+
const runtimePath = getVersionedRuntimePath(version, brainHome);
|
|
512
|
+
const hookFilePath = target.hookPath.startsWith('/')
|
|
513
|
+
? target.hookPath
|
|
514
|
+
: options.scope === 'user'
|
|
515
|
+
? join(home, target.hookPath)
|
|
516
|
+
: toAbsolute(options.root, target.hookPath);
|
|
517
|
+
const changes = [];
|
|
518
|
+
if (mode === 'init' && bundle) {
|
|
519
|
+
const existingRuntime = await readText(runtimePath);
|
|
520
|
+
if (existingRuntime !== bundle) {
|
|
521
|
+
changes.push({ path: runtimePath, before: existingRuntime, after: bundle });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
const existingHook = await readText(hookFilePath);
|
|
525
|
+
let parsed = {};
|
|
526
|
+
if (existingHook?.trim()) {
|
|
527
|
+
parsed = parseJsonc(existingHook);
|
|
528
|
+
}
|
|
529
|
+
const next = mode === 'init'
|
|
530
|
+
? client === 'claude-code'
|
|
531
|
+
? upsertClaudeManagedHooks(parsed, runtimePath, { enableNudge: Boolean(options.writeBackNudge) })
|
|
532
|
+
: client === 'cursor'
|
|
533
|
+
? upsertCursorManagedHooks(parsed, runtimePath)
|
|
534
|
+
: client === 'codex'
|
|
535
|
+
? upsertCodexManagedHooks(parsed, runtimePath)
|
|
536
|
+
: upsertVsCodeManagedHooks(parsed, runtimePath)
|
|
537
|
+
: client === 'claude-code'
|
|
538
|
+
? removeClaudeManagedHooks(parsed)
|
|
539
|
+
: client === 'cursor'
|
|
540
|
+
? removeCursorManagedHooks(parsed)
|
|
541
|
+
: client === 'codex'
|
|
542
|
+
? removeCodexManagedHooks(parsed)
|
|
543
|
+
: removeVsCodeManagedHooks(parsed);
|
|
544
|
+
const eventNames = client === 'claude-code'
|
|
545
|
+
? ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact', 'SessionEnd', 'Stop']
|
|
546
|
+
: client === 'cursor'
|
|
547
|
+
? ['sessionStart', 'beforeSubmitPrompt', 'postToolUse', 'afterAgentResponse', 'preCompact', 'sessionEnd']
|
|
548
|
+
: client === 'codex'
|
|
549
|
+
? ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact', 'SessionEnd']
|
|
550
|
+
: ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact'];
|
|
551
|
+
const nextRoot = next && typeof next === 'object' && !Array.isArray(next)
|
|
552
|
+
? next
|
|
553
|
+
: {};
|
|
554
|
+
const nextHooks = nextRoot.hooks && typeof nextRoot.hooks === 'object' && !Array.isArray(nextRoot.hooks)
|
|
555
|
+
? nextRoot.hooks
|
|
556
|
+
: {};
|
|
557
|
+
let after = existingHook ?? '{}\n';
|
|
558
|
+
if (client === 'cursor' && mode === 'init') {
|
|
559
|
+
after = upsertJsoncPath(after, ['version'], 1);
|
|
560
|
+
}
|
|
561
|
+
for (const eventName of eventNames) {
|
|
562
|
+
const value = nextHooks[eventName];
|
|
563
|
+
after = value === undefined
|
|
564
|
+
? removeJsoncPath(after, ['hooks', eventName])
|
|
565
|
+
: upsertJsoncPath(after, ['hooks', eventName], value);
|
|
566
|
+
}
|
|
567
|
+
const meaningfulRootKeys = Object.keys(nextRoot).filter((key) => key !== 'version');
|
|
568
|
+
if (mode === 'remove' && meaningfulRootKeys.length === 0)
|
|
569
|
+
after = undefined;
|
|
570
|
+
if (existingHook !== after) {
|
|
571
|
+
changes.push({ path: hookFilePath, before: existingHook, after });
|
|
572
|
+
}
|
|
414
573
|
return changes;
|
|
415
574
|
}
|
|
416
575
|
function resolveTarget(options, target) {
|
|
@@ -422,6 +581,7 @@ function resolveTarget(options, target) {
|
|
|
422
581
|
...target,
|
|
423
582
|
configPath: join(codexHome, 'config.toml'),
|
|
424
583
|
guidancePath: join(codexHome, 'AGENTS.md'),
|
|
584
|
+
hookPath: join(codexHome, 'hooks.json'),
|
|
425
585
|
format: target.configFormat,
|
|
426
586
|
rootKey: target.configRootKey,
|
|
427
587
|
};
|
|
@@ -500,4 +660,6 @@ async function previewAndApply(changes, options) {
|
|
|
500
660
|
? `Applied changes with atomic per-file writes. Backups: ${backups.join(', ')}`
|
|
501
661
|
: 'Applied changes with atomic per-file writes.');
|
|
502
662
|
}
|
|
663
|
+
export * from './auth.js';
|
|
664
|
+
export * from './dispatch.js';
|
|
503
665
|
//# sourceMappingURL=index.js.map
|