System Setup Guide for Remote Local File Manipulation Using Flask and MCP Server

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:

  1. Install the latest LTS version of Node.js from Node.js Official Website.
  2. 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:

  1. Download and install Python from Python Official Website.
  2. 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

  1. Path Formatting:
  • Ensure file paths sent to the Flask API use double backslashes (e.g., C:\\path\\to\\file).
  1. Security:
  • Add additional security layers (e.g., API Keys or access control) as file operations can pose risks.
  1. 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:

  1. Navigate to the project directory.
  2. Run the script:
   python flask_api.py
  1. API will be available at http://0.0.0.0:5000 for HTTP operations.

Testing Results

  1. Sample curl Commands (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.

Setting Up Qt Development Environment on Ubuntu

---

**Update Your Package List:**  
`sudo apt update -y`  

---

**Install Qt Creator (Qt Integrated Development Environment):**  
`sudo apt install qtcreator -y`  

---

**Install Qt 5 Development Libraries and Tools:**  
Install `qtbase5-dev` and related toolkits, which provide core development files for Qt 5:  
`sudo apt install qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools -y`  

---

**For a Complete Qt Development Environment (with GUI support):**  
You can additionally install:  
`sudo apt install qtdeclarative5-dev qttools5-dev-tools -y`  

---

**Verify Installation and Check Tool Versions:**  
Ensure `qmake` is installed and available:  
`qmake --version`  

Expected output should resemble:  

QMake version 3.x
Using Qt version 5.x in /usr/lib/x86_64-linux-gnu

---

**Test the Installation:**  
Launch the Qt Creator development tool:  
`qtcreator`  

Resize the swap partition to free space and reassign it to the root partition

1.Insert and boot your Ubuntu Live CD/USB

2.Mount the root partition (assuming nvme0n1p2 is your root partition):

sudo mkdir /mnt/root
sudo mount /dev/nvme0n1p2 /mnt/root

3.Edit the /etc/fstab file within the root partition:

sudo vi /mnt/root/etc/fstab

4.Comment out or delete the swap entry, then save it. e.g.:

# UUID=yourUUID none swap sw 0 0

5.Start GParted:

sudo gparted

6.Shrink swap partition nvme0n1p3:

Right-click nvme0n1p3 swap partition, choose Resize/Move.

Adjust it to the desired size (e.g., 16GB).

Click Resize/Move.

7.Expand root partition nvme0n1p2(Note: Resize operations are possible only on contiguous space.):

Right-click nvme0n1p2 root partition, choose Resize/Move.

Drag the right slider to use the space freed from the swap partition.

Click Resize/Move.

8.Mount the root partition again:

sudo mount /dev/nvme0n1p2 /mnt/root

Edit the /etc/fstab file within the root partition:

sudo vi /mnt/root/etc/fstab

modify the existing swap entry with the new UUID

9.Reboot to your normal system, not the Live CD/USB.

10.Enable the new swap partition:

sudo swapon -a

11.Check if the new swap partition is active:

sudo swapon --show

Confirm root and swap partition sizes:

df -hT

Solution for VS Code and KWallet Integration Issues on Ubuntu

“You’re running in a KDE environment but the OS keyring is not available for encryption. Ensure you have kwallet running.”, follow these steps to configure VS Code to use gnome-libsecret instead of KWallet:

1. Create Configuration File:

touch ~/.config/Code/User/argv.json

then write the content:

{
  "password-store": "gnome-libsecret"
}

2. Install Prerequisites:

Install gnome-keyring by running:

sudo apt install gnome-keyring -y

3. Launch VS Code with gnome-libsecret:

code --password-store="gnome-libsecret"

Using UFW Firewall with Docker Containers

Running Docker containers with UFW firewall setup can be challenging because Docker manipulates iptables rules by default. However, with some configuration, you can ensure both Docker and UFW work well together. Below is a step-by-step guide to configure Docker to not interfere with iptables and manually set up UFW rules.

1. Configure Docker Daemon, make “iptables”: false

sudo vi /etc/docker/daemon.json

should like below:

{
    "runtimes": {
        "nvidia": {
            "path": "nvidia-container-runtime",
            "runtimeArgs": []
        }
    },
    "iptables": false
}

2. Restart Docker

sudo systemctl restart docker

3. Modify UFW Forward Policy

sudo sed -i -e 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/g' /etc/default/ufw

4. Reload UFW to apply the changes:

sudo ufw reload

Reference:

How to Install CUDA12.5 on Ubuntu 22.04.4 LTS

1. Download and Install CUDA Keyring:

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
sudo dpkg -i cuda-keyring_1.1-1_all.deb

2. Update system and Install CUDA Toolkit:

sudo apt-get update -y
sudo apt-get install cuda-toolkit -y

3. Reboot:

sudo sync; sudo /sbin/shutdown -r now

4. Configure Environment Variables:

Add the following lines to the end of your ~/.bashrc file to set the environment variables:

export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-12.5/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}

