@philau2512/fast-context-mcp 1.5.5 → 1.5.6
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/package.json +2 -2
- package/src/project-path.mjs +33 -15
- package/src/server.mjs +9 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@philau2512/fast-context-mcp",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.6",
|
|
4
4
|
"description": "AI-driven semantic code search MCP server (Node.js) — Windsurf/Devin protocol",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/server.mjs",
|
|
@@ -53,4 +53,4 @@
|
|
|
53
53
|
"access": "public"
|
|
54
54
|
},
|
|
55
55
|
"license": "MIT"
|
|
56
|
-
}
|
|
56
|
+
}
|
package/src/project-path.mjs
CHANGED
|
@@ -1,43 +1,61 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
|
-
import { isAbsolute } from "node:path";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
export const PROJECT_PATH_REQUIRED_MESSAGE =
|
|
6
|
-
"project_path is
|
|
6
|
+
"project_path is optional. Pass the absolute or relative path to the project root directory, or omit to use current working directory.";
|
|
7
7
|
|
|
8
8
|
export const projectPathSchema = z
|
|
9
9
|
.string()
|
|
10
10
|
.trim()
|
|
11
|
-
.
|
|
11
|
+
.nullish()
|
|
12
|
+
.transform((val) => val ?? "")
|
|
13
|
+
.default("");
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Resolve project path to an absolute path.
|
|
17
|
+
* If empty, null, or ".", defaults to cwd (process.cwd()).
|
|
18
|
+
* If relative, resolves against cwd.
|
|
19
|
+
*
|
|
20
|
+
* @param {string|null|undefined} projectPath
|
|
21
|
+
* @param {string} [cwd]
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
export function resolveProjectPath(projectPath, cwd = process.cwd()) {
|
|
25
|
+
const trimmed = typeof projectPath === "string" ? projectPath.trim() : "";
|
|
26
|
+
if (!trimmed || trimmed === "." || trimmed === "./" || trimmed === ".\\") {
|
|
27
|
+
return cwd;
|
|
28
|
+
}
|
|
29
|
+
if (isAbsolute(trimmed)) {
|
|
30
|
+
return trimmed;
|
|
31
|
+
}
|
|
32
|
+
return resolve(cwd, trimmed);
|
|
33
|
+
}
|
|
12
34
|
|
|
13
35
|
/**
|
|
14
36
|
* Validate the project root path provided to fast_context_search.
|
|
37
|
+
* Automatically resolves relative paths or empty/omitted paths against cwd.
|
|
15
38
|
* Returns null when valid, otherwise an MCP-friendly error string.
|
|
16
39
|
*
|
|
17
40
|
* @param {string} projectPath
|
|
18
41
|
* @param {(path: string) => import("node:fs").Stats} [statFn]
|
|
42
|
+
* @param {string} [cwd]
|
|
19
43
|
* @returns {string|null}
|
|
20
44
|
*/
|
|
21
|
-
export function validateProjectPath(projectPath, statFn = statSync) {
|
|
22
|
-
|
|
23
|
-
return `Error: ${PROJECT_PATH_REQUIRED_MESSAGE}`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if (!isAbsolute(projectPath)) {
|
|
27
|
-
return `Error: project_path must be an absolute path, got: ${projectPath}`;
|
|
28
|
-
}
|
|
45
|
+
export function validateProjectPath(projectPath, statFn = statSync, cwd = process.cwd()) {
|
|
46
|
+
const resolved = resolveProjectPath(projectPath, cwd);
|
|
29
47
|
|
|
30
48
|
try {
|
|
31
|
-
const st = statFn(
|
|
49
|
+
const st = statFn(resolved);
|
|
32
50
|
if (!st.isDirectory()) {
|
|
33
|
-
return `Error: project_path is not a directory: ${
|
|
51
|
+
return `Error: project_path is not a directory: ${resolved}`;
|
|
34
52
|
}
|
|
35
53
|
} catch (error) {
|
|
36
54
|
if (error?.code === "ENOENT") {
|
|
37
|
-
return `Error: project_path does not exist: ${
|
|
55
|
+
return `Error: project_path does not exist: ${resolved}`;
|
|
38
56
|
}
|
|
39
57
|
if (error?.code === "EACCES" || error?.code === "EPERM") {
|
|
40
|
-
return `Error: cannot access project_path (${error.code}): ${
|
|
58
|
+
return `Error: cannot access project_path (${error.code}): ${resolved}`;
|
|
41
59
|
}
|
|
42
60
|
const reason = error?.message ? `${error.code || "UNKNOWN"}: ${error.message}` : String(error);
|
|
43
61
|
return `Error: failed to validate project_path: ${reason}`;
|
package/src/server.mjs
CHANGED
|
@@ -22,7 +22,11 @@ import { fileURLToPath } from "node:url";
|
|
|
22
22
|
import { z } from "zod";
|
|
23
23
|
|
|
24
24
|
import { searchWithContent, extractKeyInfo } from "./core.mjs";
|
|
25
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
projectPathSchema,
|
|
27
|
+
resolveProjectPath,
|
|
28
|
+
validateProjectPath,
|
|
29
|
+
} from "./project-path.mjs";
|
|
26
30
|
|
|
27
31
|
const PACKAGE_JSON = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
28
32
|
export const SERVER_VERSION = PACKAGE_JSON.version;
|
|
@@ -122,9 +126,9 @@ export function buildFastContextSearchTool({
|
|
|
122
126
|
'Add local-language business terms only when needed.'
|
|
123
127
|
),
|
|
124
128
|
project_path: projectPathSchema.describe(
|
|
125
|
-
"
|
|
126
|
-
"
|
|
127
|
-
"
|
|
129
|
+
"Optional path to project root directory (absolute or relative). " +
|
|
130
|
+
"Defaults to current workspace directory if omitted. " +
|
|
131
|
+
"Example: /Users/username/projects/myproject or C:/Users/username/projects/myproject or ."
|
|
128
132
|
),
|
|
129
133
|
tree_depth: z
|
|
130
134
|
.number()
|
|
@@ -192,7 +196,7 @@ export function buildFastContextSearchTool({
|
|
|
192
196
|
exclude_paths,
|
|
193
197
|
include_code_snippets,
|
|
194
198
|
}) => {
|
|
195
|
-
const projectPath = project_path;
|
|
199
|
+
const projectPath = resolveProjectPath(project_path);
|
|
196
200
|
const validationError = validatePath(projectPath);
|
|
197
201
|
if (validationError) {
|
|
198
202
|
return { content: [{ type: "text", text: validationError }] };
|