@j0hanz/filesystem-mcp 1.7.3 → 1.9.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 +635 -377
- package/dist/cli.js +2 -2
- package/dist/completions.js +2 -3
- package/dist/index.js +2 -2
- package/dist/lib/file-operations/{common.d.ts → core.d.ts} +6 -0
- package/dist/lib/file-operations/{common.js → core.js} +45 -0
- package/dist/lib/file-operations/metadata.d.ts +73 -0
- package/dist/lib/file-operations/metadata.js +889 -0
- package/dist/lib/file-operations/{search-content.d.ts → search.d.ts} +29 -3
- package/dist/lib/file-operations/{search-content.js → search.js} +409 -82
- package/dist/lib/file-operations/{glob-engine.d.ts → traversal.d.ts} +18 -1
- package/dist/lib/file-operations/{glob-engine.js → traversal.js} +25 -2
- package/dist/lib/fs-helpers.d.ts +1 -0
- package/dist/lib/fs-helpers.js +10 -2
- package/dist/lib/observability.js +1 -1
- package/dist/lib/{path-validation.d.ts → paths.d.ts} +4 -0
- package/dist/lib/{path-validation.js → paths.js} +112 -1
- package/dist/lib/utils.d.ts +15 -0
- package/dist/lib/utils.js +33 -0
- package/dist/resources/generated-instructions.js +6 -6
- package/dist/resources/tool-catalog.js +9 -9
- package/dist/resources/tool-info.js +3 -3
- package/dist/resources/workflows.js +10 -23
- package/dist/schemas.js +15 -15
- package/dist/server/bootstrap.d.ts +19 -1
- package/dist/server/bootstrap.js +103 -9
- package/dist/server/roots-manager.d.ts +2 -2
- package/dist/server/roots-manager.js +3 -3
- package/dist/tools/apply-patch.js +7 -3
- package/dist/tools/calculate-hash.js +15 -15
- package/dist/tools/create-directory.js +1 -1
- package/dist/tools/delete-file.js +7 -4
- package/dist/tools/diff-files.js +2 -2
- package/dist/tools/edit-file.js +14 -13
- package/dist/tools/list-directory.js +5 -7
- package/dist/tools/move-file.js +2 -1
- package/dist/tools/read-multiple.js +13 -26
- package/dist/tools/read.js +3 -3
- package/dist/tools/replace-in-files.js +17 -20
- package/dist/tools/roots.js +4 -6
- package/dist/tools/search-content.js +9 -11
- package/dist/tools/search-files.js +4 -6
- package/dist/tools/shared.d.ts +18 -1
- package/dist/tools/shared.js +39 -19
- package/dist/tools/stat-many.js +14 -24
- package/dist/tools/stat.js +4 -3
- package/dist/tools/task-support.js +1 -1
- package/dist/tools/tree.js +3 -4
- package/dist/tools/write-file.js +1 -1
- package/package.json +9 -5
- package/dist/lib/file-operations/file-info.d.ts +0 -10
- package/dist/lib/file-operations/file-info.js +0 -143
- package/dist/lib/file-operations/gitignore.d.ts +0 -6
- package/dist/lib/file-operations/gitignore.js +0 -45
- package/dist/lib/file-operations/list-directory.d.ts +0 -14
- package/dist/lib/file-operations/list-directory.js +0 -256
- package/dist/lib/file-operations/read-multiple-files.d.ts +0 -25
- package/dist/lib/file-operations/read-multiple-files.js +0 -252
- package/dist/lib/file-operations/search-files.d.ts +0 -27
- package/dist/lib/file-operations/search-files.js +0 -218
- package/dist/lib/file-operations/search-worker.d.ts +0 -2
- package/dist/lib/file-operations/search-worker.js +0 -129
- package/dist/lib/file-operations/tree.d.ts +0 -28
- package/dist/lib/file-operations/tree.js +0 -269
- package/dist/lib/path-format.d.ts +0 -1
- package/dist/lib/path-format.js +0 -7
- package/dist/lib/path-policy.d.ts +0 -2
- package/dist/lib/path-policy.js +0 -100
- package/dist/lib/type-guards.d.ts +0 -1
- package/dist/lib/type-guards.js +0 -3
- package/dist/server/capabilities.d.ts +0 -10
- package/dist/server/capabilities.js +0 -48
- package/dist/server/logging.d.ts +0 -7
- package/dist/server/logging.js +0 -41
- package/dist/server/types.d.ts +0 -4
- package/dist/server/types.js +0 -1
package/dist/lib/path-policy.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import * as path from 'node:path';
|
|
2
|
-
import { platform } from 'node:os';
|
|
3
|
-
import { SENSITIVE_FILE_ALLOWLIST, SENSITIVE_FILE_DENYLIST, } from './constants.js';
|
|
4
|
-
import { ErrorCode, McpError } from './errors.js';
|
|
5
|
-
import { toPosixPath } from './path-format.js';
|
|
6
|
-
const IS_WINDOWS = platform() === 'win32';
|
|
7
|
-
const WINDOWS_ABSOLUTE_RE = /^[a-z]:\//iu;
|
|
8
|
-
function normalizePathForMatch(input) {
|
|
9
|
-
return toPosixPath(path.normalize(input));
|
|
10
|
-
}
|
|
11
|
-
function normalizeForMatch(input) {
|
|
12
|
-
const normalized = normalizePathForMatch(input);
|
|
13
|
-
return IS_WINDOWS ? normalized.toLowerCase() : normalized;
|
|
14
|
-
}
|
|
15
|
-
function compilePatternGlobs(normalizedPattern) {
|
|
16
|
-
const globs = new Set([normalizedPattern]);
|
|
17
|
-
const isWindowsAbsolute = WINDOWS_ABSOLUTE_RE.test(normalizedPattern);
|
|
18
|
-
if (!normalizedPattern.startsWith('**/') && !isWindowsAbsolute) {
|
|
19
|
-
const withoutRoot = normalizedPattern.replace(/^\/+/u, '');
|
|
20
|
-
if (withoutRoot.length > 0) {
|
|
21
|
-
globs.add(`**/${withoutRoot}`);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return [...globs];
|
|
25
|
-
}
|
|
26
|
-
function compilePatterns(patterns) {
|
|
27
|
-
const unique = new Set();
|
|
28
|
-
for (const pattern of patterns) {
|
|
29
|
-
const trimmed = pattern.trim();
|
|
30
|
-
if (trimmed.length > 0) {
|
|
31
|
-
unique.add(trimmed);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
const compiled = [];
|
|
35
|
-
for (const pattern of unique) {
|
|
36
|
-
const normalized = normalizeForMatch(pattern);
|
|
37
|
-
const matchesPath = normalized.includes('/');
|
|
38
|
-
compiled.push({
|
|
39
|
-
globs: matchesPath ? compilePatternGlobs(normalized) : [normalized],
|
|
40
|
-
matchesPath,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
return compiled;
|
|
44
|
-
}
|
|
45
|
-
function toPatternSet(patterns) {
|
|
46
|
-
const pathGlobs = new Set();
|
|
47
|
-
const nameGlobs = new Set();
|
|
48
|
-
for (const pattern of patterns) {
|
|
49
|
-
const target = pattern.matchesPath ? pathGlobs : nameGlobs;
|
|
50
|
-
for (const glob of pattern.globs) {
|
|
51
|
-
target.add(glob);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return {
|
|
55
|
-
pathGlobs: [...pathGlobs],
|
|
56
|
-
nameGlobs: [...nameGlobs],
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
const DENY_PATTERNS = toPatternSet(compilePatterns(SENSITIVE_FILE_DENYLIST));
|
|
60
|
-
const ALLOW_PATTERNS = toPatternSet(compilePatterns(SENSITIVE_FILE_ALLOWLIST));
|
|
61
|
-
function uniquePair(primary, secondary) {
|
|
62
|
-
if (!secondary || secondary === primary)
|
|
63
|
-
return [primary];
|
|
64
|
-
return [primary, secondary];
|
|
65
|
-
}
|
|
66
|
-
function matchesAnyGlobs(globs, candidates) {
|
|
67
|
-
if (globs.length === 0 || candidates.length === 0)
|
|
68
|
-
return false;
|
|
69
|
-
for (const candidate of candidates) {
|
|
70
|
-
for (const glob of globs) {
|
|
71
|
-
if (path.posix.matchesGlob(candidate, glob))
|
|
72
|
-
return true;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return false;
|
|
76
|
-
}
|
|
77
|
-
export function isSensitivePath(requestedPath, resolvedPath) {
|
|
78
|
-
if (DENY_PATTERNS.pathGlobs.length === 0 &&
|
|
79
|
-
DENY_PATTERNS.nameGlobs.length === 0) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
const normalizedRequested = normalizeForMatch(requestedPath);
|
|
83
|
-
const normalizedResolved = resolvedPath
|
|
84
|
-
? normalizeForMatch(resolvedPath)
|
|
85
|
-
: undefined;
|
|
86
|
-
const pathCandidates = uniquePair(normalizedRequested, normalizedResolved);
|
|
87
|
-
const nameCandidates = uniquePair(path.posix.basename(normalizedRequested), normalizedResolved ? path.posix.basename(normalizedResolved) : undefined);
|
|
88
|
-
if (matchesAnyGlobs(ALLOW_PATTERNS.pathGlobs, pathCandidates) ||
|
|
89
|
-
matchesAnyGlobs(ALLOW_PATTERNS.nameGlobs, nameCandidates)) {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
return (matchesAnyGlobs(DENY_PATTERNS.pathGlobs, pathCandidates) ||
|
|
93
|
-
matchesAnyGlobs(DENY_PATTERNS.nameGlobs, nameCandidates));
|
|
94
|
-
}
|
|
95
|
-
export function assertAllowedFileAccess(requestedPath, resolvedPath) {
|
|
96
|
-
if (!isSensitivePath(requestedPath, resolvedPath))
|
|
97
|
-
return;
|
|
98
|
-
throw new McpError(ErrorCode.E_ACCESS_DENIED, `Access denied: sensitive file blocked by policy (${requestedPath}). ` +
|
|
99
|
-
'Set FS_CONTEXT_ALLOW_SENSITIVE=1 or use FS_CONTEXT_ALLOWLIST to override.', requestedPath);
|
|
100
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
package/dist/lib/type-guards.js
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
interface CapabilityOptions {
|
|
3
|
-
enablePromptListChanged?: boolean;
|
|
4
|
-
enableTaskToolRequests?: boolean;
|
|
5
|
-
}
|
|
6
|
-
type ServerCapabilities = NonNullable<ConstructorParameters<typeof McpServer>[1]>['capabilities'];
|
|
7
|
-
type NonOptionalServerCapabilities = NonNullable<ServerCapabilities>;
|
|
8
|
-
export declare function buildServerCapabilities(options?: CapabilityOptions): NonOptionalServerCapabilities;
|
|
9
|
-
export declare function supportsTaskToolRequests(): boolean;
|
|
10
|
-
export {};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
let cachedTaskToolSupport;
|
|
3
|
-
function detectTaskToolSupport() {
|
|
4
|
-
if (cachedTaskToolSupport !== undefined) {
|
|
5
|
-
return cachedTaskToolSupport;
|
|
6
|
-
}
|
|
7
|
-
try {
|
|
8
|
-
// Instantiate a minimal, unconnected probe server to duck-type check for
|
|
9
|
-
// task tool support. The probe has no transport or active connections, so
|
|
10
|
-
// close() only releases in-memory state; fire-and-forget is safe here.
|
|
11
|
-
const probe = new McpServer({
|
|
12
|
-
name: 'filesystem-mcp-capability-probe',
|
|
13
|
-
version: '0.0.0',
|
|
14
|
-
}, { capabilities: { tools: {} } });
|
|
15
|
-
cachedTaskToolSupport =
|
|
16
|
-
typeof probe.experimental.tasks.registerToolTask === 'function';
|
|
17
|
-
probe.close().catch(() => { });
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
cachedTaskToolSupport = false;
|
|
21
|
-
}
|
|
22
|
-
return cachedTaskToolSupport;
|
|
23
|
-
}
|
|
24
|
-
export function buildServerCapabilities(options = {}) {
|
|
25
|
-
const capabilities = {
|
|
26
|
-
logging: {},
|
|
27
|
-
resources: {},
|
|
28
|
-
tools: {},
|
|
29
|
-
prompts: options.enablePromptListChanged ? { listChanged: true } : {},
|
|
30
|
-
completions: {},
|
|
31
|
-
};
|
|
32
|
-
if (options.enableTaskToolRequests) {
|
|
33
|
-
// NOTE: enabling task tool requests requires the caller to configure
|
|
34
|
-
// an InMemoryTaskStore and InMemoryTaskMessageQueue on the McpServer.
|
|
35
|
-
// InMemoryTaskStore accumulates completed task records with no TTL eviction —
|
|
36
|
-
// suitable for short-lived stdio sessions. Long-running HTTP servers should
|
|
37
|
-
// replace it with a TTL-evicting store to avoid unbounded memory growth.
|
|
38
|
-
capabilities.tasks = {
|
|
39
|
-
list: {},
|
|
40
|
-
cancel: {},
|
|
41
|
-
requests: { tools: { call: {} } },
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
return capabilities;
|
|
45
|
-
}
|
|
46
|
-
export function supportsTaskToolRequests() {
|
|
47
|
-
return detectTaskToolSupport();
|
|
48
|
-
}
|
package/dist/server/logging.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import type { LoggingLevel } from '@modelcontextprotocol/sdk/types.js';
|
|
3
|
-
export interface LoggingState {
|
|
4
|
-
minimumLevel: LoggingLevel;
|
|
5
|
-
}
|
|
6
|
-
export declare function createLoggingState(minimumLevel?: LoggingLevel): LoggingState;
|
|
7
|
-
export declare function logToMcp(server: McpServer | undefined, level: LoggingLevel, data: string, minLevel?: LoggingLevel): void;
|
package/dist/server/logging.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { formatUnknownErrorMessage } from '../lib/errors.js';
|
|
2
|
-
import { isRecord } from '../lib/type-guards.js';
|
|
3
|
-
const MCP_LOGGER_NAME = 'filesystem-mcp';
|
|
4
|
-
const LOG_LEVEL_ORDER = {
|
|
5
|
-
debug: 0,
|
|
6
|
-
info: 1,
|
|
7
|
-
notice: 2,
|
|
8
|
-
warning: 3,
|
|
9
|
-
error: 4,
|
|
10
|
-
critical: 5,
|
|
11
|
-
alert: 6,
|
|
12
|
-
emergency: 7,
|
|
13
|
-
};
|
|
14
|
-
export function createLoggingState(minimumLevel = 'debug') {
|
|
15
|
-
return { minimumLevel };
|
|
16
|
-
}
|
|
17
|
-
function canSendMcpLogs(server) {
|
|
18
|
-
const capabilities = server.server.getClientCapabilities();
|
|
19
|
-
if (!isRecord(capabilities))
|
|
20
|
-
return false;
|
|
21
|
-
if (!('logging' in capabilities))
|
|
22
|
-
return false;
|
|
23
|
-
return !!capabilities['logging'];
|
|
24
|
-
}
|
|
25
|
-
export function logToMcp(server, level, data, minLevel = 'debug') {
|
|
26
|
-
if (LOG_LEVEL_ORDER[level] < LOG_LEVEL_ORDER[minLevel]) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
if (!server || !canSendMcpLogs(server)) {
|
|
30
|
-
console.error(data);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
const params = {
|
|
34
|
-
level,
|
|
35
|
-
logger: MCP_LOGGER_NAME,
|
|
36
|
-
data,
|
|
37
|
-
};
|
|
38
|
-
void server.sendLoggingMessage(params).catch((error) => {
|
|
39
|
-
console.error(`Failed to send MCP log: ${level} | ${data}`, formatUnknownErrorMessage(error));
|
|
40
|
-
});
|
|
41
|
-
}
|
package/dist/server/types.d.ts
DELETED
package/dist/server/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|