lmgrep 0.1.10 → 0.1.11

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 CHANGED
@@ -133,6 +133,68 @@ lmgrep includes an MCP server for use with AI coding assistants. When launched w
133
133
 
134
134
  You can also start it explicitly with `lmgrep mcp`.
135
135
 
136
+ ### Claude Code
137
+
138
+ ```sh
139
+ # If lmgrep is installed globally
140
+ claude mcp add lmgrep -s user -- lmgrep mcp
141
+
142
+ # Or without a global install
143
+ claude mcp add lmgrep -s user -- npx -y lmgrep mcp
144
+ ```
145
+
146
+ ### Codex CLI
147
+
148
+ ```sh
149
+ # If lmgrep is installed globally
150
+ codex mcp add lmgrep -- lmgrep mcp
151
+
152
+ # Or without a global install
153
+ codex mcp add lmgrep -- npx -y lmgrep mcp
154
+ ```
155
+
156
+ ### Gemini CLI
157
+
158
+ ```sh
159
+ # If lmgrep is installed globally
160
+ gemini mcp add lmgrep -- lmgrep mcp
161
+
162
+ # Or without a global install
163
+ gemini mcp add lmgrep -- npx -y lmgrep mcp
164
+ ```
165
+
166
+ ### Pi coding agent
167
+
168
+ Pi doesn't speak MCP — it uses TypeScript extensions instead. lmgrep ships one at [`pi-extension/`](./pi-extension) that registers two tools: `lmgrep_search` and `lmgrep_list_other_indexed_projects`. It imports lmgrep directly, runs an in-process file watcher to keep the index fresh, and gates tool visibility on embedder health — if lmgrep isn't configured, or the embedding provider is unreachable, the tools stay hidden so you get a clean tool surface instead of a broken one. Configure lmgrep first (`lmgrep init`) before relying on it inside Pi.
169
+
170
+ Install via Pi's package manager:
171
+
172
+ ```sh
173
+ pi install git:github.com/Aetherall/lmgrep
174
+ ```
175
+
176
+ Update with `pi update`, remove with `pi remove git:github.com/Aetherall/lmgrep`, and list installed extensions with `pi list`.
177
+
178
+ ### OpenCode
179
+
180
+ OpenCode has no one-shot install flag — add an entry to `~/.config/opencode/opencode.json` (or project-level `opencode.json`):
181
+
182
+ ```jsonc
183
+ {
184
+ "$schema": "https://opencode.ai/config.json",
185
+ "mcp": {
186
+ "lmgrep": {
187
+ "type": "local",
188
+ // If lmgrep is installed globally
189
+ "command": ["lmgrep", "mcp"],
190
+ // Or without a global install
191
+ // "command": ["npx", "-y", "lmgrep", "mcp"],
192
+ "enabled": true
193
+ }
194
+ }
195
+ }
196
+ ```
197
+
136
198
  The MCP server exposes a `search` tool and a `list_other_indexed_projects` tool. It automatically watches for file changes and keeps the index up to date.
137
199
 
138
200
  ## Configuration
