@dreb/semantic-search 2.6.1 → 2.6.3
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/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -2
- package/dist/mcp-server.d.ts +5 -5
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +17 -14
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/skills/search/SKILL.md +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "semantic-search",
|
|
3
3
|
"description": "Semantic codebase search — natural language queries over code and docs using embeddings, tree-sitter parsing, and POEM multi-signal ranking",
|
|
4
|
-
"version": "2.6.
|
|
4
|
+
"version": "2.6.3",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Drew Brereton"
|
|
7
7
|
},
|
package/README.md
CHANGED
|
@@ -47,8 +47,8 @@ The package exposes a `search` tool over the Model Context Protocol (stdio trans
|
|
|
47
47
|
| Parameter | Required | Description |
|
|
48
48
|
| ------------ | -------- | ------------------------------------------------ |
|
|
49
49
|
| `query` | yes | Natural language, identifier, or path query |
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
50
|
+
| `searchDir` | yes | Directory to index and search — each unique value gets its own independent index |
|
|
51
|
+
| `restrictToDir` | no | Filter results to files under this path within the already-built index (does not affect indexing) |
|
|
52
52
|
| `limit` | no | Maximum results to return (default: 20) |
|
|
53
53
|
| `rebuild` | no | Force a clean index rebuild (default: false) |
|
|
54
54
|
|
package/dist/mcp-server.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Exposes the SearchEngine as a single "search" tool over the Model Context Protocol,
|
|
5
5
|
* enabling any MCP-compatible client to run semantic codebase queries.
|
|
6
6
|
*
|
|
7
|
-
* The server defaults to using its CWD as the
|
|
7
|
+
* The server defaults to using its CWD as the search directory. Claude Code
|
|
8
8
|
* launches MCP servers with CWD set to the project root, so no configuration
|
|
9
9
|
* is needed for typical per-project usage.
|
|
10
10
|
*/
|
|
@@ -12,14 +12,14 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
12
12
|
/**
|
|
13
13
|
* Create an MCP server instance configured with the semantic search tool.
|
|
14
14
|
*
|
|
15
|
-
* @param
|
|
16
|
-
* the client doesn't specify `
|
|
15
|
+
* @param defaultSearchDir - Default directory to index and search. Used when
|
|
16
|
+
* the client doesn't specify `searchDir` in the tool call. Typically the
|
|
17
17
|
* server's CWD, which Claude Code sets to the project root.
|
|
18
18
|
*/
|
|
19
|
-
export declare function createMcpServer(
|
|
19
|
+
export declare function createMcpServer(defaultSearchDir: string): Server;
|
|
20
20
|
/**
|
|
21
21
|
* Create and start an MCP server over stdio.
|
|
22
22
|
* This blocks until the transport is closed.
|
|
23
23
|
*/
|
|
24
|
-
export declare function startServer(
|
|
24
|
+
export declare function startServer(searchDir: string): Promise<void>;
|
|
25
25
|
//# sourceMappingURL=mcp-server.d.ts.map
|
package/dist/mcp-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAwDnE;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,gBAAgB,EAAE,MAAM,GAAG,MAAM,CA6FhE;AAMD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlE"}
|
package/dist/mcp-server.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Exposes the SearchEngine as a single "search" tool over the Model Context Protocol,
|
|
5
5
|
* enabling any MCP-compatible client to run semantic codebase queries.
|
|
6
6
|
*
|
|
7
|
-
* The server defaults to using its CWD as the
|
|
7
|
+
* The server defaults to using its CWD as the search directory. Claude Code
|
|
8
8
|
* launches MCP servers with CWD set to the project root, so no configuration
|
|
9
9
|
* is needed for typical per-project usage.
|
|
10
10
|
*/
|
|
@@ -27,15 +27,18 @@ const SEARCH_TOOL = {
|
|
|
27
27
|
type: "object",
|
|
28
28
|
properties: {
|
|
29
29
|
query: { type: "string", description: "Search query (natural language, identifier, or path)" },
|
|
30
|
-
|
|
30
|
+
searchDir: {
|
|
31
31
|
type: "string",
|
|
32
|
-
description: "
|
|
32
|
+
description: "Directory to index and search. This controls which directory gets indexed.",
|
|
33
|
+
},
|
|
34
|
+
restrictToDir: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "Restrict results to files under this path (filters the already-built index).",
|
|
33
37
|
},
|
|
34
|
-
path: { type: "string", description: "Restrict search to files under this path" },
|
|
35
38
|
limit: { type: "number", description: "Maximum results to return (default: 20)" },
|
|
36
39
|
rebuild: { type: "boolean", description: "Force index rebuild (default: false)" },
|
|
37
40
|
},
|
|
38
|
-
required: ["query", "
|
|
41
|
+
required: ["query", "searchDir"],
|
|
39
42
|
},
|
|
40
43
|
};
|
|
41
44
|
// ============================================================================
|
|
@@ -57,11 +60,11 @@ function getSearchEngine(projectRoot) {
|
|
|
57
60
|
/**
|
|
58
61
|
* Create an MCP server instance configured with the semantic search tool.
|
|
59
62
|
*
|
|
60
|
-
* @param
|
|
61
|
-
* the client doesn't specify `
|
|
63
|
+
* @param defaultSearchDir - Default directory to index and search. Used when
|
|
64
|
+
* the client doesn't specify `searchDir` in the tool call. Typically the
|
|
62
65
|
* server's CWD, which Claude Code sets to the project root.
|
|
63
66
|
*/
|
|
64
|
-
export function createMcpServer(
|
|
67
|
+
export function createMcpServer(defaultSearchDir) {
|
|
65
68
|
const server = new Server({ name: "semantic-search", version: packageVersion }, { capabilities: { tools: {}, logging: {} } });
|
|
66
69
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
67
70
|
tools: [SEARCH_TOOL],
|
|
@@ -74,9 +77,9 @@ export function createMcpServer(defaultProjectDir) {
|
|
|
74
77
|
};
|
|
75
78
|
}
|
|
76
79
|
const args = (request.params.arguments ?? {});
|
|
77
|
-
const { query,
|
|
80
|
+
const { query, restrictToDir: pathFilter, rebuild = false } = args;
|
|
78
81
|
const limit = typeof args.limit === "number" && args.limit > 0 ? Math.floor(args.limit) : 20;
|
|
79
|
-
const
|
|
82
|
+
const searchDir = args.searchDir ? resolve(args.searchDir) : defaultSearchDir;
|
|
80
83
|
if (!SearchEngine.isAvailable()) {
|
|
81
84
|
return {
|
|
82
85
|
content: [
|
|
@@ -95,14 +98,14 @@ export function createMcpServer(defaultProjectDir) {
|
|
|
95
98
|
};
|
|
96
99
|
}
|
|
97
100
|
try {
|
|
98
|
-
const engine = getSearchEngine(
|
|
101
|
+
const engine = getSearchEngine(searchDir);
|
|
99
102
|
if (rebuild) {
|
|
100
103
|
await engine.resetIndex();
|
|
101
104
|
}
|
|
102
105
|
// Send progress via logging messages
|
|
103
106
|
const results = await engine.search(query, {
|
|
104
107
|
limit,
|
|
105
|
-
pathFilter:
|
|
108
|
+
pathFilter: pathFilter,
|
|
106
109
|
onProgress: (phase, current, total) => {
|
|
107
110
|
server
|
|
108
111
|
.sendLoggingMessage({
|
|
@@ -141,8 +144,8 @@ export function createMcpServer(defaultProjectDir) {
|
|
|
141
144
|
* Create and start an MCP server over stdio.
|
|
142
145
|
* This blocks until the transport is closed.
|
|
143
146
|
*/
|
|
144
|
-
export async function startServer(
|
|
145
|
-
const server = createMcpServer(
|
|
147
|
+
export async function startServer(searchDir) {
|
|
148
|
+
const server = createMcpServer(searchDir);
|
|
146
149
|
const transport = new StdioServerTransport();
|
|
147
150
|
await server.connect(transport);
|
|
148
151
|
}
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP stdio server adapter for semantic codebase search.\n *\n * Exposes the SearchEngine as a single \"search\" tool over the Model Context Protocol,\n * enabling any MCP-compatible client to run semantic codebase queries.\n *\n * The server defaults to using its CWD as the project directory. Claude Code\n * launches MCP servers with CWD set to the project root, so no configuration\n * is needed for typical per-project usage.\n */\n\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, type CallToolResult, ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { formatResults } from \"./format.js\";\nimport { SearchEngine } from \"./search.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version: packageVersion } = require(\"../package.json\") as { version: string };\n\n// ============================================================================\n// Tool Schema (JSON Schema for MCP)\n// ============================================================================\n\nconst SEARCH_TOOL = {\n\tname: \"search\",\n\tdescription:\n\t\t\"Search the codebase using natural language queries. Returns ranked code/doc results using semantic similarity and keyword matching. First query builds the index (may take a moment); subsequent queries are fast.\",\n\tinputSchema: {\n\t\ttype: \"object\" as const,\n\t\tproperties: {\n\t\t\tquery: { type: \"string\", description: \"Search query (natural language, identifier, or path)\" },\n\t\t\tprojectDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Absolute path to the project directory to search. Use your current working directory.\",\n\t\t\t},\n\t\t\tpath: { type: \"string\", description: \"Restrict search to files under this path\" },\n\t\t\tlimit: { type: \"number\", description: \"Maximum results to return (default: 20)\" },\n\t\t\trebuild: { type: \"boolean\", description: \"Force index rebuild (default: false)\" },\n\t\t},\n\t\trequired: [\"query\", \"projectDir\"],\n\t},\n};\n\n// ============================================================================\n// Engine Cache\n// ============================================================================\n\n/** Cache search engines per project root to reuse index across calls. */\nconst engineCache = new Map<string, SearchEngine>();\n\nfunction getSearchEngine(projectRoot: string): SearchEngine {\n\tlet engine = engineCache.get(projectRoot);\n\tif (!engine) {\n\t\tengine = new SearchEngine(projectRoot);\n\t\tengineCache.set(projectRoot, engine);\n\t}\n\treturn engine;\n}\n\n// ============================================================================\n// Server Factory\n// ============================================================================\n\n/**\n * Create an MCP server instance configured with the semantic search tool.\n *\n * @param defaultProjectDir - Default project directory for searches. Used when\n * the client doesn't specify `projectDir` in the tool call. Typically the\n * server's CWD, which Claude Code sets to the project root.\n */\nexport function createMcpServer(defaultProjectDir: string): Server {\n\tconst server = new Server(\n\t\t{ name: \"semantic-search\", version: packageVersion },\n\t\t{ capabilities: { tools: {}, logging: {} } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: [SEARCH_TOOL],\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {\n\t\tif (request.params.name !== \"search\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tconst args = (request.params.arguments ?? {}) as {\n\t\t\tquery?: string;\n\t\t\tprojectDir?: string;\n\t\t\tpath?: string;\n\t\t\tlimit?: number;\n\t\t\trebuild?: boolean;\n\t\t};\n\t\tconst { query, path: searchPath, rebuild = false } = args;\n\t\tconst limit = typeof args.limit === \"number\" && args.limit > 0 ? Math.floor(args.limit) : 20;\n\n\t\tconst projectDir = args.projectDir ? resolve(args.projectDir) : defaultProjectDir;\n\n\t\tif (!SearchEngine.isAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: \"Semantic search requires Node.js 22+ (for built-in SQLite). Current version does not support node:sqlite.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tif (!query || query.trim().length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Search query cannot be empty.\" }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst engine = getSearchEngine(projectDir);\n\n\t\t\tif (rebuild) {\n\t\t\t\tawait engine.resetIndex();\n\t\t\t}\n\n\t\t\t// Send progress via logging messages\n\t\t\tconst results = await engine.search(query, {\n\t\t\t\tlimit,\n\t\t\t\tpathFilter: searchPath,\n\t\t\t\tonProgress: (phase, current, total) => {\n\t\t\t\t\tserver\n\t\t\t\t\t\t.sendLoggingMessage({\n\t\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\t\tlogger: \"semantic-search\",\n\t\t\t\t\t\t\tdata: `${phase}: ${current}/${total}`,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// Ignore errors sending progress — client may not support logging\n\t\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst text = formatResults(results);\n\t\t\tconst stats = engine.getStats();\n\n\t\t\tlet statsLine = \"\";\n\t\t\tif (stats) {\n\t\t\t\tstatsLine = `\\n\\n[Index: ${stats.files} files, ${stats.chunks} chunks]`;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: text + statsLine }],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Search failed: ${err instanceof Error ? err.message : String(err)}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t});\n\n\treturn server;\n}\n\n// ============================================================================\n// Server Startup\n// ============================================================================\n\n/**\n * Create and start an MCP server over stdio.\n * This blocks until the transport is closed.\n */\nexport async function startServer(projectDir: string): Promise<void> {\n\tconst server = createMcpServer(projectDir);\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCP stdio server adapter for semantic codebase search.\n *\n * Exposes the SearchEngine as a single \"search\" tool over the Model Context Protocol,\n * enabling any MCP-compatible client to run semantic codebase queries.\n *\n * The server defaults to using its CWD as the search directory. Claude Code\n * launches MCP servers with CWD set to the project root, so no configuration\n * is needed for typical per-project usage.\n */\n\nimport { createRequire } from \"node:module\";\nimport { resolve } from \"node:path\";\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { CallToolRequestSchema, type CallToolResult, ListToolsRequestSchema } from \"@modelcontextprotocol/sdk/types.js\";\nimport { formatResults } from \"./format.js\";\nimport { SearchEngine } from \"./search.js\";\n\nconst require = createRequire(import.meta.url);\nconst { version: packageVersion } = require(\"../package.json\") as { version: string };\n\n// ============================================================================\n// Tool Schema (JSON Schema for MCP)\n// ============================================================================\n\nconst SEARCH_TOOL = {\n\tname: \"search\",\n\tdescription:\n\t\t\"Search the codebase using natural language queries. Returns ranked code/doc results using semantic similarity and keyword matching. First query builds the index (may take a moment); subsequent queries are fast.\",\n\tinputSchema: {\n\t\ttype: \"object\" as const,\n\t\tproperties: {\n\t\t\tquery: { type: \"string\", description: \"Search query (natural language, identifier, or path)\" },\n\t\t\tsearchDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Directory to index and search. This controls which directory gets indexed.\",\n\t\t\t},\n\t\t\trestrictToDir: {\n\t\t\t\ttype: \"string\",\n\t\t\t\tdescription: \"Restrict results to files under this path (filters the already-built index).\",\n\t\t\t},\n\t\t\tlimit: { type: \"number\", description: \"Maximum results to return (default: 20)\" },\n\t\t\trebuild: { type: \"boolean\", description: \"Force index rebuild (default: false)\" },\n\t\t},\n\t\trequired: [\"query\", \"searchDir\"],\n\t},\n};\n\n// ============================================================================\n// Engine Cache\n// ============================================================================\n\n/** Cache search engines per project root to reuse index across calls. */\nconst engineCache = new Map<string, SearchEngine>();\n\nfunction getSearchEngine(projectRoot: string): SearchEngine {\n\tlet engine = engineCache.get(projectRoot);\n\tif (!engine) {\n\t\tengine = new SearchEngine(projectRoot);\n\t\tengineCache.set(projectRoot, engine);\n\t}\n\treturn engine;\n}\n\n// ============================================================================\n// Server Factory\n// ============================================================================\n\n/**\n * Create an MCP server instance configured with the semantic search tool.\n *\n * @param defaultSearchDir - Default directory to index and search. Used when\n * the client doesn't specify `searchDir` in the tool call. Typically the\n * server's CWD, which Claude Code sets to the project root.\n */\nexport function createMcpServer(defaultSearchDir: string): Server {\n\tconst server = new Server(\n\t\t{ name: \"semantic-search\", version: packageVersion },\n\t\t{ capabilities: { tools: {}, logging: {} } },\n\t);\n\n\tserver.setRequestHandler(ListToolsRequestSchema, async () => ({\n\t\ttools: [SEARCH_TOOL],\n\t}));\n\n\tserver.setRequestHandler(CallToolRequestSchema, async (request): Promise<CallToolResult> => {\n\t\tif (request.params.name !== \"search\") {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Unknown tool: ${request.params.name}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tconst args = (request.params.arguments ?? {}) as {\n\t\t\tquery?: string;\n\t\t\tsearchDir?: string;\n\t\t\trestrictToDir?: string;\n\t\t\tlimit?: number;\n\t\t\trebuild?: boolean;\n\t\t};\n\t\tconst { query, restrictToDir: pathFilter, rebuild = false } = args;\n\t\tconst limit = typeof args.limit === \"number\" && args.limit > 0 ? Math.floor(args.limit) : 20;\n\n\t\tconst searchDir = args.searchDir ? resolve(args.searchDir) : defaultSearchDir;\n\n\t\tif (!SearchEngine.isAvailable()) {\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: \"Semantic search requires Node.js 22+ (for built-in SQLite). Current version does not support node:sqlite.\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\tif (!query || query.trim().length === 0) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: \"Search query cannot be empty.\" }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\n\t\ttry {\n\t\t\tconst engine = getSearchEngine(searchDir);\n\n\t\t\tif (rebuild) {\n\t\t\t\tawait engine.resetIndex();\n\t\t\t}\n\n\t\t\t// Send progress via logging messages\n\t\t\tconst results = await engine.search(query, {\n\t\t\t\tlimit,\n\t\t\t\tpathFilter: pathFilter,\n\t\t\t\tonProgress: (phase, current, total) => {\n\t\t\t\t\tserver\n\t\t\t\t\t\t.sendLoggingMessage({\n\t\t\t\t\t\t\tlevel: \"info\",\n\t\t\t\t\t\t\tlogger: \"semantic-search\",\n\t\t\t\t\t\t\tdata: `${phase}: ${current}/${total}`,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.catch(() => {\n\t\t\t\t\t\t\t// Ignore errors sending progress — client may not support logging\n\t\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst text = formatResults(results);\n\t\t\tconst stats = engine.getStats();\n\n\t\t\tlet statsLine = \"\";\n\t\t\tif (stats) {\n\t\t\t\tstatsLine = `\\n\\n[Index: ${stats.files} files, ${stats.chunks} chunks]`;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: text + statsLine }],\n\t\t\t};\n\t\t} catch (err) {\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Search failed: ${err instanceof Error ? err.message : String(err)}` }],\n\t\t\t\tisError: true,\n\t\t\t};\n\t\t}\n\t});\n\n\treturn server;\n}\n\n// ============================================================================\n// Server Startup\n// ============================================================================\n\n/**\n * Create and start an MCP server over stdio.\n * This blocks until the transport is closed.\n */\nexport async function startServer(searchDir: string): Promise<void> {\n\tconst server = createMcpServer(searchDir);\n\tconst transport = new StdioServerTransport();\n\tawait server.connect(transport);\n}\n"]}
|
package/package.json
CHANGED
package/skills/search/SKILL.md
CHANGED
|
@@ -24,8 +24,8 @@ The search tool supports three kinds of queries, automatically classified:
|
|
|
24
24
|
| Parameter | Required | Description |
|
|
25
25
|
| ------------ | -------- | --------------------------------------------------------------------------- |
|
|
26
26
|
| `query` | Yes | Search query — natural language, identifier, or path |
|
|
27
|
-
| `
|
|
28
|
-
| `
|
|
27
|
+
| `searchDir` | Yes | Directory to index and search — each unique value gets its own independent index |
|
|
28
|
+
| `restrictToDir` | No | Filter results to files under this subdirectory within the already-built index (does not affect which files are indexed) |
|
|
29
29
|
| `limit` | No | Maximum number of results to return (default: 20) |
|
|
30
30
|
| `rebuild` | No | Force a clean index rebuild — use when files have changed significantly |
|
|
31
31
|
|
|
@@ -53,7 +53,7 @@ Each result includes:
|
|
|
53
53
|
|
|
54
54
|
## Tips
|
|
55
55
|
|
|
56
|
-
- Start broad, then narrow with `
|
|
56
|
+
- Start broad, then narrow with `restrictToDir` if you get too many results from different areas
|
|
57
57
|
- Use `limit` to get more results when exploring a broad topic (e.g. `limit: 50`)
|
|
58
58
|
- Use `rebuild: true` after major refactors, branch switches, or large file changes
|
|
59
59
|
- Identifier queries work best for finding where something is defined or used
|