@j0hanz/filesystem-mcp 1.13.2 → 1.14.1
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 +162 -145
- package/dist/cli.js +2 -2
- package/dist/completions.js +54 -51
- package/dist/config.d.ts +13 -14
- package/dist/config.js +12 -12
- package/dist/index.js +1 -1
- package/dist/lib/abort.d.ts +7 -0
- package/dist/lib/abort.js +81 -0
- package/dist/lib/constants.d.ts +3 -1
- package/dist/lib/constants.js +8 -2
- package/dist/lib/errors.d.ts +7 -3
- package/dist/lib/errors.js +64 -41
- package/dist/lib/file-operations/core.d.ts +3 -3
- package/dist/lib/file-operations/core.js +23 -20
- package/dist/lib/file-operations/metadata.d.ts +2 -2
- package/dist/lib/file-operations/metadata.js +69 -22
- package/dist/lib/file-operations/search.d.ts +0 -1
- package/dist/lib/file-operations/search.js +87 -95
- package/dist/lib/file-operations/traversal.js +13 -15
- package/dist/lib/fs-helpers.d.ts +3 -10
- package/dist/lib/fs-helpers.js +29 -108
- package/dist/lib/globs.d.ts +2 -0
- package/dist/lib/globs.js +19 -0
- package/dist/lib/logger.d.ts +28 -0
- package/dist/lib/logger.js +91 -0
- package/dist/lib/observability.d.ts +7 -0
- package/dist/lib/observability.js +19 -9
- package/dist/lib/paths.js +55 -55
- package/dist/lib/resource-store.js +4 -4
- package/dist/lib/utils.d.ts +0 -12
- package/dist/lib/utils.js +0 -13
- package/dist/lib/zod-codecs.d.ts +2 -0
- package/dist/lib/zod-codecs.js +18 -0
- package/dist/pkg-info.d.ts +1 -0
- package/dist/pkg-info.js +2 -2
- package/dist/prompts.js +3 -3
- package/dist/resources/generated-instructions.js +41 -41
- package/dist/resources/tool-catalog.js +33 -58
- package/dist/resources/tool-info.d.ts +0 -1
- package/dist/resources/tool-info.js +44 -67
- package/dist/resources/workflows.js +47 -19
- package/dist/resources.d.ts +1 -1
- package/dist/resources.js +4 -4
- package/dist/schemas.d.ts +185 -465
- package/dist/schemas.js +174 -206
- package/dist/server/bootstrap.d.ts +12 -11
- package/dist/server/bootstrap.js +95 -86
- package/dist/server/roots-manager.d.ts +5 -2
- package/dist/server/roots-manager.js +9 -7
- package/dist/server/task-store.d.ts +10 -0
- package/dist/server/task-store.js +73 -0
- package/dist/tools/apply-patch.js +39 -20
- package/dist/tools/calculate-hash.js +14 -27
- package/dist/tools/create-directory.js +11 -9
- package/dist/tools/delete-file.js +19 -19
- package/dist/tools/diff-files.js +16 -18
- package/dist/tools/edit-file.js +11 -5
- package/dist/tools/list-directory.js +16 -21
- package/dist/tools/move-file.js +105 -100
- package/dist/tools/read-multiple.js +15 -10
- package/dist/tools/read.js +6 -7
- package/dist/tools/replace-in-files.js +76 -115
- package/dist/tools/roots.js +3 -7
- package/dist/tools/search-content.js +158 -203
- package/dist/tools/search-files.js +59 -50
- package/dist/tools/shared.d.ts +10 -0
- package/dist/tools/shared.js +105 -36
- package/dist/tools/stat-many.js +15 -9
- package/dist/tools/stat.js +6 -6
- package/dist/tools/task-support.d.ts +10 -9
- package/dist/tools/task-support.js +94 -23
- package/dist/tools/tree.js +4 -4
- package/dist/tools/write-file.js +11 -12
- package/package.json +10 -9
|
@@ -15,27 +15,16 @@ function buildCrossToolDataFlow() {
|
|
|
15
15
|
}
|
|
16
16
|
function buildCatalogGuide() {
|
|
17
17
|
const taskCapable = getTaskCapableToolNames();
|
|
18
|
-
return
|
|
18
|
+
return `# Tool Selection Guide
|
|
19
|
+
|
|
19
20
|
## Primitive Routing
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'`internal://instructions`' +
|
|
28
|
-
`, ` +
|
|
29
|
-
'`internal://tool-info/{name}`' +
|
|
30
|
-
`, and cached ` +
|
|
31
|
-
'`filesystem-mcp://result/{id}`' +
|
|
32
|
-
` output.
|
|
33
|
-
- ` +
|
|
34
|
-
'`prompts`' +
|
|
35
|
-
`: user-controlled workflow templates for help, comparison, and guided inspection.
|
|
36
|
-
- ` +
|
|
37
|
-
'`completion`' +
|
|
38
|
-
`: argument suggestions for prompts and resource templates; not a discovery mechanism.
|
|
22
|
+
| Primitive | Purpose |
|
|
23
|
+
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| \`tools\` | Model-controlled operations that inspect or mutate the filesystem within allowed roots. |
|
|
25
|
+
| \`resources\` | Application-driven context: \`internal://instructions\`, \`internal://tool-info/{name}\`, cached \`filesystem-mcp://result/{id}\`. |
|
|
26
|
+
| \`prompts\` | User-controlled workflow templates for help, comparison, and guided inspection. |
|
|
27
|
+
| \`completion\` | Argument suggestions for prompts and resource templates (not a discovery mechanism). |
|
|
39
28
|
|
|
40
29
|
## Cross-Tool Data Flow
|
|
41
30
|
|
|
@@ -45,55 +34,41 @@ ${buildCrossToolDataFlow()}
|
|
|
45
34
|
|
|
46
35
|
## Result Contract
|
|
47
36
|
|
|
48
|
-
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
'`isError: true`' +
|
|
55
|
-
` inside the tool result, not a JSON-RPC protocol error.
|
|
56
|
-
- When a tool returns ` +
|
|
57
|
-
'`resourceUri`' +
|
|
58
|
-
` or a ` +
|
|
59
|
-
'`resource_link`' +
|
|
60
|
-
`, follow it with ` +
|
|
61
|
-
'`resources/read`' +
|
|
62
|
-
` immediately.
|
|
37
|
+
- Success: returns both \`content\` (JSON text) and \`structuredContent\` (when \`outputSchema\` is declared).
|
|
38
|
+
- Error: \`isError: true\` in tool result, \`structuredContent\` omitted. Parse \`content\` text for error details.
|
|
39
|
+
- Tool/business failures use \`isError: true\` inside the tool result, not JSON-RPC protocol errors.
|
|
40
|
+
- When a response includes \`resourceUri\` or \`resource_link\`, follow up with \`resources/read\` immediately.
|
|
41
|
+
|
|
42
|
+
## Task Mode
|
|
63
43
|
|
|
64
|
-
|
|
44
|
+
Use inline execution by default. Add task mode only when the caller needs durable polling, deferred retrieval, or cancellation.
|
|
65
45
|
|
|
66
|
-
-
|
|
67
|
-
- Add task mode only when the caller needs durable polling, deferred retrieval, or cancellation after the initial response.
|
|
68
|
-
- Task-capable tools: ${taskCapable.length > 0 ? taskCapable.map((name) => `\`${name}\``).join(', ') : 'none'}.
|
|
46
|
+
Task-capable tools: ${taskCapable.length > 0 ? taskCapable.map((name) => `\`${name}\``).join(', ') : 'none'}.
|
|
69
47
|
|
|
70
48
|
## Search Strategy
|
|
71
49
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
50
|
+
| Goal | Tool |
|
|
51
|
+
| ----------------------- | ------------------------------------------ |
|
|
52
|
+
| Find files by name/glob | \`find\` |
|
|
53
|
+
| Search file contents | \`grep\` |
|
|
54
|
+
| Replace across files | \`search_and_replace\` (not for discovery) |
|
|
75
55
|
|
|
76
56
|
## Write Strategy
|
|
77
57
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
1. **Single file, targeted change?** -> \`edit\` (match exact text, replace first occurrence)
|
|
85
|
-
2. **Single file, full rewrite?** -> \`write\` (overwrite entire content)
|
|
86
|
-
3. **Multiple files, same change?** -> \`search_and_replace\` (glob + pattern across files)
|
|
87
|
-
4. **Not sure what to change?** -> \`grep\` first, then decide
|
|
58
|
+
| Scenario | Tool |
|
|
59
|
+
| --------------------------- | ----------------------------------------------------- |
|
|
60
|
+
| Single file, targeted edit | \`edit\` — match exact text, replace first occurrence |
|
|
61
|
+
| Single file, full rewrite | \`write\` — overwrite entire content |
|
|
62
|
+
| Multiple files, same change | \`search_and_replace\` — glob + pattern across files |
|
|
63
|
+
| Unsure what to change | \`grep\` first, then decide |
|
|
88
64
|
|
|
89
|
-
## Patch
|
|
65
|
+
## Patch Strategy
|
|
90
66
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
`);
|
|
67
|
+
1. Generate with \`diff_files\`.
|
|
68
|
+
2. Validate with \`apply_patch(dryRun: true)\` before writing.
|
|
69
|
+
3. Apply with \`apply_patch\`.
|
|
70
|
+
4. Multi-file patches: set \`path\` to the base directory; results are per-file.
|
|
71
|
+
`;
|
|
97
72
|
}
|
|
98
73
|
export function buildToolCatalog() {
|
|
99
74
|
return `${buildCoreContextPack()}\n\n${buildCatalogGuide()}`;
|
|
@@ -4,7 +4,6 @@ export declare function getSortedToolContracts(): ToolContract[];
|
|
|
4
4
|
export declare function pickAvailableToolNames(names: readonly string[]): string[];
|
|
5
5
|
export declare function formatToolNameList(names: readonly string[]): string;
|
|
6
6
|
export declare function getTaskCapableToolNames(): string[];
|
|
7
|
-
export declare function getTaskToolNamesBySupport(taskSupport: Extract<ToolContract['taskSupport'], 'optional' | 'required'>): string[];
|
|
8
7
|
export declare function buildCoreContextPack(): string;
|
|
9
8
|
export declare function getSharedConstraints(): string[];
|
|
10
9
|
export declare function buildToolInfo(name: string): string | undefined;
|
|
@@ -55,11 +55,6 @@ export function getTaskCapableToolNames() {
|
|
|
55
55
|
contract.taskSupport === 'required')
|
|
56
56
|
.map((contract) => contract.name);
|
|
57
57
|
}
|
|
58
|
-
export function getTaskToolNamesBySupport(taskSupport) {
|
|
59
|
-
return getSortedToolContracts()
|
|
60
|
-
.filter((contract) => contract.taskSupport === taskSupport)
|
|
61
|
-
.map((contract) => contract.name);
|
|
62
|
-
}
|
|
63
58
|
export function buildCoreContextPack() {
|
|
64
59
|
const rows = getSortedToolContracts().map((contract) => {
|
|
65
60
|
const e = ENTRIES[contract.name];
|
|
@@ -68,14 +63,14 @@ export function buildCoreContextPack() {
|
|
|
68
63
|
const annotations = e.annotations ? ` ${e.annotations.join(' ')}` : '';
|
|
69
64
|
return `| \`${e.name}\` | ${e.description}${annotations} |`;
|
|
70
65
|
});
|
|
71
|
-
return
|
|
66
|
+
return `## Tool Summary\n\n| Tool | Purpose |\n|------|---------|\n${rows.join('\n')}`;
|
|
72
67
|
}
|
|
73
68
|
export function getSharedConstraints() {
|
|
74
69
|
return [
|
|
75
|
-
'
|
|
76
|
-
'Sensitive paths are
|
|
77
|
-
`
|
|
78
|
-
'
|
|
70
|
+
'Operate within allowed roots only (negotiated at startup via CLI).',
|
|
71
|
+
'Sensitive file paths (e.g. .env, *.pem, *id_rsa*) are denied by default.',
|
|
72
|
+
`Enforced limits: max file size ${Math.floor(MAX_TEXT_FILE_SIZE / 1024 / 1024)} MB, file search cap ${MAX_SEARCH_RESULTS} results, content search cap ${DEFAULT_SEARCH_CONTENT_RESULTS} matches.`,
|
|
73
|
+
'When a response includes `resourceUri`, call `resources/read` immediately — cached results expire on server restart.',
|
|
79
74
|
];
|
|
80
75
|
}
|
|
81
76
|
function formatTaskSupportLabel(taskSupport) {
|
|
@@ -88,12 +83,17 @@ function formatTaskSupportLabel(taskSupport) {
|
|
|
88
83
|
return 'forbidden';
|
|
89
84
|
}
|
|
90
85
|
}
|
|
91
|
-
function formatAnnotationValue(value) {
|
|
92
|
-
return value ? 'true' : 'false';
|
|
93
|
-
}
|
|
94
86
|
function toJsonSchemaObject(schema, io = 'output') {
|
|
95
87
|
return z.toJSONSchema(schema, { io });
|
|
96
88
|
}
|
|
89
|
+
function summarizeArrayType(schema) {
|
|
90
|
+
if (Array.isArray(schema.prefixItems) && schema.prefixItems.length > 0) {
|
|
91
|
+
const itemTypes = schema.prefixItems.map(summarizeSchemaType).join(', ');
|
|
92
|
+
return `tuple<${itemTypes}>`;
|
|
93
|
+
}
|
|
94
|
+
const itemType = schema.items ? summarizeSchemaType(schema.items) : 'unknown';
|
|
95
|
+
return `array<${itemType}>`;
|
|
96
|
+
}
|
|
97
97
|
function summarizeSchemaType(schema) {
|
|
98
98
|
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
99
99
|
return `enum(${schema.enum.map((value) => JSON.stringify(value)).join(', ')})`;
|
|
@@ -108,14 +108,7 @@ function summarizeSchemaType(schema) {
|
|
|
108
108
|
return schema.oneOf.map(summarizeSchemaType).join(' | ');
|
|
109
109
|
}
|
|
110
110
|
if (schema.type === 'array') {
|
|
111
|
-
|
|
112
|
-
const itemTypes = schema.prefixItems.map(summarizeSchemaType).join(', ');
|
|
113
|
-
return `tuple<${itemTypes}>`;
|
|
114
|
-
}
|
|
115
|
-
const itemType = schema.items
|
|
116
|
-
? summarizeSchemaType(schema.items)
|
|
117
|
-
: 'unknown';
|
|
118
|
-
return `array<${itemType}>`;
|
|
111
|
+
return summarizeArrayType(schema);
|
|
119
112
|
}
|
|
120
113
|
if (schema.type === 'object' && schema.additionalProperties === false) {
|
|
121
114
|
return 'object (strict)';
|
|
@@ -125,16 +118,23 @@ function summarizeSchemaType(schema) {
|
|
|
125
118
|
}
|
|
126
119
|
return 'unknown';
|
|
127
120
|
}
|
|
121
|
+
function formatFieldLabel(label) {
|
|
122
|
+
return label
|
|
123
|
+
.split('_')
|
|
124
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
125
|
+
.join(' ');
|
|
126
|
+
}
|
|
128
127
|
function buildSchemaFieldLines(label, schema) {
|
|
128
|
+
const heading = `**${formatFieldLabel(label)}:**`;
|
|
129
129
|
if (!schema) {
|
|
130
|
-
return [
|
|
130
|
+
return [heading, '- none'];
|
|
131
131
|
}
|
|
132
132
|
const io = label === 'input_fields' ? 'input' : 'output';
|
|
133
133
|
const jsonSchema = toJsonSchemaObject(schema, io);
|
|
134
134
|
const properties = jsonSchema.properties ?? {};
|
|
135
135
|
const required = new Set(jsonSchema.required ?? []);
|
|
136
136
|
const fieldNames = Object.keys(properties);
|
|
137
|
-
const lines = [
|
|
137
|
+
const lines = [heading];
|
|
138
138
|
if (typeof jsonSchema.description === 'string' &&
|
|
139
139
|
jsonSchema.description.length > 0) {
|
|
140
140
|
lines.push(`- Schema constraints: ${jsonSchema.description}`);
|
|
@@ -143,7 +143,7 @@ function buildSchemaFieldLines(label, schema) {
|
|
|
143
143
|
lines.push('- Unknown fields are rejected (`additionalProperties: false`).');
|
|
144
144
|
}
|
|
145
145
|
if (fieldNames.length === 0) {
|
|
146
|
-
lines.push('- object with no fields'
|
|
146
|
+
lines.push('- object with no fields');
|
|
147
147
|
return lines;
|
|
148
148
|
}
|
|
149
149
|
lines.push(...fieldNames.map((fieldName) => {
|
|
@@ -155,75 +155,52 @@ function buildSchemaFieldLines(label, schema) {
|
|
|
155
155
|
? fieldSchema.description
|
|
156
156
|
: 'No description.';
|
|
157
157
|
return `- ${fieldName} (${type}, ${requiredLabel}): ${description}`;
|
|
158
|
-
})
|
|
158
|
+
}));
|
|
159
159
|
return lines;
|
|
160
160
|
}
|
|
161
|
-
function buildProtocolNotes(contract) {
|
|
162
|
-
const notes = [
|
|
163
|
-
'- Protocol failures use JSON-RPC `error`; execution failures use tool result `isError: true`.',
|
|
164
|
-
];
|
|
165
|
-
if (contract.outputSchema) {
|
|
166
|
-
notes.push('- Successful responses include `structuredContent` that must match the declared output schema.');
|
|
167
|
-
}
|
|
168
|
-
if (contract.taskSupport === 'optional') {
|
|
169
|
-
notes.push('- Supports inline execution by default and task mode when durable polling or deferred results are needed.');
|
|
170
|
-
}
|
|
171
|
-
if (contract.taskSupport === 'required') {
|
|
172
|
-
notes.push('- Must run in task mode; callers should poll `tasks/get` and fetch the payload via `tasks/result`.');
|
|
173
|
-
}
|
|
174
|
-
if (contract.taskSupport === 'forbidden') {
|
|
175
|
-
notes.push('- Runs inline only; task augmentation is not supported for this tool.');
|
|
176
|
-
}
|
|
177
|
-
return notes;
|
|
178
|
-
}
|
|
179
161
|
export function buildToolInfo(name) {
|
|
180
162
|
const contract = CONTRACTS_BY_NAME.get(name);
|
|
181
163
|
const entry = ENTRIES[name];
|
|
182
164
|
if (!entry || !contract)
|
|
183
165
|
return undefined;
|
|
166
|
+
const annotationLines = [];
|
|
167
|
+
if (contract.annotations?.readOnlyHint)
|
|
168
|
+
annotationLines.push('- readOnlyHint: true');
|
|
169
|
+
if (contract.annotations?.idempotentHint)
|
|
170
|
+
annotationLines.push('- idempotentHint: true');
|
|
171
|
+
if (contract.annotations?.destructiveHint)
|
|
172
|
+
annotationLines.push('- destructiveHint: true');
|
|
173
|
+
if (contract.annotations?.openWorldHint)
|
|
174
|
+
annotationLines.push('- openWorldHint: true');
|
|
184
175
|
const lines = [
|
|
185
|
-
|
|
186
|
-
|
|
176
|
+
`---`,
|
|
177
|
+
`# ${entry.name}`,
|
|
187
178
|
'',
|
|
188
|
-
|
|
189
|
-
|
|
179
|
+
`**Title:** ${entry.title}`,
|
|
180
|
+
`**Description:** ${entry.description}`,
|
|
190
181
|
'',
|
|
191
|
-
'
|
|
182
|
+
'**Execution:**',
|
|
192
183
|
`- taskSupport: ${formatTaskSupportLabel(contract.taskSupport)}`,
|
|
193
|
-
'</execution>',
|
|
194
|
-
'',
|
|
195
|
-
'<annotations>',
|
|
196
|
-
`- readOnlyHint: ${formatAnnotationValue(contract.annotations?.readOnlyHint)}`,
|
|
197
|
-
`- idempotentHint: ${formatAnnotationValue(contract.annotations?.idempotentHint)}`,
|
|
198
|
-
`- destructiveHint: ${formatAnnotationValue(contract.annotations?.destructiveHint)}`,
|
|
199
|
-
`- openWorldHint: ${formatAnnotationValue(contract.annotations?.openWorldHint)}`,
|
|
200
|
-
'</annotations>',
|
|
201
184
|
'',
|
|
202
185
|
...buildSchemaFieldLines('input_fields', contract.inputSchema),
|
|
203
186
|
'',
|
|
204
187
|
...buildSchemaFieldLines('output_fields', contract.outputSchema),
|
|
205
|
-
'',
|
|
206
|
-
'<protocol_notes>',
|
|
207
|
-
...buildProtocolNotes(contract),
|
|
208
|
-
'</protocol_notes>',
|
|
209
188
|
];
|
|
210
|
-
if (
|
|
211
|
-
lines.push('',
|
|
189
|
+
if (annotationLines.length > 0) {
|
|
190
|
+
lines.push('', '**Behavior:**', ...annotationLines);
|
|
212
191
|
}
|
|
213
192
|
if (entry.nuances && entry.nuances.length > 0) {
|
|
214
|
-
lines.push('', '
|
|
193
|
+
lines.push('', '**Usage Notes:**');
|
|
215
194
|
for (const nuance of entry.nuances) {
|
|
216
195
|
lines.push(`- ${nuance}`);
|
|
217
196
|
}
|
|
218
|
-
lines.push('</nuances>');
|
|
219
197
|
}
|
|
220
198
|
if (entry.gotchas && entry.gotchas.length > 0) {
|
|
221
|
-
lines.push('', '
|
|
199
|
+
lines.push('', '**Warnings:**');
|
|
222
200
|
for (const gotcha of entry.gotchas) {
|
|
223
201
|
lines.push(`- ${gotcha}`);
|
|
224
202
|
}
|
|
225
|
-
lines.push('</gotchas>');
|
|
226
203
|
}
|
|
227
|
-
lines.push('
|
|
204
|
+
lines.push('---');
|
|
228
205
|
return lines.join('\n');
|
|
229
206
|
}
|
|
@@ -10,23 +10,51 @@ export function buildWorkflowGuide() {
|
|
|
10
10
|
'read_many',
|
|
11
11
|
]));
|
|
12
12
|
const searchTools = formatToolNameList(pickAvailableToolNames(['find', 'grep', 'read']));
|
|
13
|
-
const editTools = formatToolNameList(pickAvailableToolNames([
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
###
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
13
|
+
const editTools = formatToolNameList(pickAvailableToolNames([
|
|
14
|
+
'edit',
|
|
15
|
+
'write',
|
|
16
|
+
'search_and_replace',
|
|
17
|
+
'mv',
|
|
18
|
+
'rm',
|
|
19
|
+
'mkdir',
|
|
20
|
+
]));
|
|
21
|
+
return `## Workflows
|
|
22
|
+
|
|
23
|
+
### A: Explore — Discover directory layout or file content
|
|
24
|
+
|
|
25
|
+
**Tools:** ${exploreTools}
|
|
26
|
+
|
|
27
|
+
1. Start with \`roots\` to identify allowed directories.
|
|
28
|
+
2. Use \`ls\` or \`tree\` to map structure, then \`stat\` or \`read\` for details.
|
|
29
|
+
|
|
30
|
+
> Resolve paths before acting. Never assume a path exists.
|
|
31
|
+
|
|
32
|
+
### B: Search — Find files by name or content
|
|
33
|
+
|
|
34
|
+
**Tools:** ${searchTools}
|
|
35
|
+
|
|
36
|
+
1. Use \`find\` for file name/glob matching.
|
|
37
|
+
2. Use \`grep\` for content search (supports regex).
|
|
38
|
+
3. Use \`read\` to inspect matched files.
|
|
39
|
+
|
|
40
|
+
> Use \`grep\` for content, \`find\` for filenames. Do not conflate them.
|
|
41
|
+
|
|
42
|
+
### C: Edit — Modify files or directory layout
|
|
43
|
+
|
|
44
|
+
**Tools:** ${editTools}
|
|
45
|
+
|
|
46
|
+
1. Use \`edit\` for targeted single-file changes (exact text match → replace).
|
|
47
|
+
2. Use \`search_and_replace\` for bulk changes across multiple files.
|
|
48
|
+
3. Use \`mv\`, \`rm\`, \`mkdir\` for structural changes.
|
|
49
|
+
|
|
50
|
+
> Confirm destructive operations (\`write\`, \`mv\`, \`rm\`, bulk replace) before executing.
|
|
51
|
+
|
|
52
|
+
### D: Patch — Generate and apply unified diffs
|
|
53
|
+
|
|
54
|
+
1. Generate: \`diff_files(original, modified)\`.
|
|
55
|
+
2. Validate: \`apply_patch(patch, dryRun: true)\`.
|
|
56
|
+
3. Apply: \`apply_patch(patch)\`.
|
|
57
|
+
|
|
58
|
+
> Multi-file patches: set \`path\` to the base directory. Results are reported per file.
|
|
59
|
+
`;
|
|
32
60
|
}
|
package/dist/resources.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
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;
|
package/dist/resources.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
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
4
|
import { buildToolCatalog } from './resources/tool-catalog.js';
|
|
@@ -104,7 +104,7 @@ export function registerResultResources(server, store, iconInfo) {
|
|
|
104
104
|
}, iconInfo), (uri, variables) => {
|
|
105
105
|
const { id } = variables;
|
|
106
106
|
if (typeof id !== 'string' || id.length === 0) {
|
|
107
|
-
throw new McpError(ErrorCode.
|
|
107
|
+
throw new McpError(ErrorCode.NOT_FOUND, 'Cached result expired. Re-run the tool to regenerate.');
|
|
108
108
|
}
|
|
109
109
|
const entry = store.getText(uri.toString());
|
|
110
110
|
return {
|
|
@@ -130,11 +130,11 @@ export function registerToolInfoResource(server, iconInfo) {
|
|
|
130
130
|
}, iconInfo), (uri, variables) => {
|
|
131
131
|
const { name } = variables;
|
|
132
132
|
if (typeof name !== 'string' || name.length === 0) {
|
|
133
|
-
throw new McpError(ErrorCode.
|
|
133
|
+
throw new McpError(ErrorCode.INVALID_INPUT, 'Tool name is required');
|
|
134
134
|
}
|
|
135
135
|
const content = buildToolInfo(name);
|
|
136
136
|
if (content === undefined) {
|
|
137
|
-
throw new McpError(ErrorCode.
|
|
137
|
+
throw new McpError(ErrorCode.INVALID_INPUT, `Tool not found: ${name}`);
|
|
138
138
|
}
|
|
139
139
|
return {
|
|
140
140
|
contents: [
|