@misterhuydo/cairn-mcp 1.0.0 → 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 +199 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Cairn MCP
|
|
2
|
+
|
|
3
|
+
> Persistent polyglot knowledge graph for Claude Code. Index once, query forever.
|
|
4
|
+
|
|
5
|
+
Claude is stateless — every session starts at zero. On a multi-repo codebase with Java backends, TypeScript frontends, and Vue components, that means 50% of every session is archaeology: finding where things live before any real work can begin.
|
|
6
|
+
|
|
7
|
+
**Cairn fixes this.** It indexes your repos into a local SQLite knowledge graph and exposes 6 MCP tools that give Claude instant, persistent memory across sessions.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @misterhuydo/cairn-mcp
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**Requirements:** Node.js >= 22.15.0
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
Add to `~/.claude/config.json`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"cairn": {
|
|
29
|
+
"command": "cairn-mcp"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Restart Claude Code. Done.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Tools
|
|
40
|
+
|
|
41
|
+
### `cairn_maintain` — Index your repos
|
|
42
|
+
Run once at the start of each session. The index persists at `~/.cairn/index.db`.
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
cairn_maintain({ roots: ["/path/to/repo1", "/path/to/repo2"] })
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"repos_indexed": 3,
|
|
51
|
+
"files_by_language": { "java": 412, "typescript": 287, "vue": 94 },
|
|
52
|
+
"symbols_total": 6841,
|
|
53
|
+
"security_findings": 47,
|
|
54
|
+
"duration_ms": 4200
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
### `cairn_search` — Find anything across all languages
|
|
61
|
+
```
|
|
62
|
+
cairn_search({ query: "user authentication", language: "typescript" })
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
[
|
|
67
|
+
{ "lang": "typescript", "kind": "function", "fqn": "src/composables/useAuth.ts::useAuth" },
|
|
68
|
+
{ "lang": "vue", "kind": "component", "fqn": "src/components/LoginForm.vue::LoginForm" },
|
|
69
|
+
{ "lang": "java", "kind": "class", "fqn": "com.example.auth.UserAuthenticator" }
|
|
70
|
+
]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
### `cairn_bundle` — Minified source snapshot for Claude to read
|
|
76
|
+
Strips comments and empty lines, writes a compressed `### File:` bundle. Use after `cairn_search` to give Claude readable source without blowing the context window.
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
cairn_bundle({ roots: [...], filter_paths: ["src/components/checkout"], bundle_name: "checkout" })
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"bundle_path": "/Users/you/.cairn/bundles/checkout.txt",
|
|
85
|
+
"original_kb": 284,
|
|
86
|
+
"compressed_kb": 91,
|
|
87
|
+
"reduction_pct": 68
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### `cairn_describe` — Summarize a module
|
|
94
|
+
```
|
|
95
|
+
cairn_describe({ path: "src/components/checkout" })
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
```json
|
|
99
|
+
{
|
|
100
|
+
"languages": ["vue", "typescript"],
|
|
101
|
+
"symbols": {
|
|
102
|
+
"component": ["CheckoutForm", "OrderSummary", "PaymentStep"],
|
|
103
|
+
"function": ["useCheckout", "usePayment"]
|
|
104
|
+
},
|
|
105
|
+
"imports_from": ["src/store/cart.ts", "src/api/orders.ts"],
|
|
106
|
+
"imported_by": ["src/views/CartView.vue"],
|
|
107
|
+
"external_deps": ["stripe", "@stripe/stripe-js"]
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### `cairn_code_graph` — Dependency health
|
|
114
|
+
```
|
|
115
|
+
cairn_code_graph({ mode: "instability" })
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"modules": [
|
|
121
|
+
{ "name": "src/views", "instability": 1.0, "status": "safe_to_refactor" },
|
|
122
|
+
{ "name": "src/composables", "instability": 0.4, "status": "review_before_change" },
|
|
123
|
+
{ "name": "src/utils", "instability": 0.1, "status": "load_bearing" }
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Modes: `instability` · `health` · `cycles`
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### `cairn_security` — Vulnerability scan
|
|
133
|
+
```
|
|
134
|
+
cairn_security({ severity: "HIGH" })
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
{
|
|
139
|
+
"total_findings": 12,
|
|
140
|
+
"by_language": { "typescript": 7, "java": 5 },
|
|
141
|
+
"findings": [
|
|
142
|
+
{ "severity": "HIGH", "cwe": "CWE-79", "file": "src/components/UserProfile.vue", "line": 84, "rule": "XSS via innerHTML" },
|
|
143
|
+
{ "severity": "HIGH", "cwe": "CWE-611", "file": "backend/src/.../XmlParser.java", "line": 47, "rule": "XXE" }
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Covers: XSS · XXE · SQL injection · command injection · weak crypto · hardcoded secrets · open redirect · unsafe deserialization
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Supported Languages
|
|
153
|
+
|
|
154
|
+
| Language | What Cairn extracts |
|
|
155
|
+
|---|---|
|
|
156
|
+
| Java | packages, classes, interfaces, enums, records, methods |
|
|
157
|
+
| TypeScript / JavaScript | classes, interfaces, functions, types, enums |
|
|
158
|
+
| Vue | components, composables, script block symbols |
|
|
159
|
+
| Python | classes, functions, decorators |
|
|
160
|
+
| SQL | tables, views, stored procedures |
|
|
161
|
+
| XML / HTML | bean ids, component names |
|
|
162
|
+
| Config (YAML, properties, .env) | top-level keys |
|
|
163
|
+
| Markdown | headings |
|
|
164
|
+
| Build files (pom.xml, package.json, build.gradle) | dependencies |
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Typical session
|
|
169
|
+
|
|
170
|
+
```
|
|
171
|
+
1. cairn_maintain → index all repos (persists between sessions)
|
|
172
|
+
2. cairn_search → find the symbols you need
|
|
173
|
+
3. cairn_bundle → get a readable snapshot of relevant files
|
|
174
|
+
4. cairn_describe → understand a module before modifying it
|
|
175
|
+
5. cairn_security → check for issues before a PR
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Custom DB path
|
|
181
|
+
|
|
182
|
+
By default the index is stored at `~/.cairn/index.db`. Override with an env variable:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"mcpServers": {
|
|
187
|
+
"cairn": {
|
|
188
|
+
"command": "cairn-mcp",
|
|
189
|
+
"env": { "CAIRN_DB_PATH": "/your/custom/path/index.db" }
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
## License
|
|
198
|
+
|
|
199
|
+
MIT
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@misterhuydo/cairn-mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Persistent polyglot knowledge graph MCP server for Claude Code. Index once, query forever — across Java, TypeScript, Vue, Python, SQL and more.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"cairn-mcp": "
|
|
8
|
+
"cairn-mcp": "bin/cairn-mcp.js"
|
|
9
9
|
},
|
|
10
10
|
"scripts": {
|
|
11
11
|
"start": "node --experimental-sqlite index.js"
|