@@ -0,0 +1,47 @@
1
+ export type HealthReason = "ok" | "not_indexed" | "embedding_failed" | "search_empty";
2
+ export interface HealthState {
3
+ healthy: boolean;
4
+ reason: HealthReason;
5
+ }
6
+ export interface SearchArgs {
7
+ query: string;
8
+ limit?: number;
9
+ filePrefix?: string;
10
+ type?: string[];
11
+ language?: string[];
12
+ project?: string;
13
+ }
14
+ export interface ToolResult {
15
+ text: string;
16
+ isError?: boolean;
17
+ }
18
+ export interface ParamSpec {
19
+ description: string;
20
+ }
21
+ export interface SearchParamSpecs {
22
+ query: ParamSpec;
23
+ limit: ParamSpec & {
24
+ default: number;
25
+ };
26
+ filePrefix: ParamSpec;
27
+ type: ParamSpec;
28
+ language: ParamSpec;
29
+ project: ParamSpec;
30
+ }
31
+ export declare const searchParamSpecs: SearchParamSpecs;
32
+ export declare const listProjectsDescription: string;
33
+ export interface LmgrepCore {
34
+ readonly cwd: string;
35
+ readonly searchParams: SearchParamSpecs;
36
+ readonly listProjectsDescription: string;
37
+ buildSearchDescription(): string;
38
+ currentHealth(): HealthState;
39
+ onHealthChange(cb: (state: HealthState) => void): () => void;
40
+ startHealthLoop(): void;
41
+ executeSearch(args: SearchArgs): Promise<ToolResult>;
42
+ executeListProjects(): Promise<ToolResult>;
43
+ dispose(): Promise<void>;
44
+ }
45
+ export declare function createLmgrepCore(opts: {
46
+ cwd: string;
47
+ }): Promise<LmgrepCore>;
@@ -0,0 +1,220 @@
1
+ import { existsSync } from "node:fs";
2
+ import { createIndex } from "../index.js";
3
+ import { TreeSitterChunker } from "./chunker/index.js";
4
+ import { loadConfig } from "./config.js";
5
+ import { AISDKEmbedder } from "./embedder.js";
6
+ import { startWatcher } from "./serve.js";
7
+ import { discoverIndexedProjects, findIndexedAncestor, getDbPath, Store, } from "./store.js";
8
+ import { silentLogger } from "./types.js";
9
+ export const searchParamSpecs = {
10
+ query: {
11
+ description: 'Natural-language description of what you\'re looking for — phrase it as a question or intent, not keywords. Good: "how are webhooks authenticated", "where is user deletion handled", "what happens when a record is created". Bad: "webhook auth", "deleteUser", "createRecord".',
12
+ },
13
+ limit: {
14
+ description: "Maximum number of results",
15
+ default: 10,
16
+ },
17
+ filePrefix: {
18
+ description: "Restrict to files under this path (e.g. 'src/lib')",
19
+ },
20
+ type: {
21
+ description: "AST node types to filter by (e.g. ['function_declaration', 'class_declaration'])",
22
+ },
23
+ language: {
24
+ description: "File extensions to filter by (e.g. ['.ts', '.py'])",
25
+ },
26
+ project: {
27
+ description: "Search a different indexed project by its root path instead of the current one",
28
+ },
29
+ };
30
+ export const listProjectsDescription = "List all indexed projects other than the current one. " +
31
+ "Use this to discover what projects are available for cross-project search " +
32
+ "via the `project` parameter on the search tool.";
33
+ export async function createLmgrepCore(opts) {
34
+ const cwd = opts.cwd;
35
+ const index = await createIndex({ cwd });
36
+ function isCurrentProjectIndexed() {
37
+ if (findIndexedAncestor(cwd))
38
+ return true;
39
+ return existsSync(getDbPath(cwd));
40
+ }
41
+ function getOtherProjects() {
42
+ const currentDb = getDbPath(cwd);
43
+ return discoverIndexedProjects()
44
+ .filter((p) => getDbPath(p.metadata.root) !== currentDb)
45
+ .map((p) => ({ root: p.metadata.root, remote: p.metadata.remote }));
46
+ }
47
+ async function checkHealth() {
48
+ if (!isCurrentProjectIndexed()) {
49
+ return { healthy: false, reason: "not_indexed" };
50
+ }
51
+ try {
52
+ const info = await index.status();
53
+ if (info.fileCount === 0) {
54
+ return { healthy: false, reason: "not_indexed" };
55
+ }
56
+ if (!info.embeddingOk) {
57
+ return { healthy: false, reason: "embedding_failed" };
58
+ }
59
+ if (!info.searchOk) {
60
+ return { healthy: false, reason: "search_empty" };
61
+ }
62
+ return { healthy: true, reason: "ok" };
63
+ }
64
+ catch {
65
+ return { healthy: false, reason: "embedding_failed" };
66
+ }
67
+ }
68
+ let state = isCurrentProjectIndexed()
69
+ ? { healthy: true, reason: "ok" }
70
+ : { healthy: false, reason: "not_indexed" };
71
+ const listeners = new Set();
72
+ let stopWatcher;
73
+ let pollTimer;
74
+ let disposed = false;
75
+ function tryStartWatcher() {
76
+ if (stopWatcher)
77
+ return;
78
+ if (!isCurrentProjectIndexed())
79
+ return;
80
+ const config = loadConfig(cwd);
81
+ const store = Store.forProject(cwd);
82
+ const embedder = new AISDKEmbedder(config);
83
+ const chunker = new TreeSitterChunker();
84
+ stopWatcher = startWatcher(cwd, store, config, embedder, chunker, silentLogger);
85
+ }
86
+ function buildSearchDescription() {
87
+ if (state.healthy) {
88
+ return [
89
+ "**lmgrep — primary search tool for this codebase.** Semantic code search powered by a local embedding model; lmgrep understands intent, not string patterns. Prefer lmgrep over Grep/Glob/find/ripgrep for almost all exploration and lookup tasks.",
90
+ "",
91
+ '**Use lmgrep for:** finding where something is handled, how something works, locating relevant code, discovering related files, understanding unfamiliar code, tracing side effects, finding usage patterns, answering "where is X?" or "how does Y work?". One good lmgrep query is usually enough to understand how to proceed.',
92
+ "",
93
+ "**Query lmgrep as natural questions or intent descriptions**, not keyword dumps:",
94
+ '- "how are webhooks authenticated" → finds middleware, token validation, auth checks',
95
+ '- "where is user deletion handled" → finds the handler and related cleanup logic',
96
+ '- "what happens when a record is created" → finds controllers, event emitters, side effects',
97
+ '- "config loading and validation"',
98
+ '- "how to run the playwright tests" → finds config, scripts, prerequisites',
99
+ "",
100
+ "**lmgrep results include** file paths, line numbers, AST node types, and surrounding context (scope, leading comments, role) — often enough to act on directly without re-reading the file. Trust lmgrep results; don't follow up with Glob/Read on files already surfaced by lmgrep unless you genuinely need content that wasn't returned.",
101
+ "",
102
+ "**Fall back to Grep only** when you need exact string or regex matches (specific identifiers, literal constants, error messages, TODO markers). Don't use Grep/Glob/find for conceptual or intent-based search — lmgrep will do better.",
103
+ ].join("\n");
104
+ }
105
+ const others = getOtherProjects();
106
+ const suffix = others.length > 0
107
+ ? " You can still search other indexed projects via the `project` parameter — call `list_other_indexed_projects` to see what's available."
108
+ : "";
109
+ switch (state.reason) {
110
+ case "not_indexed":
111
+ return ("This project is not indexed. Semantic search is not available for the current directory." +
112
+ suffix);
113
+ case "embedding_failed":
114
+ return ("The embedding provider is unreachable. Semantic search is temporarily unavailable for the current directory." +
115
+ suffix);
116
+ case "search_empty":
117
+ return ("The index for the current branch appears empty or stale — a smoke query returned no results. Re-run `lmgrep index` to rebuild." +
118
+ suffix);
119
+ default:
120
+ return "Semantic search is unavailable." + suffix;
121
+ }
122
+ }
123
+ async function refreshHealth() {
124
+ if (disposed)
125
+ return;
126
+ const next = await checkHealth();
127
+ if (next.healthy !== state.healthy || next.reason !== state.reason) {
128
+ state = next;
129
+ for (const cb of listeners)
130
+ cb(next);
131
+ }
132
+ if (next.healthy)
133
+ tryStartWatcher();
134
+ }
135
+ function startHealthLoop() {
136
+ if (pollTimer)
137
+ return;
138
+ tryStartWatcher();
139
+ // Non-local providers may bill per request — poll less often.
140
+ const intervalMs = index.config.local ? 10_000 : 60_000;
141
+ refreshHealth();
142
+ pollTimer = setInterval(refreshHealth, intervalMs);
143
+ }
144
+ async function executeSearch(args) {
145
+ if (state.reason === "embedding_failed") {
146
+ return {
147
+ text: "lmgrep is unavailable: the embedding provider is unreachable. Ask the user to check their lmgrep configuration (`lmgrep status`) before retrying.",
148
+ isError: true,
149
+ };
150
+ }
151
+ try {
152
+ const results = await index.search(args.query, {
153
+ limit: args.limit ?? searchParamSpecs.limit.default,
154
+ filePrefix: args.filePrefix,
155
+ type: args.type,
156
+ language: args.language,
157
+ project: args.project,
158
+ });
159
+ if (results.length === 0) {
160
+ return { text: "No results found." };
161
+ }
162
+ const text = results
163
+ .map((r) => {
164
+ const loc = `${r.filePath}:${r.startLine}-${r.endLine}`;
165
+ const header = `${loc} [${r.type}] ${r.name} (score: ${r.score.toFixed(3)})`;
166
+ const parts = [header];
167
+ if (r.context)
168
+ parts.push(r.context);
169
+ parts.push(r.content);
170
+ return parts.join("\n");
171
+ })
172
+ .join("\n\n---\n\n");
173
+ return { text };
174
+ }
175
+ catch (err) {
176
+ const msg = err instanceof Error ? err.message : String(err);
177
+ return { text: `Error: ${msg}`, isError: true };
178
+ }
179
+ }
180
+ async function executeListProjects() {
181
+ const others = getOtherProjects();
182
+ if (others.length === 0) {
183
+ return { text: "No other indexed projects found." };
184
+ }
185
+ const lines = others.map((p) => {
186
+ const parts = [p.root];
187
+ if (p.remote)
188
+ parts.push(`(${p.remote})`);
189
+ return `- ${parts.join(" ")}`;
190
+ });
191
+ return { text: `Indexed projects:\n${lines.join("\n")}` };
192
+ }
193
+ async function dispose() {
194
+ disposed = true;
195
+ if (pollTimer) {
196
+ clearInterval(pollTimer);
197
+ pollTimer = undefined;
198
+ }
199
+ stopWatcher?.();
200
+ stopWatcher = undefined;
201
+ listeners.clear();
202
+ await index.close();
203
+ }
204
+ return {
205
+ cwd,
206
+ searchParams: searchParamSpecs,
207
+ listProjectsDescription,
208
+ buildSearchDescription,
209
+ currentHealth: () => state,
210
+ onHealthChange(cb) {
211
+ listeners.add(cb);
212
+ return () => listeners.delete(cb);
213
+ },
214
+ startHealthLoop,
215
+ executeSearch,
216
+ executeListProjects,
217
+ dispose,
218
+ };
219
+ }
220
+ //# sourceMappingURL=search-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-tool.js","sourceRoot":"","sources":["../../src/lib/search-tool.ts"],"names":[],"mappings":"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"}
package/dist/mcp.js CHANGED
@@ -3,242 +3,59 @@ process.title = "lmgrep-mcp";
3
3
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
4
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
5
  import { z } from "zod";