then:

source ~/.bashrc

5. Verify the Installation

nvcc -V

You should see an output similar to:

nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2024 NVIDIA Corporation
Built on Thu_Jun__6_02:18:23_PDT_2024
Cuda compilation tools, release 12.5, V12.5.82
Build cuda_12.5.r12.5/compiler.34385749_0

Additional Notes:

Persistence Daemon: If you want to enable the NVIDIA Persistence Daemon for better GPU management, you can start it as root:

/usr/bin/nvidia-persistenced --verbose

Deploy GPU-accelerated applications in containers:

sudo apt-get install -y nvidia-docker2

Then test:

sudo docker run --rm --gpus all nvidia/cuda:12.5.0-base-ubuntu22.04 nvidia-smi

Install nvidia driver:

sudo apt-get install nvidia-driver-555

Then, test:

nvidia-smi

reference:

CUDA Toolkit 12.5 Update 1 Downloads

Installing the NVIDIA Container Toolkit

NVIDIA CUDA Installation Guide for Linux

How to Install CUDA on Ubuntu 22.04 | Step-by-Step

NVIDIA Driver Downloads

Optimizing Video Compression with ffmpeg and hevc_nvenc

ffmpeg -i fileName.mp4 -c:v hevc_nvenc -preset slow -rc:v vbr -cq:v 24 -b:v 0 -c:a aac -b:a 128k -vf scale=1280:-1 -movflags +faststart fileName_compressed.mp4
FlagExplanation
-i fileName.mp4Specifies the input file as fileName.mp4
-c:v hevc_nvencSets the video codec to NVIDIA’s HEVC encoder
-preset slowSets the encoding preset to “slow” for better compression efficiency
-rc:v vbrSets the rate control mode to variable bitrate
-cq:v 24Sets the Constant Quality (CQ) value to 24 (lower values mean higher quality)
-b:v 0Sets the target bitrate to 0, allowing CQ mode to determine the bitrate
-c:a aacSets the audio codec to AAC
-b:a 128kSets the audio bitrate to 128 kbps
-vf scale=1280:-1Scales the video width to 1280 pixels, height scaled proportionally
-movflags +faststartOptimizes the file for web streaming, allowing faster video startup
fileName_compressed.mp4Specifies the output filename
This command utilizes your NVIDIA GPU for encoding, which can be significantly faster than CPU encoding. The quality control is managed through the CQ (Constant Quality) value, where lower values result in higher quality but larger file sizes.

smaller:

ffmpeg -i 1.mp4 -c:v hevc_nvenc -preset slow -rc:v vbr -cq:v 29 -b:v 450k -c:a aac -b:a 96k -vf scale=960:-1 -movflags +faststart 2.mp4

Configuring a Static IP on Linux by Netplan Configuration Template

  1. Configuration File (/etc/netplan/01-network-manager-all.yaml):
# Let NetworkManager manage all devices on this system
network:
  version: 2
  renderer: NetworkManager
  ethernets:
      eth0:
          dhcp4: no
          addresses:
              - xx.xx.xx.xx/xx
          routes:
            - to: default
              via: yy.yy.yy.yy
          nameservers:
              addresses:
                  - zz.zz.zz.zz
                  - aa.aa.aa.aa
                  - bb.bb.bb.bb

