codesearch-mcp 0.0.14-alpha → 0.0.16-alpha

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.
@@ -48,29 +48,67 @@ const PKG_VERSION = (() => {
48
48
  return '0.0.0';
49
49
  }
50
50
  })();
51
- const SERVER_INSTRUCTIONS = `
52
- You have access to a local semantic code search server. Use these tools to navigate unfamiliar codebases.
51
+ function buildInstructions(t) {
52
+ return `
53
+ You have access to a local code intelligence server. Use these tools to search codebases by meaning, navigate import graphs, look up symbol definitions, and read source files.
54
+
55
+ ## Step 0 — Classify your query before starting
56
+
57
+ Pick one workflow based on what you need:
58
+
59
+ | Type | Signals | Workflow |
60
+ |---|---|---|
61
+ | **Lookup** | "where is X defined", "find Y" | find_symbol (if name known) → search_codebase (if not found) |
62
+ | **Conceptual** | "how does X work", "what is Y" | search_codebase → read_file_range |
63
+ | **Flow audit** | "how does X connect to Y", "audit this flow", "trace the path" | search_codebase → **get_dependencies + get_dependents** → Grep |
64
+ | **Impact** | "what would break if I change X", "what uses Z" | get_dependents → search_codebase for context |
65
+
66
+ > **No results?** Never conclude the code doesn't exist after a single attempt. Retry with \`threshold\` raised by 0.05–0.10 (e.g. 0.45 → 0.50 → 0.55) before giving up. The code may exist under a different name or domain term.
53
67
 
54
68
  ## Tools
55
69
 
56
70
  - **list_projects** — call this first to see what projects are indexed and their exact names.
57
71
  - **search_codebase** — semantic search across indexed source files. Returns file path, line number, and a code chunk.
58
- - **read_file_range** — read a specific line range from any indexed file. Use this to expand context around a search result.
72
+ - **read_file_range** — read a specific line range from any indexed file. Expects a **relative path** as returned by search_codebase.
59
73
  - **get_dependencies** — show what files a given file imports (direct or transitive). Use to understand what a file depends on.
60
74
  - **get_dependents** — show which files import a given file (reverse graph). Use before refactoring to find all callers.
61
75
  - **find_symbol** — find where a symbol (function, class, type, interface, variable, method) is defined by exact name. Faster than semantic search when you know the name.
62
76
  - **list_files** — browse the directory tree of a project path. Use to understand project structure before reading files.
63
- - **read_file** — read a complete file by absolute path with line numbers. Truncates at max_lines with a hint to continue.
77
+ - **read_file** — read a complete file by **absolute path** with line numbers. Truncates at max_lines with a hint to continue.
64
78
 
65
79
  ## Recommended workflow
66
80
 
