context-mcp-server 1.1.0 → 1.1.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.
Files changed (72) hide show
  1. package/README.md +29 -7
  2. package/codegraph/__pycache__/affected.cpython-313.pyc +0 -0
  3. package/codegraph/__pycache__/cache.cpython-313.pyc +0 -0
  4. package/codegraph/__pycache__/callflow_html.cpython-313.pyc +0 -0
  5. package/codegraph/__pycache__/export.cpython-313.pyc +0 -0
  6. package/codegraph/__pycache__/report.cpython-313.pyc +0 -0
  7. package/codegraph/__pycache__/server.cpython-313.pyc +0 -0
  8. package/codegraph/__pycache__/tree_html.cpython-313.pyc +0 -0
  9. package/codegraph/affected.py +233 -0
  10. package/codegraph/cache.py +51 -2
  11. package/codegraph/callflow_html.py +273 -0
  12. package/codegraph/export.py +544 -0
  13. package/codegraph/extractors/__pycache__/ast_extractor.cpython-313.pyc +0 -0
  14. package/codegraph/extractors/ast_extractor.py +143 -16
  15. package/codegraph/graph/__pycache__/builder.cpython-313.pyc +0 -0
  16. package/codegraph/graph/__pycache__/clustering.cpython-313.pyc +0 -0
  17. package/codegraph/graph/__pycache__/query.cpython-313.pyc +0 -0
  18. package/codegraph/graph/__pycache__/symbol_resolution.cpython-313.pyc +0 -0
  19. package/codegraph/graph/builder.py +10 -0
  20. package/codegraph/graph/clustering.py +247 -10
  21. package/codegraph/graph/query.py +56 -0
  22. package/codegraph/graph/symbol_resolution.py +112 -0
  23. package/codegraph/report.py +53 -0
  24. package/codegraph/server.py +99 -10
  25. package/codegraph/tree_html.py +241 -0
  26. package/package.json +2 -2
  27. package/pyproject.toml +4 -1
  28. package/src/cli.js +277 -86
  29. package/src/server.js +7 -1
  30. package/src/templates/antigravity/GEMINI.md +96 -0
  31. package/src/templates/antigravity/hooks/context-mcp-post-tool-use.js +62 -0
  32. package/src/templates/antigravity/workflows/context-resume.md +20 -0
  33. package/src/templates/antigravity/workflows/graph-build.md +23 -0
  34. package/src/templates/antigravity/workflows/save-context.md +29 -0
  35. package/src/templates/{CLAUDE.md → claude/CLAUDE.md} +3 -0
  36. package/src/templates/claude/commands/graph-build.md +9 -0
  37. package/src/templates/claude/commands/save-context.md +19 -0
  38. package/src/templates/claude/hooks/context-mcp-post-tool-use.js +59 -0
  39. package/src/templates/claude/hooks/context-mcp-pre-tool-use.js +26 -0
  40. package/src/templates/{skills → claude/skills}/SKILL.md +3 -0
  41. package/src/templates/codex/AGENTS.md +107 -0
  42. package/src/templates/codex/hooks/context-mcp-post-tool-use.js +46 -0
  43. package/src/templates/codex/hooks/context-mcp-pre-tool-use.js +23 -0
  44. package/src/templates/codex/prompts/context-resume.md +15 -0
  45. package/src/templates/codex/prompts/graph-build.md +14 -0
  46. package/src/templates/codex/prompts/save-context.md +24 -0
  47. package/src/templates/cursor/commands/context-resume.md +7 -0
  48. package/src/templates/cursor/commands/graph-build.md +7 -0
  49. package/src/templates/cursor/commands/save-context.md +12 -0
  50. package/src/templates/{cursor-rules.mdc → cursor/cursor-rules.mdc} +13 -3
  51. package/src/templates/cursor/hooks/context-mcp-post-tool-use.js +55 -0
  52. package/src/templates/{GEMINI.md → gemini/GEMINI.md} +3 -1
  53. package/src/templates/gemini/commands/context-resume.toml +15 -0
  54. package/src/templates/gemini/commands/graph-build.toml +14 -0
  55. package/src/templates/gemini/commands/save-context.toml +24 -0
  56. package/src/templates/gemini/hooks/context-mcp-after-tool.js +59 -0
  57. package/src/templates/gemini/hooks/context-mcp-before-tool.js +26 -0
  58. package/src/templates/vscode/commands/context-resume.prompt.md +15 -0
  59. package/src/templates/vscode/commands/graph-build.prompt.md +10 -0
  60. package/src/templates/vscode/commands/save-context.prompt.md +16 -0
  61. package/src/templates/vscode/hooks/context-mcp-post-tool-use.js +58 -0
  62. package/src/templates/windsurf/hooks/context-mcp-post-run-command.js +57 -0
  63. package/src/templates/{windsurf-rules.md → windsurf/windsurf-rules.md} +6 -4
  64. package/src/templates/windsurf/workflows/context-resume.md +11 -0
  65. package/src/templates/windsurf/workflows/graph-build.md +11 -0
  66. package/src/templates/windsurf/workflows/save-context.md +18 -0
  67. package/src/tools/codegraph.js +37 -0
  68. package/uv.lock +1100 -3
  69. package/src/templates/AGENTS.md +0 -90
  70. package/src/templates/commands/graph-build.md +0 -5
  71. package/src/templates/commands/save-context.md +0 -12
  72. /package/src/templates/{commands → claude/commands}/context-resume.md +0 -0
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Gemini CLI AfterTool hook for context-mcp.
5
+ *
6
+ * Input (stdin JSON): { session_id, cwd, hook_event_name: "AfterTool",
7
+ * tool_name, tool_input: { command }, tool_response }
8
+ *
9
+ * Saves failed run_shell_command invocations to context-mcp so the next
10
+ * session can see what broke. Exits silently when the command succeeded
11
+ * or the exit code cannot be determined.
12
+ */
13
+
14
+ import { spawnSync } from 'node:child_process';
15
+
16
+ process.stdin.resume();
17
+ process.stdin.setEncoding('utf8');
18
+
19
+ let input = '';
20
+ process.stdin.on('data', chunk => { input += chunk; });
21
+ process.stdin.on('end', () => {
22
+ let event = {};
23
+ try {
24
+ event = input.trim() ? JSON.parse(input) : {};
25
+ } catch {
26
+ return;
27
+ }
28
+
29
+ const toolInput = event.tool_input || {};
30
+ const toolResult = typeof event.tool_response === 'object' && event.tool_response !== null
31
+ ? event.tool_response
32
+ : {};
33
+ const command = toolInput.command || '';
34
+ const exitCode = toolResult.exit_code ?? toolResult.exitCode ?? toolResult.code;
35
+
36
+ if (!command || exitCode === undefined || Number(exitCode) === 0) return;
37
+
38
+ const output = String(
39
+ toolResult.stderr || toolResult.stdout || toolResult.output || '',
40
+ ).trim();
41
+
42
+ const content = [
43
+ `Command: ${command}`,
44
+ `Exit code: ${exitCode}`,
45
+ output ? `Output:\n${output.slice(0, 4000)}` : null,
46
+ ].filter(Boolean).join('\n\n');
47
+
48
+ spawnSync('ctx', [
49
+ 'save',
50
+ '--project', (event.cwd || process.cwd()).split(/[\\/]/).pop() || 'default',
51
+ '--type', 'bug',
52
+ '--title', `Failed shell command: ${command.slice(0, 80)}`,
53
+ '--content', content,
54
+ ], {
55
+ encoding: 'utf8',
56
+ shell: true,
57
+ stdio: 'ignore',
58
+ });
59
+ });
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Gemini CLI BeforeTool hook for context-mcp.
5
+ *
6
+ * Input (stdin JSON): { session_id, cwd, hook_event_name: "BeforeTool",
7
+ * tool_name, tool_input }
8
+ *
9
+ * This hook is intentionally conservative. It validates the hook pipeline
10
+ * runs before run_shell_command but never blocks (exit 0 with no decision =
11
+ * allow). Keep policy decisions in GEMINI.md or a dedicated security hook
12
+ * if your team needs blocking (print {"decision":"deny","reason":"..."}).
13
+ */
14
+
15
+ process.stdin.resume();
16
+ process.stdin.setEncoding('utf8');
17
+
18
+ let input = '';
19
+ process.stdin.on('data', chunk => { input += chunk; });
20
+ process.stdin.on('end', () => {
21
+ try {
22
+ if (input.trim()) JSON.parse(input);
23
+ } catch {
24
+ // Do not interrupt the user's command because hook input changed.
25
+ }
26
+ });
@@ -0,0 +1,15 @@
1
+ ---
2
+ mode: agent
3
+ description: "Resume project memory + ContextGraph from context-mcp"
4
+ ---
5
+
6
+ Call the `context` MCP tool with `action: "resume"`, infer `project` from the current working directory name, and pass `rootPath` as the absolute path to the git repo root.
7
+
8
+ Both `project` and `rootPath` are required: `project` names the memory bucket, `rootPath` enables exact graph lookup and file sandboxing.
9
+
10
+ This loads:
11
+ - Recent decisions, bugs, and notes from past sessions
12
+ - Active plans
13
+ - ContextGraph status (built or not)
14
+
15
+ If `codegraph.built` is false in the response, immediately call `codegraph_build` on the project path before proceeding.
@@ -0,0 +1,10 @@
1
+ ---
2
+ mode: agent
3
+ description: "Build the ContextGraph (AST knowledge graph) for the current project"
4
+ ---
5
+
6
+ Call `codegraph_build` with the current working directory as the path (or a path provided by the user).
7
+
8
+ This builds the ContextGraph for the project by parsing source files into an AST knowledge graph. Once built, use `codegraph_query` to answer structural questions about the codebase before reading files directly.
9
+
10
+ After the build completes, report total nodes, edges, and communities.
@@ -0,0 +1,16 @@
1
+ ---
2
+ mode: agent
3
+ description: "Save a note/decision/bug to context-mcp project memory"
4
+ argument-hint: "What to remember (e.g. 'fixed auth bug in src/auth.js')"
5
+ ---
6
+
7
+ Call the `context` MCP tool with `action: "save"` to store a note for the current project.
8
+
9
+ Infer `project` from the current working directory name. Auto-detect `type`:
10
+ - bug/fix/error → `"bug"`
11
+ - task/done/complete/shipped/implemented → `"task"`
12
+ - decision/chose/decided/approach → `"decision"`
13
+ - config/env/secret/deploy → `"config"`
14
+ - otherwise → `"note"`
15
+
16
+ Fill in `title` (up to 120 chars), `why`, `outcome`, and `files`. Confirm back to the user: title, type, why, outcome, and project.
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * VS Code Copilot PostToolUse hook for context-mcp.
5
+ *
6
+ * Input (stdin JSON): { hook_event_name: "PostToolUse", tool_name,
7
+ * tool_input: { command }, tool_output: { exit_code, stdout, stderr }, cwd }
8
+ *
9
+ * Saves failed shell commands to context-mcp so the next session can see
10
+ * what broke. Exits silently when the command succeeded or exit code is unknown.
11
+ */
12
+
13
+ import { spawnSync } from 'node:child_process';
14
+
15
+ process.stdin.resume();
16
+ process.stdin.setEncoding('utf8');
17
+
18
+ let input = '';
19
+ process.stdin.on('data', chunk => { input += chunk; });
20
+ process.stdin.on('end', () => {
21
+ let event = {};
22
+ try {
23
+ event = input.trim() ? JSON.parse(input) : {};
24
+ } catch {
25
+ return;
26
+ }
27
+
28
+ const toolInput = event.tool_input || {};
29
+ // VS Code uses tool_output (not tool_response) for the result object
30
+ const toolResult = typeof event.tool_output === 'object' && event.tool_output !== null
31
+ ? event.tool_output
32
+ : typeof event.tool_response === 'object' && event.tool_response !== null
33
+ ? event.tool_response
34
+ : {};
35
+ const command = toolInput.command || toolInput.cmd || '';
36
+ const exitCode = toolResult.exit_code ?? toolResult.exitCode ?? toolResult.code
37
+ ?? event.exit_code ?? event.exitCode;
38
+
39
+ if (!command || exitCode === undefined || Number(exitCode) === 0) return;
40
+
41
+ const output = String(
42
+ toolResult.stderr || toolResult.stdout || toolResult.output || '',
43
+ ).trim();
44
+
45
+ const content = [
46
+ `Command: ${command}`,
47
+ `Exit code: ${exitCode}`,
48
+ output ? `Output:\n${output.slice(0, 4000)}` : null,
49
+ ].filter(Boolean).join('\n\n');
50
+
51
+ spawnSync('ctx', [
52
+ 'save',
53
+ '--project', (event.cwd || process.cwd()).split(/[\\/]/).pop() || 'default',
54
+ '--type', 'bug',
55
+ '--title', `Failed shell command: ${command.slice(0, 80)}`,
56
+ '--content', content,
57
+ ], { encoding: 'utf8', shell: true, stdio: 'ignore' });
58
+ });
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Windsurf post_run_command hook for context-mcp.
5
+ *
6
+ * Input (stdin JSON): { hook_event_name: "post_run_command", tool_name,
7
+ * tool_input: { command }, tool_response: { exit_code, stdout, stderr }, cwd }
8
+ *
9
+ * Saves failed shell commands to context-mcp so the next session can see
10
+ * what broke. Exits silently when the command succeeded or exit code is unknown.
11
+ */
12
+
13
+ import { spawnSync } from 'node:child_process';
14
+
15
+ process.stdin.resume();
16
+ process.stdin.setEncoding('utf8');
17
+
18
+ let input = '';
19
+ process.stdin.on('data', chunk => { input += chunk; });
20
+ process.stdin.on('end', () => {
21
+ let event = {};
22
+ try {
23
+ event = input.trim() ? JSON.parse(input) : {};
24
+ } catch {
25
+ return;
26
+ }
27
+
28
+ const toolInput = event.tool_input || {};
29
+ const toolResult = typeof event.tool_response === 'object' && event.tool_response !== null
30
+ ? event.tool_response
31
+ : typeof event.tool_output === 'object' && event.tool_output !== null
32
+ ? event.tool_output
33
+ : {};
34
+ const command = toolInput.command || toolInput.cmd || event.command || '';
35
+ const exitCode = toolResult.exit_code ?? toolResult.exitCode ?? toolResult.code
36
+ ?? event.exit_code ?? event.exitCode;
37
+
38
+ if (!command || exitCode === undefined || Number(exitCode) === 0) return;
39
+
40
+ const output = String(
41
+ toolResult.stderr || toolResult.stdout || toolResult.output || '',
42
+ ).trim();
43
+
44
+ const content = [
45
+ `Command: ${command}`,
46
+ `Exit code: ${exitCode}`,
47
+ output ? `Output:\n${output.slice(0, 4000)}` : null,
48
+ ].filter(Boolean).join('\n\n');
49
+
50
+ spawnSync('ctx', [
51
+ 'save',
52
+ '--project', (event.cwd || process.cwd()).split(/[\\/]/).pop() || 'default',
53
+ '--type', 'bug',
54
+ '--title', `Failed shell command: ${command.slice(0, 80)}`,
55
+ '--content', content,
56
+ ], { encoding: 'utf8', shell: true, stdio: 'ignore' });
57
+ });
@@ -64,10 +64,12 @@ Call `search` before asking user to re-explain past work.
64
64
  ## 6. ContextGraph Tools
