Overview
This project aims to build and validate a remote API service enabling local filesystem operations by integrating MCP Server and Flask. The main functionalities include:
- Remote execution of operations such as directory listing, file creation, file deletion, and file modification.
- Providing an HTTP API interface with Flask, powered by MCP Server.
Setup Instructions
1. Install Required Packages
Node.js and MCP Server
MCP Server requires Node.js. Follow these steps to install:
- Install the latest LTS version of Node.js from Node.js Official Website.
- Install MCP Server globally:
npm install -g @modelcontextprotocol/server-filesystem
Python and Flask
To build the remote API server with Flask, you’ll need the Python environment:
- Download and install Python from Python Official Website.
- Install the required libraries:
pip install flask flask-cors
2. Project Directory Structure
Create the files and directories according to the following structure:
C:\dev\mcp\
│
├── server-filesystem.cmd
├── bridge.js
└── flask_api.py
Code Details
server-filesystem.cmd
A script for launching MCP Server to enable remote filesystem operations:
@echo off
npx -y @modelcontextprotocol/server-filesystem C:\dev\mcp\test
bridge.js
A Node.js script to execute and test MCP Server behaviors (CRUD operations):
const { spawn } = require("child_process");
// 调用 server-filesystem.cmd 启动 MCP Server
const mcpServer = spawn("cmd.exe", ["/c", "C:\\dev\\mcp\\server-filesystem\\server-filesystem.cmd"], {
env: process.env, // 继承当前环境变量
shell: true // 必须启用 shell 模式以运行 .cmd 文件
});
// 监听标准输出,打印 MCP 服务输出日志
mcpServer.stdout.on("data", (data) => {
console.log(`MCP Server Output: ${data}`);
});
// 监听标准错误(已分类处理)
// 将已知的启动信息归类为 "MCP Server Info",其他则作为真正的错误
mcpServer.stderr.on("data", (data) => {
const message = data.toString();
if (message.includes("Secure MCP Filesystem Server")) {
console.log(`MCP Server Info: ${message}`);
} else if (message.includes("Allowed directories")) {
console.log(`MCP Server Info: ${message}`);
} else {
console.error(`MCP Server Error: ${message}`);
}
});
// 捕获 MCP 服务关闭事件
mcpServer.on("close", (code) => {
console.log(`MCP Server exited with code ${code}`);
});
// === 新增功能:测试 MCP Server 的功能 ===
// 延迟执行功能以确保 MCP Server 已启动完成
setTimeout(() => {
// 测试 1:列出目录内容
console.log("Running Directory List Test...");
const listTest = spawn("cmd.exe", ["/c", "dir C:\\dev\\mcp\\test"], {
env: process.env,
shell: true,
});
listTest.stdout.on("data", (data) => {
console.log(`Directory List Output: ${data}`);
});
listTest.stderr.on("data", (data) => {
console.error(`Directory List Error: ${data}`);
});
listTest.on("close", () => {
console.log("Directory List Test Finished.");
});
}, 3000); // 延迟 3 秒进行目录列表测试
setTimeout(() => {
// 测试 2:创建新文件
console.log("Running File Creation Test...");
const writeTest = spawn("cmd.exe", ["/c", "echo Hello, MCP Server! > C:\\dev\\mcp\\test\\test-write.txt"], {
env: process.env,
shell: true,
});
writeTest.stdout.on("data", (data) => {
console.log(`File Creation Output: ${data}`);
});
writeTest.stderr.on("data", (data) => {
console.error(`File Creation Error: ${data}`);
});
writeTest.on("close", () => {
console.log("File Creation Test Finished. Please check the file in 'C:\\dev\\mcp\\test'.");
});
}, 7000); // 延迟 7 秒执行文件创建测试
// 测试 4:删除刚创建的文件
setTimeout(() => {
console.log("Running File Deletion Test...");
const deleteTest = spawn("cmd.exe", ["/c", "del C:\\dev\\mcp\\test\\test-write.txt"], {
env: process.env,
shell: true,
});
deleteTest.stdout.on("data", (data) => {
console.log(`File Deletion Output: ${data}`);
});
deleteTest.stderr.on("data", (data) => {
console.error(`File Deletion Error: ${data}`);
});
deleteTest.on("close", () => {
console.log("File Deletion Test Finished. Please check if the file is removed from 'C:\\dev\\mcp\\test'.");
});
}, 15000); // 延迟 15 秒测试文件删除
flask_api.py
A Flask API server that provides CRUD operations through HTTP requests:
from flask import Flask, request, jsonify, make_response
from flask_cors import CORS
import subprocess
import json # Use json module for building responses manually
# Initialize Flask app
app = Flask(__name__)
# Enable Cross-Origin Resource Sharing (CORS)
CORS(app)
# Ensure Flask does not escape non-ASCII characters in responses
app.config['JSON_AS_ASCII'] = False
# Utility function: Construct JSON response with UTF-8 encoding
def json_response(data, status=200):
response = make_response(json.dumps(data, ensure_ascii=False), status)
response.headers['Content-Type'] = 'application/json; charset=utf-8'
return response
# Route: List directory contents
@app.route('/list-files', methods=['GET'])
def list_files():
# Fetch 'dir' parameter from the GET request
directory = request.args.get('dir')
if not directory:
return json_response({"error": "Missing 'dir' parameter"}, 400)
try:
# Use subprocess to run the Windows 'dir' command
result = subprocess.run(
["cmd.exe", "/c", f"dir {directory}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
# If the command failed, return the error
if result.returncode != 0:
return json_response({"error": result.stderr.strip()}, 500)
# Return the directory listing as the response
return json_response({"output": result.stdout.strip()})
except Exception as e:
# Catch any unexpected exceptions
return json_response({"error": str(e)}, 500)
# Route: Create a file with content
@app.route('/create-file', methods=['POST'])
def create_file():
# Parse the file_path and content from the POST request
data = request.get_json()
file_path = data.get('file_path')
content = data.get('content', '')
if not file_path:
return json_response({"error": "Missing 'file_path' parameter"}, 400)
try:
# Use subprocess to run the Windows 'echo' command to write to a file
result = subprocess.run(
["cmd.exe", "/c", f"echo {content} > {file_path}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
# If the command failed, return the error
if result.returncode != 0:
return json_response({"error": result.stderr.strip()}, 500)
# Return success message
return json_response({"message": f"File '{file_path}' created successfully"})
except Exception as e:
# Catch any unexpected exceptions
return json_response({"error": str(e)}, 500)
# Route: Delete a specific file
@app.route('/delete-file', methods=['DELETE'])
def delete_file():
# Parse the file_path from the DELETE request
data = request.get_json()
file_path = data.get('file_path')
if not file_path:
return json_response({"error": "Missing 'file_path' parameter"}, 400)
try:
# Use subprocess to run the Windows 'del' command to delete the file
result = subprocess.run(
["cmd.exe", "/c", f"del {file_path}"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True
)
# If the command failed, return the error
if result.returncode != 0:
return json_response({"error": result.stderr.strip()}, 500)
# Return success message
return json_response({"message": f"File '{file_path}' deleted successfully"})
except Exception as e:
# Catch any unexpected exceptions
return json_response({"error": str(e)}, 500)
# Route: Read contents of a specific file
@app.route('/read-file', methods=['GET'])
def read_file():
# Fetch 'file_path' parameter from the GET request
file_path = request.args.get('file_path')
if not file_path:
return json_response({"error": "Missing 'file_path' parameter"}, 400)
try:
# Open the file in 'read' mode with UTF-8 encoding
with open(file_path, 'r', encoding='utf-8') as file:
content = file.read()
# Return the file content in the response
return json_response({"file_path": file_path, "content": content})
except FileNotFoundError:
# Return 404 if the file does not exist
return json_response({"error": f"File '{file_path}' not found."}, 404)
except Exception as e:
# Catch any unexpected exceptions
return json_response({"error": str(e)}, 500)
# Run the Flask app on all available IPs (0.0.0.0) at port 5000
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
Important Notes
- Path Formatting:
- Ensure file paths sent to the Flask API use double backslashes (e.g.,
C:\\path\\to\\file).
- Security:
- Add additional security layers (e.g., API Keys or access control) as file operations can pose risks.
- Production Deployment:
- Flask’s development server is not suitable for production. Use Gunicorn or uWSGI for deployment.
Using bridge.js (Node.js Script)
To test and interact with the MCP server for file operations, run:
node bridge.js
- Starts the MCP server.
- Performs directory listing, file creation, and file deletion tests, with results outputted in the console.
Starting Flask API (flask_api.py)
To host the API server:
- Navigate to the project directory.
- Run the script:
python flask_api.py
- API will be available at
http://0.0.0.0:5000for HTTP operations.
Testing Results
- Sample
curlCommands (for Ubuntu):
# check folder
curl "http://yourTargetIP:yourTargetPort/list-files?dir=C:\\dev\\mcp\\test"
# create file
curl -X POST -H "Content-Type: application/json" \
-d '{"file_path": "C:\\dev\\mcp\\test\\test.txt", "content": "Created via Flask API"}' \
"http://yourTargetIP:yourTargetPort/create-file"
# read file
curl "http://yourTargetIP:yourTargetPort/read-file?file_path=C:\\dev\\mcp\\test\\test.txt"
# delete file
curl -X DELETE -H "Content-Type: application/json" \
-d '{"file_path": "C:\\dev\\mcp\\test\\test.txt"}' \
"http://yourTargetIP:yourTargetPort/delete-file"
Future Enhancements
- Enable file upload and download functionality.
- Introduce authentication mechanisms to RESTful APIs.
- Add batch operations and file movement capabilities.