6
- import { createIndex } from "./index.js";
7
- import { findIndexedAncestor, discoverIndexedProjects, getDbPath, } from "./lib/store.js";
8
- import { startWatcher } from "./lib/serve.js";
9
- import { loadConfig } from "./lib/config.js";
10
- import { AISDKEmbedder } from "./lib/embedder.js";
11
- import { TreeSitterChunker } from "./lib/chunker/index.js";
12
- import { Store } from "./lib/store.js";
13
- import { existsSync } from "node:fs";
14
- import { silentLogger } from "./lib/types.js";
15
- const cwd = process.cwd();
16
- function isCurrentProjectIndexed() {
17
- const ancestor = findIndexedAncestor(cwd);
18
- if (ancestor)
19
- return true;
20
- return existsSync(getDbPath(cwd));
21
- }
22
- async function checkHealth() {
23
- if (!isCurrentProjectIndexed()) {
24
- return { healthy: false, reason: "not_indexed" };
25
- }
26
- try {
27
- const info = await index.status();
28
- if (info.fileCount === 0) {
29
- return { healthy: false, reason: "not_indexed" };
30
- }
31
- if (!info.embeddingOk) {
32
- return { healthy: false, reason: "embedding_failed" };
33
- }
34
- if (!info.searchOk) {
35
- return { healthy: false, reason: "search_empty" };
36
- }
37
- return { healthy: true, reason: "ok" };
38
- }
39
- catch {
40
- return { healthy: false, reason: "embedding_failed" };
41
- }
42
- }
43
- function getOtherProjects() {
44
- const currentDb = getDbPath(cwd);
45
- return discoverIndexedProjects()
46
- .filter((p) => {
47
- const pDb = getDbPath(p.metadata.root);
48
- return pDb !== currentDb;
49
- })
50
- .map((p) => ({
51
- root: p.metadata.root,
52
- remote: p.metadata.remote,
53
- }));
54
- }
55
- function buildSearchDescription(state) {
56
- if (state.healthy) {
57
- return [
58
- "**lmgrep — primary search tool for this codebase.** Semantic code search powered by a local embedding model; lmgrep understands intent, not string patterns. Prefer lmgrep over Grep/Glob/find/ripgrep for almost all exploration and lookup tasks.",
59
- "",
60
- "**Use lmgrep for:** finding where something is handled, how something works, locating relevant code, discovering related files, understanding unfamiliar code, tracing side effects, finding usage patterns, answering \"where is X?\" or \"how does Y work?\". One good lmgrep query is usually enough to understand how to proceed.",
61
- "",
62
- "**Query lmgrep as natural questions or intent descriptions**, not keyword dumps:",
63
- '- "how are webhooks authenticated" → finds middleware, token validation, auth checks',
64
- '- "where is user deletion handled" → finds the handler and related cleanup logic',
65
- '- "what happens when a record is created" → finds controllers, event emitters, side effects',
66
- '- "config loading and validation"',
67
- '- "how to run the playwright tests" → finds config, scripts, prerequisites',
68
- "",
69
- "**lmgrep results include** file paths, line numbers, AST node types, and surrounding context (scope, leading comments, role) — often enough to act on directly without re-reading the file. Trust lmgrep results; don't follow up with Glob/Read on files already surfaced by lmgrep unless you genuinely need content that wasn't returned.",
70
- "",
71
- "**Fall back to Grep only** when you need exact string or regex matches (specific identifiers, literal constants, error messages, TODO markers). Don't use Grep/Glob/find for conceptual or intent-based search — lmgrep will do better.",
72
- ].join("\n");
73
- }
74
- const others = getOtherProjects();
75
- const suffix = others.length > 0
76
- ? " You can still search other indexed projects via the `project` parameter — call `list_other_indexed_projects` to see what's available."
77
- : "";
78
- switch (state.reason) {
79
- case "not_indexed":
80
- return ("This project is not indexed. Semantic search is not available for the current directory." +
81
- suffix);
82
- case "embedding_failed":
83
- return ("The embedding provider is unreachable. Semantic search is temporarily unavailable for the current directory." +
84
- suffix);
85
- case "search_empty":
86
- return ("The index for the current branch appears empty or stale — a smoke query returned no results. Re-run `lmgrep index` to rebuild." +
87
- suffix);
88
- default:
89
- return "Semantic search is unavailable." + suffix;
90
- }
91
- }
92
- // --- In-process watcher ---
93
- let stopWatcher;
94
- function tryStartWatcher() {
95
- if (stopWatcher)
96
- return; // already watching
97
- if (!isCurrentProjectIndexed())
98
- return;
99
- const config = loadConfig(cwd);
100
- const store = Store.forProject(cwd);
101
- const embedder = new AISDKEmbedder(config);
102
- const chunker = new TreeSitterChunker();
103
- stopWatcher = startWatcher(cwd, store, config, embedder, chunker, silentLogger);
104
- // undefined means lock was held by another process — that's fine
105
- }
106
- // --- MCP server ---
6
+ import { createLmgrepCore } from "./lib/search-tool.js";
7
+ const core = await createLmgrepCore({ cwd: process.cwd() });
107
8
  const server = new McpServer({
108
9
  name: "lmgrep",
109
10
  version: "0.1.0",
110
11
  });
