@brainmcp/brainmcp 0.1.1 → 0.1.2

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.
@@ -1,4 +1,4 @@
1
- import { BRAIN_MCP_ENDPOINT, MCP_CLIENT_PROFILES, buildCodexConfigToml, buildProjectInstructionBlock, renderCursorMdc, } from '../agent-config.js';
1
+ import { BRAIN_MCP_ENDPOINT, MCP_CLIENT_PROFILES, VSCODE_USER_INSTRUCTIONS_FRONTMATTER, buildCodexConfigToml, buildProjectInstructionBlock, renderCursorMdc, } from '../agent-config.js';
2
2
  export const BRAIN_ENDPOINT = BRAIN_MCP_ENDPOINT;
3
3
  export const CLIENT_IDS = ['claude-code', 'cursor', 'codex', 'vscode', 'generic'];
4
4
  export function assertClientId(value) {
@@ -12,45 +12,48 @@ export const TOML_MARKER_START = '# brainmcp:managed:start version=2026.07.10';
12
12
  export const TOML_MARKER_END = '# brainmcp:managed:end';
13
13
  export function targetFor(client, scope) {
14
14
  const home = scope === 'user';
15
- const prefix = home ? '~/' : '';
16
15
  switch (client) {
17
16
  case 'cursor':
18
17
  return {
19
18
  client,
20
- configPath: `${prefix}.cursor/mcp.json`,
21
- guidancePath: `${prefix}.cursor/rules/brainmcp-workspace.mdc`,
19
+ configPath: '.cursor/mcp.json',
20
+ guidancePath: '.cursor/rules/brainmcp-workspace.mdc',
22
21
  configFormat: 'jsonc',
23
22
  configRootKey: 'mcpServers',
24
23
  };
25
24
  case 'claude-code':
26
25
  return {
27
26
  client,
28
- configPath: `${prefix}.mcp.json`,
29
- guidancePath: `${prefix}CLAUDE.md`,
27
+ configPath: home ? '.claude.json' : '.mcp.json',
28
+ guidancePath: home ? '.claude/CLAUDE.md' : 'CLAUDE.md',
30
29
  configFormat: 'jsonc',
31
30
  configRootKey: 'mcpServers',
32
31
  };
33
32
  case 'codex':
34
33
  return {
35
34
  client,
36
- configPath: `${prefix}.codex/config.toml`,
37
- guidancePath: `${prefix}AGENTS.md`,
35
+ configPath: '.codex/config.toml',
36
+ guidancePath: home ? '.codex/AGENTS.md' : 'AGENTS.md',
38
37
  configFormat: 'toml',
39
38
  configRootKey: 'mcpServers',
40
39
  };
41
40
  case 'vscode':
42
41
  return {
43
42
  client,
44
- configPath: `${prefix}.vscode/mcp.json`,
45
- guidancePath: `${prefix}AGENTS.md`,
43
+ // User-scope resolution maps this logical path to the platform's
44
+ // default VS Code user-profile directory.
45
+ configPath: '.vscode/mcp.json',
46
+ guidancePath: home
47
+ ? '.copilot/instructions/brainmcp.instructions.md'
48
+ : 'AGENTS.md',
46
49
  configFormat: 'jsonc',
47
50
  configRootKey: 'servers',
48
51
  };
49
52
  case 'generic':
50
53
  return {
51
54
  client,
52
- configPath: `${prefix}.mcp.json`,
53
- guidancePath: `${prefix}AGENTS.md`,
55
+ configPath: '.mcp.json',
56
+ guidancePath: 'AGENTS.md',
54
57
  configFormat: 'jsonc',
55
58
  configRootKey: 'mcpServers',
56
59
  };
@@ -68,13 +71,26 @@ export function resolveWorkspace(value) {
68
71
  }
69
72
  return workspace;
70
73
  }
74
+ export function guidancePreamble(client, scope) {
75
+ if (client === 'cursor') {
76
+ const rendered = renderCursorMdc();
77
+ const frontmatter = rendered.match(/^---\n[\s\S]*?\n---\n*/)?.[0];
78
+ if (!frontmatter)
79
+ throw new Error('Cursor guidance renderer did not return frontmatter.');
80
+ return frontmatter.trimEnd();
81
+ }
82
+ if (client === 'vscode' && scope === 'user') {
83
+ return VSCODE_USER_INSTRUCTIONS_FRONTMATTER;
84
+ }
85
+ return undefined;
86
+ }
71
87
  export function renderGuidance(client, workspaceId) {
72
88
  if (client === 'cursor') {
73
89
  const rendered = renderCursorMdc({ workspaceId });
74
90
  const frontmatter = rendered.match(/^---\n[\s\S]*?\n---\n*/)?.[0];
75
91
  if (!frontmatter)
76
92
  throw new Error('Cursor guidance renderer did not return frontmatter.');
77
- return `${frontmatter}\n${MARKER_START}\n${rendered.slice(frontmatter.length)}\n${MARKER_END}\n`;
93
+ return `${MARKER_START}\n${rendered.slice(frontmatter.length).trim()}\n${MARKER_END}\n`;
78
94
  }
79
95
  return `${MARKER_START}\n${buildProjectInstructionBlock({ workspaceId })}\n${MARKER_END}\n`;
80
96
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
package/dist/lib/files.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createHash, randomUUID } from 'node:crypto';
2
- import { access, copyFile, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
+ import { access, chmod, copyFile, lstat, mkdir, readFile, realpath, rename, rm, stat, writeFile } from 'node:fs/promises';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  export async function readText(path) {
5
5
  try {
@@ -27,17 +27,71 @@ export function renderDiff(change) {
27
27
  const before = change.before?.split('\n') ?? [];
28
28
  const after = change.after?.split('\n') ?? [];
29
29
  const header = `--- ${change.before === undefined ? '/dev/null' : change.path}\n+++ ${change.after === undefined ? '/dev/null' : change.path}`;
30
- const removed = before.filter((line) => !after.includes(line)).map((line) => `-${line}`);
31
- const added = after.filter((line) => !before.includes(line)).map((line) => `+${line}`);
32
- return [header, ...removed, ...added].join('\n');
30
+ let start = 0;
31
+ while (start < before.length && start < after.length && before[start] === after[start])
32
+ start += 1;
33
+ let beforeEnd = before.length;
34
+ let afterEnd = after.length;
35
+ while (beforeEnd > start &&
36
+ afterEnd > start &&
37
+ before[beforeEnd - 1] === after[afterEnd - 1]) {
38
+ beforeEnd -= 1;
39
+ afterEnd -= 1;
40
+ }
41
+ const contextStart = Math.max(0, start - 2);
42
+ const contextBeforeEnd = Math.min(before.length, beforeEnd + 2);
43
+ const contextAfterEnd = Math.min(after.length, afterEnd + 2);
44
+ const hunk = `@@ -${contextStart + 1},${contextBeforeEnd - contextStart} +${contextStart + 1},${contextAfterEnd - contextStart} @@`;
45
+ return [
46
+ header,
47
+ hunk,
48
+ ...before.slice(contextStart, start).map((line) => ` ${line}`),
49
+ ...before.slice(start, beforeEnd).map((line) => `-${line}`),
50
+ ...after.slice(start, afterEnd).map((line) => `+${line}`),
51
+ ...after.slice(afterEnd, contextAfterEnd).map((line) => ` ${line}`),
52
+ ].join('\n');
33
53
  }
34
54
  export async function applyChanges(changes) {
35
- const backups = [];
55
+ const prepared = [];
56
+ // Validate the whole preview before touching any file. This prevents a long
57
+ // confirmation prompt (or another client) from turning a reviewed diff into
58
+ // an overwrite of newer configuration.
36
59
  for (const change of changes) {
37
60
  if (change.before === change.after)
38
61
  continue;
39
- await mkdir(dirname(change.path), { recursive: true });
40
- if (change.before !== undefined && (await exists(change.path))) {
62
+ const current = await readText(change.path);
63
+ if (current !== change.before)
64
+ throw changedSincePreview(change.path);
65
+ let writePath = change.path;
66
+ let existingMode;
67
+ let symbolicLink = false;
68
+ if (current !== undefined) {
69
+ const metadata = await lstat(change.path);
70
+ symbolicLink = metadata.isSymbolicLink();
71
+ if (symbolicLink) {
72
+ if (change.after === undefined) {
73
+ throw new Error(`Refusing to remove symlinked configuration ${change.path}; remove its managed block or target manually.`);
74
+ }
75
+ writePath = await realpath(change.path);
76
+ }
77
+ existingMode = (await stat(writePath)).mode & 0o777;
78
+ }
79
+ prepared.push({ change, writePath, existingMode, symbolicLink });
80
+ }
81
+ const backups = [];
82
+ for (const item of prepared) {
83
+ const { change, writePath, existingMode, symbolicLink } = item;
84
+ if ((await readText(change.path)) !== change.before)
85
+ throw changedSincePreview(change.path);
86
+ if (change.before !== undefined) {
87
+ const currentMetadata = await lstat(change.path);
88
+ if (currentMetadata.isSymbolicLink() !== symbolicLink)
89
+ throw changedSincePreview(change.path);
90
+ if (symbolicLink && (await realpath(change.path)) !== writePath)
91
+ throw changedSincePreview(change.path);
92
+ }
93
+ await mkdir(dirname(writePath), { recursive: true });
94
+ if (change.before !== undefined) {
41
95
  const backup = `${change.path}.brainmcp.bak-${Date.now()}-${createHash('sha1').update(change.path).digest('hex').slice(0, 6)}`;
42
96
  await copyFile(change.path, backup);
43
97
  backups.push(backup);
@@ -46,12 +100,23 @@ export async function applyChanges(changes) {
46
100
  await rm(change.path, { force: true });
47
101
  continue;
48
102
  }
49
- const temporary = `${change.path}.brainmcp-tmp-${randomUUID()}`;
50
- await writeFile(temporary, change.after, 'utf8');
51
- await rename(temporary, change.path);
103
+ const temporary = `${writePath}.brainmcp-tmp-${randomUUID()}`;
104
+ try {
105
+ await writeFile(temporary, change.after, 'utf8');
106
+ if (existingMode !== undefined)
107
+ await chmod(temporary, existingMode);
108
+ await rename(temporary, writePath);
109
+ }
110
+ catch (error) {
111
+ await rm(temporary, { force: true });
112
+ throw error;
113
+ }
52
114
  }
53
115
  return backups;
54
116
  }
117
+ function changedSincePreview(path) {
118
+ return new Error(`Refusing to overwrite ${path}: it changed after the preview. Re-run the command and review the new diff.`);
119
+ }
55
120
  function isNotFound(error) {
56
121
  return typeof error === 'object' && error !== null && 'code' in error && error.code === 'ENOENT';
57
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/lib/files.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files.js","sourceRoot":"","sources":["../../src/lib/files.ts"],"names":[],"mappings":"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"}