81
+ ### Lookup / Conceptual
67
82
  1. Use \`list_projects\` to discover available projects before filtering by \`project\`.
68
- 2. **Before searching**: if your query uses an ambiguous term (e.g. "subscription" could mean pub/sub or billing), pass a lower \`threshold\` (e.g. \`0.35\`) to \`search_codebase\` to filter out weak matches. Default threshold is permissive — tighten it when semantic drift is likely.
69
- 3. Use \`search_codebase\` to find relevant code by meaning.
70
- 4. If a result **starts mid-function or mid-class** (e.g. you see a closing brace or a method body without the declaration), re-run the same search with \`include_neighbors: true\` — it automatically fetches the chunk before and after each match. If you need a specific line range, use \`read_file_range\` instead.
71
- 5. Use \`find_symbol\` when you know the exact name of a function, class, or method and want its definition location immediately — faster than semantic search. Use \`kind: "method"\` to find public class methods like \`canActivate\`, \`execute\`, \`handle\`.
72
- 6. Use \`list_files\` to explore project structure (src/, components/, etc.) before diving into files.
73
- 7. Use \`read_file\` to read a complete file when you have its absolute path from \`search_codebase\` results.
83
+ 2. Use \`search_codebase\` to find relevant code by meaning. If your query uses an ambiguous term (e.g. "subscription" could mean pub/sub or billing), pass a lower \`threshold\` (e.g. \`0.40–0.45\`) to filter out weak matches.
84
+ 3. If a result looks **truncated or incomplete**, call \`read_file_range\` with the returned \`file_path\` and \`start_line\`.
85
+ 4. For exploratory searches where results span chunk boundaries, pass \`include_neighbors: true\`.
86
+ 5. Use \`find_symbol\` when you know the exact name — faster than semantic search. Use \`kind: "method"\` for class methods — grep matches lines where \`public\`, \`async\`, \`static\`, or \`override\` appears before the name.
87
+ 6. Use \`list_files\` to explore project structure before diving into files. Use \`read_file\` to read a complete file by absolute path.
88
+
89
+ ### Flow audit (mandatory steps — do not skip 3 and 4)
90
+ 1. Use \`list_projects\` to confirm project names.
91
+ 2. Use \`search_codebase\` to find the **central file** (entry point of the flow).
92
+ 3. **\`get_dependencies(central_file)\`** — what does this file import? Catches configs, loaders, Redis clients, types.
93
+ 4. **\`get_dependents(central_file)\`** — who calls this file? Catches resolvers, routes, socket handlers.
94
+ 5. For each peripheral file found in steps 3–4: use \`read_file_range\` or \`find_symbol\` to inspect it.
95
+ 6. Only after steps 3–4 draw architectural conclusions — \`search_codebase\` alone misses peripheral files because they are semantically thin (configs, types, loaders contain no domain vocabulary).
96
+
97
+ > **Note:** If \`get_dependencies\` / \`get_dependents\` return empty, the file likely uses path aliases (e.g. \`@core/\`, \`@/\`, \`@db/\`). Fall back to \`Grep\` on the symbol name across the project.
98
+
99
+ ### Impact analysis
100
+ 1. \`get_dependents(target_file)\` — direct callers.
101
+ 2. \`get_dependents(target_file, transitive: true)\` — full reverse graph.
102
+ 3. \`search_codebase\` for context on unfamiliar dependents.
103
+
104
+ ## When to use read_file_range vs include_neighbors
105
+
106
+ - **include_neighbors: true** — good when context is fragmented across chunks (e.g. a class definition split across chunks).
107
+ - **read_file_range** — better for a precise section, or when one result is cut off.
108
+
109
+ ## Handling Code Structure
110
+ - **Class/Function limits**: Chunks often end abruptly. Use \`read_file_range\` to find the closing brace or method start.
111
+ - **Cross-file references**: If you see \`this.validator.validate(data)\`, use \`search_codebase\` to find \`validator\`.
74
112
 
75
113
  ## Dependency graph
76
114
 
@@ -80,8 +118,9 @@ If \`get_dependents\` returns 0 results, add \`symbol\` (the exported name you c
80
118
 
81
119
  ## Relevance scores
82
120
 
83
- Lower score = better match (cosine distance). Results above the configured threshold are filtered out automatically. Pass \`threshold\` to \`search_codebase\` to override per-query (e.g. \`0.35\` for strict, \`0.55\` for broad).
121
+ Lower score = better match (cosine distance). Results above the configured threshold are filtered out automatically. Treat scores above 0.50 as weak hints — verify with \`read_file_range\` or \`Grep\`. Pass \`threshold\` to \`search_codebase\` to override per-query: \`0.40–0.45\` for precise technical queries (known term, exact concept); \`${t}\` default (broad but reliable). Avoid \`0.35\` — too strict for DSL files (GraphQL, Prisma) and infrastructure code.
84
122
  `.trim();
