@j0hanz/filesystem-mcp 1.19.0 → 2.0.0
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 +333 -838
- package/dist/cli-help.d.ts +3 -0
- package/dist/cli-help.d.ts.map +1 -0
- package/dist/cli-help.js +169 -0
- package/dist/cli-help.js.map +1 -0
- package/dist/cli.d.ts +28 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +168 -123
- package/dist/cli.js.map +1 -0
- package/dist/core/concurrency.d.ts +70 -0
- package/dist/core/concurrency.d.ts.map +1 -0
- package/dist/core/concurrency.js +173 -0
- package/dist/core/concurrency.js.map +1 -0
- package/dist/core/config.d.ts +19 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +11 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/cursor.d.ts +23 -0
- package/dist/core/cursor.d.ts.map +1 -0
- package/dist/core/cursor.js +62 -0
- package/dist/core/cursor.js.map +1 -0
- package/dist/core/errors.d.ts +96 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +356 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/file-uri.d.ts +24 -0
- package/dist/core/file-uri.d.ts.map +1 -0
- package/dist/core/file-uri.js +52 -0
- package/dist/core/file-uri.js.map +1 -0
- package/dist/core/fmt.d.ts +38 -0
- package/dist/core/fmt.d.ts.map +1 -0
- package/dist/core/fmt.js +109 -0
- package/dist/core/fmt.js.map +1 -0
- package/dist/core/fs.d.ts +108 -0
- package/dist/core/fs.d.ts.map +1 -0
- package/dist/core/fs.js +243 -0
- package/dist/core/fs.js.map +1 -0
- package/dist/core/glob.d.ts +41 -0
- package/dist/core/glob.d.ts.map +1 -0
- package/dist/core/glob.js +399 -0
- package/dist/core/glob.js.map +1 -0
- package/dist/core/input-required.d.ts +147 -0
- package/dist/core/input-required.d.ts.map +1 -0
- package/dist/core/input-required.js +261 -0
- package/dist/core/input-required.js.map +1 -0
- package/dist/core/mime.d.ts +15 -0
- package/dist/core/mime.d.ts.map +1 -0
- package/dist/core/mime.js +188 -0
- package/dist/core/mime.js.map +1 -0
- package/dist/core/observability.d.ts +10 -0
- package/dist/core/observability.d.ts.map +1 -0
- package/dist/core/observability.js +76 -0
- package/dist/core/observability.js.map +1 -0
- package/dist/core/page-store.d.ts +41 -0
- package/dist/core/page-store.d.ts.map +1 -0
- package/dist/core/page-store.js +74 -0
- package/dist/core/page-store.js.map +1 -0
- package/dist/core/path-completer.d.ts +10 -0
- package/dist/core/path-completer.d.ts.map +1 -0
- package/dist/core/path-completer.js +227 -0
- package/dist/core/path-completer.js.map +1 -0
- package/dist/core/path-discovery.d.ts +8 -0
- package/dist/core/path-discovery.d.ts.map +1 -0
- package/dist/core/path-discovery.js +105 -0
- package/dist/core/path-discovery.js.map +1 -0
- package/dist/core/path-utils.d.ts +9 -0
- package/dist/core/path-utils.d.ts.map +1 -0
- package/dist/core/path-utils.js +121 -0
- package/dist/core/path-utils.js.map +1 -0
- package/dist/core/path.d.ts +148 -0
- package/dist/core/path.d.ts.map +1 -0
- package/dist/core/path.js +674 -0
- package/dist/core/path.js.map +1 -0
- package/dist/core/primitives.d.ts +23 -0
- package/dist/core/primitives.d.ts.map +1 -0
- package/dist/core/primitives.js +54 -0
- package/dist/core/primitives.js.map +1 -0
- package/dist/core/read.d.ts +74 -0
- package/dist/core/read.d.ts.map +1 -0
- package/dist/core/read.js +562 -0
- package/dist/core/read.js.map +1 -0
- package/dist/core/schema.d.ts +139 -0
- package/dist/core/schema.d.ts.map +1 -0
- package/dist/core/schema.js +345 -0
- package/dist/core/schema.js.map +1 -0
- package/dist/core/search.d.ts +100 -0
- package/dist/core/search.d.ts.map +1 -0
- package/dist/core/search.js +248 -0
- package/dist/core/search.js.map +1 -0
- package/dist/core/sensitive.d.ts +6 -0
- package/dist/core/sensitive.d.ts.map +1 -0
- package/dist/core/sensitive.js +142 -0
- package/dist/core/sensitive.js.map +1 -0
- package/dist/core/store.d.ts +57 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +162 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/util.d.ts +26 -0
- package/dist/core/util.d.ts.map +1 -0
- package/dist/core/util.js +66 -0
- package/dist/core/util.js.map +1 -0
- package/dist/core/watcher-registry.d.ts +68 -0
- package/dist/core/watcher-registry.d.ts.map +1 -0
- package/dist/core/watcher-registry.js +312 -0
- package/dist/core/watcher-registry.js.map +1 -0
- package/dist/http-policy.d.ts +121 -0
- package/dist/http-policy.d.ts.map +1 -0
- package/dist/http-policy.js +340 -0
- package/dist/http-policy.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -41
- package/dist/index.js.map +1 -0
- package/dist/instructions.d.ts +12 -0
- package/dist/instructions.d.ts.map +1 -0
- package/dist/instructions.js +71 -0
- package/dist/instructions.js.map +1 -0
- package/dist/prompts.d.ts +8 -6
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +74 -168
- package/dist/prompts.js.map +1 -0
- package/dist/resources.d.ts +73 -9
- package/dist/resources.d.ts.map +1 -0
- package/dist/resources.js +392 -163
- package/dist/resources.js.map +1 -0
- package/dist/server.d.ts +62 -1
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +139 -1
- package/dist/server.js.map +1 -0
- package/dist/tools/batch.d.ts +89 -0
- package/dist/tools/batch.d.ts.map +1 -0
- package/dist/tools/batch.js +157 -0
- package/dist/tools/batch.js.map +1 -0
- package/dist/tools/create.d.ts +2 -0
- package/dist/tools/create.d.ts.map +1 -0
- package/dist/tools/create.js +142 -0
- package/dist/tools/create.js.map +1 -0
- package/dist/tools/define.d.ts +110 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +394 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/delete-file.d.ts +2 -4
- package/dist/tools/delete-file.d.ts.map +1 -0
- package/dist/tools/delete-file.js +330 -87
- package/dist/tools/delete-file.js.map +1 -0
- package/dist/tools/diff.d.ts +2 -0
- package/dist/tools/diff.d.ts.map +1 -0
- package/dist/tools/diff.js +94 -0
- package/dist/tools/diff.js.map +1 -0
- package/dist/tools/edit.d.ts +2 -0
- package/dist/tools/edit.d.ts.map +1 -0
- package/dist/tools/edit.js +442 -0
- package/dist/tools/edit.js.map +1 -0
- package/dist/tools/index.d.ts +26 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +52 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/list.d.ts +2 -0
- package/dist/tools/list.d.ts.map +1 -0
- package/dist/tools/list.js +291 -0
- package/dist/tools/list.js.map +1 -0
- package/dist/tools/move.d.ts +2 -0
- package/dist/tools/move.d.ts.map +1 -0
- package/dist/tools/move.js +321 -0
- package/dist/tools/move.js.map +1 -0
- package/dist/tools/patch.d.ts +2 -0
- package/dist/tools/patch.d.ts.map +1 -0
- package/dist/tools/patch.js +155 -0
- package/dist/tools/patch.js.map +1 -0
- package/dist/tools/progress.d.ts +52 -0
- package/dist/tools/progress.d.ts.map +1 -0
- package/dist/tools/progress.js +172 -0
- package/dist/tools/progress.js.map +1 -0
- package/dist/tools/read.d.ts +2 -4
- package/dist/tools/read.d.ts.map +1 -0
- package/dist/tools/read.js +398 -152
- package/dist/tools/read.js.map +1 -0
- package/dist/tools/replace-in-files.d.ts +2 -4
- package/dist/tools/replace-in-files.d.ts.map +1 -0
- package/dist/tools/replace-in-files.js +435 -264
- package/dist/tools/replace-in-files.js.map +1 -0
- package/dist/tools/roots.d.ts +2 -4
- package/dist/tools/roots.d.ts.map +1 -0
- package/dist/tools/roots.js +29 -52
- package/dist/tools/roots.js.map +1 -0
- package/dist/tools/search-content.d.ts +2 -4
- package/dist/tools/search-content.d.ts.map +1 -0
- package/dist/tools/search-content.js +262 -228
- package/dist/tools/search-content.js.map +1 -0
- package/dist/tools/search-files.d.ts +2 -4
- package/dist/tools/search-files.d.ts.map +1 -0
- package/dist/tools/search-files.js +162 -161
- package/dist/tools/search-files.js.map +1 -0
- package/dist/tools/stat.d.ts +2 -4
- package/dist/tools/stat.d.ts.map +1 -0
- package/dist/tools/stat.js +202 -62
- package/dist/tools/stat.js.map +1 -0
- package/dist/transport/http.d.ts +5 -0
- package/dist/transport/http.d.ts.map +1 -0
- package/dist/transport/http.js +276 -0
- package/dist/transport/http.js.map +1 -0
- package/dist/transport/shared.d.ts +45 -0
- package/dist/transport/shared.d.ts.map +1 -0
- package/dist/transport/shared.js +65 -0
- package/dist/transport/shared.js.map +1 -0
- package/dist/transport/stdio.d.ts +32 -0
- package/dist/transport/stdio.d.ts.map +1 -0
- package/dist/transport/stdio.js +279 -0
- package/dist/transport/stdio.js.map +1 -0
- package/dist/transport.d.ts +5 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +4 -0
- package/dist/transport.js.map +1 -0
- package/package.json +37 -46
- package/dist/assets/logo.svg +0 -35
- package/dist/completions.d.ts +0 -2
- package/dist/completions.js +0 -572
- package/dist/config.d.ts +0 -119
- package/dist/config.js +0 -31
- package/dist/lib/abort.d.ts +0 -7
- package/dist/lib/abort.js +0 -81
- package/dist/lib/constants.d.ts +0 -42
- package/dist/lib/constants.js +0 -313
- package/dist/lib/errors.d.ts +0 -28
- package/dist/lib/errors.js +0 -301
- package/dist/lib/file-operations/core.d.ts +0 -53
- package/dist/lib/file-operations/core.js +0 -144
- package/dist/lib/file-operations/metadata.d.ts +0 -77
- package/dist/lib/file-operations/metadata.js +0 -878
- package/dist/lib/file-operations/search.d.ts +0 -46
- package/dist/lib/file-operations/search.js +0 -1194
- package/dist/lib/file-operations/traversal.d.ts +0 -40
- package/dist/lib/file-operations/traversal.js +0 -310
- package/dist/lib/fs-helpers.d.ts +0 -46
- package/dist/lib/fs-helpers.js +0 -606
- package/dist/lib/globs.d.ts +0 -2
- package/dist/lib/globs.js +0 -19
- package/dist/lib/logger.d.ts +0 -27
- package/dist/lib/logger.js +0 -91
- package/dist/lib/observability.d.ts +0 -33
- package/dist/lib/observability.js +0 -373
- package/dist/lib/paths.d.ts +0 -35
- package/dist/lib/paths.js +0 -634
- package/dist/lib/resource-store.d.ts +0 -28
- package/dist/lib/resource-store.js +0 -195
- package/dist/lib/utils.d.ts +0 -7
- package/dist/lib/utils.js +0 -37
- package/dist/lib/zod-codecs.d.ts +0 -2
- package/dist/lib/zod-codecs.js +0 -18
- package/dist/pkg-info.d.ts +0 -7
- package/dist/pkg-info.js +0 -9
- package/dist/resources/generated-instructions.d.ts +0 -1
- package/dist/resources/generated-instructions.js +0 -105
- package/dist/resources/tool-catalog.d.ts +0 -2
- package/dist/resources/tool-catalog.js +0 -78
- package/dist/resources/tool-info.d.ts +0 -9
- package/dist/resources/tool-info.js +0 -206
- package/dist/resources/workflows.d.ts +0 -1
- package/dist/resources/workflows.js +0 -72
- package/dist/schemas.d.ts +0 -505
- package/dist/schemas.js +0 -676
- package/dist/server/bootstrap.d.ts +0 -6
- package/dist/server/bootstrap.js +0 -563
- package/dist/server/event-store.d.ts +0 -18
- package/dist/server/event-store.js +0 -71
- package/dist/server/roots-manager.d.ts +0 -28
- package/dist/server/roots-manager.js +0 -227
- package/dist/server/task-store.d.ts +0 -10
- package/dist/server/task-store.js +0 -91
- package/dist/tools/apply-patch.d.ts +0 -4
- package/dist/tools/apply-patch.js +0 -235
- package/dist/tools/calculate-hash.d.ts +0 -4
- package/dist/tools/calculate-hash.js +0 -187
- package/dist/tools/contract.d.ts +0 -50
- package/dist/tools/contract.js +0 -1
- package/dist/tools/create-directory.d.ts +0 -4
- package/dist/tools/create-directory.js +0 -68
- package/dist/tools/diff-files.d.ts +0 -4
- package/dist/tools/diff-files.js +0 -136
- package/dist/tools/edit-file.d.ts +0 -4
- package/dist/tools/edit-file.js +0 -256
- package/dist/tools/icons.d.ts +0 -15
- package/dist/tools/icons.js +0 -24
- package/dist/tools/list-directory.d.ts +0 -4
- package/dist/tools/list-directory.js +0 -218
- package/dist/tools/move-file.d.ts +0 -4
- package/dist/tools/move-file.js +0 -178
- package/dist/tools/read-multiple.d.ts +0 -4
- package/dist/tools/read-multiple.js +0 -207
- package/dist/tools/shared.d.ts +0 -172
- package/dist/tools/shared.js +0 -599
- package/dist/tools/stat-many.d.ts +0 -4
- package/dist/tools/stat-many.js +0 -104
- package/dist/tools/task-support.d.ts +0 -29
- package/dist/tools/task-support.js +0 -472
- package/dist/tools/tree.d.ts +0 -4
- package/dist/tools/tree.js +0 -102
- package/dist/tools/write-file.d.ts +0 -4
- package/dist/tools/write-file.js +0 -60
- package/dist/tools.d.ts +0 -5
- package/dist/tools.js +0 -54
|
@@ -1,182 +1,183 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
import * as z from 'zod/v4';
|
|
2
|
+
import { SearchStoppedReasonSchema } from '../core/concurrency.js';
|
|
3
|
+
import { createFirstPage, readNextPage } from '../core/cursor.js';
|
|
4
|
+
import { ErrorCode } from '../core/errors.js';
|
|
5
|
+
import { formatCount, truncateProgressPattern } from '../core/fmt.js';
|
|
6
|
+
import { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';
|
|
7
|
+
import { toPosixRelative } from '../core/path.js';
|
|
8
|
+
import { CursorSchema, includeHiddenField, includeIgnoredField, maxDepthField, NextCursorSchema, NonNegInt, OptionalPath, SafeGlobPattern, } from '../core/schema.js';
|
|
9
|
+
import { searchFiles } from '../core/search.js';
|
|
10
|
+
import { putJsonResource } from '../core/store.js';
|
|
11
|
+
import { DEFAULT_SEARCH_RESULTS, DEFAULT_SEARCH_TIMEOUT_MS, MAX_SEARCH_RESULTS, } from '../core/util.js';
|
|
12
|
+
import { defineTool } from './define.js';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
const SearchFilesInputSchema = z.strictObject({
|
|
15
|
+
path: OptionalPath.describe('Base directory to search under (default: first allowed root)'),
|
|
16
|
+
pattern: SafeGlobPattern.describe('Glob pattern to match file paths (e.g. **/*.ts, src/**/*.js)'),
|
|
17
|
+
maxResults: z
|
|
18
|
+
.uint32()
|
|
19
|
+
.min(1)
|
|
20
|
+
.max(MAX_SEARCH_RESULTS)
|
|
21
|
+
.optional()
|
|
22
|
+
.default(DEFAULT_SEARCH_RESULTS)
|
|
23
|
+
.describe('Maximum number of matching files to return per page'),
|
|
24
|
+
includeIgnored: includeIgnoredField(),
|
|
25
|
+
includeHidden: includeHiddenField(),
|
|
26
|
+
sortBy: z
|
|
27
|
+
.enum(['name', 'path'])
|
|
28
|
+
.optional()
|
|
29
|
+
.default('path')
|
|
30
|
+
.describe('Sort order: path = full path (default), name = basename only'),
|
|
31
|
+
maxDepth: maxDepthField(),
|
|
32
|
+
cursor: CursorSchema,
|
|
33
|
+
});
|
|
34
|
+
const SearchFilesOutputSchema = z.strictObject({
|
|
35
|
+
root: z.string().describe('Resolved base directory used as the search root'),
|
|
36
|
+
results: z
|
|
37
|
+
.array(z.strictObject({
|
|
38
|
+
path: z.string().describe('File path relative to the search root'),
|
|
39
|
+
}))
|
|
40
|
+
.describe('Matched files ordered by sortBy'),
|
|
41
|
+
totalMatches: NonNegInt.optional().describe('Total number of matching files found'),
|
|
42
|
+
filesScanned: NonNegInt.optional().describe('Total number of files examined during the search'),
|
|
43
|
+
skippedInaccessible: NonNegInt.optional().describe('Files skipped due to permission or access errors'),
|
|
44
|
+
stoppedReason: SearchStoppedReasonSchema.describe('Why the search ended early: maxResults = result cap reached, timeout = time limit hit or the request was cancelled. Absent when the scan ran to completion.'),
|
|
45
|
+
resourceUri: z
|
|
46
|
+
.string()
|
|
47
|
+
.optional()
|
|
48
|
+
.describe('URI to the full results JSON in the resource store; first page only, when results are paginated'),
|
|
49
|
+
nextCursor: NextCursorSchema,
|
|
50
|
+
});
|
|
31
51
|
function buildRelativeResults(basePath, displayResults) {
|
|
32
52
|
const relativeResults = [];
|
|
33
53
|
for (const entry of displayResults) {
|
|
34
54
|
relativeResults.push({
|
|
35
|
-
path:
|
|
36
|
-
size: entry.size,
|
|
37
|
-
modified: entry.modified?.toISOString(),
|
|
55
|
+
path: toPosixRelative(basePath, entry.path),
|
|
38
56
|
});
|
|
39
57
|
}
|
|
40
58
|
return relativeResults;
|
|
41
59
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
60
|
+
function searchFilesQueryKey(args, basePath) {
|
|
61
|
+
return JSON.stringify({
|
|
62
|
+
method: 'find_files',
|
|
63
|
+
path: basePath,
|
|
64
|
+
pattern: args.pattern,
|
|
65
|
+
includeIgnored: args.includeIgnored,
|
|
66
|
+
includeHidden: args.includeHidden,
|
|
67
|
+
sortBy: args.sortBy,
|
|
68
|
+
maxDepth: args.maxDepth,
|
|
69
|
+
});
|
|
47
70
|
}
|
|
48
|
-
function
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
71
|
+
function searchFilesOutput(results, metadata, nextCursor) {
|
|
72
|
+
return {
|
|
73
|
+
root: metadata.root,
|
|
74
|
+
results: [...results],
|
|
75
|
+
totalMatches: metadata.totalMatches,
|
|
76
|
+
filesScanned: metadata.filesScanned,
|
|
77
|
+
...(metadata.skippedInaccessible ? { skippedInaccessible: metadata.skippedInaccessible } : {}),
|
|
78
|
+
...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),
|
|
79
|
+
...(metadata.resourceUri ? { resourceUri: metadata.resourceUri } : {}),
|
|
80
|
+
...(nextCursor !== undefined ? { nextCursor } : {}),
|
|
81
|
+
};
|
|
57
82
|
}
|
|
58
|
-
async function handleSearchFiles(args,
|
|
59
|
-
const
|
|
83
|
+
async function handleSearchFiles(args, ctx) {
|
|
84
|
+
const requestedBasePath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);
|
|
85
|
+
const queryKey = searchFilesQueryKey(args, requestedBasePath);
|
|
86
|
+
if (args.cursor !== undefined) {
|
|
87
|
+
const paged = readNextPage({
|
|
88
|
+
store: ctx.pageStore,
|
|
89
|
+
queryKey,
|
|
90
|
+
cursor: args.cursor,
|
|
91
|
+
pageSize: args.maxResults,
|
|
92
|
+
});
|
|
93
|
+
// First page only — see the same note in list.ts: the overflow entry expires
|
|
94
|
+
// on ResourceStore's clock, not this snapshot's.
|
|
95
|
+
const { resourceUri: _firstPageOnly, ...pageMetadata } = paged.metadata;
|
|
96
|
+
return {
|
|
97
|
+
structured: searchFilesOutput(paged.page, pageMetadata, paged.nextCursor),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
const basePath = await ctx.fs.pathGuard.validateExistingDirectory(requestedBasePath);
|
|
60
101
|
const excludePatterns = args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS;
|
|
61
|
-
const cursorOffset = args.cursor !== undefined ? decodeOffsetCursor(args.cursor) : 0;
|
|
62
|
-
const pageSize = args.maxResults;
|
|
63
|
-
const fetchMax = cursorOffset + pageSize;
|
|
64
102
|
const searchOptions = {
|
|
65
|
-
maxResults:
|
|
103
|
+
maxResults: MAX_SEARCH_RESULTS,
|
|
66
104
|
includeHidden: args.includeHidden,
|
|
67
105
|
sortBy: args.sortBy,
|
|
68
106
|
respectGitignore: !args.includeIgnored,
|
|
107
|
+
...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),
|
|
108
|
+
signal: ctx.signal,
|
|
69
109
|
};
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
root: basePath,
|
|
86
|
-
results: relativeResults,
|
|
110
|
+
const result = await searchFiles(basePath, args.pattern, excludePatterns, searchOptions, ctx.fs.pathGuard);
|
|
111
|
+
const relativeResults = buildRelativeResults(result.basePath, result.results);
|
|
112
|
+
// Store the full result set so a caller can fetch all matching files by URI
|
|
113
|
+
// when the response is incomplete: `nextCursor` covers the multi-page case,
|
|
114
|
+
// and `summary.truncated` covers a single page that already hit the hard result
|
|
115
|
+
// cap (no nextCursor, but more matches exist beyond the cap).
|
|
116
|
+
let resourceUri;
|
|
117
|
+
let link;
|
|
118
|
+
if (ctx.resourceStore !== undefined &&
|
|
119
|
+
(relativeResults.length > args.maxResults || result.summary.truncated)) {
|
|
120
|
+
const stored = putJsonResource(ctx.resourceStore, `${args.pattern} files`, relativeResults);
|
|
121
|
+
resourceUri = stored.entry.uri;
|
|
122
|
+
link = stored.link;
|
|
123
|
+
}
|
|
124
|
+
const metadata = {
|
|
125
|
+
root: result.basePath,
|
|
87
126
|
totalMatches: result.summary.matched,
|
|
88
127
|
filesScanned: result.summary.filesScanned,
|
|
128
|
+
...(result.summary.skippedInaccessible
|
|
129
|
+
? { skippedInaccessible: result.summary.skippedInaccessible }
|
|
130
|
+
: {}),
|
|
131
|
+
...(result.summary.stoppedReason !== undefined && result.summary.stoppedReason !== 'maxFiles'
|
|
132
|
+
? { stoppedReason: result.summary.stoppedReason }
|
|
133
|
+
: {}),
|
|
134
|
+
...(resourceUri ? { resourceUri } : {}),
|
|
89
135
|
};
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
summaryOptions.truncatedReason = truncatedReason;
|
|
97
|
-
const textLines = [];
|
|
98
|
-
if (relativeResults.length === 0) {
|
|
99
|
-
textLines.push('No matches');
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
textLines.push(`Found ${relativeResults.length}:`);
|
|
103
|
-
for (const entry of relativeResults) {
|
|
104
|
-
textLines.push(` ${entry.path}`);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
let text = joinLines(textLines) + formatOperationSummary(summaryOptions);
|
|
108
|
-
if (nextCursor) {
|
|
109
|
-
text += `\n[Next page available. Use cursor: "${nextCursor}"]`;
|
|
110
|
-
}
|
|
111
|
-
return buildToolResponse(text, structured);
|
|
112
|
-
}
|
|
113
|
-
export function registerSearchFilesTool(server, options = {}) {
|
|
114
|
-
const handler = (args, ctx) => executeToolWithDiagnostics({
|
|
115
|
-
toolName: 'find',
|
|
116
|
-
ctx,
|
|
117
|
-
outputSchema: SearchFilesOutputSchema,
|
|
118
|
-
timedSignal: { timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS },
|
|
119
|
-
context: { path: args.path ?? '.' },
|
|
120
|
-
run: async (signal) => {
|
|
121
|
-
const rawScopeLabel = args.path ? basename(args.path) : '.';
|
|
122
|
-
const scopeLabel = rawScopeLabel || '.';
|
|
123
|
-
const { pattern } = args;
|
|
124
|
-
const truncatedPattern = truncateProgressPattern(pattern);
|
|
125
|
-
const context = `${truncatedPattern} in ${scopeLabel}`;
|
|
126
|
-
let progressCursor = 0;
|
|
127
|
-
notifyProgress(ctx, {
|
|
128
|
-
current: 0,
|
|
129
|
-
message: `${SEARCH_FILES_TOOL.title}: ${truncatedPattern}`,
|
|
130
|
-
});
|
|
131
|
-
const baseReporter = createProgressReporter(ctx);
|
|
132
|
-
const progressWithMessage = ({ current, total, }) => {
|
|
133
|
-
if (current > progressCursor)
|
|
134
|
-
progressCursor = current;
|
|
135
|
-
baseReporter({
|
|
136
|
-
current,
|
|
137
|
-
...(total !== undefined ? { total } : {}),
|
|
138
|
-
message: `${SEARCH_FILES_TOOL.title}: ${truncatedPattern} [${current} files]`,
|
|
139
|
-
});
|
|
140
|
-
};
|
|
141
|
-
try {
|
|
142
|
-
const result = await handleSearchFiles(args, signal, progressWithMessage);
|
|
143
|
-
const sc = result.structuredContent;
|
|
144
|
-
const { totalMatches = 0, stoppedReason } = sc;
|
|
145
|
-
let suffix;
|
|
146
|
-
if (totalMatches === 0) {
|
|
147
|
-
suffix = 'No matches';
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
suffix = `${totalMatches} ${totalMatches === 1 ? 'match' : 'matches'}`;
|
|
151
|
-
if (stoppedReason === 'timeout') {
|
|
152
|
-
suffix += ' [timeout]';
|
|
153
|
-
}
|
|
154
|
-
else if (stoppedReason === 'maxResults') {
|
|
155
|
-
suffix += ' [max results]';
|
|
156
|
-
}
|
|
157
|
-
else if (stoppedReason === 'maxFiles') {
|
|
158
|
-
suffix += ' [max files]';
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
const finalCurrent = Math.max((sc.filesScanned ?? 0) + 1, progressCursor + 1);
|
|
162
|
-
notifyProgress(ctx, {
|
|
163
|
-
current: finalCurrent,
|
|
164
|
-
total: finalCurrent,
|
|
165
|
-
message: `${SEARCH_FILES_TOOL.title}: ${context} • ${suffix}`,
|
|
166
|
-
});
|
|
167
|
-
return result;
|
|
168
|
-
}
|
|
169
|
-
catch (error) {
|
|
170
|
-
const finalCurrent = Math.max(progressCursor + 1, 1);
|
|
171
|
-
notifyProgress(ctx, {
|
|
172
|
-
current: finalCurrent,
|
|
173
|
-
total: finalCurrent,
|
|
174
|
-
message: `${SEARCH_FILES_TOOL.title}: ${context} • ${classifyError(error)}`,
|
|
175
|
-
});
|
|
176
|
-
throw error;
|
|
177
|
-
}
|
|
178
|
-
},
|
|
179
|
-
onError: (error) => buildToolErrorResponse(error, ErrorCode.UNKNOWN, args.path),
|
|
136
|
+
const paged = createFirstPage({
|
|
137
|
+
store: ctx.pageStore,
|
|
138
|
+
queryKey,
|
|
139
|
+
items: relativeResults,
|
|
140
|
+
metadata,
|
|
141
|
+
pageSize: args.maxResults,
|
|
180
142
|
});
|
|
181
|
-
|
|
143
|
+
return {
|
|
144
|
+
structured: searchFilesOutput(paged.page, metadata, paged.nextCursor),
|
|
145
|
+
...(link !== undefined ? { link } : {}),
|
|
146
|
+
};
|
|
182
147
|
}
|
|
148
|
+
export const SEARCH_FILES = defineTool({
|
|
149
|
+
name: 'find_files',
|
|
150
|
+
title: 'Find Files',
|
|
151
|
+
description: 'Find files matching a glob pattern. Returns matched paths with optional metadata. ' +
|
|
152
|
+
'Pagination cursors reference a query-bound snapshot that expires after 60 seconds. ' +
|
|
153
|
+
'For content search use search_text; for bulk regex replacements use replace_text with the same glob.',
|
|
154
|
+
input: SearchFilesInputSchema,
|
|
155
|
+
output: SearchFilesOutputSchema,
|
|
156
|
+
annotations: {
|
|
157
|
+
readOnlyHint: true,
|
|
158
|
+
idempotentHint: true,
|
|
159
|
+
destructiveHint: false,
|
|
160
|
+
openWorldHint: false,
|
|
161
|
+
},
|
|
162
|
+
timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,
|
|
163
|
+
defaultErrorCode: ErrorCode.UNKNOWN,
|
|
164
|
+
progress: (args) => ({
|
|
165
|
+
label: 'Find',
|
|
166
|
+
subject: truncateProgressPattern(args.pattern),
|
|
167
|
+
}),
|
|
168
|
+
progressDone: (_args, result) => ({
|
|
169
|
+
detail: formatCount(result.totalMatches ?? 0, 'match', 'matches'),
|
|
170
|
+
}),
|
|
171
|
+
accessPaths: (args) => (args.path ? [args.path] : []),
|
|
172
|
+
run: async (args, ctx) => {
|
|
173
|
+
const { structured, link } = await handleSearchFiles(args, ctx);
|
|
174
|
+
const text = structured.results.length > 0
|
|
175
|
+
? structured.results.map((r) => r.path).join('\n')
|
|
176
|
+
: `No files matching '${args.pattern}'`;
|
|
177
|
+
if (link) {
|
|
178
|
+
return { structured, text, resources: [link] };
|
|
179
|
+
}
|
|
180
|
+
return { structured, text };
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
//# sourceMappingURL=search-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-files.js","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"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","sourcesContent":["import * as z from 'zod/v4';\n\nimport { SearchStoppedReasonSchema } from '../core/concurrency.js';\nimport { createFirstPage, readNextPage } from '../core/cursor.js';\nimport { ErrorCode } from '../core/errors.js';\nimport { formatCount, truncateProgressPattern } from '../core/fmt.js';\nimport { DEFAULT_EXCLUDE_PATTERNS } from '../core/glob.js';\nimport { toPosixRelative } from '../core/path.js';\nimport {\n CursorSchema,\n includeHiddenField,\n includeIgnoredField,\n maxDepthField,\n NextCursorSchema,\n NonNegInt,\n OptionalPath,\n SafeGlobPattern,\n} from '../core/schema.js';\nimport { searchFiles } from '../core/search.js';\nimport { putJsonResource } from '../core/store.js';\nimport {\n DEFAULT_SEARCH_RESULTS,\n DEFAULT_SEARCH_TIMEOUT_MS,\n MAX_SEARCH_RESULTS,\n} from '../core/util.js';\nimport { defineTool, type ToolCtx } from './define.js';\n\n// ---------------------------------------------------------------------------\n\nconst SearchFilesInputSchema = z.strictObject({\n path: OptionalPath.describe('Base directory to search under (default: first allowed root)'),\n pattern: SafeGlobPattern.describe('Glob pattern to match file paths (e.g. **/*.ts, src/**/*.js)'),\n maxResults: z\n .uint32()\n .min(1)\n .max(MAX_SEARCH_RESULTS)\n .optional()\n .default(DEFAULT_SEARCH_RESULTS)\n .describe('Maximum number of matching files to return per page'),\n includeIgnored: includeIgnoredField(),\n includeHidden: includeHiddenField(),\n sortBy: z\n .enum(['name', 'path'])\n .optional()\n .default('path')\n .describe('Sort order: path = full path (default), name = basename only'),\n maxDepth: maxDepthField(),\n cursor: CursorSchema,\n});\n\nconst SearchFilesOutputSchema = z.strictObject({\n root: z.string().describe('Resolved base directory used as the search root'),\n results: z\n .array(\n z.strictObject({\n path: z.string().describe('File path relative to the search root'),\n }),\n )\n .describe('Matched files ordered by sortBy'),\n totalMatches: NonNegInt.optional().describe('Total number of matching files found'),\n filesScanned: NonNegInt.optional().describe('Total number of files examined during the search'),\n skippedInaccessible: NonNegInt.optional().describe(\n 'Files skipped due to permission or access errors',\n ),\n stoppedReason: SearchStoppedReasonSchema.describe(\n 'Why the search ended early: maxResults = result cap reached, timeout = time limit hit or the request was cancelled. Absent when the scan ran to completion.',\n ),\n resourceUri: z\n .string()\n .optional()\n .describe(\n 'URI to the full results JSON in the resource store; first page only, when results are paginated',\n ),\n nextCursor: NextCursorSchema,\n});\n\nfunction buildRelativeResults(\n basePath: string,\n displayResults: readonly { path: string }[],\n): NonNullable<z.infer<typeof SearchFilesOutputSchema>['results']> {\n const relativeResults: NonNullable<z.infer<typeof SearchFilesOutputSchema>['results']> = [];\n for (const entry of displayResults) {\n relativeResults.push({\n path: toPosixRelative(basePath, entry.path),\n });\n }\n return relativeResults;\n}\n\ntype SearchFileResult = NonNullable<z.infer<typeof SearchFilesOutputSchema>['results']>[number];\n\ninterface SearchFilesPageMetadata {\n readonly root: string;\n readonly totalMatches: number;\n readonly filesScanned: number;\n readonly skippedInaccessible?: number;\n readonly stoppedReason?: z.infer<typeof SearchFilesOutputSchema>['stoppedReason'];\n readonly resourceUri?: string;\n}\n\nfunction searchFilesQueryKey(\n args: z.infer<typeof SearchFilesInputSchema>,\n basePath: string,\n): string {\n return JSON.stringify({\n method: 'find_files',\n path: basePath,\n pattern: args.pattern,\n includeIgnored: args.includeIgnored,\n includeHidden: args.includeHidden,\n sortBy: args.sortBy,\n maxDepth: args.maxDepth,\n });\n}\n\nfunction searchFilesOutput(\n results: readonly SearchFileResult[],\n metadata: SearchFilesPageMetadata,\n nextCursor: string | undefined,\n): z.infer<typeof SearchFilesOutputSchema> {\n return {\n root: metadata.root,\n results: [...results],\n totalMatches: metadata.totalMatches,\n filesScanned: metadata.filesScanned,\n ...(metadata.skippedInaccessible ? { skippedInaccessible: metadata.skippedInaccessible } : {}),\n ...(metadata.stoppedReason !== undefined ? { stoppedReason: metadata.stoppedReason } : {}),\n ...(metadata.resourceUri ? { resourceUri: metadata.resourceUri } : {}),\n ...(nextCursor !== undefined ? { nextCursor } : {}),\n };\n}\n\nasync function handleSearchFiles(\n args: z.infer<typeof SearchFilesInputSchema>,\n ctx: ToolCtx,\n): Promise<{\n structured: z.infer<typeof SearchFilesOutputSchema>;\n link?: ReturnType<typeof putJsonResource>['link'];\n}> {\n const requestedBasePath = ctx.fs.pathGuard.resolvePathOrRoot(args.path);\n const queryKey = searchFilesQueryKey(args, requestedBasePath);\n if (args.cursor !== undefined) {\n const paged = readNextPage<SearchFileResult, SearchFilesPageMetadata>({\n store: ctx.pageStore,\n queryKey,\n cursor: args.cursor,\n pageSize: args.maxResults,\n });\n // First page only — see the same note in list.ts: the overflow entry expires\n // on ResourceStore's clock, not this snapshot's.\n const { resourceUri: _firstPageOnly, ...pageMetadata } = paged.metadata;\n return {\n structured: searchFilesOutput(paged.page, pageMetadata, paged.nextCursor),\n };\n }\n\n const basePath = await ctx.fs.pathGuard.validateExistingDirectory(requestedBasePath);\n const excludePatterns = args.includeIgnored ? [] : DEFAULT_EXCLUDE_PATTERNS;\n const searchOptions: Parameters<typeof searchFiles>[3] = {\n maxResults: MAX_SEARCH_RESULTS,\n includeHidden: args.includeHidden,\n sortBy: args.sortBy,\n respectGitignore: !args.includeIgnored,\n ...(args.maxDepth !== undefined ? { maxDepth: args.maxDepth } : {}),\n signal: ctx.signal,\n };\n const result = await searchFiles(\n basePath,\n args.pattern,\n excludePatterns,\n searchOptions,\n ctx.fs.pathGuard,\n );\n const relativeResults = buildRelativeResults(result.basePath, result.results);\n\n // Store the full result set so a caller can fetch all matching files by URI\n // when the response is incomplete: `nextCursor` covers the multi-page case,\n // and `summary.truncated` covers a single page that already hit the hard result\n // cap (no nextCursor, but more matches exist beyond the cap).\n let resourceUri: string | undefined;\n let link: ReturnType<typeof putJsonResource>['link'] | undefined;\n if (\n ctx.resourceStore !== undefined &&\n (relativeResults.length > args.maxResults || result.summary.truncated)\n ) {\n const stored = putJsonResource(ctx.resourceStore, `${args.pattern} files`, relativeResults);\n resourceUri = stored.entry.uri;\n link = stored.link;\n }\n\n const metadata: SearchFilesPageMetadata = {\n root: result.basePath,\n totalMatches: result.summary.matched,\n filesScanned: result.summary.filesScanned,\n ...(result.summary.skippedInaccessible\n ? { skippedInaccessible: result.summary.skippedInaccessible }\n : {}),\n ...(result.summary.stoppedReason !== undefined && result.summary.stoppedReason !== 'maxFiles'\n ? { stoppedReason: result.summary.stoppedReason }\n : {}),\n ...(resourceUri ? { resourceUri } : {}),\n };\n const paged = createFirstPage<SearchFileResult, SearchFilesPageMetadata>({\n store: ctx.pageStore,\n queryKey,\n items: relativeResults,\n metadata,\n pageSize: args.maxResults,\n });\n return {\n structured: searchFilesOutput(paged.page, metadata, paged.nextCursor),\n ...(link !== undefined ? { link } : {}),\n };\n}\n\nexport const SEARCH_FILES = defineTool({\n name: 'find_files',\n title: 'Find Files',\n description:\n 'Find files matching a glob pattern. Returns matched paths with optional metadata. ' +\n 'Pagination cursors reference a query-bound snapshot that expires after 60 seconds. ' +\n 'For content search use search_text; for bulk regex replacements use replace_text with the same glob.',\n input: SearchFilesInputSchema,\n output: SearchFilesOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: false,\n },\n timeoutMs: DEFAULT_SEARCH_TIMEOUT_MS,\n defaultErrorCode: ErrorCode.UNKNOWN,\n progress: (args) => ({\n label: 'Find',\n subject: truncateProgressPattern(args.pattern),\n }),\n progressDone: (_args, result) => ({\n detail: formatCount(result.totalMatches ?? 0, 'match', 'matches'),\n }),\n accessPaths: (args) => (args.path ? [args.path] : []),\n run: async (args, ctx) => {\n const { structured, link } = await handleSearchFiles(args, ctx);\n const text =\n structured.results.length > 0\n ? structured.results.map((r) => r.path).join('\\n')\n : `No files matching '${args.pattern}'`;\n if (link) {\n return { structured, text, resources: [link] };\n }\n return { structured, text };\n },\n});\n"]}
|
package/dist/tools/stat.d.ts
CHANGED
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export declare const GET_FILE_INFO_TOOL: ToolContract;
|
|
4
|
-
export declare function registerGetFileInfoTool(server: McpServer, options?: ToolRegistrationOptions): void;
|
|
1
|
+
export declare const GET_FILE_INFO: import("./define.js").DefinedTool;
|
|
2
|
+
//# sourceMappingURL=stat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stat.d.ts","sourceRoot":"","sources":["../../src/tools/stat.ts"],"names":[],"mappings":"AAgMA,eAAO,MAAM,aAAa,mCAkFxB,CAAC"}
|