65
65
 
66
66
  ```
67
- codegraph_arch(path) → module map (files, exports, imports)
68
- codegraph_query(path, ...) → find specific function/class/file
69
- codegraph_nodes(path, type) → list all nodes of a type
70
- codegraph_report(path) → structural analysis
67
+ codegraph_arch(path) → module map (files, exports, imports)
68
+ codegraph_query(path, ...) → find specific function/class/file
69
+ codegraph_nodes(path, type) → list all nodes of a type
70
+ codegraph_report(path) → structural analysis
71
+ codegraph_affected(path, node, depth?) → blast radius — what breaks if X changes?
72
+ codegraph_html(path, formats?) → regenerate visualizations (auto on every build)
71
73
  ```
72
74
 
73
75
  Use `codegraph_arch` first. Never read files for structure questions.
@@ -0,0 +1,11 @@
1
+ # context-resume
2
+
3
+ Resume project memory and ContextGraph from context-mcp before starting any work.
4
+
5
+ 1. Call the `context` MCP tool with `action: "resume"`, infer `project` from the current working directory name, and pass `rootPath` as the absolute path to the git repo root.
6
+
7
+ 2. Read the returned `recentEntries` (last 15 entries), `activePlans`, and `codegraph` status.
8
+
9
+ 3. If `codegraph.built` is false, call `codegraph_build` on the project path immediately before proceeding.
10
+
11
+ 4. If `stats.totalEntries` is 20 or more, save a compaction summary before starting any new work.
@@ -0,0 +1,11 @@
1
+ # graph-build
2
+
3
+ Build the ContextGraph (AST knowledge graph) for the current project.
4
+
5
+ 1. Call `codegraph_build` with the current working directory as the path (or a path provided by the user).
6
+
7
+ 2. Wait for the build to complete.
8
+
9
+ 3. Report total nodes, edges, and communities found.
10
+
11
+ 4. Once built, use `codegraph_query` to answer structural questions about the codebase instead of reading files directly.
@@ -0,0 +1,18 @@
1
+ # save-context
2
+
3
+ Save a note, decision, bug, or task to context-mcp project memory.
4
+
5
+ 1. Call the `context` MCP tool with `action: "save"`.
6
+
7
+ 2. Infer `project` from the current working directory name.
8
+
9
+ 3. Auto-detect `type` from the user's description:
10
+ - bug/fix/error → `"bug"`
11
+ - task/done/complete/shipped/implemented → `"task"`
12
+ - decision/chose/decided/approach → `"decision"`
13
+ - config/env/secret/deploy → `"config"`
14
+ - otherwise → `"note"`
15
+
16
+ 4. Fill in `title` (up to 120 chars), `why`, `outcome`, and `files`.
17
+
18
+ 5. Confirm back to the user: title, type, why, outcome, and project name.
@@ -97,6 +97,43 @@ export const definitions = [
97
97
  required: ['path'],
98
98
  },
