@philau2512/fast-context-mcp 1.5.4 → 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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@philau2512/fast-context-mcp",
3
- "version": "1.5.4",
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
+ }
@@ -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 required. Pass the absolute path to the project root directory.";
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
- .min(1, PROJECT_PATH_REQUIRED_MESSAGE);
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
- if (!projectPath) {
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(projectPath);
49
+ const st = statFn(resolved);
32
50
  if (!st.isDirectory()) {
33
- return `Error: project_path is not a directory: ${projectPath}`;
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: ${projectPath}`;
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}): ${projectPath}`;
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 { projectPathSchema, validateProjectPath } from "./project-path.mjs";
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;
@@ -91,16 +95,23 @@ export function buildFastContextSearchTool({
91
95
  const runSearchWithContent = deps.searchWithContent || searchWithContent;
92
96
  const validatePath = deps.validateProjectPath || validateProjectPath;
93
97
  const description =
94
- "Fast semantic codebase search and context discovery. " +
95
- "Locates relevant files, exact line ranges, and code regions from natural language descriptions in a single step, " +
98
+ "Primary tool for semantic codebase search, context discovery, and verifying logic existence. " +
99
+ "Locates relevant files, exact line ranges, and code regions from natural language or domain concepts in a single step, " +
96
100
  "without needing manual grep trials or knowing exact filenames.\n\n" +
97
- "Recommended for:\n" +
98
- "- Finding feature implementations, business logic, and API flows (e.g. 'where is payment webhook handled', 'auth token refresh flow').\n" +
99
- "- Exploring unfamiliar codebases or locating where conceptual logic lives.\n" +
100
- "- Getting high-relevance entry points, line ranges, and suggested grep keywords before reading code.\n\n" +
101
- "Use exact-match grep instead only when searching for a known, specific symbol name or literal string.\n\n" +
102
- "For best semantic search quality, write the query primarily in English; add local-language business terms only when needed.\n" +
103
- "Use tree_depth/max_turns/max_results for task-level tuning; use exclude_paths to reduce payload or noise.\n" +
101
+ "MANDATORY REQUIREMENT:\n" +
102
+ "- 'project_path' is strictly REQUIRED. You MUST provide the absolute path to the project root directory when calling this tool.\n\n" +
103
+ "RECOMMENDED FOR:\n" +
104
+ "- Verifying feature/data existence: Checking whether a business rule, model, seed data, configuration, or API already exists (e.g. 'check if warrior coefficient seed data exists', 'has rate limiting been added').\n" +
105
+ "- Finding conceptual business logic: Locating where behavior lives across the codebase without guessing file names.\n" +
106
+ "- Tracing multi-file flows: Getting high-relevance entry points, line ranges, and suggested grep keywords before reading code.\n\n" +
107
+ "DO NOT USE WHEN (Avoid Overuse):\n" +
108
+ "- Target file is already known, opened, or specified by the user (use view_file / read_file directly).\n" +
109
+ "- Exact symbol search: Searching for an exact, known function/class/variable name (use grep instead).\n" +
110
+ "- Directory exploration: Simply listing files in a directory (use list_dir/glob instead).\n" +
111
+ "- Single-file localized edits or lint fixes.\n\n" +
112
+ "QUERY TIPS:\n" +
113
+ "- For best semantic search quality, write the query primarily in English; keep local-language domain terms when needed (e.g. 'seed data for sale he so chien binh').\n" +
114
+ "- Use tree_depth/max_turns/max_results for task-level tuning; use exclude_paths to reduce payload or noise.\n" +
104
115
  (config.includeSnippetsExplicitlySet
105
116
  ? `- include_code_snippets: Server-configured default is ${config.includeSnippets}. Do NOT override unless explicitly asked by the user.\n`
106
117
  : "- include_code_snippets: Default false (lightweight mode, ~2-5KB output). " +
@@ -115,8 +126,9 @@ export function buildFastContextSearchTool({
115
126
  'Add local-language business terms only when needed.'
116
127
  ),
117
128
  project_path: projectPathSchema.describe(
118
- "Absolute path to project root directory (required). " +
119
- "Example: /Users/username/projects/myproject or C:/Users/username/projects/myproject"
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 ."
120
132
  ),
121
133
  tree_depth: z
122
134
  .number()
@@ -184,7 +196,7 @@ export function buildFastContextSearchTool({
184
196
  exclude_paths,
185
197
  include_code_snippets,
186
198
  }) => {
187
- const projectPath = project_path;
199
+ const projectPath = resolveProjectPath(project_path);
188
200
  const validationError = validatePath(projectPath);
189
201
  if (validationError) {
190
202
  return { content: [{ type: "text", text: validationError }] };