xx.xx.xx.xx/xx: the static IP address assigned to the network interface with subnet mask information

yy.yy.yy.yy: the IP address of the gateway

zz.zz.zz.zz: Primary DNS server

aa.aa.aa.aa: Secondary DNS server

bb.bb.bb.bb: Tertiary DNS server

2. apply netplan and then rebooot

sudo netplan apply

Share Data Between Windows Server and Hyper-V Using VHDX Files

1. Creating a VHDX File on the Host:

Open Hyper-V Manager:

  • On the Windows Server host, search for and open “Hyper-V Manager”.

Create a New Virtual Hard Disk (VHDX):

  • In the right-hand action pane, choose “New” > “Hard Disk…”, to start the new virtual hard disk wizard.
  • Select the VHDX format, specify its size and save location (e.g., D:\Shared.vhdx).

Complete the Wizard:

  • Finish the wizard, ensuring you choose fixed size for better performance instead of dynamic expansion.

2. Attaching the VHDX File on the Host:

Open Disk Management:

  • Search for “Disk Management” or open it by running diskmgmt.msc.

Attach the VHDX File:

  • In the Disk Management menu, choose “Action” > “Attach VHD…”, select and attach the newly created VHDX file (D:\Shared.vhdx).
  • Initialize, partition, and format the VHDX file upon first attachment.
  • After this, the VHDX file will appear like a regular disk and can be written to.

3. Attaching the VHDX File to the Ubuntu Virtual Machine:

Open Hyper-V Manager:

  • Make sure to save any pending files and shut down the target virtual machine, and also unmount shared folder (as cannot use it meanwhile) in Windows Server side.

Access Virtual Machine Settings:

  • Right-click the target virtual machine and select “Settings”.
  • In the hardware section of the virtual machine, choose “SCSI Controller” or “IDE Controller” and click “Add Hard Drive…”.

Select the VHDX File:

  • In the pop-up dialog, choose “Use an existing virtual hard disk”, select the VHDX file created earlier (e.g., D:\Shared.vhdx).
  • Click “Apply” to save the changes.

4.confirm the VHDX File in Ubuntu:

Use the lsblk command in the terminal to check the new hard disk device.

Configuring a Static IP on Windows Server 2022 and Setting Up External Virtual Switch in Hyper-V

Configuring a Static IP on Windows Server 2022:

1. Open Network and Sharing Center:

In the left menu, select “Change adapter settings”.

2. Select and Right-Click Your Network Connection, then Select “Properties”

3. Select “Internet Protocol Version 4 (TCP/IPv4)”:

Click the item, then click “Properties”.

4. Configure IPv4 Settings:

Select “Use the following IP address” and enter the information provided by your network administrator: eg:

IP address: 10.x.x.x
Subnet mask: 255.255.254.0
Default gateway: 10.x.x.x

Select “Use the following DNS server addresses” and enter the DNS servers:

Preferred DNS server: 10.x.x.x
Alternate DNS server: 10.x.x.x or 10.x.x.x

5. Confirm and Apply Settings:

Click “OK” to complete, then click “OK” or “Close” again to close the properties window.

6. Restart Network Connection (Optional):

Right-click on the configured network connection and select “Disable”, then right-click again and select “Enable”.

Setting Up an External Virtual Switch in Hyper-V:

1. Launch Hyper-V Manager and select the host you wish to configure.

2. Create an External Virtual Switch:

In the “Actions” menu on the right, click “Virtual Switch Manager”.
Select “New virtual network switch”, then choose “External”.
Click “Create”.

3. Configure the External Virtual Switch:

In the “Name” field, give the switch a meaningful name, e.g., “ExternalSwitch”.
In the “Connection Type” section, select your only physical network adapter.
Check “Allow management operating system to share this network adapter”.

4.Apply and Confirm Settings:

Click “Apply” and “OK” to confirm.

This allows both the host and virtual machines to connect to the internet simultaneously.

通过 WordPress.com 设计一个这样的站点
从这里开始