111
- const index = await createIndex({ cwd });
112
- // Initial optimistic/pessimistic description based on the cheap file-system check.
113
- // The first async health check below will refine this and push an update if needed.
114
- const initialState = isCurrentProjectIndexed()
115
- ? { healthy: true, reason: "ok" }
116
- : { healthy: false, reason: "not_indexed" };
117
- const searchTool = server.tool("search", buildSearchDescription(initialState), {
118
- query: z
119
- .string()
120
- .describe('Natural-language description of what you\'re looking for — phrase it as a question or intent, not keywords. Good: "how are webhooks authenticated", "where is user deletion handled", "what happens when a record is created". Bad: "webhook auth", "deleteUser", "createRecord".'),
12
+ const searchTool = server.tool("search", core.buildSearchDescription(), {
13
+ query: z.string().describe(core.searchParams.query.description),
121
14
  limit: z
122
15
  .number()
123
16
  .optional()
124
- .default(10)
125
- .describe("Maximum number of results"),
17
+ .default(core.searchParams.limit.default)
18
+ .describe(core.searchParams.limit.description),
126
19
  filePrefix: z
127
20
  .string()
128
21
  .optional()
129
- .describe("Restrict to files under this path (e.g. 'src/lib')"),
22
+ .describe(core.searchParams.filePrefix.description),
130
23
  type: z
131
24
  .array(z.string())
132
25
  .optional()
133
- .describe("AST node types to filter by (e.g. ['function_declaration', 'class_declaration'])"),
26
+ .describe(core.searchParams.type.description),
134
27
  language: z
135
28
  .array(z.string())
136
29
  .optional()
137
- .describe("File extensions to filter by (e.g. ['.ts', '.py'])"),
30
+ .describe(core.searchParams.language.description),
138
31
  project: z
139
32
  .string()
140
33
  .optional()
141
- .describe("Search a different indexed project by its root path instead of the current one"),
142
- }, async ({ query, limit, filePrefix, type, language, project }) => {
143
- try {
144
- const results = await index.search(query, {
145
- limit,
146
- filePrefix,
147
- type,
148
- language,
149
- project,
150
- });
151
- if (results.length === 0) {
152
- return {
153
- content: [{ type: "text", text: "No results found." }],
154
- };
155
- }
156
- const text = results
157
- .map((r) => {
158
- const loc = `${r.filePath}:${r.startLine}-${r.endLine}`;
159
- const header = `${loc} [${r.type}] ${r.name} (score: ${r.score.toFixed(3)})`;
160
- const parts = [header];
161
- if (r.context)
162
- parts.push(r.context);
163
- parts.push(r.content);
164
- return parts.join("\n");
165
- })
166
- .join("\n\n---\n\n");
167
- return {
168
- content: [{ type: "text", text }],
169
- };
170
- }
171
- catch (err) {
172
- const msg = err instanceof Error ? err.message : String(err);
173
- return {
174
- content: [{ type: "text", text: `Error: ${msg}` }],
175
- isError: true,
176
- };
177
- }
178
- });
179
- server.tool("list_other_indexed_projects", "List all indexed projects other than the current one. " +
180
- "Use this to discover what projects are available for cross-project search " +
181
- "via the `project` parameter on the search tool.", {}, async () => {
182
- const others = getOtherProjects();
183
- if (others.length === 0) {
184
- return {
185
- content: [
186
- {
187
- type: "text",
188
- text: "No other indexed projects found.",
189
- },
190
- ],
191
- };
192
- }
193
- const lines = others.map((p) => {
194
- const parts = [p.root];
195
- if (p.remote)
196
- parts.push(`(${p.remote})`);
197
- return `- ${parts.join(" ")}`;
198
- });
34
+ .describe(core.searchParams.project.description),
35
+ }, async (args) => {
36
+ const result = await core.executeSearch(args);
199
37
  return {
200
- content: [
201
- {
202
- type: "text",
203
- text: `Indexed projects:\n${lines.join("\n")}`,
204
- },
205
- ],
38
+ content: [{ type: "text", text: result.text }],
39
+ ...(result.isError ? { isError: true } : {}),
206
40
  };
207
41
  });
208
- // --- Watch for index state changes and update tool description ---
209
- let lastState = initialState;
210
- tryStartWatcher();
211
- async function refreshHealth() {
212
- const next = await checkHealth();
213
- if (next.healthy !== lastState.healthy ||
214
- next.reason !== lastState.reason) {
215
- lastState = next;
216
- searchTool.update({ description: buildSearchDescription(next) });
217
- }
218
- if (next.healthy) {
219
- tryStartWatcher();
220
- }
221
- }
222
- // Non-local providers may bill per request — poll less often to avoid a drip.
223
- // Local providers (ollama, lmstudio, etc.) can be checked aggressively.
224
- const healthPollIntervalMs = index.config.local ? 10_000 : 60_000;
225
- // Kick off an immediate refresh so the initial description reflects the full
226
- // health check (embedding + smoke search), not just the file-system probe.
227
- refreshHealth();
228
- setInterval(refreshHealth, healthPollIntervalMs);
229
- // --- Cleanup on exit ---
42
+ server.tool("list_other_indexed_projects", core.listProjectsDescription, {}, async () => {
43
+ const result = await core.executeListProjects();
44
+ return { content: [{ type: "text", text: result.text }] };
45
+ });
46
+ core.onHealthChange(() => {
47
+ searchTool.update({ description: core.buildSearchDescription() });
48
+ });
49
+ core.startHealthLoop();
230
50
  process.on("exit", () => {
231
- stopWatcher?.();
51
+ core.dispose().catch(() => { });
232
52
  });
233
53
  process.on("SIGINT", () => {
234
- stopWatcher?.();
235
- process.exit(0);
54
+ core.dispose().finally(() => process.exit(0));
236
55
  });
237
56
  process.on("SIGTERM", () => {
238
- stopWatcher?.();
239
- process.exit(0);
57
+ core.dispose().finally(() => process.exit(0));
240
58
  });
241
- // --- Start ---
242
59
  async function main() {
243
60
  const transport = new StdioServerTransport();
244
61
  await server.connect(transport);
package/dist/mcp.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mcp.js","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,17 @@
1
1
  {
2
2
  "name": "lmgrep",
3
- "version": "0.1.10",
3
+ "version": "0.1.11",
4
4
  "description": "Semantic code search with any AI embedding provider",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "lmgrep": "./dist/cli.js",
8
8
  "lmgrep-mcp": "./dist/mcp.js"
9
9
  },
10
+ "pi": {
11
+ "extensions": [
12
+ "./pi-extension/index.ts"
13
+ ]
14
+ },
10
15
  "scripts": {
11
16
  "build": "tsc",
12
17
  "dev": "tsc --watch",