@idea404/repocontext 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.
@@ -0,0 +1,132 @@
1
+ import { searchFiles, fuzzyFindFiles } from './search.js';
2
+ import { parseFile, detectLanguageForPath } from './parser.js';
3
+ import { safeReadFile } from './files.js';
4
+ import { linesAround, DEFAULT_SEARCH_LIMIT, formatLines } from './utils.js';
5
+ export async function findSymbols(query, options = {}) {
6
+ const limit = options.limit ?? DEFAULT_SEARCH_LIMIT;
7
+ const results = [];
8
+ const seen = new Set();
9
+ async function collectFromFile(filePath) {
10
+ if (results.length >= limit)
11
+ return;
12
+ if (options.language) {
13
+ const lang = detectLanguageForPath(filePath);
14
+ if (lang !== options.language)
15
+ return;
16
+ }
17
+ const parsed = await parseFile(filePath);
18
+ if (!parsed?.structure)
19
+ return;
20
+ for (const item of parsed.structure) {
21
+ if (!item.name)
22
+ continue;
23
+ if (options.kind && !item.kind.toLowerCase().includes(options.kind.toLowerCase()))
24
+ continue;
25
+ if (!item.name.toLowerCase().includes(query.toLowerCase()))
26
+ continue;
27
+ const key = `${filePath}:${item.name}:${item.startLine}`;
28
+ if (seen.has(key))
29
+ continue;
30
+ seen.add(key);
31
+ results.push({
32
+ name: item.name,
33
+ kind: item.kind,
34
+ file: filePath,
35
+ startLine: item.startLine,
36
+ endLine: item.endLine,
37
+ docComment: item.docComment,
38
+ });
39
+ if (results.length >= limit)
40
+ break;
41
+ }
42
+ }
43
+ // First, try fuzzy file name matches for short, identifier-like queries.
44
+ if (/^[a-zA-Z0-9_]+$/.test(query)) {
45
+ const fileMatches = await fuzzyFindFiles(query, { limit: limit * 2 });
46
+ for (const file of fileMatches) {
47
+ await collectFromFile(file.absolutePath);
48
+ if (results.length >= limit)
49
+ return results;
50
+ }
51
+ }
52
+ // Then search code content, prioritizing definition-classified matches.
53
+ const matches = await searchFiles(query, {
54
+ mode: 'plain',
55
+ glob: options.glob,
56
+ limit: 200,
57
+ });
58
+ const definitionFiles = matches
59
+ .filter((m) => m.isDefinition)
60
+ .map((m) => m.absolutePath);
61
+ const otherFiles = matches
62
+ .filter((m) => !m.isDefinition)
63
+ .map((m) => m.absolutePath);
64
+ for (const filePath of [...new Set([...definitionFiles, ...otherFiles])]) {
65
+ await collectFromFile(filePath);
66
+ if (results.length >= limit)
67
+ return results;
68
+ }
69
+ return results;
70
+ }
71
+ export async function traceSymbol(name, options = {}) {
72
+ let definition = null;
73
+ if (options.path) {
74
+ const parsed = await parseFile(options.path);
75
+ if (parsed?.structure) {
76
+ const item = parsed.structure.find((s) => s.name === name &&
77
+ (!options.kind || s.kind.toLowerCase().includes(options.kind.toLowerCase())));
78
+ if (item) {
79
+ definition = {
80
+ name: item.name,
81
+ kind: item.kind,
82
+ file: options.path,
83
+ startLine: item.startLine,
84
+ endLine: item.endLine,
85
+ docComment: item.docComment,
86
+ };
87
+ }
88
+ }
89
+ }
90
+ if (!definition) {
91
+ const candidates = await findSymbols(name, { kind: options.kind, limit: 10 });
92
+ definition = candidates[0] ?? null;
93
+ }
94
+ const refs = await searchFiles(name, { mode: 'plain', limit: 50 });
95
+ const references = [];
96
+ for (const ref of refs) {
97
+ if (definition && ref.absolutePath === definition.file && ref.lineNumber === definition.startLine) {
98
+ continue;
99
+ }
100
+ const buffer = await safeReadFile(ref.absolutePath);
101
+ if (!buffer)
102
+ continue;
103
+ const source = buffer.toString('utf-8');
104
+ const allLines = source.split('\n');
105
+ const around = linesAround(allLines, ref.lineNumber, 2);
106
+ references.push({
107
+ ...ref,
108
+ snippet: formatLines(around.lines, around.start),
109
+ });
110
+ }
111
+ return { definition, references: references.slice(0, DEFAULT_SEARCH_LIMIT) };
112
+ }
113
+ export async function getImports(filePath) {
114
+ const parsed = await parseFile(filePath);
115
+ if (!parsed)
116
+ return null;
117
+ return (parsed.imports?.map((imp) => ({
118
+ source: imp.source ?? '',
119
+ items: imp.items ?? [],
120
+ isWildcard: imp.isWildcard ?? false,
121
+ })) ?? []);
122
+ }
123
+ export async function getExports(filePath) {
124
+ const parsed = await parseFile(filePath);
125
+ if (!parsed)
126
+ return null;
127
+ return (parsed.exports?.map((exp) => ({
128
+ name: exp.name ?? '',
129
+ kind: exp.kind ?? '',
130
+ })) ?? []);
131
+ }
132
+ //# sourceMappingURL=symbols.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symbols.js","sourceRoot":"","sources":["../src/symbols.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ export interface ParseResult {
2
+ language: string;
3
+ metrics: {
4
+ totalLines: number;
5
+ codeLines: number;
6
+ commentLines: number;
7
+ blankLines: number;
8
+ totalBytes: number;
9
+ nodeCount: number;
10
+ errorCount: number;
11
+ maxDepth: number;
12
+ };
13
+ structure: Array<{
14
+ kind: string;
15
+ name: string;
16
+ startLine: number;
17
+ endLine: number;
18
+ docComment?: string;
19
+ signature?: string;
20
+ }>;
21
+ imports: Array<{
22
+ source: string;
23
+ items: string[];
24
+ isWildcard: boolean;
25
+ }>;
26
+ exports: Array<{
27
+ name: string;
28
+ kind: string;
29
+ }>;
30
+ }
31
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE;QACP,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,SAAS,EAAE,KAAK,CAAC;QACf,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC,CAAC;IACH,OAAO,EAAE,KAAK,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,MAAM,CAAC;KACd,CAAC,CAAC;CACJ"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,18 @@
1
+ import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
+ export declare const DEFAULT_SNIPPET_MAX_LINES = 50;
3
+ export declare const DEFAULT_SEARCH_LIMIT = 25;
4
+ export declare const DEFAULT_MAX_FILE_BYTES: number;
5
+ export declare const DEFAULT_PARSER_CACHE_SIZE = 200;
6
+ export declare const DEFAULT_SCAN_TIMEOUT_MS = 5000;
7
+ export declare function log(level: 'debug' | 'info' | 'warning' | 'error', message: string): void;
8
+ export declare function okResult(text: string, extra?: Record<string, unknown>): CallToolResult;
9
+ export declare function errorResult(message: string): CallToolResult;
10
+ export declare function clamp(num: number, min: number, max: number): number;
11
+ export declare function linesAround(allLines: string[], targetLineOneIndexed: number, contextLines: number): {
12
+ start: number;
13
+ end: number;
14
+ lines: string[];
15
+ };
16
+ export declare function getLines(source: string, startOneIndexed: number, endOneIndexed: number): string[];
17
+ export declare function formatLines(lines: string[], startLine: number): string;
18
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,eAAO,MAAM,yBAAyB,KAAK,CAAC;AAC5C,eAAO,MAAM,oBAAoB,KAAK,CAAC;AACvC,eAAO,MAAM,sBAAsB,QAAc,CAAC;AAClD,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAC7C,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,wBAAgB,GAAG,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAIxF;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,cAAc,CAKtF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAK3D;AAED,wBAAgB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAAE,EAClB,oBAAoB,EAAE,MAAM,EAC5B,YAAY,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,EAAE,CAAA;CAAE,CAQjD;AAED,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,EAAE,CAKjG;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAKtE"}
package/dist/utils.js ADDED
@@ -0,0 +1,47 @@
1
+ export const DEFAULT_SNIPPET_MAX_LINES = 50;
2
+ export const DEFAULT_SEARCH_LIMIT = 25;
3
+ export const DEFAULT_MAX_FILE_BYTES = 1024 * 1024; // 1 MB
4
+ export const DEFAULT_PARSER_CACHE_SIZE = 200;
5
+ export const DEFAULT_SCAN_TIMEOUT_MS = 5000;
6
+ export function log(level, message) {
7
+ // Use stderr for logging so stdout stays clean for MCP messages.
8
+ const timestamp = new Date().toISOString();
9
+ console.error(`[${timestamp}] [${level.toUpperCase()}] @idea404/repocontext: ${message}`);
10
+ }
11
+ export function okResult(text, extra) {
12
+ return {
13
+ content: [{ type: 'text', text }],
14
+ ...extra,
15
+ };
16
+ }
17
+ export function errorResult(message) {
18
+ return {
19
+ content: [{ type: 'text', text: message }],
20
+ isError: true,
21
+ };
22
+ }
23
+ export function clamp(num, min, max) {
24
+ return Math.max(min, Math.min(max, num));
25
+ }
26
+ export function linesAround(allLines, targetLineOneIndexed, contextLines) {
27
+ const start = clamp(targetLineOneIndexed - contextLines - 1, 0, allLines.length);
28
+ const end = clamp(targetLineOneIndexed + contextLines, 0, allLines.length);
29
+ return {
30
+ start: start + 1,
31
+ end,
32
+ lines: allLines.slice(start, end),
33
+ };
34
+ }
35
+ export function getLines(source, startOneIndexed, endOneIndexed) {
36
+ const lines = source.split('\n');
37
+ const start = clamp(startOneIndexed - 1, 0, lines.length);
38
+ const end = clamp(endOneIndexed, 0, lines.length);
39
+ return lines.slice(start, end);
40
+ }
41
+ export function formatLines(lines, startLine) {
42
+ const width = String(startLine + lines.length).length;
43
+ return lines
44
+ .map((line, idx) => `${String(startLine + idx).padStart(width, ' ')}: ${line}`)
45
+ .join('\n');
46
+ }
47
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,EAAE,CAAC;AAC5C,MAAM,CAAC,MAAM,oBAAoB,GAAG,EAAE,CAAC;AACvC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;AAC1D,MAAM,CAAC,MAAM,yBAAyB,GAAG,GAAG,CAAC;AAC7C,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,MAAM,UAAU,GAAG,CAAC,KAA6C,EAAE,OAAe;IAChF,iEAAiE;IACjE,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC3C,OAAO,CAAC,KAAK,CAAC,IAAI,SAAS,MAAM,KAAK,CAAC,WAAW,EAAE,2BAA2B,OAAO,EAAE,CAAC,CAAC;AAC5F,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,IAAY,EAAE,KAA+B;IACpE,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QACjC,GAAG,KAAK;KACT,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC1C,OAAO,EAAE,IAAI;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW,EAAE,GAAW,EAAE,GAAW;IACzD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,QAAkB,EAClB,oBAA4B,EAC5B,YAAoB;IAEpB,MAAM,KAAK,GAAG,KAAK,CAAC,oBAAoB,GAAG,YAAY,GAAG,CAAC,EAAE,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IACjF,MAAM,GAAG,GAAG,KAAK,CAAC,oBAAoB,GAAG,YAAY,EAAE,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC3E,OAAO;QACL,KAAK,EAAE,KAAK,GAAG,CAAC;QAChB,GAAG;QACH,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC;KAClC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,eAAuB,EAAE,aAAqB;IACrF,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,KAAK,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1D,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,EAAE,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAe,EAAE,SAAiB;IAC5D,MAAM,KAAK,GAAG,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IACtD,OAAO,KAAK;SACT,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;SAC9E,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "@idea404/repocontext",
3
+ "version": "0.1.0",
4
+ "description": "The only MCP server you need for context-efficient codebase learning",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "repocontext": "dist/cli.js"
10
+ },
11
+ "files": [
12
+ "dist/",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "scripts": {
17
+ "build": "tsc",
18
+ "dev": "tsc --watch",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest",
21
+ "lint": "tsc --noEmit",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "mcp",
26
+ "codebase",
27
+ "tree-sitter",
28
+ "agent",
29
+ "code-exploration",
30
+ "opencode"
31
+ ],
32
+ "author": "",
33
+ "license": "MIT",
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "engines": {
38
+ "node": ">=20"
39
+ },
40
+ "dependencies": {
41
+ "@ff-labs/fff-node": "^0.9.4",
42
+ "@modelcontextprotocol/sdk": "1.29.0",
43
+ "fast-fuzzy": "^1.12.0",
44
+ "tree-sitter": "0.25.0",
45
+ "tree-sitter-bash": "0.25.1",
46
+ "tree-sitter-c": "0.24.1",
47
+ "tree-sitter-c-sharp": "0.23.5",
48
+ "tree-sitter-cpp": "0.23.4",
49
+ "tree-sitter-css": "0.25.0",
50
+ "tree-sitter-elixir": "0.3.5",
51
+ "tree-sitter-go": "0.25.0",
52
+ "tree-sitter-haskell": "0.23.1",
53
+ "tree-sitter-html": "0.23.2",
54
+ "tree-sitter-java": "0.23.5",
55
+ "tree-sitter-javascript": "0.25.0",
56
+ "tree-sitter-json": "0.24.8",
57
+ "tree-sitter-kotlin": "0.3.8",
58
+ "tree-sitter-ocaml": "0.24.2",
59
+ "tree-sitter-perl": "1.1.2",
60
+ "tree-sitter-php": "0.24.2",
61
+ "tree-sitter-python": "0.25.0",
62
+ "tree-sitter-ruby": "0.23.1",
63
+ "tree-sitter-rust": "0.24.0",
64
+ "tree-sitter-scala": "0.24.0",
65
+ "tree-sitter-swift": "0.7.1",
66
+ "tree-sitter-typescript": "0.23.2",
67
+ "zod": "^3.25.0"
68
+ },
69
+ "devDependencies": {
70
+ "@types/node": "^22.15.0",
71
+ "typescript": "^5.8.0",
72
+ "vitest": "^3.2.0"
73
+ },
74
+ "overrides": {
75
+ "tree-sitter": "0.25.0"
76
+ }
77
+ }