context-mcp-server 1.0.7 → 1.1.0
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 +10 -11
- package/codegraph/__pycache__/server.cpython-313.pyc +0 -0
- package/codegraph/graph/__pycache__/query.cpython-313.pyc +0 -0
- package/codegraph/graph/query.py +43 -0
- package/codegraph/server.py +20 -17
- package/package.json +2 -2
- package/pyproject.toml +1 -1
- package/src/cli.js +152 -229
- package/src/db.js +923 -805
- package/src/guard.js +9 -3
- package/src/search.js +73 -9
- package/src/server.js +7 -6
- package/src/templates/AGENTS.md +56 -53
- package/src/templates/CLAUDE.md +89 -61
- package/src/templates/GEMINI.md +56 -53
- package/src/templates/commands/context-resume.md +1 -1
- package/src/templates/commands/save-context.md +6 -3
- package/src/templates/cursor-rules.mdc +3 -3
- package/src/templates/skills/SKILL.md +87 -60
- package/src/templates/windsurf-rules.md +69 -20
- package/src/tools/codegraph.js +46 -43
- package/src/tools/context.js +44 -28
- package/src/tools/gitTools.js +1 -3
- package/src/tools/plan.js +133 -0
- package/uv.lock +1 -1
- package/src/tools/discussion.js +0 -123
package/README.md
CHANGED
|
@@ -25,8 +25,8 @@ This gets worse as projects grow — reading 20 files to answer "what calls this
|
|
|
25
25
|
|
|
26
26
|
## What It Solves
|
|
27
27
|
|
|
28
|
-
- **Persistent memory** — decisions, bugs, notes, and
|
|
29
|
-
- **Shared store** — `~/.context-mcp
|
|
28
|
+
- **Persistent memory** — decisions, bugs, notes, and config saved across sessions, loaded automatically at conversation start
|
|
29
|
+
- **Shared store** — `~/.context-mcp/projects/<name>/` per-project on your machine; all AI tools read and write it
|
|
30
30
|
- **ContextGraph** — build a knowledge graph of your codebase once, answer structural questions in ~500 tokens instead of ~50,000
|
|
31
31
|
|
|
32
32
|
Real measured reduction on this project: **162× fewer tokens**, **99.38% reduction** per conversation.
|
|
@@ -95,10 +95,10 @@ ctx online --port 3200 # different port
|
|
|
95
95
|
Both `ctx` and `context` are aliases for the same CLI.
|
|
96
96
|
|
|
97
97
|
```bash
|
|
98
|
-
ctx # interactive mode (UI
|
|
98
|
+
ctx # interactive mode (UI)
|
|
99
99
|
|
|
100
100
|
# Context
|
|
101
|
-
ctx list [project] # list entries
|
|
101
|
+
ctx list [project] # list entries by tree: graph / context / summary / plans
|
|
102
102
|
ctx projects # all projects with graph status + recent entries
|
|
103
103
|
ctx search "query" # keyword → semantic fallback search
|
|
104
104
|
ctx add # add entry interactively
|
|
@@ -115,7 +115,6 @@ ctx settings # view and edit config interactively
|
|
|
115
115
|
|
|
116
116
|
# Tools
|
|
117
117
|
ctx benchmark # token savings report (memory + graph)
|
|
118
|
-
ctx discuss [project] # view discussions
|
|
119
118
|
```
|
|
120
119
|
|
|
121
120
|
---
|
|
@@ -136,12 +135,12 @@ Any file or git operation outside that directory is rejected. Applies to all HTT
|
|
|
136
135
|
|
|
137
136
|
### Memory
|
|
138
137
|
|
|
139
|
-
- `context.resume` — loads recent entries,
|
|
140
|
-
- `context.save` — store
|
|
141
|
-
- `context.get` / `context.update` / `context.delete` — full CRUD
|
|
138
|
+
- `context.resume` — loads recent entries, active plans, and graph status; registers `rootPath` for sandboxing
|
|
139
|
+
- `context.save` — store context with 4 types: `decision`, `bug`, `note`, `config`
|
|
140
|
+
- `context.get` / `context.update` / `context.delete` — full CRUD, single or batch
|
|
142
141
|
- `search` — keyword-first, semantic fallback
|
|
143
|
-
- `
|
|
144
|
-
- Auto-deduplication on save; auto-compact at 20 entries
|
|
142
|
+
- `plan` — auto-triggered when AI makes any plan; saves a markdown summary to a `planDir` you specify
|
|
143
|
+
- Auto-deduplication on save; auto-compact at 20 entries → stored in `summary.json`
|
|
145
144
|
|
|
146
145
|
### ContextGraph
|
|
147
146
|
|
|
@@ -153,7 +152,7 @@ Any file or git operation outside that directory is rejected. Applies to all HTT
|
|
|
153
152
|
codegraph_build(path)
|
|
154
153
|
```
|
|
155
154
|
|
|
156
|
-
Parses codebase via tree-sitter AST (16 languages, regex fallback). Extracts functions, classes, imports, call edges.
|
|
155
|
+
Parses codebase via tree-sitter AST (16 languages, regex fallback). Extracts functions, classes, imports, call edges. Build metadata saved to `~/.context-mcp/projects/<name>/graph.json`.
|
|
157
156
|
|
|
158
157
|
**Step 2 — Query** (instant, forever):
|
|
159
158
|
|
|
Binary file
|
|
Binary file
|
package/codegraph/graph/query.py
CHANGED
|
@@ -237,6 +237,49 @@ def _general_search(matched: list, nodes: list, edges: list) -> dict:
|
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
|
|
240
|
+
def module_map(graph_dict: dict, limit: int = 100) -> dict:
|
|
241
|
+
"""
|
|
242
|
+
Return a module map: for each file, its exported functions/classes and what it imports.
|
|
243
|
+
Output grouped by file, sorted by export count descending.
|
|
244
|
+
"""
|
|
245
|
+
nodes = graph_dict.get("nodes", [])
|
|
246
|
+
edges = graph_dict.get("edges", [])
|
|
247
|
+
|
|
248
|
+
files: dict[str, dict] = {}
|
|
249
|
+
for n in nodes:
|
|
250
|
+
f = n.get("file") or "unknown"
|
|
251
|
+
if f not in files:
|
|
252
|
+
files[f] = {"exports": [], "imports": set()}
|
|
253
|
+
node_type = n.get("type", "?")
|
|
254
|
+
if node_type in ("function", "class", "struct"):
|
|
255
|
+
files[f]["exports"].append({"name": n["name"], "type": node_type})
|
|
256
|
+
|
|
257
|
+
node_map = {n["id"]: n for n in nodes}
|
|
258
|
+
for e in edges:
|
|
259
|
+
from_node = node_map.get(e.get("from", ""))
|
|
260
|
+
to_node = node_map.get(e.get("to", ""))
|
|
261
|
+
if not from_node or not to_node:
|
|
262
|
+
continue
|
|
263
|
+
from_file = from_node.get("file") or "unknown"
|
|
264
|
+
to_file = to_node.get("file") or "unknown"
|
|
265
|
+
if from_file != to_file and from_file in files:
|
|
266
|
+
files[from_file]["imports"].add(to_file)
|
|
267
|
+
|
|
268
|
+
result = []
|
|
269
|
+
for fpath, data in sorted(files.items(), key=lambda x: -len(x[1]["exports"])):
|
|
270
|
+
result.append({
|
|
271
|
+
"file": fpath,
|
|
272
|
+
"exports": data["exports"][:30],
|
|
273
|
+
"imports": sorted(data["imports"])[:20],
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
return {
|
|
277
|
+
"files": result[:limit],
|
|
278
|
+
"total_files": len(files),
|
|
279
|
+
"truncated": len(files) > limit,
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
240
283
|
def _render_subgraph(result_nodes: list, all_edges: list, token_budget: int) -> str:
|
|
241
284
|
"""
|
|
242
285
|
Render a subgraph as structured plain text (graphify-style).
|
package/codegraph/server.py
CHANGED
|
@@ -4,10 +4,10 @@ codegraph/server.py — MCP server exposing codebase knowledge graph tools.
|
|
|
4
4
|
|
|
5
5
|
Tools:
|
|
6
6
|
codegraph_build — scan project, extract AST nodes, build graph (local only, no API)
|
|
7
|
-
codegraph_query — structural question OR single-node lookup (or both)
|
|
7
|
+
codegraph_query — structural question OR single-node lookup (or both)
|
|
8
|
+
codegraph_arch — module map: every file with its exports and imports
|
|
8
9
|
codegraph_report — return full CODEGRAPH_REPORT.md
|
|
9
10
|
codegraph_nodes — list nodes of a given type
|
|
10
|
-
codegraph_path — shortest path between two concepts
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import asyncio
|
|
@@ -25,7 +25,7 @@ from .config import classify_file
|
|
|
25
25
|
from .cache import file_hash, set_cached_nodes, save_cache
|
|
26
26
|
from .extractors.ast_extractor import extract as ast_extract
|
|
27
27
|
from .graph.builder import build, to_json_dict, save_graph, load_graph
|
|
28
|
-
from .graph.query import answer as graph_answer,
|
|
28
|
+
from .graph.query import answer as graph_answer, module_map
|
|
29
29
|
from .graph.clustering import detect_communities
|
|
30
30
|
from .report import generate as generate_report
|
|
31
31
|
|
|
@@ -95,16 +95,19 @@ TOOLS = [
|
|
|
95
95
|
},
|
|
96
96
|
),
|
|
97
97
|
Tool(
|
|
98
|
-
name="
|
|
99
|
-
description=
|
|
98
|
+
name="codegraph_arch",
|
|
99
|
+
description=(
|
|
100
|
+
"Return a module map: every file with its exported functions/classes and what it imports. "
|
|
101
|
+
"Use this to understand project structure without reading any files. "
|
|
102
|
+
"Call after codegraph_build. Much faster than reading each file."
|
|
103
|
+
),
|
|
100
104
|
inputSchema={
|
|
101
105
|
"type": "object",
|
|
102
106
|
"properties": {
|
|
103
|
-
"path":
|
|
104
|
-
"
|
|
105
|
-
"to": {"type": "string"},
|
|
107
|
+
"path": {"type": "string", "description": "Project root"},
|
|
108
|
+
"limit": {"type": "integer", "description": "Max files in output (default 100)"},
|
|
106
109
|
},
|
|
107
|
-
"required": ["path"
|
|
110
|
+
"required": ["path"],
|
|
108
111
|
},
|
|
109
112
|
),
|
|
110
113
|
]
|
|
@@ -125,12 +128,11 @@ async def call_tool(name: str, arguments: dict):
|
|
|
125
128
|
|
|
126
129
|
|
|
127
130
|
async def _dispatch(name: str, args: dict):
|
|
128
|
-
if name == "codegraph_build":
|
|
129
|
-
if name == "codegraph_query":
|
|
130
|
-
if name == "
|
|
131
|
-
if name == "
|
|
132
|
-
if name == "
|
|
133
|
-
if name == "codegraph_path": return await _path(args)
|
|
131
|
+
if name == "codegraph_build": return await _build(args)
|
|
132
|
+
if name == "codegraph_query": return await _query(args)
|
|
133
|
+
if name == "codegraph_report": return await _report(args)
|
|
134
|
+
if name == "codegraph_nodes": return await _nodes(args)
|
|
135
|
+
if name == "codegraph_arch": return await _arch(args)
|
|
134
136
|
raise ValueError(f"Unknown tool: {name}")
|
|
135
137
|
|
|
136
138
|
|
|
@@ -285,11 +287,12 @@ async def _nodes(args: dict) -> dict:
|
|
|
285
287
|
return {"type": node_type, "count": len(matched), "nodes": matched[:limit]}
|
|
286
288
|
|
|
287
289
|
|
|
288
|
-
async def
|
|
290
|
+
async def _arch(args: dict) -> dict:
|
|
289
291
|
graph_dict = load_graph(args["path"])
|
|
290
292
|
if not graph_dict:
|
|
291
293
|
raise ValueError("No graph found. Run codegraph_build first.")
|
|
292
|
-
|
|
294
|
+
limit = args.get("limit", 100)
|
|
295
|
+
return module_map(graph_dict, limit=limit)
|
|
293
296
|
|
|
294
297
|
|
|
295
298
|
# ── Entry point ───────────────────────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "context-mcp-server",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
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": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"mcp": "node src/index.js",
|
|
15
15
|
"mcp-server": "node src/http.js",
|
|
16
16
|
"cli": "node src/cli.js",
|
|
17
|
-
"check": "node --check src/index.js && node --check src/server.js && node --check src/db.js && node --check src/vector.js && node --check src/summarizer.js && node --check src/search.js && node --check src/config.js && node --check src/cli.js && node --check src/http.js && node --check src/tools/context.js && node --check src/tools/search.js && node --check src/tools/
|
|
17
|
+
"check": "node --check src/index.js && node --check src/server.js && node --check src/db.js && node --check src/vector.js && node --check src/summarizer.js && node --check src/search.js && node --check src/config.js && node --check src/cli.js && node --check src/http.js && node --check src/tools/context.js && node --check src/tools/search.js && node --check src/tools/plan.js &&node --check src/tools/errorCheck.js && node --check src/tools/fileTools.js && node --check src/tools/gitTools.js && node --check src/tools/codegraph.js && node --check src/hooks/autoLink.js && node --check src/hooks/autoContext.js",
|
|
18
18
|
"check-mcp": "npm run check",
|
|
19
19
|
"test": "node --test",
|
|
20
20
|
"prepublishOnly": "npm run check"
|
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.1.0"
|
|
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"
|