99
99
  },
100
+ {
101
+ name: 'codegraph_affected',
102
+ description:
103
+ 'BFS traversal: given a node name, find every node that would be affected if you change it — ' +
104
+ 'callers, importers, inheritors, etc. Use before refactoring to understand blast radius. ' +
105
+ 'Returns affected nodes with file paths, relation types, and traversal depth.',
106
+ inputSchema: {
107
+ type: 'object',
108
+ properties: {
109
+ path: { type: 'string', description: 'Project root' },
110
+ node: { type: 'string', description: 'Node name, ID, or file path to start from' },
111
+ depth: { type: 'integer', description: 'BFS depth (default 2, max 5)' },
112
+ },
113
+ required: ['path', 'node'],
114
+ },
115
+ },
116
+ {
117
+ name: 'codegraph_html',
118
+ description:
119
+ 'Generate interactive visualizations from the knowledge graph. ' +
120
+ 'Outputs: graph.html (vis.js force graph, dark theme, search, community toggle), ' +
121
+ 'tree.html (D3 collapsible file tree), callflow.html (Mermaid architecture diagrams), ' +
122
+ 'graph.graphml (Gephi/yEd), obsidian/ vault (per-node .md with wikilinks). ' +
123
+ 'Run after codegraph_build. Pass formats array to select specific outputs.',
124
+ inputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ path: { type: 'string', description: 'Project root' },
128
+ formats: {
129
+ type: 'array',
130
+ items: { type: 'string', enum: ['html', 'tree', 'callflow', 'graphml', 'obsidian'] },
131
+ description: 'Formats to generate (default: all)',
132
+ },
133
+ },
134
+ required: ['path'],
135
+ },
136
+ },
100
137
  ];
101
138
 
102
139
  export const TOOL_NAMES = new Set(definitions.map(d => d.name));