@exero1/claudecontext 0.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 +286 -0
- package/dist/installer/install.d.ts +12 -0
- package/dist/installer/install.d.ts.map +1 -0
- package/dist/installer/install.js +714 -0
- package/dist/installer/install.js.map +1 -0
- package/dist/src/cache/budget.d.ts +48 -0
- package/dist/src/cache/budget.d.ts.map +1 -0
- package/dist/src/cache/budget.js +55 -0
- package/dist/src/cache/budget.js.map +1 -0
- package/dist/src/cache/compressor.d.ts +21 -0
- package/dist/src/cache/compressor.d.ts.map +1 -0
- package/dist/src/cache/compressor.js +89 -0
- package/dist/src/cache/compressor.js.map +1 -0
- package/dist/src/cache/levels.d.ts +16 -0
- package/dist/src/cache/levels.d.ts.map +1 -0
- package/dist/src/cache/levels.js +41 -0
- package/dist/src/cache/levels.js.map +1 -0
- package/dist/src/cache/manager.d.ts +38 -0
- package/dist/src/cache/manager.d.ts.map +1 -0
- package/dist/src/cache/manager.js +196 -0
- package/dist/src/cache/manager.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +279 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/detection/areas.d.ts +13 -0
- package/dist/src/detection/areas.d.ts.map +1 -0
- package/dist/src/detection/areas.js +96 -0
- package/dist/src/detection/areas.js.map +1 -0
- package/dist/src/detection/task.d.ts +28 -0
- package/dist/src/detection/task.d.ts.map +1 -0
- package/dist/src/detection/task.js +77 -0
- package/dist/src/detection/task.js.map +1 -0
- package/dist/src/gating/gate.d.ts +38 -0
- package/dist/src/gating/gate.d.ts.map +1 -0
- package/dist/src/gating/gate.js +74 -0
- package/dist/src/gating/gate.js.map +1 -0
- package/dist/src/graph/edges.d.ts +41 -0
- package/dist/src/graph/edges.d.ts.map +1 -0
- package/dist/src/graph/edges.js +115 -0
- package/dist/src/graph/edges.js.map +1 -0
- package/dist/src/graph/indexer.d.ts +38 -0
- package/dist/src/graph/indexer.d.ts.map +1 -0
- package/dist/src/graph/indexer.js +228 -0
- package/dist/src/graph/indexer.js.map +1 -0
- package/dist/src/graph/traversal.d.ts +25 -0
- package/dist/src/graph/traversal.d.ts.map +1 -0
- package/dist/src/graph/traversal.js +173 -0
- package/dist/src/graph/traversal.js.map +1 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +82 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/indexing/codebase.d.ts +30 -0
- package/dist/src/indexing/codebase.d.ts.map +1 -0
- package/dist/src/indexing/codebase.js +127 -0
- package/dist/src/indexing/codebase.js.map +1 -0
- package/dist/src/markdown/writer.d.ts +34 -0
- package/dist/src/markdown/writer.d.ts.map +1 -0
- package/dist/src/markdown/writer.js +96 -0
- package/dist/src/markdown/writer.js.map +1 -0
- package/dist/src/server.d.ts +15 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +520 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/storage/db.d.ts +123 -0
- package/dist/src/storage/db.d.ts.map +1 -0
- package/dist/src/storage/db.js +318 -0
- package/dist/src/storage/db.js.map +1 -0
- package/dist/src/utils/glob.d.ts +11 -0
- package/dist/src/utils/glob.d.ts.map +1 -0
- package/dist/src/utils/glob.js +20 -0
- package/dist/src/utils/glob.js.map +1 -0
- package/hooks/post-write.mjs +57 -0
- package/hooks/pre-compact.mjs +44 -0
- package/hooks/pre-tool-use.mjs +87 -0
- package/hooks/session-start.mjs +54 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traversal.js","sourceRoot":"","sources":["../../../src/graph/traversal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* ClaudeContext MCP server entry point.
|
|
4
|
+
*
|
|
5
|
+
* CRITICAL: Never console.log() — stdout is the JSON-RPC channel.
|
|
6
|
+
* All logging goes to process.stderr.write().
|
|
7
|
+
*/
|
|
8
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
9
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
10
|
+
import { existsSync, readFileSync, mkdirSync } from 'node:fs';
|
|
11
|
+
import { join, resolve } from 'node:path';
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { Db } from './storage/db.js';
|
|
14
|
+
import { registerTools } from './server.js';
|
|
15
|
+
import { readLastLines, appendLog } from './markdown/writer.js';
|
|
16
|
+
const log = (msg) => {
|
|
17
|
+
process.stderr.write(`[claudecontext] ${msg}\n`);
|
|
18
|
+
};
|
|
19
|
+
async function main() {
|
|
20
|
+
const startMs = Date.now();
|
|
21
|
+
// Determine project root from env or cwd
|
|
22
|
+
const projectRoot = resolve(process.env['CLAUDECONTEXT_PROJECT_ROOT'] ?? process.cwd());
|
|
23
|
+
const stateDir = join(projectRoot, '.claudecontext');
|
|
24
|
+
if (!existsSync(stateDir)) {
|
|
25
|
+
mkdirSync(stateDir, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
const dbPath = join(stateDir, 'state.db');
|
|
28
|
+
const l0LogPath = join(stateDir, 'l0.log');
|
|
29
|
+
const areasPath = join(stateDir, 'areas.json');
|
|
30
|
+
// Load and validate areas config with Zod
|
|
31
|
+
const AreaDefSchema = z.object({
|
|
32
|
+
name: z.string().min(1),
|
|
33
|
+
globs: z.array(z.string()),
|
|
34
|
+
docPath: z.string().min(1),
|
|
35
|
+
});
|
|
36
|
+
let areas = [];
|
|
37
|
+
if (existsSync(areasPath)) {
|
|
38
|
+
try {
|
|
39
|
+
const parsed = JSON.parse(readFileSync(areasPath, 'utf8'));
|
|
40
|
+
areas = z.array(AreaDefSchema).parse(parsed);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
log(`Warning: failed to parse/validate areas.json: ${e}. Proceeding without areas.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Check for session lock conflict
|
|
47
|
+
if (Db.isLocked(stateDir)) {
|
|
48
|
+
log('Warning: another MCP server may be running for this project (stale lock ignored)');
|
|
49
|
+
}
|
|
50
|
+
// Open database
|
|
51
|
+
const db = new Db(dbPath);
|
|
52
|
+
log(`Database opened: ${dbPath}`);
|
|
53
|
+
// Recover L0 from disk (in case of crash)
|
|
54
|
+
const l0Lines = readLastLines(l0LogPath, 200);
|
|
55
|
+
if (l0Lines.length > 0) {
|
|
56
|
+
log(`Recovered ${l0Lines.length} L0 log lines from disk`);
|
|
57
|
+
}
|
|
58
|
+
// Record startup in L0
|
|
59
|
+
appendLog(l0LogPath, `[${new Date().toISOString()}] MCP server started (pid=${process.pid})`);
|
|
60
|
+
// Create MCP server
|
|
61
|
+
const server = new Server({ name: 'claudecontext', version: '0.1.0' }, { capabilities: { tools: {} } });
|
|
62
|
+
// Register all tools
|
|
63
|
+
registerTools(server, db, { projectRoot, stateDir, areas });
|
|
64
|
+
// Graceful shutdown
|
|
65
|
+
const shutdown = () => {
|
|
66
|
+
log('Shutting down...');
|
|
67
|
+
appendLog(l0LogPath, `[${new Date().toISOString()}] MCP server stopped`);
|
|
68
|
+
db.close();
|
|
69
|
+
process.exit(0);
|
|
70
|
+
};
|
|
71
|
+
process.on('SIGTERM', shutdown);
|
|
72
|
+
process.on('SIGINT', shutdown);
|
|
73
|
+
// Start stdio transport
|
|
74
|
+
const transport = new StdioServerTransport();
|
|
75
|
+
await server.connect(transport);
|
|
76
|
+
log(`ClaudeContext MCP server ready (startup=${Date.now() - startMs}ms)`);
|
|
77
|
+
}
|
|
78
|
+
main().catch(err => {
|
|
79
|
+
process.stderr.write(`[claudecontext] Fatal error: ${err}\n`);
|
|
80
|
+
process.exit(1);
|
|
81
|
+
});
|
|
82
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Db } from '../storage/db.js';
|
|
2
|
+
export interface RankedFile {
|
|
3
|
+
path: string;
|
|
4
|
+
score: number;
|
|
5
|
+
lastTouched: number;
|
|
6
|
+
touchCount: number;
|
|
7
|
+
graphNeighborBoost: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Score a file for relevance to the active task.
|
|
11
|
+
*
|
|
12
|
+
* Score components:
|
|
13
|
+
* - Recency: exp(-0.05 * daysSinceTouch) — files touched today score ~1.0
|
|
14
|
+
* - Frequency: log(touchCount + 1) / log(10) — diminishing returns on repeated touches
|
|
15
|
+
* - Graph boost: +0.2 if file has edges to active task files within 2 hops
|
|
16
|
+
*/
|
|
17
|
+
export declare function scoreFile(lastTouched: number, touchCount: number, hasGraphNeighbor: boolean, now?: number): number;
|
|
18
|
+
/**
|
|
19
|
+
* Rank all indexed files by relevance to the active task.
|
|
20
|
+
* Returns top N files sorted by score descending.
|
|
21
|
+
*/
|
|
22
|
+
export declare function rankFiles(db: Db, taskFiles: string[], limit?: number): RankedFile[];
|
|
23
|
+
/**
|
|
24
|
+
* Search for files matching a query string.
|
|
25
|
+
* Path-substring match + optional ripgrep content search (searchContent=true).
|
|
26
|
+
* Content matches receive a +0.5 score boost vs pure path matches.
|
|
27
|
+
* Multi-word queries default to searchContent=true (caller-controlled via server.ts).
|
|
28
|
+
*/
|
|
29
|
+
export declare function searchFiles(db: Db, query: string, taskFiles: string[], projectRoot: string, limit?: number, searchContent?: boolean): RankedFile[];
|
|
30
|
+
//# sourceMappingURL=codebase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codebase.d.ts","sourceRoot":"","sources":["../../../src/indexing/codebase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAG3C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CACvB,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,gBAAgB,EAAE,OAAO,EACzB,GAAG,SAAa,GACf,MAAM,CAMR;AAsBD;;;GAGG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,EAAE,EACN,SAAS,EAAE,MAAM,EAAE,EACnB,KAAK,SAAK,GACT,UAAU,EAAE,CAed;AAyBD;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,EAAE,EAAE,EAAE,EACN,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EAAE,EACnB,WAAW,EAAE,MAAM,EACnB,KAAK,SAAK,EACV,aAAa,UAAQ,GACpB,UAAU,EAAE,CAoDd"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
/**
|
|
3
|
+
* Score a file for relevance to the active task.
|
|
4
|
+
*
|
|
5
|
+
* Score components:
|
|
6
|
+
* - Recency: exp(-0.05 * daysSinceTouch) — files touched today score ~1.0
|
|
7
|
+
* - Frequency: log(touchCount + 1) / log(10) — diminishing returns on repeated touches
|
|
8
|
+
* - Graph boost: +0.2 if file has edges to active task files within 2 hops
|
|
9
|
+
*/
|
|
10
|
+
export function scoreFile(lastTouched, touchCount, hasGraphNeighbor, now = Date.now()) {
|
|
11
|
+
const daysSince = (now - lastTouched) / (24 * 60 * 60 * 1000);
|
|
12
|
+
const recency = Math.exp(-0.05 * daysSince);
|
|
13
|
+
const frequency = Math.log(touchCount + 1) / Math.log(10);
|
|
14
|
+
const boost = hasGraphNeighbor ? 0.2 : 0.0;
|
|
15
|
+
return recency + frequency + boost;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Find files that are graph neighbors of the active task files (within 2 hops).
|
|
19
|
+
*/
|
|
20
|
+
function getGraphNeighbors(db, taskFiles) {
|
|
21
|
+
const neighbors = new Set();
|
|
22
|
+
for (const file of taskFiles) {
|
|
23
|
+
// Hop 1
|
|
24
|
+
const hop1 = db.getEdgesFrom(file, 20);
|
|
25
|
+
for (const edge of hop1) {
|
|
26
|
+
neighbors.add(edge.to_node);
|
|
27
|
+
// Hop 2
|
|
28
|
+
const hop2 = db.getEdgesFrom(edge.to_node, 10);
|
|
29
|
+
for (const e2 of hop2) {
|
|
30
|
+
neighbors.add(e2.to_node);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return neighbors;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Rank all indexed files by relevance to the active task.
|
|
38
|
+
* Returns top N files sorted by score descending.
|
|
39
|
+
*/
|
|
40
|
+
export function rankFiles(db, taskFiles, limit = 20) {
|
|
41
|
+
const graphNeighbors = getGraphNeighbors(db, taskFiles);
|
|
42
|
+
const allFiles = db.getTopFiles(500); // Pull enough from DB for re-ranking
|
|
43
|
+
const now = Date.now();
|
|
44
|
+
const ranked = allFiles.map(f => ({
|
|
45
|
+
path: f.path,
|
|
46
|
+
score: scoreFile(f.last_touched, f.touch_count, graphNeighbors.has(f.path), now),
|
|
47
|
+
lastTouched: f.last_touched,
|
|
48
|
+
touchCount: f.touch_count,
|
|
49
|
+
graphNeighborBoost: graphNeighbors.has(f.path),
|
|
50
|
+
}));
|
|
51
|
+
ranked.sort((a, b) => b.score - a.score);
|
|
52
|
+
return ranked.slice(0, limit);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Search file contents using ripgrep. Returns absolute paths of matching files.
|
|
56
|
+
* Falls back to empty array if rg is not available.
|
|
57
|
+
*/
|
|
58
|
+
function searchByContent(query, projectRoot, limit = 50) {
|
|
59
|
+
const result = spawnSync('rg', [
|
|
60
|
+
'--files-with-matches',
|
|
61
|
+
'--ignore-case',
|
|
62
|
+
'--max-count=1',
|
|
63
|
+
'--',
|
|
64
|
+
query,
|
|
65
|
+
projectRoot,
|
|
66
|
+
], { encoding: 'utf8', timeout: 10_000 });
|
|
67
|
+
if (result.error || result.status !== 0)
|
|
68
|
+
return [];
|
|
69
|
+
return result.stdout
|
|
70
|
+
.split('\n')
|
|
71
|
+
.map(l => l.trim())
|
|
72
|
+
.filter(l => l.length > 0)
|
|
73
|
+
.slice(0, limit);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Search for files matching a query string.
|
|
77
|
+
* Path-substring match + optional ripgrep content search (searchContent=true).
|
|
78
|
+
* Content matches receive a +0.5 score boost vs pure path matches.
|
|
79
|
+
* Multi-word queries default to searchContent=true (caller-controlled via server.ts).
|
|
80
|
+
*/
|
|
81
|
+
export function searchFiles(db, query, taskFiles, projectRoot, limit = 10, searchContent = false) {
|
|
82
|
+
const graphNeighbors = getGraphNeighbors(db, taskFiles);
|
|
83
|
+
const allFiles = db.getTopFiles(1000);
|
|
84
|
+
const lowerQuery = query.toLowerCase();
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
const contentMatchBoost = 0.5;
|
|
87
|
+
// Path matches from DB
|
|
88
|
+
const pathMatchPaths = new Set(allFiles.filter(f => f.path.toLowerCase().includes(lowerQuery)).map(f => f.path));
|
|
89
|
+
// Content matches via ripgrep (if enabled)
|
|
90
|
+
const contentMatchPaths = new Set();
|
|
91
|
+
if (searchContent) {
|
|
92
|
+
for (const f of searchByContent(query, projectRoot, 50)) {
|
|
93
|
+
contentMatchPaths.add(f);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Score DB-indexed files that match path or content
|
|
97
|
+
const allMatchPaths = new Set([...pathMatchPaths, ...contentMatchPaths]);
|
|
98
|
+
const matches = allFiles
|
|
99
|
+
.filter(f => allMatchPaths.has(f.path))
|
|
100
|
+
.map(f => {
|
|
101
|
+
const baseScore = scoreFile(f.last_touched, f.touch_count, graphNeighbors.has(f.path), now);
|
|
102
|
+
// Boost content-only matches (not path matches) to surface content hits
|
|
103
|
+
const boost = contentMatchPaths.has(f.path) && !pathMatchPaths.has(f.path) ? contentMatchBoost : 0;
|
|
104
|
+
return {
|
|
105
|
+
path: f.path,
|
|
106
|
+
score: baseScore + boost,
|
|
107
|
+
lastTouched: f.last_touched,
|
|
108
|
+
touchCount: f.touch_count,
|
|
109
|
+
graphNeighborBoost: graphNeighbors.has(f.path),
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
// Add content-matched files not yet indexed in DB
|
|
113
|
+
for (const f of contentMatchPaths) {
|
|
114
|
+
if (!allFiles.some(af => af.path === f)) {
|
|
115
|
+
matches.push({
|
|
116
|
+
path: f,
|
|
117
|
+
score: contentMatchBoost,
|
|
118
|
+
lastTouched: 0,
|
|
119
|
+
touchCount: 0,
|
|
120
|
+
graphNeighborBoost: false,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
matches.sort((a, b) => b.score - a.score);
|
|
125
|
+
return matches.slice(0, limit);
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=codebase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codebase.js","sourceRoot":"","sources":["../../../src/indexing/codebase.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Atomic write: write to a temp file, then rename into place.
|
|
3
|
+
* This prevents partial writes corrupting the target file.
|
|
4
|
+
*/
|
|
5
|
+
export declare function atomicWrite(filePath: string, content: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Read a file, returning empty string if it doesn't exist.
|
|
8
|
+
*/
|
|
9
|
+
export declare function safeRead(filePath: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Patch a specific section in a markdown file.
|
|
12
|
+
* Sections are delimited by ## headings.
|
|
13
|
+
* If the section doesn't exist, it is appended.
|
|
14
|
+
*
|
|
15
|
+
* @param filePath - path to the markdown file
|
|
16
|
+
* @param sectionHeading - exact heading text (e.g. "Files touched")
|
|
17
|
+
* @param newContent - new content for the section (without the heading line)
|
|
18
|
+
*/
|
|
19
|
+
export declare function patchSection(filePath: string, sectionHeading: string, newContent: string): void;
|
|
20
|
+
/**
|
|
21
|
+
* Append a line to an append-only log file (e.g., l0.log).
|
|
22
|
+
* Creates the file if it doesn't exist.
|
|
23
|
+
* If maxLines is set, rotates the file to keep only the last maxLines lines after appending.
|
|
24
|
+
*/
|
|
25
|
+
export declare function appendLog(filePath: string, line: string, maxLines?: number): void;
|
|
26
|
+
/**
|
|
27
|
+
* Read the last N lines from a log file (tail behaviour).
|
|
28
|
+
*/
|
|
29
|
+
export declare function readLastLines(filePath: string, n: number): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Ensure a file exists with default content. Does nothing if file already exists.
|
|
32
|
+
*/
|
|
33
|
+
export declare function ensureFile(filePath: string, defaultContent: string): void;
|
|
34
|
+
//# sourceMappingURL=writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.d.ts","sourceRoot":"","sources":["../../../src/markdown/writer.ts"],"names":[],"mappings":"AAIA;;;GAGG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAQnE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CA6B/F;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAWjF;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAKnE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,IAAI,CAIzE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { writeFileSync, readFileSync, existsSync, mkdirSync, renameSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { randomBytes } from 'node:crypto';
|
|
4
|
+
/**
|
|
5
|
+
* Atomic write: write to a temp file, then rename into place.
|
|
6
|
+
* This prevents partial writes corrupting the target file.
|
|
7
|
+
*/
|
|
8
|
+
export function atomicWrite(filePath, content) {
|
|
9
|
+
const dir = dirname(filePath);
|
|
10
|
+
if (!existsSync(dir)) {
|
|
11
|
+
mkdirSync(dir, { recursive: true });
|
|
12
|
+
}
|
|
13
|
+
const tmp = join(dir, `.tmp-${randomBytes(6).toString('hex')}`);
|
|
14
|
+
writeFileSync(tmp, content, 'utf8');
|
|
15
|
+
renameSync(tmp, filePath);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Read a file, returning empty string if it doesn't exist.
|
|
19
|
+
*/
|
|
20
|
+
export function safeRead(filePath) {
|
|
21
|
+
if (!existsSync(filePath))
|
|
22
|
+
return '';
|
|
23
|
+
return readFileSync(filePath, 'utf8');
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Patch a specific section in a markdown file.
|
|
27
|
+
* Sections are delimited by ## headings.
|
|
28
|
+
* If the section doesn't exist, it is appended.
|
|
29
|
+
*
|
|
30
|
+
* @param filePath - path to the markdown file
|
|
31
|
+
* @param sectionHeading - exact heading text (e.g. "Files touched")
|
|
32
|
+
* @param newContent - new content for the section (without the heading line)
|
|
33
|
+
*/
|
|
34
|
+
export function patchSection(filePath, sectionHeading, newContent) {
|
|
35
|
+
const existing = safeRead(filePath);
|
|
36
|
+
const headingLine = `## ${sectionHeading}`;
|
|
37
|
+
const lines = existing.split('\n');
|
|
38
|
+
const startIdx = lines.findIndex(l => l.trim() === headingLine);
|
|
39
|
+
if (startIdx === -1) {
|
|
40
|
+
// Section doesn't exist — append it
|
|
41
|
+
const appended = existing.trimEnd() + `\n\n${headingLine}\n${newContent}\n`;
|
|
42
|
+
atomicWrite(filePath, appended);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Find the next ## heading after startIdx
|
|
46
|
+
let endIdx = lines.length;
|
|
47
|
+
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
48
|
+
if (lines[i] !== undefined && lines[i].startsWith('## ')) {
|
|
49
|
+
endIdx = i;
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const before = lines.slice(0, startIdx + 1).join('\n');
|
|
54
|
+
const after = lines.slice(endIdx).join('\n');
|
|
55
|
+
const patched = after
|
|
56
|
+
? `${before}\n${newContent}\n${after.startsWith('\n') ? after : '\n' + after}`
|
|
57
|
+
: `${before}\n${newContent}\n`;
|
|
58
|
+
atomicWrite(filePath, patched);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Append a line to an append-only log file (e.g., l0.log).
|
|
62
|
+
* Creates the file if it doesn't exist.
|
|
63
|
+
* If maxLines is set, rotates the file to keep only the last maxLines lines after appending.
|
|
64
|
+
*/
|
|
65
|
+
export function appendLog(filePath, line, maxLines) {
|
|
66
|
+
const dir = dirname(filePath);
|
|
67
|
+
if (!existsSync(dir))
|
|
68
|
+
mkdirSync(dir, { recursive: true });
|
|
69
|
+
const entry = line.endsWith('\n') ? line : line + '\n';
|
|
70
|
+
writeFileSync(filePath, entry, { flag: 'a', encoding: 'utf8' });
|
|
71
|
+
if (maxLines !== undefined) {
|
|
72
|
+
const all = readFileSync(filePath, 'utf8').split('\n').filter(l => l.trim());
|
|
73
|
+
if (all.length > maxLines) {
|
|
74
|
+
writeFileSync(filePath, all.slice(-maxLines).join('\n') + '\n', 'utf8');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Read the last N lines from a log file (tail behaviour).
|
|
80
|
+
*/
|
|
81
|
+
export function readLastLines(filePath, n) {
|
|
82
|
+
if (!existsSync(filePath))
|
|
83
|
+
return [];
|
|
84
|
+
const content = readFileSync(filePath, 'utf8');
|
|
85
|
+
const lines = content.split('\n').filter(l => l.trim().length > 0);
|
|
86
|
+
return lines.slice(-n);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Ensure a file exists with default content. Does nothing if file already exists.
|
|
90
|
+
*/
|
|
91
|
+
export function ensureFile(filePath, defaultContent) {
|
|
92
|
+
if (!existsSync(filePath)) {
|
|
93
|
+
atomicWrite(filePath, defaultContent);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"writer.js","sourceRoot":"","sources":["../../../src/markdown/writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import type { Db } from './storage/db.js';
|
|
3
|
+
import type { AreaDef } from './graph/indexer.js';
|
|
4
|
+
export interface ServerConfig {
|
|
5
|
+
projectRoot: string;
|
|
6
|
+
stateDir: string;
|
|
7
|
+
areas: AreaDef[];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Register all 10 ClaudeContext MCP tools on the given server.
|
|
11
|
+
* Protocol: 2025-03-26 — tool annotations required.
|
|
12
|
+
* NEVER console.log() — stdout is the JSON-RPC channel.
|
|
13
|
+
*/
|
|
14
|
+
export declare function registerTools(server: Server, db: Db, config: ServerConfig): void;
|
|
15
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,iBAAiB,CAAC;AAM1C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAOlD,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,OAAO,EAAE,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,YAAY,GAAG,IAAI,CA0gBhF"}
|