context-mcp-server 1.0.1
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 +464 -0
- package/codegraph/__init__.py +0 -0
- package/codegraph/__main__.py +24 -0
- package/codegraph/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/__main__.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/cache.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/config.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/report.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/scanner.cpython-313.pyc +0 -0
- package/codegraph/__pycache__/server.cpython-313.pyc +0 -0
- package/codegraph/cache.py +137 -0
- package/codegraph/config.py +31 -0
- package/codegraph/extractors/__init__.py +0 -0
- package/codegraph/extractors/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codegraph/extractors/__pycache__/ast_extractor.cpython-313.pyc +0 -0
- package/codegraph/extractors/__pycache__/audio_extractor.cpython-313.pyc +0 -0
- package/codegraph/extractors/__pycache__/doc_extractor.cpython-313.pyc +0 -0
- package/codegraph/extractors/__pycache__/image_extractor.cpython-313.pyc +0 -0
- package/codegraph/extractors/ast_extractor.py +222 -0
- package/codegraph/extractors/audio_extractor.py +8 -0
- package/codegraph/extractors/doc_extractor.py +34 -0
- package/codegraph/extractors/image_extractor.py +26 -0
- package/codegraph/graph/__init__.py +0 -0
- package/codegraph/graph/__pycache__/__init__.cpython-313.pyc +0 -0
- package/codegraph/graph/__pycache__/builder.cpython-313.pyc +0 -0
- package/codegraph/graph/__pycache__/clustering.cpython-313.pyc +0 -0
- package/codegraph/graph/__pycache__/query.cpython-313.pyc +0 -0
- package/codegraph/graph/builder.py +145 -0
- package/codegraph/graph/clustering.py +40 -0
- package/codegraph/graph/query.py +283 -0
- package/codegraph/report.py +115 -0
- package/codegraph/scanner.py +92 -0
- package/codegraph/server.py +514 -0
- package/package.json +62 -0
- package/src/cli.js +1010 -0
- package/src/config.js +89 -0
- package/src/db.js +786 -0
- package/src/guard.js +20 -0
- package/src/hooks/autoContext.js +17 -0
- package/src/hooks/autoLink.js +7 -0
- package/src/http.js +765 -0
- package/src/index.js +47 -0
- package/src/search.js +50 -0
- package/src/server.js +80 -0
- package/src/summarizer.js +124 -0
- package/src/templates/AGENTS.md +76 -0
- package/src/templates/CLAUDE.md +94 -0
- package/src/templates/GEMINI.md +76 -0
- package/src/templates/cursor-rules.mdc +41 -0
- package/src/templates/windsurf-rules.md +35 -0
- package/src/tools/codegraph.js +215 -0
- package/src/tools/context.js +188 -0
- package/src/tools/discussion.js +123 -0
- package/src/tools/errorCheck.js +65 -0
- package/src/tools/fileTools.js +185 -0
- package/src/tools/gitTools.js +259 -0
- package/src/tools/search.js +55 -0
- package/src/vector.js +153 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createServer } from './server.js';
|
|
3
|
+
|
|
4
|
+
// ── CLI flags ─────────────────────────────────────────────────────────────────
|
|
5
|
+
// --data-dir <path> Override ~/.context-mcp storage directory
|
|
6
|
+
// --help Show usage
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
|
|
10
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
11
|
+
console.log(`
|
|
12
|
+
context-mcp — Persistent AI memory MCP server (stdio transport)
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
context-mcp [options]
|
|
16
|
+
npx context-mcp-server@latest [options]
|
|
17
|
+
|
|
18
|
+
Options:
|
|
19
|
+
--data-dir <path> Override storage directory (default: ~/.context-mcp)
|
|
20
|
+
Also settable via env: CONTEXT_MCP_DIR=<path>
|
|
21
|
+
--help, -h Show this help
|
|
22
|
+
|
|
23
|
+
Platform setup (stdio):
|
|
24
|
+
Claude Code: claude mcp add context-mcp npx context-mcp-server@latest
|
|
25
|
+
Cursor: add to .cursor/mcp.json
|
|
26
|
+
VS Code: add to .vscode/mcp.json
|
|
27
|
+
Gemini CLI: add to .gemini/settings.json
|
|
28
|
+
Codex CLI: add to .codex/config.toml
|
|
29
|
+
Windsurf: add to global mcp_config.json
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
context-mcp
|
|
33
|
+
context-mcp --data-dir /my/project/.ctx
|
|
34
|
+
CONTEXT_MCP_DIR=/tmp/ctx context-mcp
|
|
35
|
+
`);
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const dataDirIdx = args.indexOf('--data-dir');
|
|
40
|
+
if (dataDirIdx !== -1 && args[dataDirIdx + 1]) {
|
|
41
|
+
process.env.CONTEXT_MCP_DIR = args[dataDirIdx + 1];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const { StdioServerTransport } = await import('@modelcontextprotocol/sdk/server/stdio.js');
|
|
45
|
+
const server = createServer();
|
|
46
|
+
const transport = new StdioServerTransport();
|
|
47
|
+
await server.connect(transport);
|
package/src/search.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* search.js — unified search entry point
|
|
3
|
+
*
|
|
4
|
+
* Single function replaces direct calls to searchContext / vectorSearch / findRelated
|
|
5
|
+
* across index.js, cli.js, and error_check. db.js + vector.js stay as low-level impls.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getContext, searchContext } from './db.js';
|
|
9
|
+
import { vectorSearch, findRelated } from './vector.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {Object} opts
|
|
13
|
+
* @param {string} opts.query - search query (keyword/semantic)
|
|
14
|
+
* @param {string} [opts.mode] - 'keyword' | 'semantic' | 'related' (default: semantic)
|
|
15
|
+
* @param {string} [opts.project] - scope to project
|
|
16
|
+
* @param {number} [opts.limit] - max results (default 10)
|
|
17
|
+
* @param {string} [opts.id] - [related] entry ID
|
|
18
|
+
* @param {boolean} [opts.compact] - return compact previews
|
|
19
|
+
*/
|
|
20
|
+
export function search({ query, mode = 'semantic', project, limit = 10, id, compact = false }) {
|
|
21
|
+
switch (mode) {
|
|
22
|
+
case 'keyword': {
|
|
23
|
+
if (!query) throw new Error('query required for keyword search');
|
|
24
|
+
return searchContext({ query, project, limit, compact });
|
|
25
|
+
}
|
|
26
|
+
case 'semantic': {
|
|
27
|
+
if (!query) throw new Error('query required for semantic search');
|
|
28
|
+
const corpus = getContext({ project, limit: 500 });
|
|
29
|
+
return vectorSearch(query, corpus, limit);
|
|
30
|
+
}
|
|
31
|
+
case 'related': {
|
|
32
|
+
if (!id) throw new Error('id required for related search');
|
|
33
|
+
const all = getContext({ limit: 1000 });
|
|
34
|
+
const target = all.find(e => e.id === id || e.id.startsWith(id));
|
|
35
|
+
if (!target) throw new Error(`No entry found with id starting "${id}"`);
|
|
36
|
+
// explicit relations first, semantic enrichment for remainder
|
|
37
|
+
const explicitIds = new Set([
|
|
38
|
+
...(target.relations || []).map(r => r.id),
|
|
39
|
+
...(target.relatedBy || []).map(r => r.id),
|
|
40
|
+
]);
|
|
41
|
+
const explicit = all.filter(e => explicitIds.has(e.id));
|
|
42
|
+
const semantic = explicitIds.size < limit
|
|
43
|
+
? findRelated(target, all.filter(e => !explicitIds.has(e.id) && e.id !== target.id), limit - explicitIds.size)
|
|
44
|
+
: [];
|
|
45
|
+
return { target, results: [...explicit, ...semantic].slice(0, limit) };
|
|
46
|
+
}
|
|
47
|
+
default:
|
|
48
|
+
throw new Error(`Unknown search mode: ${mode}. Use: keyword, semantic, related`);
|
|
49
|
+
}
|
|
50
|
+
}
|
package/src/server.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
+
|
|
4
|
+
import { getConfig } from './config.js';
|
|
5
|
+
|
|
6
|
+
import * as contextTool from './tools/context.js';
|
|
7
|
+
import * as searchTool from './tools/search.js';
|
|
8
|
+
import * as discussionTool from './tools/discussion.js';
|
|
9
|
+
import * as errorCheckTool from './tools/errorCheck.js';
|
|
10
|
+
import * as fileTool from './tools/fileTools.js';
|
|
11
|
+
import * as gitTool from './tools/gitTools.js';
|
|
12
|
+
import * as codegraphTool from './tools/codegraph.js';
|
|
13
|
+
|
|
14
|
+
const FILE_TOOL_NAMES = new Set(fileTool.definitions.map(d => d.name));
|
|
15
|
+
const GIT_TOOL_NAMES = new Set(gitTool.definitions.map(d => d.name));
|
|
16
|
+
const CODEGRAPH_TOOL_NAMES = codegraphTool.TOOL_NAMES;
|
|
17
|
+
|
|
18
|
+
export function createServer({ enableFileTools = false, enableGitTools = getConfig().access_git === true } = {}) {
|
|
19
|
+
const state = {
|
|
20
|
+
sessionProject: null,
|
|
21
|
+
discussionId: null,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const server = new Server(
|
|
25
|
+
{ name: 'context-mcp', version: '1.0.0' },
|
|
26
|
+
{ capabilities: { tools: {} } }
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
30
|
+
const tools = [
|
|
31
|
+
contextTool.definition,
|
|
32
|
+
searchTool.definition,
|
|
33
|
+
discussionTool.definition,
|
|
34
|
+
errorCheckTool.definition,
|
|
35
|
+
];
|
|
36
|
+
if (enableFileTools) tools.push(...fileTool.definitions);
|
|
37
|
+
if (enableGitTools) tools.push(...gitTool.definitions);
|
|
38
|
+
tools.push(...codegraphTool.definitions);
|
|
39
|
+
return { tools };
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
43
|
+
const { name, arguments: args = {} } = request.params;
|
|
44
|
+
|
|
45
|
+
if (FILE_TOOL_NAMES.has(name) && !enableFileTools) {
|
|
46
|
+
throw new Error(`Tool "${name}" is only available in online (HTTP) mode.`);
|
|
47
|
+
}
|
|
48
|
+
if (GIT_TOOL_NAMES.has(name) && !enableGitTools) {
|
|
49
|
+
throw new Error(`Tool "${name}" requires ACCESS_GIT=true.`);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try {
|
|
53
|
+
let result;
|
|
54
|
+
|
|
55
|
+
if (name === contextTool.definition.name) {
|
|
56
|
+
result = await contextTool.handle(args, state);
|
|
57
|
+
} else if (name === searchTool.definition.name) {
|
|
58
|
+
result = await searchTool.handle(args, state);
|
|
59
|
+
} else if (name === discussionTool.definition.name) {
|
|
60
|
+
result = await discussionTool.handle(args, state);
|
|
61
|
+
} else if (name === errorCheckTool.definition.name) {
|
|
62
|
+
result = await errorCheckTool.handle(args, state);
|
|
63
|
+
} else if (FILE_TOOL_NAMES.has(name)) {
|
|
64
|
+
result = await fileTool.handle(name, args, state);
|
|
65
|
+
} else if (GIT_TOOL_NAMES.has(name)) {
|
|
66
|
+
result = await gitTool.handle(name, args, state);
|
|
67
|
+
} else if (CODEGRAPH_TOOL_NAMES.has(name)) {
|
|
68
|
+
result = codegraphTool.handle(name, args, state);
|
|
69
|
+
} else {
|
|
70
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
|
|
74
|
+
} catch (err) {
|
|
75
|
+
return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return server;
|
|
80
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* summarizer.js — session auto-summarizer
|
|
3
|
+
*
|
|
4
|
+
* Groups recent context entries by project and tag, then produces
|
|
5
|
+
* a structured Markdown summary you can save back as a single entry.
|
|
6
|
+
*
|
|
7
|
+
* Uses extractive summarization (no LLM needed):
|
|
8
|
+
* 1. Score sentences by TF-IDF weight against the session's corpus
|
|
9
|
+
* 2. Pick top N sentences in original order
|
|
10
|
+
* 3. Format as structured Markdown
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { vectorSearch } from './vector.js';
|
|
14
|
+
|
|
15
|
+
// ── Sentence scoring ──────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
function sentences(text) {
|
|
18
|
+
return String(text || '')
|
|
19
|
+
.replace(/\n+/g, ' ')
|
|
20
|
+
.split(/(?<=[.!?])\s+/)
|
|
21
|
+
.map(s => s.trim())
|
|
22
|
+
.filter(s => s.length > 20);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const STOP = new Set([
|
|
26
|
+
'a','an','the','and','or','but','in','on','at','to','for','of','with',
|
|
27
|
+
'by','from','is','it','its','as','be','was','are','this','that','i','we',
|
|
28
|
+
]);
|
|
29
|
+
|
|
30
|
+
function tokens(text) {
|
|
31
|
+
return text.toLowerCase().replace(/[^a-z0-9\s]/g, ' ').split(/\s+/)
|
|
32
|
+
.filter(w => w.length > 2 && !STOP.has(w));
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function scoreEntry(entry, corpusTokenFreq) {
|
|
36
|
+
const toks = tokens(`${entry.title || ''} ${entry.content || ''}`);
|
|
37
|
+
if (!toks.length) return 0;
|
|
38
|
+
return toks.reduce((s, t) => s + (corpusTokenFreq[t] || 0), 0) / toks.length;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function buildFreq(entries) {
|
|
42
|
+
const freq = {};
|
|
43
|
+
for (const e of entries) {
|
|
44
|
+
for (const t of tokens(`${e.title || ''} ${e.content || ''}`)) {
|
|
45
|
+
freq[t] = (freq[t] || 0) + 1;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return freq;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ── Group by tag ──────────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
function groupByTag(entries) {
|
|
54
|
+
const groups = {};
|
|
55
|
+
for (const e of entries) {
|
|
56
|
+
const tags = Array.isArray(e.tags) ? e.tags : [];
|
|
57
|
+
const primaryTag = tags[0] || 'general';
|
|
58
|
+
if (!groups[primaryTag]) groups[primaryTag] = [];
|
|
59
|
+
groups[primaryTag].push(e);
|
|
60
|
+
}
|
|
61
|
+
return groups;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ── Build Markdown summary ────────────────────────────────────────────────────
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Summarize a set of context entries into structured Markdown.
|
|
68
|
+
*
|
|
69
|
+
* @param {Array} entries - context entries to summarize
|
|
70
|
+
* @param {Object} opts
|
|
71
|
+
* @param {string} opts.project
|
|
72
|
+
* @param {string} opts.sessionLabel - e.g. "2025-01-15 morning session"
|
|
73
|
+
* @param {number} opts.topN - top entries per group (default 3)
|
|
74
|
+
* @returns {string} Markdown summary
|
|
75
|
+
*/
|
|
76
|
+
export function summarizeEntries(entries, { project = 'global', sessionLabel = '', topN = 3 } = {}) {
|
|
77
|
+
if (!entries.length) return '_No entries to summarize._';
|
|
78
|
+
|
|
79
|
+
const freq = buildFreq(entries);
|
|
80
|
+
const label = sessionLabel || new Date().toISOString().slice(0, 10);
|
|
81
|
+
const groups = groupByTag(entries);
|
|
82
|
+
|
|
83
|
+
const lines = [
|
|
84
|
+
`## Session summary — ${project} · ${label}`,
|
|
85
|
+
'',
|
|
86
|
+
`**${entries.length} context entries** across ${Object.keys(groups).length} topic(s).`,
|
|
87
|
+
'',
|
|
88
|
+
];
|
|
89
|
+
|
|
90
|
+
for (const [tag, group] of Object.entries(groups)) {
|
|
91
|
+
lines.push(`### ${tag}`);
|
|
92
|
+
// Score and pick top N
|
|
93
|
+
const ranked = group
|
|
94
|
+
.map(e => ({ ...e, _score: scoreEntry(e, freq) }))
|
|
95
|
+
.sort((a, b) => b._score - a._score)
|
|
96
|
+
.slice(0, topN);
|
|
97
|
+
|
|
98
|
+
for (const e of ranked) {
|
|
99
|
+
lines.push(`- **${e.title || e.id.slice(0, 8)}** _(${e.source || 'user'}, ${(e.createdAt || '').slice(0, 10)})_`);
|
|
100
|
+
// Extract most informative sentence
|
|
101
|
+
const sents = sentences(e.content);
|
|
102
|
+
const best = sents.sort((a, b) =>
|
|
103
|
+
tokens(b).reduce((s, t) => s + (freq[t] || 0), 0) -
|
|
104
|
+
tokens(a).reduce((s, t) => s + (freq[t] || 0), 0)
|
|
105
|
+
)[0];
|
|
106
|
+
if (best) lines.push(` ${best.length > 140 ? best.slice(0, 137) + '...' : best}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (group.length > topN) {
|
|
110
|
+
lines.push(` _…and ${group.length - topN} more ${tag} entries_`);
|
|
111
|
+
}
|
|
112
|
+
lines.push('');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// Key terms
|
|
116
|
+
const topTerms = Object.entries(freq)
|
|
117
|
+
.sort((a, b) => b[1] - a[1])
|
|
118
|
+
.slice(0, 10)
|
|
119
|
+
.map(([t]) => `\`${t}\``);
|
|
120
|
+
lines.push(`**Key terms:** ${topTerms.join(', ')}`);
|
|
121
|
+
|
|
122
|
+
return lines.join('\n');
|
|
123
|
+
}
|
|
124
|
+
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Context-MCP — Codex CLI Usage Guide
|
|
2
|
+
|
|
3
|
+
Persistent memory + codebase knowledge graph.
|
|
4
|
+
Every conversation starts with `context.resume`. Every structural question uses `codegraph_query`. Files only read for bugs/logic.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Start of Every Conversation (MANDATORY)
|
|
9
|
+
|
|
10
|
+
Call the `context` MCP tool with `action: "resume"`, `project: "<project-name>"` **before anything else**.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
- `recentEntries` — decisions, bugs, notes from previous conversations
|
|
14
|
+
- `activeDiscussions` — ongoing topics
|
|
15
|
+
- `codegraph` — `{ built: true/false, nodes, edges, communities }`
|
|
16
|
+
|
|
17
|
+
Then:
|
|
18
|
+
- `codegraph.built: true` → use `codegraph_query` before reading any files
|
|
19
|
+
- `codegraph.built: false` → call `codegraph_build(path)` first, then proceed
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. During the Conversation
|
|
24
|
+
|
|
25
|
+
| Situation | Action |
|
|
26
|
+
|-----------|--------|
|
|
27
|
+
| Decision made | `context.save` type: `"decision"` |
|
|
28
|
+
| Bug found/fixed | `context.save` type: `"bug"` |
|
|
29
|
+
| Architecture understood | `context.save` type: `"architecture"` |
|
|
30
|
+
| User says "save/remember this" | `context.save` immediately |
|
|
31
|
+
| Feature spans sessions | `discussion.save` status: `"active"` |
|
|
32
|
+
| Need past info | `search` before asking user |
|
|
33
|
+
|
|
34
|
+
Always pass `project`. Auto-compact fires at >50 entries.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3. CodeGraph Pipeline
|
|
39
|
+
|
|
40
|
+
### Step 1 — Build (once, free)
|
|
41
|
+
```
|
|
42
|
+
codegraph_build(path) → AST graph: functions, classes, imports, edges
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Step 2 — Enrich (one-time per file)
|
|
46
|
+
```
|
|
47
|
+
codegraph_extract(path) → file content + node list
|
|
48
|
+
codegraph_add_nodes(path, nodes) → semantic descriptions (permanent cache)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Step 3 — Query (free, instant)
|
|
52
|
+
```
|
|
53
|
+
codegraph_query(path, question) → NODE/EDGE subgraph (token_budget default 2000)
|
|
54
|
+
codegraph_explain(path, node) → single node + neighbors
|
|
55
|
+
codegraph_path(path, from, to) → shortest path
|
|
56
|
+
codegraph_nodes(path, type) → list nodes by type
|
|
57
|
+
codegraph_report(path) → full graph analysis
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 4. Graph vs File
|
|
63
|
+
|
|
64
|
+
**Graph** — structural questions: dependencies, callers, imports.
|
|
65
|
+
**File** — bugs, logic, tracing behavior.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 5. Rules
|
|
70
|
+
|
|
71
|
+
1. **`context.resume` first** — before any tool or response
|
|
72
|
+
2. **Always pass `project`**
|
|
73
|
+
3. **`search` before asking** — if user references past work
|
|
74
|
+
4. **`codegraph_query` before reading files**
|
|
75
|
+
5. **Read files for bugs/logic only**
|
|
76
|
+
6. **Enrich once** — descriptions persist forever
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: context-mcp
|
|
3
|
+
description: >
|
|
4
|
+
Guides Claude on using the context-mcp memory + knowledge graph system.
|
|
5
|
+
Trigger at the start of every conversation, when the user mentions a project,
|
|
6
|
+
asks to remember/save something, or says "pick up where we left off".
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Context-MCP — Claude Usage Guide
|
|
10
|
+
|
|
11
|
+
Persistent memory + codebase knowledge graph for Claude.
|
|
12
|
+
Every conversation starts with `context.resume`. Every structural question uses `codegraph_query`. Files only read for bugs/logic.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## 1. Start of Every Conversation (MANDATORY)
|
|
17
|
+
|
|
18
|
+
Call `context` tool, `action: "resume"`, `project: "<project-name>"` **before anything else**.
|
|
19
|
+
|
|
20
|
+
Returns:
|
|
21
|
+
- `recentEntries` — decisions, bugs, notes from previous conversations
|
|
22
|
+
- `activeDiscussions` — ongoing topics (auto-linked if exactly one active)
|
|
23
|
+
- `codegraph` — `{ built: true/false, nodes, edges, communities }`
|
|
24
|
+
|
|
25
|
+
Then:
|
|
26
|
+
- `codegraph.built: true` → use `codegraph_query` before reading any files
|
|
27
|
+
- `codegraph.built: false` → call `codegraph_build(path)` first, then proceed
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2. During the Conversation
|
|
32
|
+
|
|
33
|
+
| Situation | Action |
|
|
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 |
|
|
41
|
+
|
|
42
|
+
Always pass `project`. Auto-compact fires at >50 entries — oldest summarized automatically.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 3. CodeGraph Pipeline
|
|
47
|
+
|
|
48
|
+
### Step 1 — Build (once per project, free)
|
|
49
|
+
```
|
|
50
|
+
codegraph_build(path)
|
|
51
|
+
→ AST: code files → functions, classes, imports, edges
|
|
52
|
+
→ Config: .yaml .toml .sql → schema nodes
|
|
53
|
+
→ Docs: .md .txt .pdf → pending (no content yet)
|
|
54
|
+
```
|
|
55
|
+
Saves graph to `~/.context-mcp/graphs.json`. Visible on `context.resume`.
|
|
56
|
+
|
|
57
|
+
### Step 2 — Enrich (one-time cost per file)
|
|
58
|
+
```
|
|
59
|
+
codegraph_extract(path)
|
|
60
|
+
→ returns changed code files (with existing node list) + doc files (raw text)
|
|
61
|
+
|
|
62
|
+
For each code file: write description for each node listed in existing_nodes
|
|
63
|
+
For each doc file: extract concept nodes + relationships
|
|
64
|
+
|
|
65
|
+
codegraph_add_nodes(path, nodes)
|
|
66
|
+
→ stores descriptions in semantic cache (never overwritten by rebuild)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Step 3 — Query (free, instant forever)
|
|
70
|
+
```
|
|
71
|
+
codegraph_query(path, question) → NODE/EDGE subgraph, token_budget param (default 2000)
|
|
72
|
+
codegraph_explain(path, node) → one node: description + depends_on + used_by
|
|
73
|
+
codegraph_path(path, from, to) → shortest path between two concepts
|
|
74
|
+
codegraph_nodes(path, type) → list all nodes of a type
|
|
75
|
+
codegraph_report(path) → god nodes, clusters, surprises
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 4. Graph vs File
|
|
81
|
+
|
|
82
|
+
**Graph** — structural questions: dependencies, callers, imports, paths between concepts.
|
|
83
|
+
**File** — bugs, logic inside a function, tracing unexpected behavior.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 5. Rules
|
|
88
|
+
|
|
89
|
+
1. **`context.resume` first** — before any tool or response
|
|
90
|
+
2. **Always pass `project`** — never save to global unless truly cross-project
|
|
91
|
+
3. **`search` before asking** — if user references past work, find it first
|
|
92
|
+
4. **`codegraph_query` before reading files** — graph is faster and cheaper
|
|
93
|
+
5. **Read files for bugs/logic** — graph is structure only, not behavior
|
|
94
|
+
6. **Enrich once** — run extract → add_nodes once per project; descriptions persist forever
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Context-MCP — Gemini CLI Usage Guide
|
|
2
|
+
|
|
3
|
+
Persistent memory + codebase knowledge graph.
|
|
4
|
+
Every conversation starts with `context.resume`. Every structural question uses `codegraph_query`. Files only read for bugs/logic.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 1. Start of Every Conversation (MANDATORY)
|
|
9
|
+
|
|
10
|
+
Call the `context` MCP tool with `action: "resume"`, `project: "<project-name>"` **before anything else**.
|
|
11
|
+
|
|
12
|
+
Returns:
|
|
13
|
+
- `recentEntries` — decisions, bugs, notes from previous conversations
|
|
14
|
+
- `activeDiscussions` — ongoing topics (auto-linked if exactly one active)
|
|
15
|
+
- `codegraph` — `{ built: true/false, nodes, edges, communities }`
|
|
16
|
+
|
|
17
|
+
Then:
|
|
18
|
+
- `codegraph.built: true` → use `codegraph_query` before reading any files
|
|
19
|
+
- `codegraph.built: false` → call `codegraph_build(path)` first, then proceed
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## 2. During the Conversation
|
|
24
|
+
|
|
25
|
+
| Situation | Action |
|
|
26
|
+
|-----------|--------|
|
|
27
|
+
| Decision made | `context.save` type: `"decision"` |
|
|
28
|
+
| Bug found/fixed | `context.save` type: `"bug"` |
|
|
29
|
+
| Architecture understood | `context.save` type: `"architecture"` |
|
|
30
|
+
| User says "save/remember this" | `context.save` immediately |
|
|
31
|
+
| Feature spans sessions | `discussion.save` then `discussion.update` |
|
|
32
|
+
| Need past info | `search` before asking user |
|
|
33
|
+
|
|
34
|
+
Always pass `project`. Auto-compact fires at >50 entries.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 3. CodeGraph Pipeline
|
|
39
|
+
|
|
40
|
+
### Step 1 — Build (once, free)
|
|
41
|
+
```
|
|
42
|
+
codegraph_build(path) → AST graph: functions, classes, imports, edges
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Step 2 — Enrich (one-time per file)
|
|
46
|
+
```
|
|
47
|
+
codegraph_extract(path) → file content + node list
|
|
48
|
+
codegraph_add_nodes(path, nodes) → semantic descriptions (permanent cache)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Step 3 — Query (free, instant)
|
|
52
|
+
```
|
|
53
|
+
codegraph_query(path, question) → NODE/EDGE subgraph (token_budget default 2000)
|
|
54
|
+
codegraph_explain(path, node) → single node + neighbors
|
|
55
|
+
codegraph_path(path, from, to) → shortest path
|
|
56
|
+
codegraph_nodes(path, type) → list nodes by type
|
|
57
|
+
codegraph_report(path) → full graph analysis
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## 4. Graph vs File
|
|
63
|
+
|
|
64
|
+
**Graph** — structural questions: dependencies, callers, imports.
|
|
65
|
+
**File** — bugs, logic, tracing behavior.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 5. Rules
|
|
70
|
+
|
|
71
|
+
1. **`context.resume` first** — before any tool or response
|
|
72
|
+
2. **Always pass `project`** — never save to global unless truly cross-project
|
|
73
|
+
3. **`search` before asking** — if user references past work, find it first
|
|
74
|
+
4. **`codegraph_query` before reading files** — graph is faster and cheaper
|
|
75
|
+
5. **Read files for bugs/logic** — graph is structure only, not behavior
|
|
76
|
+
6. **Enrich once** — descriptions persist forever
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Use context-mcp for persistent memory and codebase knowledge graph across all AI sessions.
|
|
3
|
+
globs: ["**/*"]
|
|
4
|
+
alwaysApply: true
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Context-MCP — Cursor Usage Guide
|
|
8
|
+
|
|
9
|
+
Persistent memory + codebase knowledge graph for Cursor.
|
|
10
|
+
Every conversation starts with `context.resume`. Every structural question uses `codegraph_query`. Files only read for bugs/logic.
|
|
11
|
+
|
|
12
|
+
## 1. Start of Every Conversation (MANDATORY)
|
|
13
|
+
|
|
14
|
+
Call `context` tool, `action: "resume"`, `project: "<project-name>"` before anything else.
|
|
15
|
+
|
|
16
|
+
Returns: `recentEntries`, `activeDiscussions`, `codegraph { built, nodes, edges }`.
|
|
17
|
+
|
|
18
|
+
- `codegraph.built: true` → use `codegraph_query` before reading files
|
|
19
|
+
- `codegraph.built: false` → run `codegraph_build(path)` first
|
|
20
|
+
|
|
21
|
+
## 2. Save Context
|
|
22
|
+
|
|
23
|
+
| Situation | Action |
|
|
24
|
+
|-----------|--------|
|
|
25
|
+
| Decision made | `context.save` type: `"decision"` |
|
|
26
|
+
| Bug found/fixed | `context.save` type: `"bug"` |
|
|
27
|
+
| Architecture understood | `context.save` type: `"architecture"` |
|
|
28
|
+
| Multi-session feature | `discussion.create` |
|
|
29
|
+
|
|
30
|
+
## 3. CodeGraph
|
|
31
|
+
|
|
32
|
+
Build once: `codegraph_build(path)` — then query forever.
|
|
33
|
+
Use `codegraph_query` for structural questions. Read files for bugs/logic.
|
|
34
|
+
|
|
35
|
+
## Rules
|
|
36
|
+
|
|
37
|
+
1. `context.resume` first — every conversation
|
|
38
|
+
2. Always pass `project`
|
|
39
|
+
3. `search` before asking the user about past work
|
|
40
|
+
4. `codegraph_query` before reading files
|
|
41
|
+
5. Files only for bugs and logic
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Context-MCP — Windsurf Usage Guide
|
|
2
|
+
|
|
3
|
+
Persistent memory + codebase knowledge graph for Windsurf.
|
|
4
|
+
Every conversation starts with `context.resume`. Every structural question uses `codegraph_query`. Files only read for bugs/logic.
|
|
5
|
+
|
|
6
|
+
## 1. Start of Every Conversation (MANDATORY)
|
|
7
|
+
|
|
8
|
+
Call `context` tool, `action: "resume"`, `project: "<project-name>"` before anything else.
|
|
9
|
+
|
|
10
|
+
Returns: `recentEntries`, `activeDiscussions`, `codegraph { built, nodes, edges }`.
|
|
11
|
+
|
|
12
|
+
- `codegraph.built: true` → use `codegraph_query` before reading files
|
|
13
|
+
- `codegraph.built: false` → run `codegraph_build(path)` first
|
|
14
|
+
|
|
15
|
+
## 2. Save Context
|
|
16
|
+
|
|
17
|
+
| Situation | Action |
|
|
18
|
+
|-----------|--------|
|
|
19
|
+
| Decision made | `context.save` type: `"decision"` |
|
|
20
|
+
| Bug found/fixed | `context.save` type: `"bug"` |
|
|
21
|
+
| Architecture understood | `context.save` type: `"architecture"` |
|
|
22
|
+
| Multi-session feature | `discussion.create` |
|
|
23
|
+
|
|
24
|
+
## 3. CodeGraph
|
|
25
|
+
|
|
26
|
+
Build once: `codegraph_build(path)` — then query forever.
|
|
27
|
+
Use `codegraph_query` for structural questions. Read files for bugs/logic.
|
|
28
|
+
|
|
29
|
+
## Rules
|
|
30
|
+
|
|
31
|
+
1. `context.resume` first — every conversation
|
|
32
|
+
2. Always pass `project`
|
|
33
|
+
3. `search` before asking the user about past work
|
|
34
|
+
4. `codegraph_query` before reading files
|
|
35
|
+
5. Files only for bugs and logic
|