rittika-file-assistant 1.0.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/index.js +118 -0
- package/package.json +16 -0
- package/workspace/test.txt +0 -0
package/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
// index.js
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
const ROOT_DIR = path.join(process.cwd(), "workspace");
|
|
10
|
+
if (!fs.existsSync(ROOT_DIR)) fs.mkdirSync(ROOT_DIR);
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: "File MCP Server",
|
|
15
|
+
version: "1.0.0",
|
|
16
|
+
description: "A simple MCP server to read, write, edit, and list files inside a folder."
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
// ๐งพ TOOL 1: List files
|
|
21
|
+
server.registerTool(
|
|
22
|
+
"list_files",
|
|
23
|
+
{
|
|
24
|
+
description: "List all files inside the workspace folder",
|
|
25
|
+
outputSchema: { files: z.array(z.string()) },
|
|
26
|
+
},
|
|
27
|
+
async () => {
|
|
28
|
+
const files = fs.readdirSync(ROOT_DIR);
|
|
29
|
+
return { structuredContent: { files } };
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
// ๐ TOOL 2: Read a file
|
|
35
|
+
server.registerTool(
|
|
36
|
+
"read_file",
|
|
37
|
+
{
|
|
38
|
+
description: "Read content of a file",
|
|
39
|
+
inputSchema: { filename: z.string() },
|
|
40
|
+
outputSchema: { content: z.string() },
|
|
41
|
+
},
|
|
42
|
+
async ({ filename }) => {
|
|
43
|
+
const filePath = path.join(ROOT_DIR, filename);
|
|
44
|
+
if (!fs.existsSync(filePath)) throw new Error("File not found");
|
|
45
|
+
const content = fs.readFileSync(filePath, "utf-8");
|
|
46
|
+
return { structuredContent: { content } };
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
// โ๏ธ TOOL 3: Write or overwrite file
|
|
52
|
+
server.registerTool(
|
|
53
|
+
"write_file",
|
|
54
|
+
{
|
|
55
|
+
description: "Create or overwrite a file with given content",
|
|
56
|
+
inputSchema: { filename: z.string(), content: z.string() },
|
|
57
|
+
outputSchema: { success: z.boolean() },
|
|
58
|
+
},
|
|
59
|
+
async ({ filename, content }) => {
|
|
60
|
+
const filePath = path.join(ROOT_DIR, filename);
|
|
61
|
+
fs.writeFileSync(filePath, content, "utf-8");
|
|
62
|
+
return { structuredContent: { success: true } };
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
// ๐ง TOOL 4: Edit specific lines
|
|
68
|
+
server.registerTool(
|
|
69
|
+
"edit_file",
|
|
70
|
+
{
|
|
71
|
+
description: "Edit specific lines in an existing file",
|
|
72
|
+
inputSchema: {
|
|
73
|
+
filename: z.string(),
|
|
74
|
+
edits: z.array(z.object({ line: z.number().min(1), newText: z.string() })),
|
|
75
|
+
},
|
|
76
|
+
outputSchema: { success: z.boolean(), message: z.string() },
|
|
77
|
+
},
|
|
78
|
+
async ({ filename, edits }) => {
|
|
79
|
+
const filePath = path.join(ROOT_DIR, filename);
|
|
80
|
+
if (!fs.existsSync(filePath)) throw new Error("File not found");
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
const lines = fs.readFileSync(filePath, "utf-8").split("\n");
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
edits.forEach(({ line, newText }) => {
|
|
87
|
+
const idx = line - 1;
|
|
88
|
+
if (idx < 0 || idx >= lines.length) throw new Error(`Invalid line number: ${line}`);
|
|
89
|
+
lines[idx] = newText;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
fs.writeFileSync(filePath, lines.join("\n"), "utf-8");
|
|
94
|
+
return { structuredContent: { success: true, message: `Edited ${edits.length} line(s).` } };
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// ๐๏ธ TOOL 5: Delete a file
|
|
100
|
+
server.registerTool(
|
|
101
|
+
"delete_file",
|
|
102
|
+
{
|
|
103
|
+
description: "Delete a file by name",
|
|
104
|
+
inputSchema: { filename: z.string() },
|
|
105
|
+
outputSchema: { success: z.boolean() },
|
|
106
|
+
},
|
|
107
|
+
async ({ filename }) => {
|
|
108
|
+
const filePath = path.join(ROOT_DIR, filename);
|
|
109
|
+
if (fs.existsSync(filePath)) fs.unlinkSync(filePath);
|
|
110
|
+
return { structuredContent: { success: true } };
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
// ๐ Start the server over stdio transport
|
|
116
|
+
await server.connect(new StdioServerTransport());
|
|
117
|
+
console.log("โ
File MCP Server started successfully!");
|
|
118
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "rittika-file-assistant",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "",
|
|
11
|
+
"license": "ISC",
|
|
12
|
+
"description": "",
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@modelcontextprotocol/sdk": "^1.21.0"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
Binary file
|