fileditor-mcp 1.0.2 → 1.0.3
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/1781792324448_PixelTunnelSender.exe +0 -0
- package/LICENSE +21 -21
- package/README.md +128 -128
- package/docs/MCP-INTERFACE.cn.md +975 -1061
- package/docs/MCP-INTERFACE.en.md +881 -974
- package/docs/README.cn.md +128 -128
- package/package.json +30 -31
- package/src/handlers/applyDiff.js +298 -324
- package/src/handlers/insertContent.js +179 -153
- package/src/handlers/listFiles.js +65 -54
- package/src/handlers/readFile.js +109 -109
- package/src/handlers/searchAndReplace.js +198 -217
- package/src/handlers/setWorkspace.js +26 -26
- package/src/handlers/writeFile.js +97 -91
- package/src/index.js +22 -22
- package/src/server.js +85 -85
- package/src/tools/toolDefinitions.js +291 -301
- package/src/utils/fileUtils.js +238 -716
- package/test/ApplyDiffHandler.test.js +754 -754
- package/test/InsertContentHandler.test.js +371 -369
- package/test/ListFilesHandler.test.js +302 -300
- package/test/ReadFileHandler.test.js +213 -213
- package/test/SearchAndReplaceHandler.test.js +505 -505
- package/test/SetWorkspaceHandler.test.js +290 -290
- package/test/WriteFileHandler.test.js +289 -289
- package/test/runAllTests.js +233 -233
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
import { FileUtils } from '../utils/fileUtils.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* set_workspace tool handler
|
|
5
|
-
*/
|
|
6
|
-
export class SetWorkspaceHandler {
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Handle set_workspace request
|
|
10
|
-
* @param {Object} args - Request parameters
|
|
11
|
-
* @returns {Promise<Object>} Response result
|
|
12
|
-
*/
|
|
13
|
-
static async handle(args) {
|
|
14
|
-
const { path } = args;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
// Set new workspace root directory
|
|
18
|
-
FileUtils.setWorkspaceRoot(path);
|
|
19
|
-
|
|
20
|
-
const message = `Successfully set workspace root to: ${FileUtils.getWorkspaceRoot()}`;
|
|
21
|
-
return FileUtils.createResponse(message);
|
|
22
|
-
} catch (error) {
|
|
23
|
-
throw new Error(`Failed to set workspace: ${error.message}`);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
1
|
+
import { FileUtils } from '../utils/fileUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* set_workspace tool handler
|
|
5
|
+
*/
|
|
6
|
+
export class SetWorkspaceHandler {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Handle set_workspace request
|
|
10
|
+
* @param {Object} args - Request parameters
|
|
11
|
+
* @returns {Promise<Object>} Response result
|
|
12
|
+
*/
|
|
13
|
+
static async handle(args) {
|
|
14
|
+
const { path } = args;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// Set new workspace root directory
|
|
18
|
+
FileUtils.setWorkspaceRoot(path);
|
|
19
|
+
|
|
20
|
+
const message = `Successfully set workspace root to: ${FileUtils.getWorkspaceRoot()}`;
|
|
21
|
+
return FileUtils.createResponse(message);
|
|
22
|
+
} catch (error) {
|
|
23
|
+
throw new Error(`Failed to set workspace: ${error.message}`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -1,92 +1,98 @@
|
|
|
1
|
-
import { FileUtils } from '../utils/fileUtils.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* write_files tool handler
|
|
5
|
-
*/
|
|
6
|
-
export class WriteFileHandler {
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Handle write_files request
|
|
10
|
-
* @param {Object} args - Request parameters
|
|
11
|
-
* @returns {Promise<Object>} Response result
|
|
12
|
-
*/
|
|
13
|
-
static async handle(args) {
|
|
14
|
-
const { path, content, line_count } = args;
|
|
15
|
-
|
|
16
|
-
try {
|
|
17
|
-
//
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
1
|
+
import { FileUtils } from '../utils/fileUtils.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* write_files tool handler
|
|
5
|
+
*/
|
|
6
|
+
export class WriteFileHandler {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Handle write_files request
|
|
10
|
+
* @param {Object} args - Request parameters
|
|
11
|
+
* @returns {Promise<Object>} Response result
|
|
12
|
+
*/
|
|
13
|
+
static async handle(args) {
|
|
14
|
+
const { path, content, line_count } = args;
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// Handle single file or multiple files
|
|
18
|
+
const paths = Array.isArray(path) ? path : [path];
|
|
19
|
+
const contents = Array.isArray(content) ? content : [content];
|
|
20
|
+
const lineCounts = Array.isArray(line_count) ? line_count : [line_count];
|
|
21
|
+
|
|
22
|
+
// Validate array length consistency
|
|
23
|
+
if (Array.isArray(path)) {
|
|
24
|
+
if (Array.isArray(content) && contents.length !== paths.length) {
|
|
25
|
+
throw new Error(`Path count (${paths.length}) doesn't match content count (${contents.length})`);
|
|
26
|
+
}
|
|
27
|
+
if (Array.isArray(line_count) && lineCounts.length !== paths.length) {
|
|
28
|
+
throw new Error(`Path count (${paths.length}) doesn't match line_count array length (${lineCounts.length})`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const results = [];
|
|
33
|
+
const writeOperations = [];
|
|
34
|
+
|
|
35
|
+
// Perform all write operations
|
|
36
|
+
for (let i = 0; i < paths.length; i++) {
|
|
37
|
+
const filePath = paths[i];
|
|
38
|
+
const fileContent = Array.isArray(content) ? contents[i] : content;
|
|
39
|
+
const expectedLines = Array.isArray(line_count) ? lineCounts[i] : line_count;
|
|
40
|
+
|
|
41
|
+
// Execute write operations in parallel
|
|
42
|
+
writeOperations.push(
|
|
43
|
+
FileUtils.writeFile(filePath, fileContent).then(() => {
|
|
44
|
+
// Validate line count
|
|
45
|
+
const actualLines = FileUtils.countLines(fileContent);
|
|
46
|
+
if (actualLines !== expectedLines) {
|
|
47
|
+
console.warn(`Warning: ${filePath} - Expected ${expectedLines} lines, but got ${actualLines} lines`);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
path: filePath,
|
|
52
|
+
actualLines,
|
|
53
|
+
expectedLines,
|
|
54
|
+
success: true
|
|
55
|
+
};
|
|
56
|
+
}).catch(error => {
|
|
57
|
+
return {
|
|
58
|
+
path: filePath,
|
|
59
|
+
success: false,
|
|
60
|
+
error: error.message
|
|
61
|
+
};
|
|
62
|
+
})
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Wait for all write operations to complete
|
|
67
|
+
const writeResults = await Promise.all(writeOperations);
|
|
68
|
+
|
|
69
|
+
// Check for failed operations
|
|
70
|
+
const failures = writeResults.filter(result => !result.success);
|
|
71
|
+
if (failures.length > 0) {
|
|
72
|
+
const errorMessages = failures.map(f => `${f.path}: ${f.error}`);
|
|
73
|
+
throw new Error(`Failed to write ${failures.length} file(s): ${errorMessages.join(', ')}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Build success message
|
|
77
|
+
const successResults = writeResults.filter(result => result.success);
|
|
78
|
+
const totalFiles = successResults.length;
|
|
79
|
+
const totalLines = successResults.reduce((sum, result) => sum + result.actualLines, 0);
|
|
80
|
+
|
|
81
|
+
let message;
|
|
82
|
+
if (totalFiles === 1) {
|
|
83
|
+
const result = successResults[0];
|
|
84
|
+
message = `File written successfully: ${result.path} (${result.actualLines} lines)`;
|
|
85
|
+
} else {
|
|
86
|
+
message = `Successfully wrote ${totalFiles} files (${totalLines} total lines):\n` +
|
|
87
|
+
successResults.map(result =>
|
|
88
|
+
` - ${result.path} (${result.actualLines} lines)`
|
|
89
|
+
).join('\n');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return FileUtils.createResponse(message);
|
|
93
|
+
|
|
94
|
+
} catch (error) {
|
|
95
|
+
throw new Error(`Failed to write file(s): ${error.message}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
92
98
|
}
|
package/src/index.js
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
-
import { FileEditorMCPServer } from './server.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Entry point for FileEditor MCP server
|
|
8
|
-
*/
|
|
9
|
-
async function main() {
|
|
10
|
-
try {
|
|
11
|
-
const server = new FileEditorMCPServer();
|
|
12
|
-
const transport = new StdioServerTransport();
|
|
13
|
-
|
|
14
|
-
await server.start(transport);
|
|
15
|
-
} catch (error) {
|
|
16
|
-
console.error("Failed to start FileEditor MCP server:", error);
|
|
17
|
-
process.exit(1);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Start the server
|
|
22
|
-
main();
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { FileEditorMCPServer } from './server.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Entry point for FileEditor MCP server
|
|
8
|
+
*/
|
|
9
|
+
async function main() {
|
|
10
|
+
try {
|
|
11
|
+
const server = new FileEditorMCPServer();
|
|
12
|
+
const transport = new StdioServerTransport();
|
|
13
|
+
|
|
14
|
+
await server.start(transport);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.error("Failed to start FileEditor MCP server:", error);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Start the server
|
|
22
|
+
main();
|
package/src/server.js
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
-
import {
|
|
3
|
-
CallToolRequestSchema,
|
|
4
|
-
ListToolsRequestSchema,
|
|
5
|
-
} from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
-
|
|
7
|
-
import { toolDefinitions } from './tools/toolDefinitions.js';
|
|
8
|
-
import { SetWorkspaceHandler } from './handlers/setWorkspace.js';
|
|
9
|
-
import { ReadFileHandler } from './handlers/readFile.js';
|
|
10
|
-
import { WriteFileHandler } from './handlers/writeFile.js';
|
|
11
|
-
import { ListFilesHandler } from './handlers/listFiles.js';
|
|
12
|
-
import { InsertContentHandler } from './handlers/insertContent.js';
|
|
13
|
-
import { ApplyDiffHandler } from './handlers/applyDiff.js';
|
|
14
|
-
import { SearchAndReplaceHandler } from './handlers/searchAndReplace.js';
|
|
15
|
-
import { FileUtils } from './utils/fileUtils.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Main class for FileEditor MCP server
|
|
19
|
-
*/
|
|
20
|
-
export class FileEditorMCPServer {
|
|
21
|
-
constructor() {
|
|
22
|
-
this.server = new Server(
|
|
23
|
-
{
|
|
24
|
-
name: "fileditor-mcp",
|
|
25
|
-
version: "1.0.0",
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
capabilities: {
|
|
29
|
-
tools: {},
|
|
30
|
-
},
|
|
31
|
-
}
|
|
32
|
-
);
|
|
33
|
-
|
|
34
|
-
this.setupHandlers();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Set up request handlers
|
|
39
|
-
*/
|
|
40
|
-
setupHandlers() {
|
|
41
|
-
// List available tools
|
|
42
|
-
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
43
|
-
return {
|
|
44
|
-
tools: toolDefinitions
|
|
45
|
-
};
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
// Handle tool calls
|
|
49
|
-
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
50
|
-
try {
|
|
51
|
-
const { name, arguments: args } = request.params;
|
|
52
|
-
|
|
53
|
-
switch (name) {
|
|
54
|
-
case "set_workspace":
|
|
55
|
-
return await SetWorkspaceHandler.handle(args);
|
|
56
|
-
case "read_files":
|
|
57
|
-
return await ReadFileHandler.handle(args);
|
|
58
|
-
case "write_files":
|
|
59
|
-
return await WriteFileHandler.handle(args);
|
|
60
|
-
case "list_files":
|
|
61
|
-
return await ListFilesHandler.handle(args);
|
|
62
|
-
case "insert_contents":
|
|
63
|
-
return await InsertContentHandler.handle(args);
|
|
64
|
-
case "apply_diffs":
|
|
65
|
-
return await ApplyDiffHandler.handle(args);
|
|
66
|
-
case "search_and_replace":
|
|
67
|
-
return await SearchAndReplaceHandler.handle(args);
|
|
68
|
-
default:
|
|
69
|
-
throw new Error(`Unknown tool: ${name}`);
|
|
70
|
-
}
|
|
71
|
-
} catch (error) {
|
|
72
|
-
return FileUtils.createErrorResponse(error.message);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Start the server
|
|
79
|
-
* @param {Object} transport - Transport object
|
|
80
|
-
*/
|
|
81
|
-
async start(transport) {
|
|
82
|
-
await this.server.connect(transport);
|
|
83
|
-
console.error("FileEditor MCP server running on stdio");
|
|
84
|
-
}
|
|
85
|
-
}
|
|
1
|
+
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
2
|
+
import {
|
|
3
|
+
CallToolRequestSchema,
|
|
4
|
+
ListToolsRequestSchema,
|
|
5
|
+
} from "@modelcontextprotocol/sdk/types.js";
|
|
6
|
+
|
|
7
|
+
import { toolDefinitions } from './tools/toolDefinitions.js';
|
|
8
|
+
import { SetWorkspaceHandler } from './handlers/setWorkspace.js';
|
|
9
|
+
import { ReadFileHandler } from './handlers/readFile.js';
|
|
10
|
+
import { WriteFileHandler } from './handlers/writeFile.js';
|
|
11
|
+
import { ListFilesHandler } from './handlers/listFiles.js';
|
|
12
|
+
import { InsertContentHandler } from './handlers/insertContent.js';
|
|
13
|
+
import { ApplyDiffHandler } from './handlers/applyDiff.js';
|
|
14
|
+
import { SearchAndReplaceHandler } from './handlers/searchAndReplace.js';
|
|
15
|
+
import { FileUtils } from './utils/fileUtils.js';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Main class for FileEditor MCP server
|
|
19
|
+
*/
|
|
20
|
+
export class FileEditorMCPServer {
|
|
21
|
+
constructor() {
|
|
22
|
+
this.server = new Server(
|
|
23
|
+
{
|
|
24
|
+
name: "fileditor-mcp",
|
|
25
|
+
version: "1.0.0",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
capabilities: {
|
|
29
|
+
tools: {},
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
this.setupHandlers();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Set up request handlers
|
|
39
|
+
*/
|
|
40
|
+
setupHandlers() {
|
|
41
|
+
// List available tools
|
|
42
|
+
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
43
|
+
return {
|
|
44
|
+
tools: toolDefinitions
|
|
45
|
+
};
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Handle tool calls
|
|
49
|
+
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
50
|
+
try {
|
|
51
|
+
const { name, arguments: args } = request.params;
|
|
52
|
+
|
|
53
|
+
switch (name) {
|
|
54
|
+
case "set_workspace":
|
|
55
|
+
return await SetWorkspaceHandler.handle(args);
|
|
56
|
+
case "read_files":
|
|
57
|
+
return await ReadFileHandler.handle(args);
|
|
58
|
+
case "write_files":
|
|
59
|
+
return await WriteFileHandler.handle(args);
|
|
60
|
+
case "list_files":
|
|
61
|
+
return await ListFilesHandler.handle(args);
|
|
62
|
+
case "insert_contents":
|
|
63
|
+
return await InsertContentHandler.handle(args);
|
|
64
|
+
case "apply_diffs":
|
|
65
|
+
return await ApplyDiffHandler.handle(args);
|
|
66
|
+
case "search_and_replace":
|
|
67
|
+
return await SearchAndReplaceHandler.handle(args);
|
|
68
|
+
default:
|
|
69
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
70
|
+
}
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return FileUtils.createErrorResponse(error.message);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Start the server
|
|
79
|
+
* @param {Object} transport - Transport object
|
|
80
|
+
*/
|
|
81
|
+
async start(transport) {
|
|
82
|
+
await this.server.connect(transport);
|
|
83
|
+
console.error("FileEditor MCP server running on stdio");
|
|
84
|
+
}
|
|
85
|
+
}
|