@mcptoolshop/file-forge 0.1.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/LICENSE +21 -0
- package/README.md +125 -0
- package/build/config/index.d.ts +29 -0
- package/build/config/index.d.ts.map +1 -0
- package/build/config/index.js +229 -0
- package/build/config/index.js.map +1 -0
- package/build/index.d.ts +9 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +23 -0
- package/build/index.js.map +1 -0
- package/build/security/index.d.ts +8 -0
- package/build/security/index.d.ts.map +1 -0
- package/build/security/index.js +8 -0
- package/build/security/index.js.map +1 -0
- package/build/security/read-only.d.ts +32 -0
- package/build/security/read-only.d.ts.map +1 -0
- package/build/security/read-only.js +62 -0
- package/build/security/read-only.js.map +1 -0
- package/build/security/sandbox.d.ts +60 -0
- package/build/security/sandbox.d.ts.map +1 -0
- package/build/security/sandbox.js +231 -0
- package/build/security/sandbox.js.map +1 -0
- package/build/server.d.ts +20 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +63 -0
- package/build/server.js.map +1 -0
- package/build/tools/metadata.d.ts +11 -0
- package/build/tools/metadata.d.ts.map +1 -0
- package/build/tools/metadata.js +423 -0
- package/build/tools/metadata.js.map +1 -0
- package/build/tools/read.d.ts +11 -0
- package/build/tools/read.d.ts.map +1 -0
- package/build/tools/read.js +335 -0
- package/build/tools/read.js.map +1 -0
- package/build/tools/scaffold.d.ts +11 -0
- package/build/tools/scaffold.d.ts.map +1 -0
- package/build/tools/scaffold.js +345 -0
- package/build/tools/scaffold.js.map +1 -0
- package/build/tools/search.d.ts +11 -0
- package/build/tools/search.d.ts.map +1 -0
- package/build/tools/search.js +250 -0
- package/build/tools/search.js.map +1 -0
- package/build/tools/write.d.ts +11 -0
- package/build/tools/write.d.ts.map +1 -0
- package/build/tools/write.js +538 -0
- package/build/tools/write.js.map +1 -0
- package/build/types.d.ts +402 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +146 -0
- package/build/types.js.map +1 -0
- package/build/utils/errors.d.ts +43 -0
- package/build/utils/errors.d.ts.map +1 -0
- package/build/utils/errors.js +125 -0
- package/build/utils/errors.js.map +1 -0
- package/build/utils/index.d.ts +10 -0
- package/build/utils/index.d.ts.map +1 -0
- package/build/utils/index.js +9 -0
- package/build/utils/index.js.map +1 -0
- package/build/utils/logger.d.ts +88 -0
- package/build/utils/logger.d.ts.map +1 -0
- package/build/utils/logger.js +166 -0
- package/build/utils/logger.js.map +1 -0
- package/build/utils/validation.d.ts +43 -0
- package/build/utils/validation.d.ts.map +1 -0
- package/build/utils/validation.js +196 -0
- package/build/utils/validation.js.map +1 -0
- package/package.json +64 -0
- package/templates/typescript-starter/package.json +18 -0
- package/templates/typescript-starter/src/index.ts +9 -0
- package/templates/typescript-starter/template.json +24 -0
- package/templates/typescript-starter/tsconfig.json +14 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP File Forge - Project Scaffolding Tools
|
|
3
|
+
*
|
|
4
|
+
* Tools for creating projects from templates.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'node:fs/promises';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { ScaffoldProjectInputSchema, ListTemplatesInputSchema } from '../types.js';
|
|
10
|
+
/**
|
|
11
|
+
* Get the default template paths.
|
|
12
|
+
*/
|
|
13
|
+
function getTemplatePaths() {
|
|
14
|
+
return [
|
|
15
|
+
path.join(process.cwd(), 'templates'),
|
|
16
|
+
path.join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.mcp-file-forge', 'templates'),
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Find a template by name or path.
|
|
21
|
+
*/
|
|
22
|
+
async function findTemplate(nameOrPath) {
|
|
23
|
+
// Check if it's an absolute or relative path
|
|
24
|
+
if (path.isAbsolute(nameOrPath) || nameOrPath.startsWith('.')) {
|
|
25
|
+
const templatePath = path.resolve(nameOrPath);
|
|
26
|
+
try {
|
|
27
|
+
const metadataPath = path.join(templatePath, 'template.json');
|
|
28
|
+
const metadataContent = await fs.readFile(metadataPath, 'utf-8');
|
|
29
|
+
const metadata = JSON.parse(metadataContent);
|
|
30
|
+
return { path: templatePath, metadata };
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Check if it's a valid directory without metadata
|
|
34
|
+
try {
|
|
35
|
+
const stats = await fs.stat(templatePath);
|
|
36
|
+
if (stats.isDirectory()) {
|
|
37
|
+
return {
|
|
38
|
+
path: templatePath,
|
|
39
|
+
metadata: {
|
|
40
|
+
name: path.basename(templatePath),
|
|
41
|
+
description: 'Template directory',
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Search in template paths
|
|
52
|
+
for (const basePath of getTemplatePaths()) {
|
|
53
|
+
const templatePath = path.join(basePath, nameOrPath);
|
|
54
|
+
try {
|
|
55
|
+
const stats = await fs.stat(templatePath);
|
|
56
|
+
if (stats.isDirectory()) {
|
|
57
|
+
const metadataPath = path.join(templatePath, 'template.json');
|
|
58
|
+
try {
|
|
59
|
+
const metadataContent = await fs.readFile(metadataPath, 'utf-8');
|
|
60
|
+
const metadata = JSON.parse(metadataContent);
|
|
61
|
+
return { path: templatePath, metadata };
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return {
|
|
65
|
+
path: templatePath,
|
|
66
|
+
metadata: {
|
|
67
|
+
name: nameOrPath,
|
|
68
|
+
description: 'Template directory',
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
// Template not found in this path, continue searching
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Process template variables in content.
|
|
82
|
+
*/
|
|
83
|
+
function processTemplateContent(content, variables) {
|
|
84
|
+
let result = content;
|
|
85
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
86
|
+
// Replace {{variable}} syntax
|
|
87
|
+
result = result.replace(new RegExp(`\\{\\{\\s*${key}\\s*\\}\\}`, 'g'), value);
|
|
88
|
+
// Replace ${variable} syntax
|
|
89
|
+
result = result.replace(new RegExp(`\\$\\{${key}\\}`, 'g'), value);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Process template file name (replace variables in path).
|
|
95
|
+
*/
|
|
96
|
+
function processTemplatePath(filePath, variables) {
|
|
97
|
+
let result = filePath;
|
|
98
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
99
|
+
// Replace __variable__ syntax in paths
|
|
100
|
+
result = result.replace(new RegExp(`__${key}__`, 'g'), value);
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Copy a directory recursively, processing templates.
|
|
106
|
+
*/
|
|
107
|
+
async function copyTemplateDir(src, dest, variables, overwrite) {
|
|
108
|
+
const files = [];
|
|
109
|
+
const skipped = [];
|
|
110
|
+
await fs.mkdir(dest, { recursive: true });
|
|
111
|
+
const entries = await fs.readdir(src, { withFileTypes: true });
|
|
112
|
+
for (const entry of entries) {
|
|
113
|
+
// Skip template.json
|
|
114
|
+
if (entry.name === 'template.json')
|
|
115
|
+
continue;
|
|
116
|
+
const srcPath = path.join(src, entry.name);
|
|
117
|
+
const processedName = processTemplatePath(entry.name, variables);
|
|
118
|
+
const destPath = path.join(dest, processedName);
|
|
119
|
+
if (entry.isDirectory()) {
|
|
120
|
+
const result = await copyTemplateDir(srcPath, destPath, variables, overwrite);
|
|
121
|
+
files.push(...result.files);
|
|
122
|
+
skipped.push(...result.skipped);
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Check if destination exists
|
|
126
|
+
let exists = false;
|
|
127
|
+
try {
|
|
128
|
+
await fs.access(destPath);
|
|
129
|
+
exists = true;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// File doesn't exist
|
|
133
|
+
}
|
|
134
|
+
if (exists && !overwrite) {
|
|
135
|
+
skipped.push(destPath);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// Read and process file
|
|
139
|
+
const content = await fs.readFile(srcPath, 'utf-8');
|
|
140
|
+
const processedContent = processTemplateContent(content, variables);
|
|
141
|
+
// Ensure parent directory exists
|
|
142
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
143
|
+
// Write processed file
|
|
144
|
+
await fs.writeFile(destPath, processedContent, 'utf-8');
|
|
145
|
+
files.push(destPath);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { files, skipped };
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Scaffold a project from a template.
|
|
152
|
+
*/
|
|
153
|
+
async function scaffoldProjectImpl(input) {
|
|
154
|
+
try {
|
|
155
|
+
// Find the template
|
|
156
|
+
const template = await findTemplate(input.template);
|
|
157
|
+
if (!template) {
|
|
158
|
+
return {
|
|
159
|
+
isError: true,
|
|
160
|
+
content: [
|
|
161
|
+
{
|
|
162
|
+
type: 'text',
|
|
163
|
+
text: JSON.stringify({
|
|
164
|
+
code: 'FILE_NOT_FOUND',
|
|
165
|
+
message: `Template not found: ${input.template}`,
|
|
166
|
+
details: {
|
|
167
|
+
searched_paths: getTemplatePaths(),
|
|
168
|
+
},
|
|
169
|
+
}),
|
|
170
|
+
},
|
|
171
|
+
],
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
// Check destination
|
|
175
|
+
const destPath = path.resolve(input.destination);
|
|
176
|
+
let destExists = false;
|
|
177
|
+
try {
|
|
178
|
+
await fs.access(destPath);
|
|
179
|
+
destExists = true;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// Destination doesn't exist
|
|
183
|
+
}
|
|
184
|
+
if (destExists && !input.overwrite) {
|
|
185
|
+
// Check if directory is empty
|
|
186
|
+
const entries = await fs.readdir(destPath);
|
|
187
|
+
if (entries.length > 0) {
|
|
188
|
+
return {
|
|
189
|
+
isError: true,
|
|
190
|
+
content: [
|
|
191
|
+
{
|
|
192
|
+
type: 'text',
|
|
193
|
+
text: JSON.stringify({
|
|
194
|
+
code: 'ALREADY_EXISTS',
|
|
195
|
+
message: `Destination directory is not empty: ${input.destination}`,
|
|
196
|
+
}),
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
// Merge default variables with provided variables
|
|
203
|
+
const variables = {
|
|
204
|
+
PROJECT_NAME: path.basename(destPath),
|
|
205
|
+
CURRENT_YEAR: new Date().getFullYear().toString(),
|
|
206
|
+
CURRENT_DATE: new Date().toISOString().split('T')[0],
|
|
207
|
+
...input.variables,
|
|
208
|
+
};
|
|
209
|
+
// Copy template to destination
|
|
210
|
+
const result = await copyTemplateDir(template.path, destPath, variables, input.overwrite);
|
|
211
|
+
return {
|
|
212
|
+
content: [
|
|
213
|
+
{
|
|
214
|
+
type: 'text',
|
|
215
|
+
text: JSON.stringify({
|
|
216
|
+
success: true,
|
|
217
|
+
template: {
|
|
218
|
+
name: template.metadata.name,
|
|
219
|
+
path: template.path,
|
|
220
|
+
},
|
|
221
|
+
destination: destPath,
|
|
222
|
+
files_created: result.files.length,
|
|
223
|
+
files_skipped: result.skipped.length,
|
|
224
|
+
variables_used: variables,
|
|
225
|
+
}, null, 2),
|
|
226
|
+
},
|
|
227
|
+
],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const err = error;
|
|
232
|
+
return {
|
|
233
|
+
isError: true,
|
|
234
|
+
content: [
|
|
235
|
+
{
|
|
236
|
+
type: 'text',
|
|
237
|
+
text: JSON.stringify({
|
|
238
|
+
code: 'UNKNOWN_ERROR',
|
|
239
|
+
message: `Error scaffolding project: ${err.message}`,
|
|
240
|
+
}),
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* List available project templates.
|
|
248
|
+
*/
|
|
249
|
+
async function listTemplatesImpl(input) {
|
|
250
|
+
try {
|
|
251
|
+
const templates = [];
|
|
252
|
+
for (const basePath of getTemplatePaths()) {
|
|
253
|
+
try {
|
|
254
|
+
const entries = await fs.readdir(basePath, { withFileTypes: true });
|
|
255
|
+
for (const entry of entries) {
|
|
256
|
+
if (!entry.isDirectory())
|
|
257
|
+
continue;
|
|
258
|
+
const templatePath = path.join(basePath, entry.name);
|
|
259
|
+
const metadataPath = path.join(templatePath, 'template.json');
|
|
260
|
+
let metadata = {
|
|
261
|
+
name: entry.name,
|
|
262
|
+
description: 'Template directory',
|
|
263
|
+
};
|
|
264
|
+
try {
|
|
265
|
+
const metadataContent = await fs.readFile(metadataPath, 'utf-8');
|
|
266
|
+
metadata = JSON.parse(metadataContent);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// No metadata file, use defaults
|
|
270
|
+
}
|
|
271
|
+
// Filter by category if specified
|
|
272
|
+
if (input.category && metadata.category !== input.category) {
|
|
273
|
+
continue;
|
|
274
|
+
}
|
|
275
|
+
templates.push({
|
|
276
|
+
name: metadata.name,
|
|
277
|
+
path: templatePath,
|
|
278
|
+
description: metadata.description,
|
|
279
|
+
category: metadata.category,
|
|
280
|
+
variables: metadata.variables?.map((v) => ({
|
|
281
|
+
name: v.name,
|
|
282
|
+
description: v.description,
|
|
283
|
+
})),
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// Template path doesn't exist, skip
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
content: [
|
|
293
|
+
{
|
|
294
|
+
type: 'text',
|
|
295
|
+
text: JSON.stringify({
|
|
296
|
+
template_paths: getTemplatePaths(),
|
|
297
|
+
count: templates.length,
|
|
298
|
+
templates,
|
|
299
|
+
}, null, 2),
|
|
300
|
+
},
|
|
301
|
+
],
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
const err = error;
|
|
306
|
+
return {
|
|
307
|
+
isError: true,
|
|
308
|
+
content: [
|
|
309
|
+
{
|
|
310
|
+
type: 'text',
|
|
311
|
+
text: JSON.stringify({
|
|
312
|
+
code: 'UNKNOWN_ERROR',
|
|
313
|
+
message: `Error listing templates: ${err.message}`,
|
|
314
|
+
}),
|
|
315
|
+
},
|
|
316
|
+
],
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Register project scaffolding tools with the MCP server.
|
|
322
|
+
*/
|
|
323
|
+
export function registerScaffoldTools(server) {
|
|
324
|
+
// scaffold_project tool
|
|
325
|
+
server.tool('scaffold_project', 'Create a project from a template', {
|
|
326
|
+
template: z.string().describe('Template name or path'),
|
|
327
|
+
destination: z.string().describe('Destination directory'),
|
|
328
|
+
variables: z
|
|
329
|
+
.record(z.string())
|
|
330
|
+
.optional()
|
|
331
|
+
.describe('Template variables'),
|
|
332
|
+
overwrite: z.boolean().optional().describe('Overwrite existing files'),
|
|
333
|
+
}, async (args) => {
|
|
334
|
+
const input = ScaffoldProjectInputSchema.parse(args);
|
|
335
|
+
return await scaffoldProjectImpl(input);
|
|
336
|
+
});
|
|
337
|
+
// list_templates tool
|
|
338
|
+
server.tool('list_templates', 'List available project templates', {
|
|
339
|
+
category: z.string().optional().describe('Filter by category'),
|
|
340
|
+
}, async (args) => {
|
|
341
|
+
const input = ListTemplatesInputSchema.parse(args);
|
|
342
|
+
return await listTemplatesImpl(input);
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=scaffold.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/tools/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP File Forge - File Search Tools
|
|
3
|
+
*
|
|
4
|
+
* Tools for searching files by pattern and content.
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
/**
|
|
8
|
+
* Register file search tools with the MCP server.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerSearchTools(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=search.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA4PpE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiD3D"}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP File Forge - File Search Tools
|
|
3
|
+
*
|
|
4
|
+
* Tools for searching files by pattern and content.
|
|
5
|
+
*/
|
|
6
|
+
import * as fs from 'node:fs/promises';
|
|
7
|
+
import * as path from 'node:path';
|
|
8
|
+
import { glob } from 'glob';
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { GlobSearchInputSchema, GrepSearchInputSchema } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Search for files matching a glob pattern.
|
|
13
|
+
*/
|
|
14
|
+
async function globSearchImpl(input) {
|
|
15
|
+
try {
|
|
16
|
+
const basePath = input.base_path ? path.resolve(input.base_path) : process.cwd();
|
|
17
|
+
// Use glob to find matching files
|
|
18
|
+
const matches = await glob(input.pattern, {
|
|
19
|
+
cwd: basePath,
|
|
20
|
+
nodir: !input.include_dirs,
|
|
21
|
+
absolute: true,
|
|
22
|
+
maxDepth: 20, // Prevent excessive recursion
|
|
23
|
+
});
|
|
24
|
+
// Limit results
|
|
25
|
+
const limitedMatches = matches.slice(0, input.max_results);
|
|
26
|
+
// Get basic info for each match
|
|
27
|
+
const results = await Promise.all(limitedMatches.map(async (filePath) => {
|
|
28
|
+
try {
|
|
29
|
+
const stats = await fs.stat(filePath);
|
|
30
|
+
return {
|
|
31
|
+
path: filePath,
|
|
32
|
+
name: path.basename(filePath),
|
|
33
|
+
isFile: stats.isFile(),
|
|
34
|
+
isDirectory: stats.isDirectory(),
|
|
35
|
+
size: stats.size,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return {
|
|
40
|
+
path: filePath,
|
|
41
|
+
name: path.basename(filePath),
|
|
42
|
+
error: 'Could not stat file',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}));
|
|
46
|
+
return {
|
|
47
|
+
content: [
|
|
48
|
+
{
|
|
49
|
+
type: 'text',
|
|
50
|
+
text: JSON.stringify({
|
|
51
|
+
count: results.length,
|
|
52
|
+
total_matches: matches.length,
|
|
53
|
+
truncated: matches.length > input.max_results,
|
|
54
|
+
results,
|
|
55
|
+
}, null, 2),
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const err = error;
|
|
62
|
+
return {
|
|
63
|
+
isError: true,
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: JSON.stringify({
|
|
68
|
+
code: 'UNKNOWN_ERROR',
|
|
69
|
+
message: `Error in glob search: ${err.message}`,
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Search file contents using regex.
|
|
78
|
+
*/
|
|
79
|
+
async function grepSearchImpl(input) {
|
|
80
|
+
try {
|
|
81
|
+
const searchPath = input.path ? path.resolve(input.path) : process.cwd();
|
|
82
|
+
const matches = [];
|
|
83
|
+
// Create regex
|
|
84
|
+
const flags = input.case_sensitive ? '' : 'i';
|
|
85
|
+
let regex;
|
|
86
|
+
try {
|
|
87
|
+
regex = new RegExp(input.pattern, flags);
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
return {
|
|
91
|
+
isError: true,
|
|
92
|
+
content: [
|
|
93
|
+
{
|
|
94
|
+
type: 'text',
|
|
95
|
+
text: JSON.stringify({
|
|
96
|
+
code: 'INVALID_PATH',
|
|
97
|
+
message: `Invalid regex pattern: ${input.pattern}`,
|
|
98
|
+
}),
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Determine files to search
|
|
104
|
+
let files;
|
|
105
|
+
const stats = await fs.stat(searchPath);
|
|
106
|
+
if (stats.isFile()) {
|
|
107
|
+
files = [searchPath];
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// Use glob to find files in directory
|
|
111
|
+
const globPattern = input.glob ?? '**/*';
|
|
112
|
+
files = await glob(globPattern, {
|
|
113
|
+
cwd: searchPath,
|
|
114
|
+
nodir: true,
|
|
115
|
+
absolute: true,
|
|
116
|
+
maxDepth: 20,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// Search each file
|
|
120
|
+
for (const file of files) {
|
|
121
|
+
if (matches.length >= input.max_results)
|
|
122
|
+
break;
|
|
123
|
+
try {
|
|
124
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
125
|
+
const lines = content.split('\n');
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
if (matches.length >= input.max_results)
|
|
128
|
+
break;
|
|
129
|
+
const line = lines[i];
|
|
130
|
+
const match = regex.exec(line);
|
|
131
|
+
if (match) {
|
|
132
|
+
const grepMatch = {
|
|
133
|
+
file,
|
|
134
|
+
line: i + 1,
|
|
135
|
+
column: match.index + 1,
|
|
136
|
+
match: line.trim(),
|
|
137
|
+
};
|
|
138
|
+
// Add context if requested
|
|
139
|
+
if (input.context_lines > 0) {
|
|
140
|
+
const beforeStart = Math.max(0, i - input.context_lines);
|
|
141
|
+
const afterEnd = Math.min(lines.length, i + input.context_lines + 1);
|
|
142
|
+
grepMatch.context = {
|
|
143
|
+
before: lines.slice(beforeStart, i).map((l) => l.trim()),
|
|
144
|
+
after: lines.slice(i + 1, afterEnd).map((l) => l.trim()),
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
matches.push(grepMatch);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Skip files that can't be read (binary, permissions, etc.)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return {
|
|
156
|
+
content: [
|
|
157
|
+
{
|
|
158
|
+
type: 'text',
|
|
159
|
+
text: JSON.stringify({
|
|
160
|
+
pattern: input.pattern,
|
|
161
|
+
count: matches.length,
|
|
162
|
+
truncated: matches.length >= input.max_results,
|
|
163
|
+
matches,
|
|
164
|
+
}, null, 2),
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
const err = error;
|
|
171
|
+
if (err.code === 'ENOENT') {
|
|
172
|
+
return {
|
|
173
|
+
isError: true,
|
|
174
|
+
content: [
|
|
175
|
+
{
|
|
176
|
+
type: 'text',
|
|
177
|
+
text: JSON.stringify({
|
|
178
|
+
code: 'FILE_NOT_FOUND',
|
|
179
|
+
message: `Path not found: ${input.path}`,
|
|
180
|
+
}),
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
isError: true,
|
|
187
|
+
content: [
|
|
188
|
+
{
|
|
189
|
+
type: 'text',
|
|
190
|
+
text: JSON.stringify({
|
|
191
|
+
code: 'UNKNOWN_ERROR',
|
|
192
|
+
message: `Error in grep search: ${err.message}`,
|
|
193
|
+
}),
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Find files by content (simpler interface for grep).
|
|
201
|
+
*/
|
|
202
|
+
async function findByContentImpl(input) {
|
|
203
|
+
// Escape special regex characters for literal search
|
|
204
|
+
const escapedText = input.text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
205
|
+
return await grepSearchImpl({
|
|
206
|
+
pattern: escapedText,
|
|
207
|
+
path: input.path,
|
|
208
|
+
glob: input.file_pattern,
|
|
209
|
+
case_sensitive: true,
|
|
210
|
+
max_results: input.max_results ?? 100,
|
|
211
|
+
context_lines: 0,
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Register file search tools with the MCP server.
|
|
216
|
+
*/
|
|
217
|
+
export function registerSearchTools(server) {
|
|
218
|
+
// glob_search tool
|
|
219
|
+
server.tool('glob_search', 'Find files matching a glob pattern', {
|
|
220
|
+
pattern: z.string().describe('Glob pattern (e.g., **/*.ts)'),
|
|
221
|
+
base_path: z.string().optional().describe('Base directory for search'),
|
|
222
|
+
max_results: z.number().optional().describe('Maximum results (default: 1000)'),
|
|
223
|
+
include_dirs: z.boolean().optional().describe('Include directories in results'),
|
|
224
|
+
}, async (args) => {
|
|
225
|
+
const input = GlobSearchInputSchema.parse(args);
|
|
226
|
+
return await globSearchImpl(input);
|
|
227
|
+
});
|
|
228
|
+
// grep_search tool
|
|
229
|
+
server.tool('grep_search', 'Search file contents with regex', {
|
|
230
|
+
pattern: z.string().describe('Regex pattern to search for'),
|
|
231
|
+
path: z.string().optional().describe('File or directory to search'),
|
|
232
|
+
glob: z.string().optional().describe('File pattern filter (e.g., *.ts)'),
|
|
233
|
+
case_sensitive: z.boolean().optional().describe('Case sensitive search'),
|
|
234
|
+
max_results: z.number().optional().describe('Maximum results (default: 100)'),
|
|
235
|
+
context_lines: z.number().optional().describe('Lines of context around matches'),
|
|
236
|
+
}, async (args) => {
|
|
237
|
+
const input = GrepSearchInputSchema.parse(args);
|
|
238
|
+
return await grepSearchImpl(input);
|
|
239
|
+
});
|
|
240
|
+
// find_by_content tool (simpler interface)
|
|
241
|
+
server.tool('find_by_content', 'Find files containing specific text', {
|
|
242
|
+
text: z.string().describe('Text to search for (literal, not regex)'),
|
|
243
|
+
path: z.string().optional().describe('Directory to search'),
|
|
244
|
+
file_pattern: z.string().optional().describe('File pattern (e.g., *.ts)'),
|
|
245
|
+
max_results: z.number().optional().describe('Maximum results'),
|
|
246
|
+
}, async (args) => {
|
|
247
|
+
return await findByContentImpl(args);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/tools/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP File Forge - File Writing Tools
|
|
3
|
+
*
|
|
4
|
+
* Tools for writing, copying, moving, and deleting files.
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
/**
|
|
8
|
+
* Register file writing tools with the MCP server.
|
|
9
|
+
*/
|
|
10
|
+
export declare function registerWriteTools(server: McpServer): void;
|
|
11
|
+
//# sourceMappingURL=write.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAmhBpE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8E1D"}
|