File size: 4,921 Bytes
2f99641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f36616f
 
99d29c7
 
 
 
f36616f
 
2f99641
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import gradio as gr
from pathlib import Path
import traceback
from filesystem_access import FilesystemAccess
import os

fs = FilesystemAccess(os.getenv("FILES_DIR"))

allow_writes = os.getenv("ALLOW_EDITING") == "true" or os.getenv("ALLOW_EDITING") == "1"

def safe_exec(func, *args, **kwargs):
    try:
        return func(*args, **kwargs)
    except FileNotFoundError as e:
        print(f"Not found: {str(e)}")
        return f"Error: Not found"
    except FileExistsError as e:
        print(f"Already exists: {str(e)}")
        return f"Error: Already exists"
    except Exception as e:
        print(f"Error: {str(e)}\n{traceback.format_exc()}")
        return f"Error"

def read_file(path):
    return safe_exec(fs.read_file, path)

def read_multiple_files(paths):
    path_list = [p.strip() for p in paths.split(',') if p.strip()]

    file_contents = []
    try: 
        for path in path_list:
            
            try:
                file_content = fs.read_file(path)
                file_contents.append(f"{path}:\n{file_content}\n")
            except Exception as e:
                file_contents.append(f"{path}:Error - Could not read file")
        return "\n---\n".join(file_contents)
    
    except Exception as e:
        print(f"Error: {str(e)}\n{traceback.format_exc()}")
        return f"Error"

def write_file(path, content):
    return safe_exec(fs.write_file, path, content) or "File written successfully."

def create_directory(path):
    return safe_exec(fs.create_directory, path) or "Directory ensured."

def list_directory(path):
    return '\n'.join(safe_exec(fs.list_directory, path))

def move_file(source, destination):
    return safe_exec(fs.move_file, source, destination) or "Move successful."

def search_files(path, pattern, exclude):
    exclude_list = [e.strip() for e in exclude.split(',') if e.strip()]
    return '\n'.join(safe_exec(fs.search_files, path, pattern, exclude_list))

def directory_tree(path):
    return safe_exec(fs.directory_tree, path)

with gr.Blocks() as demo:

    gr.Markdown("""
        # Motion Canvas Docs MCP Server
        This is a simple MCP server based on Gradio that allows you to read doc files for Motion Canvas.
        It is based on the Gradio Fileserver MCP Server: https://huggingface.co/spaces/prathje/gradio_fileserver_mcp
        The API is a simpler version of https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem
    """)

    with gr.Tab("Read File"):
        path = gr.Textbox(label="Path", value="index.md")
        output = gr.Textbox(label="File Contents")
        btn = gr.Button("Read")
        btn.click(fn=read_file, inputs=path, outputs=output)

    with gr.Tab("Read Multiple Files"):
        paths = gr.Textbox(label="Comma-separated Paths", value="index.md,index.html")
        output = gr.Textbox(label="Results")
        btn = gr.Button("Read")
        btn.click(fn=read_multiple_files, inputs=paths, outputs=output)

    with gr.Tab("List Directory"):
        path = gr.Textbox(label="Directory Path", value=".")
        output = gr.Textbox(label="Contents")
        btn = gr.Button("List")
        btn.click(fn=list_directory, inputs=path, outputs=output)

    with gr.Tab("Directory Tree"):
        path = gr.Textbox(label="Directory Path", value=".")
        output = gr.Textbox(label="Contents")
        btn = gr.Button("Show Tree")
        btn.click(fn=directory_tree, inputs=path, outputs=output)

    with gr.Tab("Search Files"):
        path = gr.Textbox(label="Search Directory", value=".")
        pattern = gr.Textbox(label="Pattern", value="*.html")
        exclude = gr.Textbox(label="Exclude Patterns (comma-separated)", value="*.md")
        output = gr.Textbox(label="Matches")
        btn = gr.Button("Search")
        btn.click(fn=search_files, inputs=[path, pattern, exclude], outputs=output)

    if allow_writes:
        with gr.Tab("Write File"):
            path = gr.Textbox(label="Path", value="index.html")
            content = gr.Textbox(label="Content", lines=10, value="<html><body><h1>Hello World</h1></body></html>")
            output = gr.Textbox(label="Status")
            btn = gr.Button("Write")
            btn.click(fn=write_file, inputs=[path, content], outputs=output)

        with gr.Tab("Create Directory"):
            path = gr.Textbox(label="Directory Path", value="test")
            output = gr.Textbox(label="Status")
            btn = gr.Button("Create")
            btn.click(fn=create_directory, inputs=path, outputs=output)

        with gr.Tab("Move File"):
            source = gr.Textbox(label="Source Path", value="index.html")
            destination = gr.Textbox(label="Destination Path", value="test/index.html")
            output = gr.Textbox(label="Status")
            btn = gr.Button("Move")
            btn.click(fn=move_file, inputs=[source, destination], outputs=output)
    

if __name__ == "__main__":
    demo.launch()