@j0hanz/filesystem-mcp 1.4.0 → 1.5.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/dist/config.d.ts +2 -1
- package/dist/lib/constants.d.ts +0 -3
- package/dist/lib/observability.d.ts +1 -1
- package/dist/resources/generated-instructions.js +14 -30
- package/dist/resources/tool-catalog.d.ts +2 -0
- package/dist/resources/tool-catalog.js +29 -0
- package/dist/resources/tool-info.d.ts +4 -0
- package/dist/resources/tool-info.js +44 -0
- package/dist/resources/workflows.d.ts +1 -0
- package/dist/resources/workflows.js +36 -0
- package/dist/resources.d.ts +2 -0
- package/dist/resources.js +46 -0
- package/dist/server/bootstrap.js +3 -1
- package/dist/server/capabilities.d.ts +1 -1
- package/dist/server.d.ts +0 -1
- package/dist/tools/shared.d.ts +0 -1
- package/dist/tools/shared.js +1 -1
- package/dist/tools/task-support.d.ts +0 -6
- package/dist/tools/task-support.js +1 -1
- package/package.json +1 -1
package/dist/config.d.ts
CHANGED
|
@@ -112,8 +112,9 @@ export declare const ErrorCode: {
|
|
|
112
112
|
export type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
113
113
|
export declare function formatBytes(bytes: number): string;
|
|
114
114
|
export declare function joinLines(lines: readonly string[]): string;
|
|
115
|
-
|
|
115
|
+
interface OperationSummary {
|
|
116
116
|
truncated?: boolean;
|
|
117
117
|
truncatedReason?: string;
|
|
118
118
|
}
|
|
119
119
|
export declare function formatOperationSummary(summary: OperationSummary): string;
|
|
120
|
+
export {};
|
package/dist/lib/constants.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
declare const VALID_LOG_LEVELS: readonly ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"];
|
|
2
|
-
export type ValidLogLevel = (typeof VALID_LOG_LEVELS)[number];
|
|
3
1
|
export declare const DEFAULT_LOG_LEVEL: "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency";
|
|
4
2
|
export declare const PARALLEL_CONCURRENCY: number;
|
|
5
3
|
export declare const MAX_SEARCHABLE_FILE_SIZE: number;
|
|
@@ -22,4 +20,3 @@ export declare const SENSITIVE_FILE_ALLOWLIST: string[];
|
|
|
22
20
|
export declare const KNOWN_BINARY_EXTENSIONS: Set<string>;
|
|
23
21
|
export declare const DEFAULT_EXCLUDE_PATTERNS: string[];
|
|
24
22
|
export declare function getMimeType(ext: string): string;
|
|
25
|
-
export {};
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { buildToolCatalogDetailsOnly } from './tool-catalog.js';
|
|
2
|
+
import { buildCoreContextPack, getSharedConstraints, getToolContracts, } from './tool-info.js';
|
|
3
|
+
import { buildWorkflowGuide } from './workflows.js';
|
|
2
4
|
const INSTRUCTIONS_HEADER = `# FILESYSTEM-MCP INSTRUCTIONS
|
|
3
5
|
|
|
4
6
|
> Resource: \`internal://instructions\` | Prompt: \`get-help\`
|
|
@@ -24,39 +26,15 @@ const INSTRUCTIONS_HEADER = `# FILESYSTEM-MCP INSTRUCTIONS
|
|
|
24
26
|
|
|
25
27
|
## GOLDEN PATH WORKFLOWS
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
1. \`roots\` (List allowed paths).
|
|
29
|
-
2. \`ls\` (files) | \`tree\` (structure).
|
|
30
|
-
3. \`stat\` | \`stat_many\` (size/type check).
|
|
31
|
-
4. \`read\` | \`read_many\` (content).
|
|
32
|
-
> **Strict:** Never guess paths. Resolve first.
|
|
29
|
+
See "Workflow Reference" below for detailed execution sequences.
|
|
33
30
|
|
|
34
|
-
### B: SEARCH
|
|
35
|
-
1. \`find\` (glob candidates).
|
|
36
|
-
2. \`grep\` (content search).
|
|
37
|
-
3. \`read\` (verify context).
|
|
38
|
-
> **Tip:** Content search requires \`grep\`, not \`find\`.
|
|
39
|
-
|
|
40
|
-
### C: EDIT
|
|
41
|
-
1. \`edit\` (precise string match).
|
|
42
|
-
2. \`search_and_replace\` (bulk regex/glob).
|
|
43
|
-
3. \`mv\` | \`rm\` (file layout).
|
|
44
|
-
4. \`mkdir\` (create dirs).
|
|
45
|
-
> **Strict:** Confirm destructive ops (\`write\`, \`mv\`, \`rm\`, bulk replace).
|
|
46
|
-
|
|
47
|
-
### D: PATCH
|
|
48
|
-
1. \`diff_files\` (generate).
|
|
49
|
-
2. \`apply_patch\` (dryRun: true).
|
|
50
|
-
3. \`apply_patch\` (dryRun: false).
|
|
51
|
-
> **Tip:** Use \`diff_files\` output directly.
|
|
52
31
|
`;
|
|
53
32
|
const INSTRUCTIONS_FOOTER = `
|
|
54
33
|
## CONSTRAINTS
|
|
55
34
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- **Cache:** Externalized results are ephemeral (in-memory).
|
|
35
|
+
${getSharedConstraints()
|
|
36
|
+
.map((c) => `- ${c}`)
|
|
37
|
+
.join('\n')}
|
|
60
38
|
|
|
61
39
|
## ERROR HANDLING
|
|
62
40
|
|
|
@@ -87,13 +65,19 @@ function formatToolSection(tool) {
|
|
|
87
65
|
return parts.join('\n');
|
|
88
66
|
}
|
|
89
67
|
export function buildServerInstructions() {
|
|
90
|
-
const toolSections =
|
|
68
|
+
const toolSections = getToolContracts().map(formatToolSection).join('\n\n');
|
|
91
69
|
return [
|
|
92
70
|
INSTRUCTIONS_HEADER,
|
|
71
|
+
buildCoreContextPack(),
|
|
72
|
+
'',
|
|
73
|
+
buildToolCatalogDetailsOnly(),
|
|
74
|
+
'',
|
|
93
75
|
'## TOOL REFERENCE',
|
|
94
76
|
'',
|
|
95
77
|
toolSections,
|
|
96
78
|
'',
|
|
79
|
+
buildWorkflowGuide(),
|
|
80
|
+
'',
|
|
97
81
|
'---',
|
|
98
82
|
INSTRUCTIONS_FOOTER,
|
|
99
83
|
].join('\n');
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { buildCoreContextPack } from './tool-info.js';
|
|
2
|
+
const CATALOG_GUIDE = `## Tool Catalog Details
|
|
3
|
+
|
|
4
|
+
## Cross-Tool Data Flow
|
|
5
|
+
|
|
6
|
+
\`\`\`
|
|
7
|
+
find -> output_paths -> grep.paths
|
|
8
|
+
diff_files -> output_patch -> apply_patch.patch
|
|
9
|
+
\`\`\`
|
|
10
|
+
|
|
11
|
+
## Search Strategy Strategy
|
|
12
|
+
|
|
13
|
+
- Use \`find\` for glob-based file discovery.
|
|
14
|
+
- Use \`grep\` for content-based searches.
|
|
15
|
+
- Use \`search_and_replace\` ONLY for bulk replacements, not for discovery.
|
|
16
|
+
|
|
17
|
+
## Patch Management
|
|
18
|
+
|
|
19
|
+
- Always generate a patch with \`diff_files\` first.
|
|
20
|
+
- Always use \`dryRun: true\` with \`apply_patch\` to verify changes.
|
|
21
|
+
- \`apply_patch\` works on unified diff format.
|
|
22
|
+
`;
|
|
23
|
+
export function buildToolCatalog() {
|
|
24
|
+
// Return combined view for standalone resource usage
|
|
25
|
+
return `${buildCoreContextPack()}\n\n${CATALOG_GUIDE}`;
|
|
26
|
+
}
|
|
27
|
+
export function buildToolCatalogDetailsOnly() {
|
|
28
|
+
return CATALOG_GUIDE;
|
|
29
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ALL_TOOLS } from '../tools.js';
|
|
2
|
+
function toEntry(contract) {
|
|
3
|
+
const annotations = [];
|
|
4
|
+
if (contract.annotations?.destructiveHint)
|
|
5
|
+
annotations.push('[Destructive]');
|
|
6
|
+
if (contract.annotations?.idempotentHint)
|
|
7
|
+
annotations.push('[Idempotent]');
|
|
8
|
+
if (contract.annotations?.readOnlyHint)
|
|
9
|
+
annotations.push('[Read-Only]');
|
|
10
|
+
return {
|
|
11
|
+
name: contract.name,
|
|
12
|
+
description: contract.description,
|
|
13
|
+
...(annotations.length > 0 ? { annotations } : {}),
|
|
14
|
+
...(contract.nuances && contract.nuances.length > 0
|
|
15
|
+
? { nuances: contract.nuances }
|
|
16
|
+
: {}),
|
|
17
|
+
...(contract.gotchas && contract.gotchas.length > 0
|
|
18
|
+
? { gotchas: contract.gotchas }
|
|
19
|
+
: {}),
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
const ENTRIES = Object.fromEntries(ALL_TOOLS.map((contract) => [contract.name, toEntry(contract)]));
|
|
23
|
+
export function getToolContracts() {
|
|
24
|
+
return ALL_TOOLS;
|
|
25
|
+
}
|
|
26
|
+
export function buildCoreContextPack() {
|
|
27
|
+
const names = Object.keys(ENTRIES).sort((a, b) => a.localeCompare(b));
|
|
28
|
+
const rows = names.map((name) => {
|
|
29
|
+
const e = ENTRIES[name];
|
|
30
|
+
if (!e)
|
|
31
|
+
return '';
|
|
32
|
+
const annotations = e.annotations ? ` ${e.annotations.join(' ')}` : '';
|
|
33
|
+
return `| \`${e.name}\` | ${e.description}${annotations} |`;
|
|
34
|
+
});
|
|
35
|
+
return `## Core Context Pack\n\n| Tool | Purpose |\n|------|---------|\n${rows.join('\n')}`;
|
|
36
|
+
}
|
|
37
|
+
export function getSharedConstraints() {
|
|
38
|
+
return [
|
|
39
|
+
'Allowed roots only (negotiated via CLI).',
|
|
40
|
+
'Sensitive files denylisted by default.',
|
|
41
|
+
'Max file size & search results enforced.',
|
|
42
|
+
'Externalized results are ephemeral (in-memory).',
|
|
43
|
+
];
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function buildWorkflowGuide(): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getSharedConstraints } from './tool-info.js';
|
|
2
|
+
export function buildWorkflowGuide() {
|
|
3
|
+
return `## Workflow Reference
|
|
4
|
+
|
|
5
|
+
### A: EXPLORE
|
|
6
|
+
1. \`roots\` (List allowed paths).
|
|
7
|
+
2. \`ls\` (files) | \`tree\` (structure).
|
|
8
|
+
3. \`stat\` | \`stat_many\` (size/type check).
|
|
9
|
+
4. \`read\` | \`read_many\` (content).
|
|
10
|
+
> **Strict:** Never guess paths. Resolve first.
|
|
11
|
+
|
|
12
|
+
### B: SEARCH
|
|
13
|
+
1. \`find\` (glob candidates).
|
|
14
|
+
2. \`grep\` (content search).
|
|
15
|
+
3. \`read\` (verify context).
|
|
16
|
+
> **Tip:** Content search requires \`grep\`, not \`find\`.
|
|
17
|
+
|
|
18
|
+
### C: EDIT
|
|
19
|
+
1. \`edit\` (precise string match).
|
|
20
|
+
2. \`search_and_replace\` (bulk regex/glob).
|
|
21
|
+
3. \`mv\` | \`rm\` (file layout).
|
|
22
|
+
4. \`mkdir\` (create dirs).
|
|
23
|
+
> **Strict:** Confirm destructive ops (\`write\`, \`mv\`, \`rm\`, bulk replace).
|
|
24
|
+
|
|
25
|
+
### D: PATCH
|
|
26
|
+
1. \`diff_files\` (generate).
|
|
27
|
+
2. \`apply_patch\` (dryRun: true).
|
|
28
|
+
3. \`apply_patch\` (dryRun: false).
|
|
29
|
+
> **Tip:** Use \`diff_files\` output directly.
|
|
30
|
+
|
|
31
|
+
## Shared Constraints
|
|
32
|
+
${getSharedConstraints()
|
|
33
|
+
.map((c) => `- ${c}`)
|
|
34
|
+
.join('\n')}
|
|
35
|
+
`;
|
|
36
|
+
}
|
package/dist/resources.d.ts
CHANGED
|
@@ -2,5 +2,7 @@ import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
2
2
|
import type { ResourceStore } from './lib/resource-store.js';
|
|
3
3
|
import { type IconInfo } from './tools/shared.js';
|
|
4
4
|
export declare function registerInstructionResource(server: McpServer, instructions: string, iconInfo?: IconInfo): void;
|
|
5
|
+
export declare function registerToolCatalogResource(server: McpServer, iconInfo?: IconInfo): void;
|
|
6
|
+
export declare function registerWorkflowGuideResource(server: McpServer, iconInfo?: IconInfo): void;
|
|
5
7
|
export declare function registerResultResources(server: McpServer, store: ResourceStore, iconInfo?: IconInfo): void;
|
|
6
8
|
export declare function registerMetricsResource(server: McpServer, iconInfo?: IconInfo): void;
|
package/dist/resources.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { ErrorCode, McpError } from './lib/errors.js';
|
|
3
3
|
import { globalMetrics } from './lib/observability.js';
|
|
4
|
+
import { buildToolCatalog } from './resources/tool-catalog.js';
|
|
5
|
+
import { buildWorkflowGuide } from './resources/workflows.js';
|
|
4
6
|
import { withDefaultIcons } from './tools/shared.js';
|
|
5
7
|
const RESULT_TEMPLATE = new ResourceTemplate('filesystem-mcp://result/{id}', {
|
|
6
8
|
list: undefined,
|
|
@@ -13,6 +15,12 @@ const RESULT_RESOURCE_DESCRIPTION = 'Ephemeral cached tool output exposed as an
|
|
|
13
15
|
const METRICS_RESOURCE_NAME = 'filesystem-mcp-metrics';
|
|
14
16
|
const METRICS_RESOURCE_URI = 'filesystem-mcp://metrics';
|
|
15
17
|
const METRICS_RESOURCE_DESCRIPTION = 'Live per-tool call/error/avgDurationMs metrics snapshot.';
|
|
18
|
+
const CATALOG_RESOURCE_NAME = 'filesystem-mcp-catalog';
|
|
19
|
+
const CATALOG_RESOURCE_URI = 'internal://tool-catalog';
|
|
20
|
+
const CATALOG_RESOURCE_DESCRIPTION = 'Detailed catalog of tools and their inter-dependencies.';
|
|
21
|
+
const WORKFLOW_RESOURCE_NAME = 'filesystem-mcp-workflows';
|
|
22
|
+
const WORKFLOW_RESOURCE_URI = 'internal://workflows';
|
|
23
|
+
const WORKFLOW_RESOURCE_DESCRIPTION = 'Recommended workflows for common tasks.';
|
|
16
24
|
export function registerInstructionResource(server, instructions, iconInfo) {
|
|
17
25
|
server.registerResource(INSTRUCTIONS_RESOURCE_NAME, INSTRUCTIONS_RESOURCE_URI, withDefaultIcons({
|
|
18
26
|
title: 'Server Instructions',
|
|
@@ -32,6 +40,44 @@ export function registerInstructionResource(server, instructions, iconInfo) {
|
|
|
32
40
|
],
|
|
33
41
|
}));
|
|
34
42
|
}
|
|
43
|
+
export function registerToolCatalogResource(server, iconInfo) {
|
|
44
|
+
server.registerResource(CATALOG_RESOURCE_NAME, CATALOG_RESOURCE_URI, withDefaultIcons({
|
|
45
|
+
title: 'Tool Catalog',
|
|
46
|
+
description: CATALOG_RESOURCE_DESCRIPTION,
|
|
47
|
+
mimeType: 'text/markdown',
|
|
48
|
+
annotations: {
|
|
49
|
+
audience: ['assistant'],
|
|
50
|
+
priority: 0.6,
|
|
51
|
+
},
|
|
52
|
+
}, iconInfo), (uri) => ({
|
|
53
|
+
contents: [
|
|
54
|
+
{
|
|
55
|
+
uri: uri.href,
|
|
56
|
+
mimeType: 'text/markdown',
|
|
57
|
+
text: buildToolCatalog(),
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
export function registerWorkflowGuideResource(server, iconInfo) {
|
|
63
|
+
server.registerResource(WORKFLOW_RESOURCE_NAME, WORKFLOW_RESOURCE_URI, withDefaultIcons({
|
|
64
|
+
title: 'Workflow Guide',
|
|
65
|
+
description: WORKFLOW_RESOURCE_DESCRIPTION,
|
|
66
|
+
mimeType: 'text/markdown',
|
|
67
|
+
annotations: {
|
|
68
|
+
audience: ['assistant'],
|
|
69
|
+
priority: 0.7,
|
|
70
|
+
},
|
|
71
|
+
}, iconInfo), (uri) => ({
|
|
72
|
+
contents: [
|
|
73
|
+
{
|
|
74
|
+
uri: uri.href,
|
|
75
|
+
mimeType: 'text/markdown',
|
|
76
|
+
text: buildWorkflowGuide(),
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
}));
|
|
80
|
+
}
|
|
35
81
|
export function registerResultResources(server, store, iconInfo) {
|
|
36
82
|
server.registerResource(RESULT_RESOURCE_NAME, RESULT_TEMPLATE, withDefaultIcons({
|
|
37
83
|
title: 'Cached Tool Result',
|
package/dist/server/bootstrap.js
CHANGED
|
@@ -12,7 +12,7 @@ import { formatUnknownErrorMessage } from '../lib/errors.js';
|
|
|
12
12
|
import { createInMemoryResourceStore } from '../lib/resource-store.js';
|
|
13
13
|
import { pkgInfo } from '../pkg-info.js';
|
|
14
14
|
import { registerGetHelpPrompt } from '../prompts.js';
|
|
15
|
-
import { registerInstructionResource, registerMetricsResource, registerResultResources, } from '../resources.js';
|
|
15
|
+
import { registerInstructionResource, registerMetricsResource, registerResultResources, registerToolCatalogResource, registerWorkflowGuideResource, } from '../resources.js';
|
|
16
16
|
import { buildServerInstructions } from '../resources/generated-instructions.js';
|
|
17
17
|
import { registerAllTools } from '../tools.js';
|
|
18
18
|
import { withDefaultIcons } from '../tools/shared.js';
|
|
@@ -86,6 +86,8 @@ export async function createServer(options = {}) {
|
|
|
86
86
|
return {};
|
|
87
87
|
});
|
|
88
88
|
registerInstructionResource(server, serverInstructions, localIcon);
|
|
89
|
+
registerToolCatalogResource(server, localIcon);
|
|
90
|
+
registerWorkflowGuideResource(server, localIcon);
|
|
89
91
|
registerGetHelpPrompt(server, serverInstructions, localIcon);
|
|
90
92
|
registerResultResources(server, resourceStore, localIcon);
|
|
91
93
|
registerMetricsResource(server, localIcon);
|
package/dist/server.d.ts
CHANGED
package/dist/tools/shared.d.ts
CHANGED
|
@@ -48,7 +48,6 @@ interface ToolErrorResponse extends Record<string, unknown> {
|
|
|
48
48
|
isError: true;
|
|
49
49
|
}
|
|
50
50
|
export type ToolResult<T> = ToolResponse<T> | ToolErrorResponse;
|
|
51
|
-
export declare function parseToolArgs<Schema extends z.ZodType>(schema: Schema, args: unknown): z.infer<Schema>;
|
|
52
51
|
export declare function withValidatedArgs<Args, Result>(schema: z.ZodType<Args>, handler: (args: Args, extra: ToolExtra) => Promise<ToolResult<Result>>): (args: unknown, extra: ToolExtra) => Promise<ToolResult<Result>>;
|
|
53
52
|
type ProgressToken = string | number;
|
|
54
53
|
export interface ToolExtra {
|
package/dist/tools/shared.js
CHANGED
|
@@ -107,7 +107,7 @@ function resolveDetailedError(error, defaultCode, path) {
|
|
|
107
107
|
export function buildToolResponse(text, structuredContent, extraContent = []) {
|
|
108
108
|
return buildContentBlock(text, structuredContent, extraContent);
|
|
109
109
|
}
|
|
110
|
-
|
|
110
|
+
function parseToolArgs(schema, args) {
|
|
111
111
|
const candidate = args === undefined ? {} : args;
|
|
112
112
|
const parsed = schema.safeParse(candidate);
|
|
113
113
|
if (parsed.success) {
|
|
@@ -9,12 +9,6 @@ type TaskToolExtra = ToolExtra & {
|
|
|
9
9
|
taskRequestedTtl?: number | null;
|
|
10
10
|
};
|
|
11
11
|
type ToolArgs<Args extends ZodRawShapeCompat | AnySchema | undefined> = Args extends ZodRawShapeCompat ? ShapeOutput<Args> : Args extends AnySchema ? SchemaOutput<Args> : undefined;
|
|
12
|
-
/**
|
|
13
|
-
* Registers a tool preferring task-capable registration when available, and
|
|
14
|
-
* returns `true`. Returns `false` so the caller can fall through to standard
|
|
15
|
-
* `server.registerTool`.
|
|
16
|
-
*/
|
|
17
|
-
export declare function tryRegisterToolTask<Args extends ZodRawShapeCompat | AnySchema | undefined>(server: McpServer, toolName: string, toolDef: object, taskHandler: ToolTaskHandler<Args>, iconInfo: IconInfo | undefined): boolean;
|
|
18
12
|
export declare function registerToolTaskIfAvailable<Args extends ZodRawShapeCompat | AnySchema | undefined, Result>(server: McpServer, toolName: string, toolDef: object, run: (args: ToolArgs<Args>, extra: TaskToolExtra) => Promise<ToolResult<Result>>, iconInfo: IconInfo | undefined, guard?: () => boolean): boolean;
|
|
19
13
|
export declare function createToolTaskHandler<Result>(run: (args: undefined, extra: TaskToolExtra) => Promise<ToolResult<Result>>, options?: {
|
|
20
14
|
guard?: () => boolean;
|
|
@@ -298,7 +298,7 @@ async function runTaskInBackground(run, args, extra, taskStore, taskId, toolName
|
|
|
298
298
|
* returns `true`. Returns `false` so the caller can fall through to standard
|
|
299
299
|
* `server.registerTool`.
|
|
300
300
|
*/
|
|
301
|
-
|
|
301
|
+
function tryRegisterToolTask(server, toolName, toolDef, taskHandler, iconInfo) {
|
|
302
302
|
if (!hasTaskToolCapability(server))
|
|
303
303
|
return false;
|
|
304
304
|
const tasks = getExperimentalTaskRegistration(server);
|