context-mcp-server 1.0.4 → 1.0.5
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 +23 -10
- package/package.json +1 -1
- package/pyproject.toml +1 -1
- package/src/cli.js +247 -58
- package/src/templates/AGENTS.md +29 -11
- package/src/templates/CLAUDE.md +33 -11
- package/src/templates/GEMINI.md +29 -11
- package/src/templates/commands/context-resume.md +8 -0
- package/src/templates/commands/graph-build.md +5 -0
- package/src/templates/commands/save-context.md +9 -0
- package/src/templates/skills/SKILL.md +112 -0
- package/uv.lock +1 -1
package/README.md
CHANGED
|
@@ -371,7 +371,10 @@ Available to web clients (Claude.ai, ChatGPT) only — local AI clients use thei
|
|
|
371
371
|
|
|
372
372
|
All file and git operations are sandboxed to the registered project root. Enable git tools with `--access-git` or `access_git: true` in config.
|
|
373
373
|
|
|
374
|
-
### CodeGraph
|
|
374
|
+
### ContextGraph (CodeGraph)
|
|
375
|
+
|
|
376
|
+
> Also referred to as **ContextGraph** — the MCP tools use the `codegraph_*` prefix but both names mean the same thing.
|
|
377
|
+
|
|
375
378
|
- `codegraph_build` — AST scan using tree-sitter: functions, classes, imports, edges. Runs locally, no API cost.
|
|
376
379
|
- `codegraph_query` — fetch any details about the codebase using natural language: find functions, classes, files, dependencies, callers
|
|
377
380
|
- `codegraph_explain` — single node: type, file location, all direct connections (depends_on, used_by)
|
|
@@ -381,15 +384,25 @@ All file and git operations are sandboxed to the registered project root. Enable
|
|
|
381
384
|
|
|
382
385
|
### Multi-AI Support
|
|
383
386
|
|
|
384
|
-
| AI | Config File |
|
|
385
|
-
|
|
386
|
-
| Claude Code | `.claude/mcp.json` |
|
|
387
|
-
|
|
|
388
|
-
|
|
|
389
|
-
| Gemini CLI | `.gemini/settings.json` | `GEMINI.md` |
|
|
390
|
-
| Codex CLI | `.codex/config.toml` | `AGENTS.md` |
|
|
391
|
-
|
|
|
392
|
-
| Claude.ai / ChatGPT | HTTP (`ctx online`) | — |
|
|
387
|
+
| AI | Config File | Instructions | Slash Commands |
|
|
388
|
+
|----|------------|--------------|----------------|
|
|
389
|
+
| Claude Code | `.claude/mcp.json` | Skill → `~/.claude/skills/context-mcp/` (global) | ✓ (3 commands) |
|
|
390
|
+
| Cursor | `.cursor/mcp.json` | Rule → `.cursor/rules/context-mcp.mdc` | — |
|
|
391
|
+
| Windsurf | `~/.codeium/windsurf/mcp_config.json` | Rule → `.windsurf/rules/context-mcp.md` | — |
|
|
392
|
+
| Gemini CLI | `.gemini/settings.json` | `GEMINI.md` | — |
|
|
393
|
+
| Codex CLI | `.codex/config.toml` | `AGENTS.md` | — |
|
|
394
|
+
| VS Code Copilot | `.vscode/mcp.json` | — | — |
|
|
395
|
+
| Claude.ai / ChatGPT | HTTP (`ctx online`) | — | — |
|
|
396
|
+
|
|
397
|
+
> Claude Code installs context-mcp as a **skill** (`~/.claude/skills/context-mcp/SKILL.md`) — available globally across all projects, not just the current one. Cursor and Windsurf use their native rules system. Gemini and Codex use plain instruction files since they have no skill/rules system.
|
|
398
|
+
|
|
399
|
+
`ctx install --claude` also writes slash commands into `.claude/commands/`:
|
|
400
|
+
|
|
401
|
+
| Command | What it does |
|
|
402
|
+
|---------|-------------|
|
|
403
|
+
| `/context-resume` | Resume context for the current project |
|
|
404
|
+
| `/graph-build` | Build or rebuild the ContextGraph |
|
|
405
|
+
| `/save-context` | Save a note, decision, or bug to context |
|
|
393
406
|
|
|
394
407
|
> The context store lives at `~/.context-mcp/` — not inside any tool, IDE, or session. A decision saved in Claude Code is visible in Cursor. A bug logged from Gemini CLI shows up when you resume in Codex.
|
|
395
408
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Persistent AI memory + codebase knowledge graph MCP server. Works across Claude Code, Cursor, Gemini CLI, Codex, Windsurf, VS Code Copilot, Claude.ai, and ChatGPT.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
package/pyproject.toml
CHANGED
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "codegraph-mcp"
|
|
7
|
-
version = "1.0.
|
|
7
|
+
version = "1.0.5"
|
|
8
8
|
description = "Codebase knowledge graph MCP server — AST extraction, graph queries, community detection"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
package/src/cli.js
CHANGED
|
@@ -106,28 +106,46 @@ function printSection(title, meta = '') {
|
|
|
106
106
|
|
|
107
107
|
function printUsage() {
|
|
108
108
|
printBanner();
|
|
109
|
-
|
|
109
|
+
|
|
110
|
+
// Terminal commands (ctx ...)
|
|
111
|
+
printSection('Terminal commands', 'run from your shell');
|
|
110
112
|
const cmd = (c, desc) => console.log(` ${accent(c.padEnd(40))} ${faint(desc)}`);
|
|
111
|
-
cmd('ctx',
|
|
112
|
-
cmd('ctx list [project]',
|
|
113
|
-
cmd('ctx search <query>',
|
|
114
|
-
cmd('ctx add',
|
|
115
|
-
cmd('ctx delete <id-prefix>',
|
|
116
|
-
cmd('ctx delete project <name|id>',
|
|
117
|
-
cmd('ctx summary [project]',
|
|
118
|
-
cmd('ctx projects',
|
|
119
|
-
cmd('ctx discuss [project]',
|
|
120
|
-
cmd('ctx benchmark',
|
|
113
|
+
cmd('ctx', 'open interactive mode');
|
|
114
|
+
cmd('ctx list [project]', 'list entries + discussions + graphs');
|
|
115
|
+
cmd('ctx search <query>', 'keyword → semantic fallback search');
|
|
116
|
+
cmd('ctx add', 'add entry interactively');
|
|
117
|
+
cmd('ctx delete <id-prefix>', 'delete one entry');
|
|
118
|
+
cmd('ctx delete project <name|id>', 'delete all entries for a project');
|
|
119
|
+
cmd('ctx summary [project]', 'summarize recent entries');
|
|
120
|
+
cmd('ctx projects', 'show all projects + graphs');
|
|
121
|
+
cmd('ctx discuss [project]', 'show discussions');
|
|
122
|
+
cmd('ctx benchmark', 'token savings report (memory + graph)');
|
|
121
123
|
console.log('');
|
|
122
|
-
cmd('ctx install --initial',
|
|
123
|
-
cmd('ctx install --<platform>', 'write MCP config +
|
|
124
|
+
cmd('ctx install --initial', 'install / update Node.js + Python (codegraph) deps');
|
|
125
|
+
cmd('ctx install --<platform>', 'write MCP config + skill/rules for an AI platform');
|
|
124
126
|
cmd('ctx install --all', 'install for all platforms at once');
|
|
125
|
-
cmd('ctx online [--port N]', 'start HTTP server
|
|
127
|
+
cmd('ctx online [--port N]', 'start HTTP server for Claude.ai / ChatGPT');
|
|
126
128
|
cmd('ctx online --close', 'stop the running HTTP server');
|
|
127
129
|
cmd('ctx settings', 'view and edit config (port, host, client id/secret)');
|
|
128
|
-
|
|
130
|
+
cmd('ctx update', 'check for and apply latest version');
|
|
129
131
|
cmd('ctx help', 'show this screen');
|
|
130
132
|
console.log('');
|
|
133
|
+
|
|
134
|
+
// Interactive mode commands (no ctx prefix)
|
|
135
|
+
printSection('Interactive mode', 'type these inside ctx (no "ctx" prefix)');
|
|
136
|
+
const icmd = (c, desc) => console.log(` ${accent(c.padEnd(40))} ${faint(desc)}`);
|
|
137
|
+
icmd('list [project]', 'list entries');
|
|
138
|
+
icmd('search <query>', 'search context');
|
|
139
|
+
icmd('add', 'add entry');
|
|
140
|
+
icmd('projects', 'show all projects');
|
|
141
|
+
icmd('discuss [project]', 'show discussions');
|
|
142
|
+
icmd('summary [project]', 'summarize recent entries');
|
|
143
|
+
icmd('benchmark', 'token savings report');
|
|
144
|
+
icmd('install --<platform>', 'install for a platform');
|
|
145
|
+
icmd('settings', 'edit config');
|
|
146
|
+
icmd('clear', 'clear screen');
|
|
147
|
+
icmd('exit / quit / q', 'exit interactive mode');
|
|
148
|
+
console.log('');
|
|
131
149
|
}
|
|
132
150
|
function clearScreen() {
|
|
133
151
|
// \x1b[2J = clear screen, \x1b[3J = clear scrollback, \x1b[H = cursor home
|
|
@@ -531,65 +549,163 @@ function _writeFile(filePath, content, label) {
|
|
|
531
549
|
console.log(` ${ok('✓')} ${label.padEnd(28)} ${faint(filePath.replace(/\\/g, '/'))}`);
|
|
532
550
|
}
|
|
533
551
|
|
|
552
|
+
// Entries ctx install writes into project roots — add to user's global gitignore if one exists
|
|
553
|
+
const _GLOBAL_GITIGNORE_ENTRIES = [
|
|
554
|
+
// Installed instruction files
|
|
555
|
+
'CLAUDE.md',
|
|
556
|
+
'GEMINI.md',
|
|
557
|
+
'AGENTS.md',
|
|
558
|
+
// AI/IDE platform config folders (context-mcp specific — safe to ignore globally)
|
|
559
|
+
'.claude/',
|
|
560
|
+
'.cursor/',
|
|
561
|
+
'.vscode/',
|
|
562
|
+
'.gemini/',
|
|
563
|
+
'.codex/',
|
|
564
|
+
'.windsurf/',
|
|
565
|
+
// Build outputs and session artifacts
|
|
566
|
+
'codegraph-cache/',
|
|
567
|
+
'.mcp.json',
|
|
568
|
+
];
|
|
569
|
+
|
|
570
|
+
function _updateGlobalGitignore() {
|
|
571
|
+
// Resolve global gitignore path: git config > ~/.gitignore_global > ~/.gitignore
|
|
572
|
+
let giPath = null;
|
|
573
|
+
const gitCfg = spawnSync('git', ['config', '--global', 'core.excludesFile'], { encoding: 'utf8' });
|
|
574
|
+
if (gitCfg.status === 0 && gitCfg.stdout.trim()) {
|
|
575
|
+
const resolved = gitCfg.stdout.trim().replace(/^~/, homedir());
|
|
576
|
+
if (existsSync(resolved)) giPath = resolved;
|
|
577
|
+
}
|
|
578
|
+
if (!giPath) {
|
|
579
|
+
for (const candidate of [join(homedir(), '.gitignore_global'), join(homedir(), '.gitignore')]) {
|
|
580
|
+
if (existsSync(candidate)) { giPath = candidate; break; }
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (!giPath) return; // no global gitignore — skip silently
|
|
584
|
+
|
|
585
|
+
const existing = readFileSync(giPath, 'utf8');
|
|
586
|
+
const lines = existing.split(/\r?\n/);
|
|
587
|
+
const missing = _GLOBAL_GITIGNORE_ENTRIES.filter(e => !lines.includes(e));
|
|
588
|
+
if (!missing.length) return;
|
|
589
|
+
|
|
590
|
+
const block = '\n# context-mcp — written by ctx install\n' + missing.join('\n') + '\n';
|
|
591
|
+
writeFileSync(giPath, existing.trimEnd() + block, 'utf8');
|
|
592
|
+
console.log(` ${ok('✓')} ${'global gitignore'.padEnd(28)} ${faint(giPath.replace(/\\/g, '/'))}`);
|
|
593
|
+
for (const e of missing) console.log(` ${faint('+ ' + e)}`);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
function _writeCommands(baseDir) {
|
|
597
|
+
const cmdsDir = join(TPLS, 'commands');
|
|
598
|
+
const destDir = join(baseDir, '.claude', 'commands');
|
|
599
|
+
for (const [name, label] of [
|
|
600
|
+
['context-resume.md', '/context-resume'],
|
|
601
|
+
['graph-build.md', '/graph-build'],
|
|
602
|
+
['save-context.md', '/save-context'],
|
|
603
|
+
]) {
|
|
604
|
+
const src = join(cmdsDir, name);
|
|
605
|
+
if (existsSync(src)) {
|
|
606
|
+
_writeFile(join(destDir, name), readFileSync(src, 'utf8'), label);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
const MCP_SERVER_CMD = { command: 'npx', args: ['-y', 'context-mcp-server@latest'] };
|
|
612
|
+
|
|
534
613
|
const PLATFORMS = {
|
|
535
614
|
claude: {
|
|
536
615
|
label: 'Claude Code',
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
616
|
+
restartNote: 'Type /context-resume in Claude Code to start using context-mcp.',
|
|
617
|
+
install(dir, scope) {
|
|
618
|
+
// Install as a skill (global, works across all projects) instead of a flat CLAUDE.md
|
|
619
|
+
const skillSrc = join(TPLS, 'skills', 'SKILL.md');
|
|
620
|
+
const skillDest = join(homedir(), '.claude', 'skills', 'context-mcp', 'SKILL.md');
|
|
621
|
+
if (existsSync(skillSrc)) {
|
|
622
|
+
_writeFile(skillDest, readFileSync(skillSrc, 'utf8'), '~/.claude/skills/context-mcp/');
|
|
623
|
+
}
|
|
624
|
+
// Slash commands are always user-global (not project-scoped)
|
|
625
|
+
_writeCommands(homedir());
|
|
626
|
+
// Register via claude CLI so the server is trusted immediately (no manual trust prompt)
|
|
627
|
+
const scopeFlag = scope === 'global' ? 'user' : 'project';
|
|
628
|
+
const reg = spawnSync(
|
|
629
|
+
'claude', ['mcp', 'add', '--scope', scopeFlag, 'context-mcp', '--', 'npx', '-y', 'context-mcp-server@latest'],
|
|
630
|
+
{ encoding: 'utf8', shell: true },
|
|
631
|
+
);
|
|
632
|
+
if (reg.status === 0) {
|
|
633
|
+
console.log(` ${ok('✓')} ${'registered via claude mcp add'.padEnd(28)} ${faint('scope: ' + scopeFlag)}`);
|
|
634
|
+
} else {
|
|
635
|
+
console.log(` ${faint('ℹ')} claude CLI not found — open Claude Code and trust context-mcp when prompted`);
|
|
636
|
+
}
|
|
544
637
|
},
|
|
545
638
|
},
|
|
546
639
|
cursor: {
|
|
547
640
|
label: 'Cursor',
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
641
|
+
restartNote: 'Restart Cursor to load the new MCP server.',
|
|
642
|
+
install(dir, scope) {
|
|
643
|
+
const mcpJson = JSON.stringify({ mcpServers: { 'context-mcp': MCP_SERVER_CMD } }, null, 2);
|
|
644
|
+
_writeFile(join(dir, '.cursor', 'mcp.json'), mcpJson, '.cursor/mcp.json');
|
|
645
|
+
if (scope === 'project') {
|
|
646
|
+
const mdc = _tpl('cursor-rules.mdc');
|
|
647
|
+
if (mdc) _writeFile(join(dir, '.cursor', 'rules', 'context-mcp.mdc'), mdc, '.cursor/rules/context-mcp.mdc');
|
|
648
|
+
}
|
|
649
|
+
// Try to enable via cursor CLI (enable/disable only — no add command)
|
|
650
|
+
const reg = spawnSync(
|
|
651
|
+
'cursor', ['agent', 'mcp', 'enable', 'context-mcp'],
|
|
652
|
+
{ encoding: 'utf8', shell: true },
|
|
653
|
+
);
|
|
654
|
+
if (reg.status === 0) {
|
|
655
|
+
console.log(` ${ok('✓')} ${'enabled via cursor agent mcp'.padEnd(28)}`);
|
|
656
|
+
}
|
|
555
657
|
},
|
|
556
658
|
},
|
|
557
659
|
vscode: {
|
|
558
660
|
label: 'VS Code Copilot',
|
|
559
|
-
|
|
661
|
+
restartNote: 'Reload VS Code window (Ctrl+Shift+P → "Reload Window").',
|
|
662
|
+
install(dir) {
|
|
560
663
|
const mcpJson = JSON.stringify({
|
|
561
|
-
servers: { 'context-mcp': { type: 'stdio',
|
|
664
|
+
servers: { 'context-mcp': { type: 'stdio', ...MCP_SERVER_CMD } },
|
|
562
665
|
}, null, 2);
|
|
563
|
-
_writeFile(join(
|
|
564
|
-
const md = _tpl('CLAUDE.md');
|
|
565
|
-
if (md) _writeFile(join(cwd, 'CLAUDE.md'), md, 'CLAUDE.md');
|
|
666
|
+
_writeFile(join(dir, '.vscode', 'mcp.json'), mcpJson, '.vscode/mcp.json');
|
|
566
667
|
},
|
|
567
668
|
},
|
|
568
669
|
gemini: {
|
|
569
670
|
label: 'Gemini CLI',
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
671
|
+
restartNote: 'Restart your Gemini CLI session.',
|
|
672
|
+
install(dir, scope) {
|
|
673
|
+
const cfg = JSON.stringify({ mcpServers: { 'context-mcp': MCP_SERVER_CMD } }, null, 2);
|
|
674
|
+
_writeFile(join(dir, '.gemini', 'settings.json'), cfg, '.gemini/settings.json');
|
|
675
|
+
if (scope === 'project') {
|
|
676
|
+
const md = _tpl('GEMINI.md');
|
|
677
|
+
if (md) _writeFile(join(dir, 'GEMINI.md'), md, 'GEMINI.md');
|
|
678
|
+
}
|
|
577
679
|
},
|
|
578
680
|
},
|
|
579
681
|
codex: {
|
|
580
682
|
label: 'Codex CLI',
|
|
581
|
-
|
|
683
|
+
restartNote: 'Restart your Codex CLI session.',
|
|
684
|
+
install(dir, scope) {
|
|
582
685
|
const toml = `[[mcp_servers]]\nname = "context-mcp"\ncommand = "npx"\nargs = ["-y", "context-mcp-server@latest"]\n`;
|
|
583
|
-
_writeFile(join(
|
|
584
|
-
|
|
585
|
-
|
|
686
|
+
_writeFile(join(dir, '.codex', 'config.toml'), toml, '.codex/config.toml');
|
|
687
|
+
if (scope === 'project') {
|
|
688
|
+
const md = _tpl('AGENTS.md');
|
|
689
|
+
if (md) _writeFile(join(dir, 'AGENTS.md'), md, 'AGENTS.md');
|
|
690
|
+
}
|
|
691
|
+
// Register via codex CLI so server is active immediately
|
|
692
|
+
const reg = spawnSync(
|
|
693
|
+
'codex', ['mcp', 'add', 'context-mcp', '--', 'npx', '-y', 'context-mcp-server@latest'],
|
|
694
|
+
{ encoding: 'utf8', shell: true },
|
|
695
|
+
);
|
|
696
|
+
if (reg.status === 0) {
|
|
697
|
+
console.log(` ${ok('✓')} ${'registered via codex mcp add'.padEnd(28)}`);
|
|
698
|
+
} else {
|
|
699
|
+
console.log(` ${faint('ℹ')} codex CLI not found — server will load on next Codex session`);
|
|
700
|
+
}
|
|
586
701
|
},
|
|
587
702
|
},
|
|
588
703
|
windsurf: {
|
|
589
704
|
label: 'Windsurf',
|
|
590
|
-
|
|
705
|
+
restartNote: 'Restart Windsurf to load the updated MCP config.',
|
|
706
|
+
install(dir) {
|
|
591
707
|
const rules = _tpl('windsurf-rules.md');
|
|
592
|
-
if (rules) _writeFile(join(
|
|
708
|
+
if (rules) _writeFile(join(dir, '.windsurf', 'rules', 'context-mcp.md'), rules, '.windsurf/rules/context-mcp.md');
|
|
593
709
|
const globalCfgPath = join(homedir(), '.codeium', 'windsurf', 'mcp_config.json');
|
|
594
710
|
let existing = {};
|
|
595
711
|
try { existing = JSON.parse(readFileSync(globalCfgPath, 'utf8')); } catch {}
|
|
@@ -600,7 +716,7 @@ const PLATFORMS = {
|
|
|
600
716
|
},
|
|
601
717
|
};
|
|
602
718
|
|
|
603
|
-
function cmdInstall(args) {
|
|
719
|
+
async function cmdInstall(args) {
|
|
604
720
|
const flags = new Set(args.map(a => a.replace(/^--/, '')));
|
|
605
721
|
const all = flags.has('all');
|
|
606
722
|
const initial = flags.has('initial');
|
|
@@ -665,22 +781,56 @@ function cmdInstall(args) {
|
|
|
665
781
|
return;
|
|
666
782
|
}
|
|
667
783
|
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
784
|
+
// ── Scope prompt (skip for windsurf-only installs — it's always global) ──────
|
|
785
|
+
const nonWindsurf = keys.filter(k => k !== 'windsurf');
|
|
786
|
+
let scope = 'project';
|
|
787
|
+
let baseDir = process.cwd();
|
|
788
|
+
|
|
789
|
+
if (nonWindsurf.length > 0) {
|
|
790
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
791
|
+
const ask = q => new Promise(resolve => rl.question(` ${accent('›')} ${muted(q)} `, resolve));
|
|
792
|
+
|
|
793
|
+
printSection('Install', keys.map(k => PLATFORMS[k].label).join(', '));
|
|
794
|
+
console.log('');
|
|
795
|
+
console.log(` ${muted('Install scope:')}`);
|
|
796
|
+
console.log(` ${accent('1.')} For this project ${faint('(writes config into current directory)')}`);
|
|
797
|
+
console.log(` ${accent('2.')} Globally ${faint('(writes config to your home directory)')}`);
|
|
798
|
+
console.log('');
|
|
799
|
+
const answer = (await ask('Choose (1/2) [1]:')).trim();
|
|
800
|
+
rl.close();
|
|
801
|
+
console.log('');
|
|
802
|
+
|
|
803
|
+
if (answer === '2') {
|
|
804
|
+
scope = 'global';
|
|
805
|
+
baseDir = homedir();
|
|
806
|
+
}
|
|
807
|
+
} else {
|
|
808
|
+
printSection('Install', keys.map(k => PLATFORMS[k].label).join(', '));
|
|
809
|
+
console.log('');
|
|
810
|
+
}
|
|
671
811
|
|
|
672
812
|
for (const key of keys) {
|
|
673
|
-
|
|
813
|
+
const platform = PLATFORMS[key];
|
|
814
|
+
console.log(` ${bold(lblue(platform.label))}`);
|
|
815
|
+
const dir = key === 'windsurf' ? process.cwd() : baseDir;
|
|
674
816
|
try {
|
|
675
|
-
|
|
817
|
+
platform.install(dir, scope);
|
|
676
818
|
} catch (err) {
|
|
677
819
|
console.log(` ${bad('✗')} failed: ${err.message}`);
|
|
678
820
|
}
|
|
821
|
+
if (platform.restartNote) {
|
|
822
|
+
console.log(` ${faint('→ ' + platform.restartNote)}`);
|
|
823
|
+
}
|
|
679
824
|
console.log('');
|
|
680
825
|
}
|
|
681
826
|
|
|
827
|
+
const destLabel = scope === 'global' ? homedir().replace(/\\/g, '/') : process.cwd().replace(/\\/g, '/');
|
|
682
828
|
console.log(line());
|
|
683
|
-
console.log(faint(` ${keys.length} platform(s) installed
|
|
829
|
+
console.log(faint(` ${keys.length} platform(s) installed · scope: ${scope} · ${destLabel}`));
|
|
830
|
+
console.log('');
|
|
831
|
+
|
|
832
|
+
// ── Global gitignore — add context-mcp runtime files if global gitignore exists ──
|
|
833
|
+
_updateGlobalGitignore();
|
|
684
834
|
console.log('');
|
|
685
835
|
|
|
686
836
|
// ── Python / uv setup (codegraph) ─────────────────────────────────────────
|
|
@@ -853,10 +1003,10 @@ async function cmdSettings(existingRl) {
|
|
|
853
1003
|
console.log('');
|
|
854
1004
|
|
|
855
1005
|
const choice = (await ask('Edit field (1-' + FIELDS.length + '):')).trim();
|
|
856
|
-
if (!existingRl) rl.close();
|
|
857
1006
|
|
|
858
1007
|
const idx = parseInt(choice) - 1;
|
|
859
1008
|
if (isNaN(idx) || idx < 0 || idx >= FIELDS.length) {
|
|
1009
|
+
if (!existingRl) rl.close();
|
|
860
1010
|
console.log(` ${faint('no changes made')}`);
|
|
861
1011
|
return;
|
|
862
1012
|
}
|
|
@@ -1007,7 +1157,7 @@ async function interactive() {
|
|
|
1007
1157
|
case 'benchmark': case 'bench':
|
|
1008
1158
|
clearScreen(); printCompactHeader('benchmark'); cmdBenchmark(); break;
|
|
1009
1159
|
case 'install':
|
|
1010
|
-
clearScreen(); printCompactHeader('install'); cmdInstall(rest); break;
|
|
1160
|
+
clearScreen(); printCompactHeader('install'); await cmdInstall(rest); break;
|
|
1011
1161
|
case 'online':
|
|
1012
1162
|
clearScreen(); printCompactHeader('online'); cmdOnline(rest); break;
|
|
1013
1163
|
case 'settings': case 'config':
|
|
@@ -1033,6 +1183,25 @@ function printBye() {
|
|
|
1033
1183
|
console.log(`\n ${ok('✓')} ${bold(lblue('goodbye'))} ${faint('keep building')}\n`);
|
|
1034
1184
|
}
|
|
1035
1185
|
|
|
1186
|
+
// ── Update check ──────────────────────────────────────────────────────────────
|
|
1187
|
+
|
|
1188
|
+
async function checkForUpdate() {
|
|
1189
|
+
try {
|
|
1190
|
+
const result = spawnSync(
|
|
1191
|
+
'npm', ['view', 'context-mcp-server', 'version', '--json'],
|
|
1192
|
+
{ encoding: 'utf8', timeout: 3000, shell: true },
|
|
1193
|
+
);
|
|
1194
|
+
if (result.status !== 0 || !result.stdout) return;
|
|
1195
|
+
const parsed = JSON.parse(result.stdout.trim());
|
|
1196
|
+
const latest = typeof parsed === 'string' ? parsed : String(parsed);
|
|
1197
|
+
const current = pkg.version;
|
|
1198
|
+
if (latest && latest !== current) {
|
|
1199
|
+
console.log(` ${warn('↑')} ${bold('Update available')} ${faint(current)} ${accent('→')} ${ok(latest)} ${faint('run:')} ${accent('npm i -g context-mcp-server@latest')}`);
|
|
1200
|
+
console.log('');
|
|
1201
|
+
}
|
|
1202
|
+
} catch {}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1036
1205
|
// ── CLI entry point ───────────────────────────────────────────────────────────
|
|
1037
1206
|
|
|
1038
1207
|
(async () => {
|
|
@@ -1052,7 +1221,24 @@ function printBye() {
|
|
|
1052
1221
|
case 'benchmark': case 'bench':
|
|
1053
1222
|
cmdBenchmark(); break;
|
|
1054
1223
|
case 'install':
|
|
1055
|
-
cmdInstall(rest);
|
|
1224
|
+
await cmdInstall(rest);
|
|
1225
|
+
process.exit(0);
|
|
1226
|
+
break;
|
|
1227
|
+
case 'update': {
|
|
1228
|
+
printSection('Update');
|
|
1229
|
+
console.log('');
|
|
1230
|
+
const upd = spawnSync(
|
|
1231
|
+
'npm', ['install', '-g', 'context-mcp-server@latest'],
|
|
1232
|
+
{ encoding: 'utf8', shell: true, stdio: 'inherit' },
|
|
1233
|
+
);
|
|
1234
|
+
if (upd.status === 0) {
|
|
1235
|
+
console.log(`\n ${ok('✓')} ${bold('context-mcp updated to latest')}`);
|
|
1236
|
+
} else {
|
|
1237
|
+
console.log(`\n ${bad('✗')} update failed — try: ${accent('npm i -g context-mcp-server@latest')}`);
|
|
1238
|
+
}
|
|
1239
|
+
console.log('');
|
|
1240
|
+
break;
|
|
1241
|
+
}
|
|
1056
1242
|
case 'online':
|
|
1057
1243
|
cmdOnline(rest); break;
|
|
1058
1244
|
case 'settings': case 'config':
|
|
@@ -1062,10 +1248,13 @@ function printBye() {
|
|
|
1062
1248
|
case 'delete': case 'del': case 'rm':
|
|
1063
1249
|
cmdDelete(rest); break;
|
|
1064
1250
|
case 'help': case '--help': case '-h':
|
|
1065
|
-
|
|
1251
|
+
await checkForUpdate();
|
|
1252
|
+
printUsage();
|
|
1253
|
+
break;
|
|
1066
1254
|
case '--version': case '-v':
|
|
1067
1255
|
console.log(pkg.version); break;
|
|
1068
1256
|
default:
|
|
1257
|
+
await checkForUpdate();
|
|
1069
1258
|
await interactive();
|
|
1070
1259
|
}
|
|
1071
1260
|
})();
|
package/src/templates/AGENTS.md
CHANGED
|
@@ -20,22 +20,40 @@ Then:
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
## 2.
|
|
23
|
+
## 2. When to Auto-Save Context
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
| Need past info | `search` before asking user |
|
|
25
|
+
**After graph build or rebuild** — every time `codegraph_build` completes:
|
|
26
|
+
```
|
|
27
|
+
context.save type: "architecture" title: "ContextGraph built — <project>"
|
|
28
|
+
content: "nodes: X | edges: Y | communities: Z"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**User explicitly asks** — "save this", "remember this", "note that" → save immediately.
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
**During plan / implementation / discussion / research** — save only when genuinely valuable:
|
|
34
|
+
|
|
35
|
+
| What happened | Type |
|
|
36
|
+
|--------------|------|
|
|
37
|
+
| Approach / library / pattern decided | `decision` |
|
|
38
|
+
| Bug found (root cause known) or fixed | `bug` |
|
|
39
|
+
| System structure understood | `architecture` |
|
|
40
|
+
| Gotcha, constraint, non-obvious behavior | `note` |
|
|
41
|
+
| Config / env var / secret key discovered | `config` |
|
|
42
|
+
| External API or service integration learned | `note` |
|
|
43
|
+
| Performance insight (why something is slow/fast) | `note` |
|
|
44
|
+
| How to run tests / test pattern discovered | `note` |
|
|
45
|
+
| Deploy / release step discovered | `note` |
|
|
46
|
+
| Milestone / feature / task completed | `note` |
|
|
47
|
+
|
|
48
|
+
Do NOT save: routine reads, search results, temporary debugging dead-ends.
|
|
49
|
+
Feature spans sessions → `discussion.save` status: `"active"`.
|
|
50
|
+
Need past info → `search` before asking. Always pass `project`.
|
|
35
51
|
|
|
36
52
|
---
|
|
37
53
|
|
|
38
|
-
## 3.
|
|
54
|
+
## 3. ContextGraph Pipeline
|
|
55
|
+
|
|
56
|
+
> The knowledge graph is also called **ContextGraph**. The MCP tools use the `codegraph_*` prefix — both names refer to the same thing.
|
|
39
57
|
|
|
40
58
|
### Step 1 — Build (once, fast, local)
|
|
41
59
|
```
|
package/src/templates/CLAUDE.md
CHANGED
|
@@ -28,22 +28,44 @@ Then:
|
|
|
28
28
|
|
|
29
29
|
---
|
|
30
30
|
|
|
31
|
-
## 2.
|
|
31
|
+
## 2. When to Auto-Save Context
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|-----------|--------|
|
|
35
|
-
| Decision made | `context.save` type: `"decision"` |
|
|
36
|
-
| Bug found/fixed | `context.save` type: `"bug"` |
|
|
37
|
-
| Architecture understood | `context.save` type: `"architecture"` |
|
|
38
|
-
| User says "save/remember this" | `context.save` immediately |
|
|
39
|
-
| Feature spans multiple conversations | `discussion.create` or `discussion.update` |
|
|
40
|
-
| Need past info | `search` before asking user |
|
|
33
|
+
### Always save — no user prompt needed
|
|
41
34
|
|
|
42
|
-
|
|
35
|
+
**After graph build or rebuild** — every time `codegraph_build` completes:
|
|
36
|
+
```
|
|
37
|
+
context.save type: "architecture" title: "ContextGraph built — <project>"
|
|
38
|
+
content: "nodes: X | edges: Y | communities: Z"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**User explicitly asks** — any phrase like "save this", "remember this", "note that" → save immediately.
|
|
42
|
+
|
|
43
|
+
**During plan / implementation / discussion / research** — save only when genuinely valuable:
|
|
44
|
+
|
|
45
|
+
| What happened | Type |
|
|
46
|
+
|--------------|------|
|
|
47
|
+
| Approach / library / pattern decided | `decision` |
|
|
48
|
+
| Bug found (root cause known) or fixed | `bug` |
|
|
49
|
+
| System structure understood | `architecture` |
|
|
50
|
+
| Gotcha, constraint, non-obvious behavior | `note` |
|
|
51
|
+
| Config / env var / secret key discovered | `config` |
|
|
52
|
+
| External API or service integration learned | `note` |
|
|
53
|
+
| Performance insight (why something is slow/fast) | `note` |
|
|
54
|
+
| How to run tests / test pattern discovered | `note` |
|
|
55
|
+
| Deploy / release step discovered | `note` |
|
|
56
|
+
| Milestone / feature / task completed | `note` |
|
|
57
|
+
|
|
58
|
+
Do NOT save: routine reads, search results, temporary debugging dead-ends.
|
|
59
|
+
|
|
60
|
+
Feature spans multiple sessions → `discussion.create` or `discussion.update`.
|
|
61
|
+
Need past info → `search` before asking user.
|
|
62
|
+
Always pass `project`. Auto-compact fires at >50 entries.
|
|
43
63
|
|
|
44
64
|
---
|
|
45
65
|
|
|
46
|
-
## 3.
|
|
66
|
+
## 3. ContextGraph Pipeline
|
|
67
|
+
|
|
68
|
+
> The knowledge graph is also called **ContextGraph**. The MCP tools use the `codegraph_*` prefix — both names refer to the same thing.
|
|
47
69
|
|
|
48
70
|
### Step 1 — Build (once per project, fast, local)
|
|
49
71
|
```
|
package/src/templates/GEMINI.md
CHANGED
|
@@ -20,22 +20,40 @@ Then:
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
## 2.
|
|
23
|
+
## 2. When to Auto-Save Context
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
| Need past info | `search` before asking user |
|
|
25
|
+
**After graph build or rebuild** — every time `codegraph_build` completes:
|
|
26
|
+
```
|
|
27
|
+
context.save type: "architecture" title: "ContextGraph built — <project>"
|
|
28
|
+
content: "nodes: X | edges: Y | communities: Z"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**User explicitly asks** — "save this", "remember this", "note that" → save immediately.
|
|
33
32
|
|
|
34
|
-
|
|
33
|
+
**During plan / implementation / discussion / research** — save only when genuinely valuable:
|
|
34
|
+
|
|
35
|
+
| What happened | Type |
|
|
36
|
+
|--------------|------|
|
|
37
|
+
| Approach / library / pattern decided | `decision` |
|
|
38
|
+
| Bug found (root cause known) or fixed | `bug` |
|
|
39
|
+
| System structure understood | `architecture` |
|
|
40
|
+
| Gotcha, constraint, non-obvious behavior | `note` |
|
|
41
|
+
| Config / env var / secret key discovered | `config` |
|
|
42
|
+
| External API or service integration learned | `note` |
|
|
43
|
+
| Performance insight (why something is slow/fast) | `note` |
|
|
44
|
+
| How to run tests / test pattern discovered | `note` |
|
|
45
|
+
| Deploy / release step discovered | `note` |
|
|
46
|
+
| Milestone / feature / task completed | `note` |
|
|
47
|
+
|
|
48
|
+
Do NOT save: routine reads, search results, temporary debugging dead-ends.
|
|
49
|
+
Feature spans sessions → `discussion.save` then `discussion.update`.
|
|
50
|
+
Need past info → `search` before asking. Always pass `project`.
|
|
35
51
|
|
|
36
52
|
---
|
|
37
53
|
|
|
38
|
-
## 3.
|
|
54
|
+
## 3. ContextGraph Pipeline
|
|
55
|
+
|
|
56
|
+
> The knowledge graph is also called **ContextGraph**. The MCP tools use the `codegraph_*` prefix — both names refer to the same thing.
|
|
39
57
|
|
|
40
58
|
### Step 1 — Build (once, fast, local)
|
|
41
59
|
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
Call the `context` MCP tool with `action: "resume"` and `project: "$ARGUMENTS"` (if no argument given, infer the project name from the current working directory name).
|
|
2
|
+
|
|
3
|
+
This loads:
|
|
4
|
+
- Recent decisions, bugs, and notes from past sessions
|
|
5
|
+
- Active discussions
|
|
6
|
+
- ContextGraph status (built or not)
|
|
7
|
+
|
|
8
|
+
If `codegraph.built` is false in the response, immediately call `codegraph_build` on the project path before proceeding.
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
Call `codegraph_build` with the path `$ARGUMENTS` (if no argument given, use the current working directory).
|
|
2
|
+
|
|
3
|
+
This builds the ContextGraph for the project — parses all source files into an AST knowledge graph using tree-sitter. Takes a few seconds. Once built, use `codegraph_query` to answer any structural question about the codebase instead of reading files directly.
|
|
4
|
+
|
|
5
|
+
After build completes, report: total nodes, edges, and communities found.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Call the `context` MCP tool with `action: "save"` to store a note for the current project.
|
|
2
|
+
|
|
3
|
+
Parse `$ARGUMENTS` to determine:
|
|
4
|
+
- `project`: infer from current working directory name if not specified
|
|
5
|
+
- `title`: first sentence or phrase from the argument
|
|
6
|
+
- `content`: full argument text
|
|
7
|
+
- `type`: auto-detect — if mentions a bug/fix → `"bug"`, decision/chose/decided → `"decision"`, structure/architecture → `"architecture"`, otherwise `"note"`
|
|
8
|
+
|
|
9
|
+
Confirm to the user what was saved (title, type, project).
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-mcp
|
|
3
|
+
description: >
|
|
4
|
+
Persistent memory + ContextGraph (codebase knowledge graph) for Claude.
|
|
5
|
+
Use at the START of every conversation to resume project context. Use
|
|
6
|
+
whenever the user mentions a project, asks to remember/save something,
|
|
7
|
+
references past work, or says "pick up where we left off". Also use
|
|
8
|
+
when the user asks about code structure, dependencies, or what exists
|
|
9
|
+
in a codebase — query the ContextGraph before reading any files.
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Context-MCP
|
|
13
|
+
|
|
14
|
+
Persistent memory + codebase knowledge graph across every conversation.
|
|
15
|
+
`context.resume` starts every session. `codegraph_query` answers every structure question. Files only for bugs/logic.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## MANDATORY: Start of Every Conversation
|
|
20
|
+
|
|
21
|
+
Call `context` tool, `action: "resume"`, `project: "<project-name>"` **before any tool or response**.
|
|
22
|
+
|
|
23
|
+
Infer `project` from the working directory name if not stated.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
- `recentEntries` — decisions, bugs, notes from past sessions
|
|
27
|
+
- `activeDiscussions` — ongoing topics (auto-linked if exactly one active)
|
|
28
|
+
- `codegraph` — `{ built: true/false, nodes, edges, communities }`
|
|
29
|
+
|
|
30
|
+
Then:
|
|
31
|
+
- `codegraph.built: true` → use `codegraph_query` before reading any files
|
|
32
|
+
- `codegraph.built: false` → call `codegraph_build(path)` first, then proceed
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## When to Auto-Save Context
|
|
37
|
+
|
|
38
|
+
### Always save — no user prompt needed
|
|
39
|
+
|
|
40
|
+
**1. After graph build or rebuild**
|
|
41
|
+
Every time `codegraph_build` completes successfully, immediately call:
|
|
42
|
+
```
|
|
43
|
+
context.save type: "architecture" title: "ContextGraph built — <project>"
|
|
44
|
+
content: "nodes: X | edges: Y | communities: Z | built: <timestamp>"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**2. When user explicitly asks**
|
|
48
|
+
Any phrase like "save this", "remember this", "note that", "log this" → `context.save` immediately with whatever was just discussed.
|
|
49
|
+
|
|
50
|
+
**3. During plan / implementation / discussion / research — save when something valuable happens**
|
|
51
|
+
Only save if the moment is genuinely worth keeping across sessions:
|
|
52
|
+
- A decision was made and agreed on (approach, library, pattern, architecture)
|
|
53
|
+
- A bug was found with its root cause identified, or fixed
|
|
54
|
+
- An important discovery (gotcha, constraint, non-obvious behavior, env requirement)
|
|
55
|
+
- A significant milestone reached (feature complete, refactor done, plan finalized)
|
|
56
|
+
- Something that would save future-you from re-learning it
|
|
57
|
+
|
|
58
|
+
Do NOT save for: routine file reads, search results, explanations of existing code, temporary debugging steps that led nowhere.
|
|
59
|
+
|
|
60
|
+
| What happened | Type |
|
|
61
|
+
|--------------|------|
|
|
62
|
+
| Approach / library / pattern decided | `decision` |
|
|
63
|
+
| Bug found (root cause known) or fixed | `bug` |
|
|
64
|
+
| System structure understood | `architecture` |
|
|
65
|
+
| Gotcha, constraint, non-obvious behavior | `note` |
|
|
66
|
+
| Config / env var / secret key discovered | `config` |
|
|
67
|
+
| External API or service integration learned | `note` |
|
|
68
|
+
| Performance insight (why something is slow/fast) | `note` |
|
|
69
|
+
| How to run tests / test pattern discovered | `note` |
|
|
70
|
+
| Deploy / release step discovered | `note` |
|
|
71
|
+
| Milestone / feature / task completed | `note` |
|
|
72
|
+
|
|
73
|
+
Always pass `project`. Feature spans multiple sessions → `discussion.create` or `discussion.update`. Need past info → `search` before asking user. Auto-compact fires at >50 entries.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## ContextGraph Pipeline
|
|
78
|
+
|
|
79
|
+
> Also called **CodeGraph**. MCP tools use the `codegraph_*` prefix — both names mean the same thing.
|
|
80
|
+
|
|
81
|
+
### Build (once per project, ~seconds, local)
|
|
82
|
+
```
|
|
83
|
+
codegraph_build(path)
|
|
84
|
+
```
|
|
85
|
+
Parses codebase into AST graph via tree-sitter. Extracts functions, classes, imports, call edges for 16+ languages. Build files get a single metadata node. Saved to `~/.context-mcp/graphs.json`.
|
|
86
|
+
|
|
87
|
+
### Query (free, instant, forever)
|
|
88
|
+
```
|
|
89
|
+
codegraph_query(path, question) → find functions, classes, files, dependencies, callers
|
|
90
|
+
codegraph_explain(path, node) → one node: type, file, depends_on, used_by
|
|
91
|
+
codegraph_path(path, from, to) → shortest path between two concepts
|
|
92
|
+
codegraph_nodes(path, type) → list all nodes of a type
|
|
93
|
+
codegraph_report(path) → god nodes, clusters, surprises
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Graph vs File
|
|
99
|
+
|
|
100
|
+
**Graph** — what exists: finding functions, classes, files, dependencies, callers, imports, paths between concepts.
|
|
101
|
+
|
|
102
|
+
**File** — bugs, logic inside a specific function, tracing unexpected behavior.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Rules
|
|
107
|
+
|
|
108
|
+
1. **`context.resume` first** — before any tool or response
|
|
109
|
+
2. **Always pass `project`** — never save to global unless truly cross-project
|
|
110
|
+
3. **`search` before asking** — if user references past work, find it first
|
|
111
|
+
4. **`codegraph_query` before reading files** — graph is faster and cheaper
|
|
112
|
+
5. **Read files for bugs/logic only** — graph is structure, not behavior
|