123
+ }
85
124
  class McpServer {
86
125
  searcher;
87
126
  config;
@@ -92,7 +131,7 @@ class McpServer {
92
131
  this.logger = logger;
93
132
  }
94
133
  async start(startupError) {
95
- const server = new index_js_1.Server({ name: 'local-rag', version: PKG_VERSION }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
134
+ const server = new index_js_1.Server({ name: 'local-rag', version: PKG_VERSION }, { capabilities: { tools: {} }, instructions: buildInstructions(this.config.search.similarityThreshold) });
96
135
  server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({
97
136
  tools: [
98
137
  {
@@ -105,14 +144,14 @@ class McpServer {
105
144
  limit: { type: 'number', description: `Max results (default ${this.config.search.defaultLimit}, max ${this.config.search.maxLimit})` },
106
145
  project: { type: 'string', description: 'Filter by project name (optional). Use list_projects to see available names.' },
107
146
  include_neighbors: { type: 'boolean', description: 'Also include the chunk before and after each result from the same file (Small-to-Big retrieval). Useful when results look truncated.' },
108
- threshold: { type: 'number', description: `Max cosine distance (0–1). Lower = stricter. Default: ${this.config.search.similarityThreshold}. Use a lower value (e.g. 0.35) to filter out weak matches.` },
147
+ threshold: { type: 'number', description: `Max cosine distance (0–1). Lower = stricter. Default: ${this.config.search.similarityThreshold}. Use 0.40–0.45 for precise technical queries, 0.55–0.60 for broad exploration.` },
109
148
  },
110
149
  required: ['query'],
111
150
  },
112
151
  },
113
152
  {
114
153
  name: 'list_projects',
115
- description: 'List all indexed projects with their chunk counts',
154
+ description: 'List all indexed projects with their chunk counts and metadata (description, stack, notes, relations from .ragmeta.json).',
116
155
  inputSchema: { type: 'object', properties: {} },
117
156
  },
118
157
  {
@@ -185,11 +224,11 @@ class McpServer {
185
224
  },
186
225
  {
187
226
  name: 'read_file',
188
- description: 'Read a file from the workspace by absolute path (as returned by search_codebase). Returns contents with line numbers. Truncates at max_lines with a hint to continue with read_file_range.',
227
+ description: 'Read a file by absolute path. Returns contents with line numbers. Truncates at max_lines with a hint to continue with read_file_range.',
189
228
  inputSchema: {
190
229
  type: 'object',
191
230
  properties: {
192
- file_path: { type: 'string', description: 'Absolute path to the file (as returned in filePath by search_codebase)' },
231
+ file_path: { type: 'string', description: 'Absolute path to the file. Note: search_codebase returns relative paths — construct the absolute path from your workspace root.' },
193
232
  max_lines: { type: 'number', description: 'Maximum lines to return (default 300, max 1000)' },
194
233
  },
195
234
  required: ['file_path'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codesearch-mcp",
3
- "version": "0.0.14-alpha",
3
+ "version": "0.0.16-alpha",
4
4
  "description": "Local semantic codebase search via MCP — indexes projects into pgvector, exposes search to Claude",
5
5
  "license": "MIT",
6
6
  "main": "dist/app.js",
@@ -12,7 +12,8 @@
12
12
  "files": [
13
13
  "dist/",
14
14
  "docker/",
15
- "README.md"
15
+ "README.md",
16
+ "CHANGELOG.md"
16
17
  ],
17
18
  "scripts": {
18
19
  "build": "tsc",
@@ -33,14 +34,13 @@
33
34
  "@modelcontextprotocol/sdk": "^1.0.0",
34
35
  "cli-progress": "^3.12.0",
35
36
  "dotenv": "^17.4.2",
37
+ "drizzle-orm": "^0.45.2",
36
38
  "ignore": "^7.0.5",
37
39
  "ollama": "^0.5.0",
38
40
  "pg": "^8.13.0",
39
41
  "pino": "^10.3.1",
40
42
  "pino-roll": "^4.0.0",
41
- "reflect-metadata": "^0.2.2",
42
43
  "ts-morph": "^28.0.0",
43
- "typeorm": "^0.3.20",
44
44
  "zod": "^4.3.6"
45
45
  },
46
46
  "devDependencies": {