mcp-code-context 3.9.0 → 3.9.2

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.
Files changed (98) hide show
  1. package/CHANGELOG.md +227 -205
  2. package/INSTRUCTIONS.md +17 -11
  3. package/README.md +32 -11
  4. package/dist/src/core/engine.d.ts +1 -1
  5. package/dist/src/core/engine.js +1 -1
  6. package/dist/src/core/indexManager.d.ts +1 -1
  7. package/dist/src/core/indexManager.js +26 -26
  8. package/dist/src/core/sessionManager.d.ts +1 -1
  9. package/dist/src/core/sessionManager.js +1 -1
  10. package/dist/src/core/validator.d.ts +2 -2
  11. package/dist/src/core/validator.js +8 -2
  12. package/dist/src/core/validator.js.map +1 -1
  13. package/dist/src/index.d.ts +1 -1
  14. package/dist/src/index.js +2 -2
  15. package/dist/src/operations/astTransform.d.ts +1 -1
  16. package/dist/src/operations/astTransform.js +1 -1
  17. package/dist/src/operations/compress.d.ts +1 -1
  18. package/dist/src/operations/compress.js +1 -1
  19. package/dist/src/operations/confirmationStore.d.ts +1 -1
  20. package/dist/src/operations/confirmationStore.js +1 -1
  21. package/dist/src/operations/write.d.ts +1 -1
  22. package/dist/src/operations/write.js +1 -1
  23. package/dist/src/parsers/base.d.ts +2 -2
  24. package/dist/src/parsers/base.js +2 -2
  25. package/dist/src/parsers/csharp.d.ts +1 -1
  26. package/dist/src/parsers/csharp.js +1 -1
  27. package/dist/src/parsers/dartTreeSitter.d.ts +1 -1
  28. package/dist/src/parsers/dartTreeSitter.js +1 -1
  29. package/dist/src/parsers/go.d.ts +1 -1
  30. package/dist/src/parsers/go.js +1 -1
  31. package/dist/src/parsers/java.d.ts +1 -1
  32. package/dist/src/parsers/java.js +1 -1
  33. package/dist/src/parsers/kotlin.d.ts +1 -1
  34. package/dist/src/parsers/kotlin.js +1 -1
  35. package/dist/src/parsers/php.d.ts +1 -1
  36. package/dist/src/parsers/php.js +1 -1
  37. package/dist/src/parsers/python.d.ts +2 -2
  38. package/dist/src/parsers/python.js +2 -2
  39. package/dist/src/parsers/registry.d.ts +1 -1
  40. package/dist/src/parsers/registry.js +1 -1
  41. package/dist/src/parsers/ruby.d.ts +2 -2
  42. package/dist/src/parsers/ruby.js +2 -2
  43. package/dist/src/parsers/rust.d.ts +1 -1
  44. package/dist/src/parsers/rust.js +1 -1
  45. package/dist/src/parsers/typescript.d.ts +1 -1
  46. package/dist/src/parsers/typescript.js +1 -1
  47. package/dist/src/tools/adminHandlers.js +8 -7
  48. package/dist/src/tools/adminHandlers.js.map +1 -1
  49. package/dist/src/tools/readHandlers.js +20 -18
  50. package/dist/src/tools/readHandlers.js.map +1 -1
  51. package/dist/src/tools/toolDefinitions.d.ts +7 -2
  52. package/dist/src/tools/toolDefinitionsAdmin.d.ts +1 -1
  53. package/dist/src/tools/toolDefinitionsAdmin.js +12 -12
  54. package/dist/src/tools/toolDefinitionsAdmin.js.map +1 -1
  55. package/dist/src/tools/toolDefinitionsCore.d.ts +6 -1
  56. package/dist/src/tools/toolDefinitionsCore.js +40 -40
  57. package/dist/src/tools/toolDefinitionsCore.js.map +1 -1
  58. package/dist/src/tools/writeHandlers.js +28 -16
  59. package/dist/src/tools/writeHandlers.js.map +1 -1
  60. package/dist/src/utils/appDir.d.ts +1 -1
  61. package/dist/src/utils/appDir.js +1 -1
  62. package/dist/src/utils/auditLogger.d.ts +1 -1
  63. package/dist/src/utils/auditLogger.js +1 -1
  64. package/dist/src/utils/backupManager.d.ts +1 -1
  65. package/dist/src/utils/backupManager.js +1 -1
  66. package/dist/src/utils/constants.d.ts +1 -1
  67. package/dist/src/utils/constants.js +1 -1
  68. package/dist/src/utils/diff.d.ts +2 -2
  69. package/dist/src/utils/diff.js +2 -2
  70. package/dist/src/utils/fileLock.d.ts +1 -1
  71. package/dist/src/utils/fileLock.js +1 -1
  72. package/dist/src/utils/fileWalker.d.ts +1 -1
  73. package/dist/src/utils/fileWalker.js +1 -1
  74. package/dist/src/utils/fileWatcher.d.ts +1 -1
  75. package/dist/src/utils/fileWatcher.js +1 -1
  76. package/dist/src/utils/fuzzySearch.d.ts +1 -1
  77. package/dist/src/utils/fuzzySearch.js +1 -1
  78. package/dist/src/utils/gemfileParser.d.ts +1 -1
  79. package/dist/src/utils/gemfileParser.js +1 -1
  80. package/dist/src/utils/logger.d.ts +1 -1
  81. package/dist/src/utils/logger.js +1 -1
  82. package/dist/src/utils/metaprogramming.d.ts +1 -1
  83. package/dist/src/utils/metaprogramming.js +1 -1
  84. package/dist/src/utils/projectRoot.d.ts +9 -0
  85. package/dist/src/utils/projectRoot.js +94 -0
  86. package/dist/src/utils/projectRoot.js.map +1 -0
  87. package/dist/src/utils/railsRoutes.d.ts +4 -3
  88. package/dist/src/utils/railsRoutes.js +62 -67
  89. package/dist/src/utils/railsRoutes.js.map +1 -1
  90. package/dist/src/utils/rateLimiter.d.ts +1 -1
  91. package/dist/src/utils/rateLimiter.js +1 -1
  92. package/dist/src/utils/streaming.d.ts +1 -1
  93. package/dist/src/utils/streaming.js +1 -1
  94. package/dist/src/utils/telemetry.d.ts +1 -1
  95. package/dist/src/utils/telemetry.js +1 -1
  96. package/llms.txt +60 -21
  97. package/package.json +1 -1
  98. package/vitest.config.ts +0 -37
