@brainmcp/brainmcp 0.1.12 → 0.1.13
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 +72 -5
- package/dist/agent-config.js +153 -24
- package/dist/commands/auth.d.ts +47 -0
- package/dist/commands/auth.js +390 -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 +180 -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 +203 -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/http.d.ts +3 -0
- package/dist/lib/http.js +50 -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 +154 -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 +3211 -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 +14 -0
- package/dist/runtime/doctor-checks.js +205 -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 +255 -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 +12 -10
|
@@ -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,13 @@
|
|
|
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 } from '../runtime/doctor-checks.js';
|
|
8
|
+
import { getBrainHome } from '../runtime/storage.js';
|
|
9
|
+
import { cliPackageVersion, getVersionedRuntimePath, loadPackagedRuntimeBundle, } from '../runtime/installer.js';
|
|
10
|
+
import { removeClaudeManagedHooks, removeCodexManagedHooks, removeCursorManagedHooks, removeVsCodeManagedHooks, upsertClaudeManagedHooks, upsertCodexManagedHooks, upsertCursorManagedHooks, upsertVsCodeManagedHooks, } from '../hooks/managed-hooks.js';
|
|
7
11
|
export async function detectClients(root) {
|
|
8
12
|
const candidates = [
|
|
9
13
|
['cursor', ['.cursor', '.cursor/mcp.json']],
|
|
@@ -32,6 +36,7 @@ export async function chooseClient(options) {
|
|
|
32
36
|
}
|
|
33
37
|
export async function init(options) {
|
|
34
38
|
const client = await chooseClient(options);
|
|
39
|
+
await assertSingleMcpConfigScope(options, [client]);
|
|
35
40
|
const workspace = resolveWorkspace(options.workspace);
|
|
36
41
|
const changes = await plannedChanges(options, client, workspace, 'init');
|
|
37
42
|
await previewAndApply(changes, options);
|
|
@@ -40,6 +45,7 @@ export async function init(options) {
|
|
|
40
45
|
}
|
|
41
46
|
export async function initAll(options) {
|
|
42
47
|
const workspace = resolveWorkspace(options.workspace);
|
|
48
|
+
await assertSingleMcpConfigScope(options, BRAINMCP_GLOBAL_CLIENTS);
|
|
43
49
|
const groups = await Promise.all(BRAINMCP_GLOBAL_CLIENTS.map((client) => plannedChanges(options, client, workspace, 'init')));
|
|
44
50
|
await previewAndApply(mergeFileChanges(groups.flat()), options);
|
|
45
51
|
options.output(`BrainMCP configured for ${BRAINMCP_GLOBAL_CLIENTS.map(clientLabel).join(', ')}.`);
|
|
@@ -74,7 +80,9 @@ function renderSetupNextSteps(clients, scope, workspace) {
|
|
|
74
80
|
'3. Log in to brain from every client you plan to use:',
|
|
75
81
|
...authorizationSteps,
|
|
76
82
|
'4. In browser consent, review the scopes, select the workspace(s) this client may reach, and choose its default workspace.',
|
|
77
|
-
|
|
83
|
+
`5. Verify with a read-only agent prompt (guidance ${GUIDANCE_VERSION}):`,
|
|
84
|
+
` ${buildBrainVerificationPrompt({ workspaceId: workspace })}`,
|
|
85
|
+
' Confirm the dashboard Connect view shows Agent seen after a successful authenticated tool call.',
|
|
78
86
|
'6. If the workspace is empty, copy and paste this bootstrap command into the connected agent:',
|
|
79
87
|
...BRAIN_BOOTSTRAP_PROMPT.split('\n').map((line) => ` ${line}`),
|
|
80
88
|
'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 +144,20 @@ export async function doctor(options) {
|
|
|
136
144
|
}
|
|
137
145
|
if (guidance !== undefined) {
|
|
138
146
|
const occurrences = (guidance.match(/brainmcp:managed:start/g) ?? []).length;
|
|
139
|
-
|
|
147
|
+
const normalizedGuidance = guidance.replace(/\r\n/g, '\n');
|
|
148
|
+
const ends = (guidance.match(/brainmcp:managed:end/g) ?? []).length;
|
|
149
|
+
const blocks = normalizedGuidance.match(/<!-- brainmcp:managed:start[^\n]*-->[\s\S]*?<!-- brainmcp:managed:end -->/g) ?? [];
|
|
150
|
+
const validMarkers = occurrences === 1 && ends === 1 && blocks.length === 1;
|
|
151
|
+
checks.push(['managed guidance markers', validMarkers, validMarkers ? 'one complete managed block' : `${occurrences} starts, ${ends} ends, ${blocks.length} complete blocks`]);
|
|
152
|
+
const installedWorkspace = blocks[0]?.match(/^Workspace id: (.+)$/m)?.[1]?.trim();
|
|
153
|
+
const expectedWorkspace = resolveWorkspace(options.workspace) ?? installedWorkspace;
|
|
154
|
+
const expectedGuidance = renderGuidance(client, expectedWorkspace).trim();
|
|
155
|
+
const currentGuidance = validMarkers && blocks[0] === expectedGuidance;
|
|
156
|
+
checks.push([
|
|
157
|
+
'managed guidance content', currentGuidance,
|
|
158
|
+
currentGuidance ? `matches bundled guidance ${GUIDANCE_VERSION}` :
|
|
159
|
+
`outdated or modified; preview repair with ${buildBrainmcpInitCommand({ client, scope: options.scope, workspaceId: expectedWorkspace })}`,
|
|
160
|
+
]);
|
|
140
161
|
checks.push(['workspace binding', !options.workspace || guidance.includes(`Workspace id: ${resolveWorkspace(options.workspace)}`), options.workspace ? 'requested workspace binding' : 'no workspace requested']);
|
|
141
162
|
if ((client === 'vscode' || client === 'copilot') && options.scope === 'user') {
|
|
142
163
|
checks.push([
|
|
@@ -157,38 +178,18 @@ export async function doctor(options) {
|
|
|
157
178
|
]);
|
|
158
179
|
}
|
|
159
180
|
}
|
|
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
|
-
}
|
|
181
|
+
if (requiresSingleMcpConfigScope(client)) {
|
|
182
|
+
const otherScope = oppositeScope(options.scope);
|
|
183
|
+
const duplicate = await inspectOtherMcpConfigScope(options, client);
|
|
184
|
+
checks.push([
|
|
185
|
+
'single MCP configuration scope',
|
|
186
|
+
duplicate.status === 'absent',
|
|
187
|
+
duplicate.status === 'present'
|
|
188
|
+
? `brain is also configured at ${duplicate.path}; keep it in only one scope`
|
|
189
|
+
: duplicate.status === 'invalid'
|
|
190
|
+
? `cannot inspect ${duplicate.path}: ${duplicate.error}`
|
|
191
|
+
: `no ${otherScope}-scope brain entry`,
|
|
192
|
+
]);
|
|
192
193
|
}
|
|
193
194
|
const fetchImpl = options.fetch ?? fetch;
|
|
194
195
|
for (const [name, url] of [
|
|
@@ -253,11 +254,73 @@ export async function doctor(options) {
|
|
|
253
254
|
catch (error) {
|
|
254
255
|
checks.push(['endpoint challenge', false, error instanceof Error ? error.message : String(error)]);
|
|
255
256
|
}
|
|
257
|
+
const brainHome = options.home ? join(options.home, '.brainmcp') : getBrainHome();
|
|
258
|
+
const credCheck = await checkCredentialHealth(brainHome, { probeVault: !options.home });
|
|
259
|
+
checks.push([credCheck.name, credCheck.passed, credCheck.detail]);
|
|
260
|
+
const driftCheck = checkRuntimeDrift(cliPackageVersion(), brainHome);
|
|
261
|
+
checks.push([driftCheck.name, driftCheck.passed, driftCheck.detail]);
|
|
262
|
+
const consentCheck = checkConsentPreferences(brainHome);
|
|
263
|
+
checks.push([consentCheck.name, consentCheck.passed, consentCheck.detail]);
|
|
264
|
+
const queueCheck = checkQueueStatus(brainHome);
|
|
265
|
+
checks.push([queueCheck.name, queueCheck.passed, queueCheck.detail]);
|
|
256
266
|
for (const [name, passed, detail] of checks)
|
|
257
267
|
options.output(`${passed ? '✓' : '✗'} ${name}: ${detail}`);
|
|
258
268
|
if (checks.some(([, passed]) => !passed))
|
|
259
269
|
throw new Error('BrainMCP doctor found configuration issues.');
|
|
260
270
|
}
|
|
271
|
+
const SINGLE_SCOPE_MCP_CLIENTS = new Set([
|
|
272
|
+
'antigravity',
|
|
273
|
+
'codex',
|
|
274
|
+
'copilot',
|
|
275
|
+
'cursor',
|
|
276
|
+
'vscode',
|
|
277
|
+
]);
|
|
278
|
+
function requiresSingleMcpConfigScope(client) {
|
|
279
|
+
return SINGLE_SCOPE_MCP_CLIENTS.has(client);
|
|
280
|
+
}
|
|
281
|
+
function oppositeScope(scope) {
|
|
282
|
+
return scope === 'project' ? 'user' : 'project';
|
|
283
|
+
}
|
|
284
|
+
async function inspectOtherMcpConfigScope(options, client) {
|
|
285
|
+
const otherScope = oppositeScope(options.scope);
|
|
286
|
+
const currentTarget = resolveTarget(options, targetFor(client, options.scope));
|
|
287
|
+
const otherTarget = resolveTarget({ ...options, scope: otherScope }, targetFor(client, otherScope));
|
|
288
|
+
if (otherTarget.configPath === currentTarget.configPath) {
|
|
289
|
+
return { path: otherTarget.configPath, status: 'absent' };
|
|
290
|
+
}
|
|
291
|
+
const otherConfig = await readText(otherTarget.configPath);
|
|
292
|
+
if (otherConfig === undefined) {
|
|
293
|
+
return { path: otherTarget.configPath, status: 'absent' };
|
|
294
|
+
}
|
|
295
|
+
try {
|
|
296
|
+
return {
|
|
297
|
+
path: otherTarget.configPath,
|
|
298
|
+
status: hasBrainServerConfig(otherConfig, otherTarget) ? 'present' : 'absent',
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
return {
|
|
303
|
+
error: error instanceof Error ? error.message : String(error),
|
|
304
|
+
path: otherTarget.configPath,
|
|
305
|
+
status: 'invalid',
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
async function assertSingleMcpConfigScope(options, clients) {
|
|
310
|
+
for (const client of clients) {
|
|
311
|
+
if (!requiresSingleMcpConfigScope(client))
|
|
312
|
+
continue;
|
|
313
|
+
const duplicate = await inspectOtherMcpConfigScope(options, client);
|
|
314
|
+
if (duplicate.status === 'absent')
|
|
315
|
+
continue;
|
|
316
|
+
const otherScope = oppositeScope(options.scope);
|
|
317
|
+
if (duplicate.status === 'invalid') {
|
|
318
|
+
throw new Error(`Cannot inspect the existing ${clientLabel(client)} ${otherScope}-scope configuration at ${duplicate.path}: ${duplicate.error}`);
|
|
319
|
+
}
|
|
320
|
+
throw new Error(`Brain is already configured for ${clientLabel(client)} at ${duplicate.path} (${otherScope} scope). ` +
|
|
321
|
+
`Keep it in exactly one scope: run \`brainmcp remove --client ${client} --scope ${otherScope} --yes\`, then retry.`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
261
324
|
function hasBrainServerConfig(config, target) {
|
|
262
325
|
if (target.format === 'toml') {
|
|
263
326
|
return /\[mcp_servers\.brain\]/.test(config);
|
|
@@ -411,6 +474,84 @@ async function plannedChanges(options, client, workspace, mode) {
|
|
|
411
474
|
}
|
|
412
475
|
}
|
|
413
476
|
}
|
|
477
|
+
const hookChanges = await plannedHookChanges(options, client, target, mode);
|
|
478
|
+
changes.push(...hookChanges);
|
|
479
|
+
return changes;
|
|
480
|
+
}
|
|
481
|
+
async function plannedHookChanges(options, client, target, mode) {
|
|
482
|
+
if (!target.supportsHooks || !target.hookPath)
|
|
483
|
+
return [];
|
|
484
|
+
if (mode === 'init' && options.noHooks)
|
|
485
|
+
return [];
|
|
486
|
+
const bundle = loadPackagedRuntimeBundle();
|
|
487
|
+
if (mode === 'init' && !bundle) {
|
|
488
|
+
throw new Error('The packaged BrainMCP hook runtime is missing. Reinstall or rebuild the CLI before enabling hooks.');
|
|
489
|
+
}
|
|
490
|
+
const home = options.home ?? homedir();
|
|
491
|
+
const brainHome = options.home ? join(options.home, '.brainmcp') : getBrainHome();
|
|
492
|
+
const version = cliPackageVersion();
|
|
493
|
+
const runtimePath = getVersionedRuntimePath(version, brainHome);
|
|
494
|
+
const hookFilePath = target.hookPath.startsWith('/')
|
|
495
|
+
? target.hookPath
|
|
496
|
+
: options.scope === 'user'
|
|
497
|
+
? join(home, target.hookPath)
|
|
498
|
+
: toAbsolute(options.root, target.hookPath);
|
|
499
|
+
const changes = [];
|
|
500
|
+
if (mode === 'init' && bundle) {
|
|
501
|
+
const existingRuntime = await readText(runtimePath);
|
|
502
|
+
if (existingRuntime !== bundle) {
|
|
503
|
+
changes.push({ path: runtimePath, before: existingRuntime, after: bundle });
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
const existingHook = await readText(hookFilePath);
|
|
507
|
+
let parsed = {};
|
|
508
|
+
if (existingHook?.trim()) {
|
|
509
|
+
parsed = parseJsonc(existingHook);
|
|
510
|
+
}
|
|
511
|
+
const next = mode === 'init'
|
|
512
|
+
? client === 'claude-code'
|
|
513
|
+
? upsertClaudeManagedHooks(parsed, runtimePath, { enableNudge: Boolean(options.writeBackNudge) })
|
|
514
|
+
: client === 'cursor'
|
|
515
|
+
? upsertCursorManagedHooks(parsed, runtimePath)
|
|
516
|
+
: client === 'codex'
|
|
517
|
+
? upsertCodexManagedHooks(parsed, runtimePath)
|
|
518
|
+
: upsertVsCodeManagedHooks(parsed, runtimePath)
|
|
519
|
+
: client === 'claude-code'
|
|
520
|
+
? removeClaudeManagedHooks(parsed)
|
|
521
|
+
: client === 'cursor'
|
|
522
|
+
? removeCursorManagedHooks(parsed)
|
|
523
|
+
: client === 'codex'
|
|
524
|
+
? removeCodexManagedHooks(parsed)
|
|
525
|
+
: removeVsCodeManagedHooks(parsed);
|
|
526
|
+
const eventNames = client === 'claude-code'
|
|
527
|
+
? ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact', 'SessionEnd', 'Stop']
|
|
528
|
+
: client === 'cursor'
|
|
529
|
+
? ['sessionStart', 'beforeSubmitPrompt', 'postToolUse', 'afterAgentResponse', 'preCompact', 'sessionEnd']
|
|
530
|
+
: client === 'codex'
|
|
531
|
+
? ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact', 'SessionEnd']
|
|
532
|
+
: ['SessionStart', 'UserPromptSubmit', 'PostToolUse', 'PreCompact'];
|
|
533
|
+
const nextRoot = next && typeof next === 'object' && !Array.isArray(next)
|
|
534
|
+
? next
|
|
535
|
+
: {};
|
|
536
|
+
const nextHooks = nextRoot.hooks && typeof nextRoot.hooks === 'object' && !Array.isArray(nextRoot.hooks)
|
|
537
|
+
? nextRoot.hooks
|
|
538
|
+
: {};
|
|
539
|
+
let after = existingHook ?? '{}\n';
|
|
540
|
+
if (client === 'cursor' && mode === 'init') {
|
|
541
|
+
after = upsertJsoncPath(after, ['version'], 1);
|
|
542
|
+
}
|
|
543
|
+
for (const eventName of eventNames) {
|
|
544
|
+
const value = nextHooks[eventName];
|
|
545
|
+
after = value === undefined
|
|
546
|
+
? removeJsoncPath(after, ['hooks', eventName])
|
|
547
|
+
: upsertJsoncPath(after, ['hooks', eventName], value);
|
|
548
|
+
}
|
|
549
|
+
const meaningfulRootKeys = Object.keys(nextRoot).filter((key) => key !== 'version');
|
|
550
|
+
if (mode === 'remove' && meaningfulRootKeys.length === 0)
|
|
551
|
+
after = undefined;
|
|
552
|
+
if (existingHook !== after) {
|
|
553
|
+
changes.push({ path: hookFilePath, before: existingHook, after });
|
|
554
|
+
}
|
|
414
555
|
return changes;
|
|
415
556
|
}
|
|
416
557
|
function resolveTarget(options, target) {
|
|
@@ -422,6 +563,7 @@ function resolveTarget(options, target) {
|
|
|
422
563
|
...target,
|
|
423
564
|
configPath: join(codexHome, 'config.toml'),
|
|
424
565
|
guidancePath: join(codexHome, 'AGENTS.md'),
|
|
566
|
+
hookPath: join(codexHome, 'hooks.json'),
|
|
425
567
|
format: target.configFormat,
|
|
426
568
|
rootKey: target.configRootKey,
|
|
427
569
|
};
|
|
@@ -500,4 +642,6 @@ async function previewAndApply(changes, options) {
|
|
|
500
642
|
? `Applied changes with atomic per-file writes. Backups: ${backups.join(', ')}`
|
|
501
643
|
: 'Applied changes with atomic per-file writes.');
|
|
502
644
|
}
|
|
645
|
+
export * from './auth.js';
|
|
646
|
+
export * from './dispatch.js';
|
|
503
647
|
//# sourceMappingURL=index.js.map
|