@@ -1,5 +1,5 @@
1
1
  /**
2
- * File Watcher - v3.9.0
2
+ * File Watcher - v3.9.2
3
3
  * Auto-invalidate cache on file changes with chokidar
4
4
  */
5
5
  import chokidar from 'chokidar';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Fuzzy Search - v3.9.0
2
+ * Fuzzy Search - v3.9.2
3
3
  * Typo-tolerant search with fuse.js
4
4
  */
5
5
  export interface FuzzySearchOptions {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Fuzzy Search - v3.9.0
2
+ * Fuzzy Search - v3.9.2
3
3
  * Typo-tolerant search with fuse.js
4
4
  */
5
5
  import Fuse from 'fuse.js';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Gemfile Parser - v3.9.0
2
+ * Gemfile Parser - v3.9.2
3
3
  * Parses Ruby Gemfile to extract gem dependencies and infer implicit behavior.
4
4
  * Uses a JSON data file for gem descriptions so they can be updated without recompile.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Gemfile Parser - v3.9.0
2
+ * Gemfile Parser - v3.9.2
3
3
  * Parses Ruby Gemfile to extract gem dependencies and infer implicit behavior.
4
4
  * Uses a JSON data file for gem descriptions so they can be updated without recompile.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Logger - v3.9.0
2
+ * Logger - v3.9.2
3
3
  * Structured logging with pino (JSON to stderr, MCP-safe)
4
4
  */
5
5
  import pino from 'pino';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Logger - v3.9.0
2
+ * Logger - v3.9.2
3
3
  * Structured logging with pino (JSON to stderr, MCP-safe)
4
4
  */
5
5
  import pino from 'pino';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Metaprogramming Entry Point Scanner - v3.9.0
2
+ * Metaprogramming Entry Point Scanner - v3.9.2
3
3
  * Identifies where Ruby's "magic" methods are generated in a codebase.
4
4
  * Does not resolve what methods are created — it surfaces WHERE to look.
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Metaprogramming Entry Point Scanner - v3.9.0
2
+ * Metaprogramming Entry Point Scanner - v3.9.2
3
3
  * Identifies where Ruby's "magic" methods are generated in a codebase.
4
4
  * Does not resolve what methods are created — it surfaces WHERE to look.
5
5
  */
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Searches upward from startPath to find the nearest project root directory marked by common indicators.
3
+ */
4
+ export declare function findProjectRoot(startPath: string): string;
5
+ /**
6
+ * Resolves the effective projectRoot from tool arguments, candidate paths, or process.cwd().
7
+ * Eliminates the bug where undefined projectRoot was stringified as literal "undefined".
8
+ */
9
+ export declare function resolveProjectRoot(args?: Record<string, unknown>, fallbackPath?: string): string;
@@ -0,0 +1,94 @@
1
+ import * as path from "node:path";
2
+ import * as fs from "node:fs";
3
+ const ROOT_MARKERS = [
4
+ ".git",
5
+ "package.json",
6
+ "composer.json",
7
+ "pyproject.toml",
8
+ "requirements.txt",
9
+ "Cargo.toml",
10
+ "go.mod",
11
+ "Gemfile",
12
+ "pom.xml",
13
+ "build.gradle",
14
+ ];
15
+ /**
16
+ * Searches upward from startPath to find the nearest project root directory marked by common indicators.
17
+ */
18
+ export function findProjectRoot(startPath) {
19
+ try {
20
+ let current = path.resolve(startPath);
21
+ if (fs.existsSync(current)) {
22
+ const stat = fs.statSync(current);
23
+ if (stat.isFile()) {
24
+ current = path.dirname(current);
25
+ }
26
+ }
27
+ else {
28
+ // If path does not exist yet, start from dirname
29
+ current = path.dirname(current);
30
+ }
31
+ while (true) {
32
+ for (const marker of ROOT_MARKERS) {
33
+ if (fs.existsSync(path.join(current, marker))) {
34
+ return current;
35
+ }
36
+ }
37
+ const parent = path.dirname(current);
38
+ if (parent === current) {
39
+ break;
40
+ }
41
+ current = parent;
42
+ }
43
+ }
44
+ catch {
45
+ // Fallback if filesystem access fails
46
+ }
47
+ return path.resolve(startPath);
48
+ }
49
+ /**
50
+ * Resolves the effective projectRoot from tool arguments, candidate paths, or process.cwd().
51
+ * Eliminates the bug where undefined projectRoot was stringified as literal "undefined".
52
+ */
53
+ export function resolveProjectRoot(args, fallbackPath) {
54
+ if (args) {
55
+ if (typeof args.projectRoot === "string" &&
56
+ args.projectRoot.trim().length > 0 &&
57
+ args.projectRoot !== "undefined" &&
58
+ args.projectRoot !== "null") {
59
+ return path.resolve(args.projectRoot.trim());
60
+ }
61
+ if (typeof args.rootDir === "string" &&
62
+ args.rootDir.trim().length > 0 &&
63
+ args.rootDir !== "undefined" &&
64
+ args.rootDir !== "null") {
65
+ return findProjectRoot(args.rootDir.trim());
66
+ }
67
+ if (typeof args.directoryPath === "string" &&
68
+ args.directoryPath.trim().length > 0 &&
69
+ args.directoryPath !== "undefined" &&
70
+ args.directoryPath !== "null") {
71
+ return findProjectRoot(args.directoryPath.trim());
72
+ }
73
+ if (typeof args.filePath === "string" &&
74
+ args.filePath.trim().length > 0 &&
75
+ args.filePath !== "undefined" &&
76
+ args.filePath !== "null") {
77
+ return findProjectRoot(args.filePath.trim());
78
+ }
79
+ if (Array.isArray(args.reads) && args.reads.length > 0) {
80
+ const first = args.reads[0];
81
+ if (first && typeof first === "object" && typeof first.filePath === "string") {
82
+ return findProjectRoot(first.filePath);
83
+ }
84
+ }
85
+ }
86
+ if (typeof fallbackPath === "string" &&
87
+ fallbackPath.trim().length > 0 &&
88
+ fallbackPath !== "undefined" &&
89
+ fallbackPath !== "null") {
90
+ return findProjectRoot(fallbackPath.trim());
91
+ }
92
+ return process.cwd();
93
+ }
94
+ //# sourceMappingURL=projectRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../../src/utils/projectRoot.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,9 @@
1
1
  /**
2
- * Rails Routes Parser - v3.9.0
2
+ * Rails Routes Parser - v3.9.2
3
3
  * Parses config/routes.rb to map HTTP routes to controller actions.
4
- * v1: handles resources, resource, explicit get/post/patch/put/delete/root.
5
- * v1 limitation: only:/except:/shallow:/nested resources — emits warnings, does not generate false routes.
4
+ * Uses indentation-based namespace tracking (immune to do/end counting errors).
5
+ * Supports: resources, resource, explicit HTTP verbs, namespace/scope, root.
6
+ * v1 limitations: only:/except:/shallow:/nested resources — emits warnings, no false routes.
6
7
  */
7
8
  export interface RouteEntry {
8
9
  method: string;
@@ -1,8 +1,9 @@
1
1
  /**
2
- * Rails Routes Parser - v3.9.0
2
+ * Rails Routes Parser - v3.9.2
3
3
  * Parses config/routes.rb to map HTTP routes to controller actions.
4
- * v1: handles resources, resource, explicit get/post/patch/put/delete/root.
5
- * v1 limitation: only:/except:/shallow:/nested resources — emits warnings, does not generate false routes.
4
+ * Uses indentation-based namespace tracking (immune to do/end counting errors).
5
+ * Supports: resources, resource, explicit HTTP verbs, namespace/scope, root.
6
+ * v1 limitations: only:/except:/shallow:/nested resources — emits warnings, no false routes.
6
7
  */
7
8
  import * as fs from "node:fs/promises";
8
9
  import * as path from "node:path";
@@ -10,22 +11,22 @@ import * as path from "node:path";
10
11
  const routesCache = new Map();
11
12
  /** Standard 7 REST actions for `resources` */
12
13
  const RESOURCES_ACTIONS = [
13
- { method: "GET", path: "", action: "index", controller: "" },
14
- { method: "GET", path: "/new", action: "new", controller: "" },
15
- { method: "POST", path: "", action: "create", controller: "" },
16
- { method: "GET", path: "/:id", action: "show", controller: "" },
17
- { method: "GET", path: "/:id/edit", action: "edit", controller: "" },
18
- { method: "PATCH", path: "/:id", action: "update", controller: "" },
19
- { method: "DELETE", path: "/:id", action: "destroy", controller: "" },
14
+ { method: "GET", path: "", action: "index" },
15
+ { method: "GET", path: "/new", action: "new" },
16
+ { method: "POST", path: "", action: "create" },
17
+ { method: "GET", path: "/:id", action: "show" },
18
+ { method: "GET", path: "/:id/edit", action: "edit" },
19
+ { method: "PATCH", path: "/:id", action: "update" },
20
+ { method: "DELETE", path: "/:id", action: "destroy" },
20
21
  ];
21
22
  /** Standard 6 singular REST actions for `resource` */
22
23
  const RESOURCE_ACTIONS = [
23
- { method: "GET", path: "/new", action: "new", controller: "" },
24
- { method: "POST", path: "", action: "create", controller: "" },
25
- { method: "GET", path: "", action: "show", controller: "" },
26
- { method: "GET", path: "/edit", action: "edit", controller: "" },
27
- { method: "PATCH", path: "", action: "update", controller: "" },
28
- { method: "DELETE", path: "", action: "destroy", controller: "" },
24
+ { method: "GET", path: "/new", action: "new" },
25
+ { method: "POST", path: "", action: "create" },
26
+ { method: "GET", path: "", action: "show" },
27
+ { method: "GET", path: "/edit", action: "edit" },
28
+ { method: "PATCH", path: "", action: "update" },
29
+ { method: "DELETE", path: "", action: "destroy" },
29
30
  ];
30
31
  export async function parseRailsRoutes(projectRoot) {
31
32
  const routesPath = path.join(projectRoot, "config", "routes.rb");
@@ -47,52 +48,57 @@ export async function parseRailsRoutes(projectRoot) {
47
48
  export function parseRoutesContent(content) {
48
49
  const routes = [];
49
50
  const warnings = [];
50
- // Stack for namespace/scope prefix accumulation
51
- const prefixStack = [];
51
+ const nsStack = [];
52
+ // Helper: get current url prefix and controller namespace from stack
53
+ const getPrefix = () => nsStack.length > 0 ? "/" + nsStack.map(e => e.prefix).join("/") : "";
54
+ const getNsPrefix = () => nsStack.length > 0 ? nsStack.map(e => e.nsPrefix).join("/") + "/" : "";
55
+ // Helper: measure leading spaces
56
+ const indentOf = (raw) => raw.match(/^(\s*)/)?.[1].length ?? 0;
52
57
  const lines = content.split("\n");
53
58
  for (const rawLine of lines) {
59
+ const indent = indentOf(rawLine);
54
60
  const line = rawLine.trim();
55
- // Skip comments and blank lines
56
- if (line.startsWith("#") || line === "")
57
- continue;
58
- // Namespace/scope push
59
- const nsMatch = line.match(/^(?:namespace|scope)\s+[:'"]([^'"]+)['"]/);
60
- if (nsMatch) {
61
- prefixStack.push(nsMatch[1].replace(/^:/, ""));
61
+ // Skip blank lines and comments
62
+ if (line === "" || line.startsWith("#"))
62
63
  continue;
64
+ // Pop namespace stack entries whose indent is >= current indent
65
+ // (meaning we've dedented past them — their `end` was processed)
66
+ while (nsStack.length > 0 && indent <= nsStack[nsStack.length - 1].indent) {
67
+ nsStack.pop();
63
68
  }
64
- // Closing end — pop prefix stack
65
- if (line === "end" && prefixStack.length > 0) {
66
- prefixStack.pop();
69
+ // namespace :admin do / namespace 'admin' do / scope :admin do
70
+ // Handles both symbol (:admin) and string ('admin'/"admin") syntax
71
+ const nsSymbolMatch = line.match(/^(?:namespace|scope)\s+:(\w+)/);
72
+ const nsStringMatch = line.match(/^(?:namespace|scope)\s+['"]([^'"]+)['"]/);
73
+ const nsMatch = nsSymbolMatch ?? nsStringMatch;
74
+ if (nsMatch) {
75
+ const seg = nsMatch[1];
76
+ // scope doesn't add controller namespace, namespace does
77
+ const isNamespace = line.startsWith("namespace");
78
+ nsStack.push({ indent, prefix: seg, nsPrefix: isNamespace ? seg : "" });
67
79
  continue;
68
80
  }
69
- const prefix = prefixStack.length > 0 ? "/" + prefixStack.join("/") : "";
70
- // Detect unsupported options — warn instead of generating wrong output
81
+ const urlPrefix = getPrefix();
82
+ const ctrlPrefix = getNsPrefix();
83
+ // Detect option flags
71
84
  const hasOnlyExcept = /\bonly:\s*\[/.test(line) || /\bexcept:\s*\[/.test(line);
72
85
  const hasShallow = /\bshallow:\s*true\b/.test(line);
73
- const hasNested = line.includes("do") && (line.startsWith("resources") || line.startsWith("resource"));
74
- // resources :name
86
+ // Nested resources: line ends with `do` (opens a block we won't parse deeply)
87
+ const hasNestedDo = /\bdo\s*$/.test(line) && (line.startsWith("resources") || line.startsWith("resource"));
88
+ // resources :name / resources :name, only: [...] / resources :name do
75
89
  const resourcesMatch = line.match(/^resources\s+:(\w+)/);
76
90
  if (resourcesMatch) {
77
91
  const name = resourcesMatch[1];
78
- const controller = nameToController(name, prefixStack);
79
- const basePath = `${prefix}/${name}`;
80
- if (hasOnlyExcept) {
92
+ const controller = `${ctrlPrefix}${name}`;
93
+ const basePath = `${urlPrefix}/${name}`;
94
+ if (hasOnlyExcept)
81
95
  warnings.push(`resources :${name} uses only:/except: — route list may be incomplete. Full support planned for v2.`);
82
- }
83
- if (hasShallow) {
96
+ if (hasShallow)
84
97
  warnings.push(`resources :${name} uses shallow: — nested shallow routes not fully parsed.`);
85
- }
86
- if (hasNested) {
98
+ if (hasNestedDo)
87
99
  warnings.push(`resources :${name} has nested resources (do block) — only top-level routes parsed.`);
88
- }
89
- for (const action of RESOURCES_ACTIONS) {
90
- routes.push({
91
- method: action.method,
92
- path: basePath + action.path,
93
- controller,
94
- action: action.action,
95
- });
100
+ for (const a of RESOURCES_ACTIONS) {
101
+ routes.push({ method: a.method, path: basePath + a.path, controller, action: a.action });
96
102
  }
97
103
  continue;
98
104
  }
@@ -100,38 +106,32 @@ export function parseRoutesContent(content) {
100
106
  const resourceMatch = line.match(/^resource\s+:(\w+)/);
101
107
  if (resourceMatch) {
102
108
  const name = resourceMatch[1];
103
- const controller = nameToController(name + "s", prefixStack); // pluralize for controller
104
- const basePath = `${prefix}/${name}`;
105
- if (hasOnlyExcept) {
109
+ const controller = `${ctrlPrefix}${name}s`; // pluralize for controller
110
+ const basePath = `${urlPrefix}/${name}`;
111
+ if (hasOnlyExcept)
106
112
  warnings.push(`resource :${name} uses only:/except: — route list may be incomplete.`);
107
- }
108
- for (const action of RESOURCE_ACTIONS) {
109
- routes.push({
110
- method: action.method,
111
- path: basePath + action.path,
112
- controller,
113
- action: action.action,
114
- });
113
+ for (const a of RESOURCE_ACTIONS) {
114
+ routes.push({ method: a.method, path: basePath + a.path, controller, action: a.action });
115
115
  }
116
116
  continue;
117
117
  }
118
- // Explicit HTTP verb routes: get '/path', to: 'controller#action'
118
+ // Explicit HTTP verb: get '/path', to: 'controller#action'
119
119
  const verbMatch = line.match(/^(get|post|patch|put|delete|head|options)\s+['"]([^'"]+)['"]\s*,\s*to:\s*['"]([^#'"]+)#([^'"]+)['"]/i);
120
120
  if (verbMatch) {
121
121
  routes.push({
122
122
  method: verbMatch[1].toUpperCase(),
123
- path: prefix + verbMatch[2],
123
+ path: urlPrefix + verbMatch[2],
124
124
  controller: verbMatch[3].trim(),
125
125
  action: verbMatch[4].trim(),
126
126
  });
127
127
  continue;
128
128
  }
129
- // root to: 'controller#action'
129
+ // root to: 'controller#action' / root 'controller#action'
130
130
  const rootMatch = line.match(/^root\s+(?:to:\s*)?['"]([^#'"]+)#([^'"]+)['"]/);
131
131
  if (rootMatch) {
132
132
  routes.push({
133
133
  method: "GET",
134
- path: prefix + "/",
134
+ path: urlPrefix + "/",
135
135
  controller: rootMatch[1].trim(),
136
136
  action: rootMatch[2].trim(),
137
137
  });
@@ -140,9 +140,4 @@ export function parseRoutesContent(content) {
140
140
  }
141
141
  return { routes, warnings };
142
142
  }
143
- /** Convert resource name + namespace stack to controller name */
144
- function nameToController(name, prefixStack) {
145
- const ns = prefixStack.length > 0 ? prefixStack.join("/") + "/" : "";
146
- return `${ns}${name}`;
147
- }
148
143
  //# sourceMappingURL=railsRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"railsRoutes.js","sourceRoot":"","sources":["../../../src/utils/railsRoutes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"railsRoutes.js","sourceRoot":"","sources":["../../../src/utils/railsRoutes.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Rate Limiter - v3.9.0
2
+ * Rate Limiter - v3.9.2
3
3
  * Token bucket algorithm for DoS protection
4
4
  */
5
5
  interface RateLimitConfig {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Rate Limiter - v3.9.0
2
+ * Rate Limiter - v3.9.2
3
3
  * Token bucket algorithm for DoS protection
4
4
  */
5
5
  export class RateLimiter {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * File Streaming - v3.9.0
2
+ * File Streaming - v3.9.2
3
3
  * Stream large files in chunks to avoid memory exhaustion
4
4
  */
5
5
  import type { BaseParser, SymbolInfo } from "../parsers/base.js";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * File Streaming - v3.9.0
2
+ * File Streaming - v3.9.2
3
3
  * Stream large files in chunks to avoid memory exhaustion
4
4
  */
5
5
  import * as fs from "node:fs";
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Telemetry - v3.9.0
2
+ * Telemetry - v3.9.2
3
3
  * Metrics collection and monitoring
4
4
  */
5
5
  export interface Metric {
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Telemetry - v3.9.0
2
+ * Telemetry - v3.9.2
3
3
  * Metrics collection and monitoring
4
4
  */
5
5
  export class TelemetryCollector {
package/llms.txt CHANGED
@@ -1,21 +1,39 @@
1
- # mcp-code-context v3.9.0
1
+ # mcp-code-context v3.9.2
2
2
 
3
3
  > A Model Context Protocol (MCP) server with **Tree-sitter WASM parsers** for 100% AST accuracy. Zero native dependencies. Production-ready with middleware pipeline, session-scoped state, and crash recovery.
4
4
 
5
- ## What's New in v3.9.0
5
+ ## What's New in v3.9.2
6
+
7
+ 🛡️ **Project Root Fallback & Schema Freedom Release**:
8
+ - ✅ **Smart Project Root Discovery**: `resolveProjectRoot` & `findProjectRoot` walk up directory trees detecting `.git`, `package.json`, `composer.json`, `pyproject.toml`, etc. Eliminates false-positive `outside project boundary ".../undefined"` security errors.
9
+ - ✅ **Optional Schema Requirements**: `projectRoot` is now optional across all tools in `CORE_TOOLS` and `ADMIN_TOOLS`. LLM agents can perform surgical operations with just `filePath` or `rootDir`.
10
+ - ✅ **SecurityValidator Guard**: `SecurityValidator` safely defaults `undefined`/`null` roots to `process.cwd()`.
11
+ - ✅ **Startup Diagnostics Signature**: Emits `[mcp-code-context] v3.9.2 running on stdio` on startup.
12
+
13
+ ## Previously Added in v3.9.1
14
+
15
+ 🐛 **Bug Fix Release**:
16
+ - ✅ **`get_rails_routes` namespace fix**: Routes inside `namespace :admin do` now produce `/admin/users` (was `/users`). Controllers correctly namespaced as `admin/users`. Fixed regex that captured `admin do` instead of `admin` with symbol syntax.
17
+ - ✅ **`get_rails_routes` indentation parser**: Replaced fragile `do/end` depth counter with indentation-based stack. Handles nested namespaces (`api/v1`), `member do` blocks, and `scope` correctly.
18
+ - ✅ **Repo map Gems + Concerns**: `get_semantic_repo_map` appends `<gem>` behavior blocks and `<concern>` entries when Gemfile and concerns directories are present.
19
+
20
+ ## Previously Added in v3.9.0
21
+
22
+ - ✅ **`get_gemfile_context`**: Parse Gemfile, return implicit behaviors for known gems (devise, sidekiq, pundit, kaminari, paper_trail, geocoder, etc.)
23
+ - ✅ **`find_metaprogramming`**: Scan Ruby for `define_method`, `method_missing`, `class_eval`, `ActiveSupport::Concern`, `delegate`, `has_many :through` etc.
24
+ - ✅ **`get_rails_routes`**: Parse `config/routes.rb` into structured route map
25
+ - ✅ **Concern resolution in `analyze_impact`**: Checks `app/models/concerns` and `app/controllers/concerns` before file scan
26
+
27
+ ## Previously Added in v3.8.x
6
28
 
7
- 🚀 **CRITICAL FIXES - Production Readiness Release**:
8
29
  - ✅ **Session-scoped state**: Each MCP client gets isolated locks, confirmation store, rate limiter (no state leakage)
9
30
  - ✅ **Crash recovery**: SQLite-backed pending operations store - survive restarts
10
31
  - ✅ **Expanded ReDoS protection**: 15+ patterns (was 6) - better security
11
32
  - ✅ **Auto-persist before eviction**: CacheManager now persists before LRU eviction
12
33
  - ✅ **Higher file limits**: MAX_FILES_REPO_MAP = 2000 (was 500)
13
- - ✅ **Multi-client tests**: New integration tests for concurrent MCP clients
14
34
  - ✅ **Ruby full support**: Complete `RubyParser` with `search()` for `search_code_pattern` compatibility
15
35
  - ✅ **ActiveRecord Virtual Schema**: Parses `db/schema.rb` and injects column annotations on AR model reads
16
36
 
17
- ## Previously Added in v3.7.x
18
-
19
37
  - ✅ 4 new tools: `search_symbols`, `explain_symbol`, `batch_read`, `get_rate_limit_status`
20
38
  - ✅ `diffFormat` parameter on all write tools (`unified`, `compact`, `summary`, `none`)
21
39
  - ✅ Phase 2 no longer requires `newContent`/`code` — server stores content from Phase 1
@@ -149,13 +167,13 @@ This MCP server solves two problems:
149
167
  - `steps` (optional): Number of versions to go back (1-5, default: 1).
150
168
  **What it does:** Reverts the file to the state it was in before the last 1-5 modifications.
151
169
 
152
- ### Write Tools (v3.9.0 Two-Phase Workflow)
170
+ ### Write Tools (Two-Phase Workflow)
153
171
 
154
172
  All write tools follow a **Two-Phase Workflow**:
155
173
  1. **Phase 1 (Preview)**: Call without a token to get a unified `diff` and a `confirmationToken`.
156
174
  2. **Phase 2 (Apply)**: Call with `confirmationToken` and `confirm: true` to apply the changes.
157
175
 
158
- **Important Notes (v3.9.0):**
176
+ **Important Safety Features:**
159
177
  - ✅ **Windows CRLF Support**: Fully resolved. All operations work correctly on Windows files with CRLF line endings.
160
178
  - ✅ **Parameter Brace Handling**: Methods with braces in parameters (e.g., `{int? cart}`) are now handled correctly.
161
179
  - ✅ **Session-scoped state**: Each MCP client gets isolated state (locks, confirmation store, rate limiter).
@@ -236,9 +254,36 @@ All write tools follow a **Two-Phase Workflow**:
236
254
 
237
255
  **Best used when:** Cleaning up deprecated functions or unused code.
238
256
 
239
- ## New Tools (v3.9.0)
257
+ ## New Tools (v3.9.x)
258
+
259
+ #### 11. `get_gemfile_context`
260
+ **Purpose:** Parse the Gemfile and return known gem behaviors with their implicit Rails conventions.
261
+
262
+ **Input:** `projectRoot` (required).
263
+
264
+ **Returns:** List of all gems, known gems with their implicit behavior descriptions, and an XML annotation block.
265
+
266
+ **Best used when:** Starting work on a Rails project to understand what auth/authorization/pagination/etc. gems are active without reading docs.
240
267
 
241
- #### 11. `get_session_stats`
268
+ #### 12. `find_metaprogramming`
269
+ **Purpose:** Scan Ruby files for dynamic method generation entry points.
270
+
271
+ **Input:** `projectRoot` (required), `filePath` (optional — scan single file), `rootDir` (optional — scan subdirectory).
272
+
273
+ **Returns:** All matches grouped by file, with line number, pattern name, description, and code snippet.
274
+
275
+ **Best used when:** Investigating where "magic methods" are defined in a Rails project (before using `analyze_impact`).
276
+
277
+ #### 13. `get_rails_routes`
278
+ **Purpose:** Parse `config/routes.rb` and return a structured route map.
279
+
280
+ **Input:** `projectRoot` (required).
281
+
282
+ **Returns:** Array of routes with `method`, `path`, `controller`, `action`. Includes warnings for `only:/except:` and nested resources.
283
+
284
+ **Best used when:** Understanding API surface of a Rails app, finding what controller handles a given route.
285
+
286
+ #### 14. `get_session_stats`
242
287
  **Purpose:** Get statistics for the current MCP client session.
243
288
 
244
289
  **Input:** None.
@@ -248,27 +293,21 @@ All write tools follow a **Two-Phase Workflow**:
248
293
  - `locksHeld`: Number of file locks currently held
249
294
  - `rateLimiterTokens`: Current token balance for this session
250
295
 
251
- **Best used when:** Diagnosing session-specific issues or understanding your client's resource usage.
252
-
253
- #### 12. `clear_session_cache`
296
+ #### 15. `clear_session_cache`
254
297
  **Purpose:** Clear the cache for the current MCP client session only.
255
298
 
256
299
  **Input:** None.
257
300
 
258
301
  **Returns:** `cacheEntriesCleared` - Number of cache entries removed.
259
302
 
260
- **Best used when:** You want to reset your client's cache without affecting other MCP clients.
261
-
262
- #### 13. `list_pending_operations`
303
+ #### 16. `list_pending_operations`
263
304
  **Purpose:** List all pending operations (for recovery after crash).
264
305
 
265
306
  **Input:** None.
266
307
 
267
308
  **Returns:** Array of pending operations with tokens, file paths, and timestamps.
268
309
 
269
- **Best used when:** Recovering work after a server crash.
270
-
271
- ## Previously Added Tools (v3.9.0)
310
+ ## Previously Added Tools (v3.9.x)
272
311
 
273
312
  #### 14. `parse_file`
274
313
  **Purpose:** Parse a file using Tree-sitter and extract all symbols.
@@ -313,7 +352,7 @@ All write tools follow a **Two-Phase Workflow**:
313
352
  5. **Phase 2: Apply Edit** → Verify the diff, then call with the token and `confirm: true`.
314
353
  6. **Recovery** → Use `rollback_file` if needed.
315
354
 
316
- ## Session State Configuration (v3.9.0+)
355
+ ## Session State Configuration (v3.8.0+)
317
356
 
318
357
  ### Critical: Session-Scoped State
319
358
 
@@ -429,6 +468,6 @@ No additional configuration is needed beyond adding the MCP server definition. S
429
468
 
430
469
  ---
431
470
 
432
- **Version**: 3.9.0
471
+ **Version**: 3.9.2
433
472
  **Last Updated**: June 8, 2026
434
473
  **Status**: Production-ready with session-scoped state and crash recovery