|
|
Python에서 FastMCP를 이용해 MCP 서버를 만들고 싶습니다.
@ mcp.tool() 데코레이터를 사용해서 아래 기능을 지원하는 서버 코드를 작성해 주세요:
1. D:/Github/Claude_Code_WS/basic/file2/ 아래에 새 폴더 생성(create_folder)
2. D:/Github/Claude_Code_WS/basic/file2/ 아래 폴더 삭제(delete_folder)
3. D:/Github/Claude_Code_WS/basic/file2/ 아래 폴더 목록 반환(list_folders)
4. D:/Github/Claude_Code_WS/basic/file2/ 아래에 새 파일 생성 및 내용 작성(write_file)
5. D:/Github/Claude_Code_WS/basic/file2/ 아래 파일 내용 읽기(read_file)
6. D:/Github/Claude_Code_WS/basic/file2/아래 파일에 내용 추가(append_to_file)
7. D:/Github/Claude_Code_WS/basic/file2/ 아래 파일 목록 반환(list_files)
각 함수는 문자열 또는 리스트를 반환하고, 예외 발생 시 사용자 친화적인 오류 메시지를 반환하도록 해주세요.
마지막에는 if __name__ == "__main__": mcp.run() 구문으로 서버 실행 부분도 포함해 주세요.
#!/usr/bin/env python3
"""
FastMCP를 사용한 파일 관리 MCP 서버
D:/Github/Claude_Code_WS/basic/file2/ 경로 하위에서 파일 및 폴더 관리 기능 제공
"""
import os
from pathlib import Path
from typing import List, Union
from mcp.server.fastmcp import FastMCP
# MCP 서버 인스턴스 생성
mcp = FastMCP("File Manager")
# 기본 작업 디렉토리 설정
BASE_PATH = Path("D:/Github/Claude_Code_WS/basic/file2")
def ensure_base_path():
"""기본 경로가 존재하지 않으면 생성"""
try:
BASE_PATH.mkdir(parents=True, exist_ok=True)
return True
except Exception as e:
return False
def validate_path(path: str) -> Path:
"""경로 유효성 검사 및 절대 경로 반환"""
full_path = BASE_PATH / path
# 보안을 위해 BASE_PATH 하위에서만 작업하도록 제한
try:
full_path.resolve().relative_to(BASE_PATH.resolve())
return full_path
except ValueError:
raise ValueError("경로는 기본 디렉토리 내부에 있어야 합니다.")
@mcp.tool()
def create_folder(folder_name: str) -> str:
"""
새 폴더를 생성합니다.
Args:
folder_name (str): 생성할 폴더명 (상대 경로 가능)
Returns:
str: 성공/실패 메시지
"""
try:
ensure_base_path()
folder_path = validate_path(folder_name)
if folder_path.exists():
return f"❌ 폴더가 이미 존재합니다: {folder_name}"
folder_path.mkdir(parents=True, exist_ok=False)
return f"✅ 폴더가 성공적으로 생성되었습니다: {folder_name}"
except ValueError as e:
return f"❌ 경로 오류: {str(e)}"
except PermissixxxxonError:
return f"❌ 권한 부족: {folder_name} 폴더를 생성할 수 없습니다."
except Exception as e:
return f"❌ 폴더 생성 실패: {str(e)}"
@mcp.tool()
def delete_folder(folder_name: str) -> str:
"""
폴더를 삭제합니다 (비어있는 폴더만).
Args:
folder_name (str): 삭제할 폴더명 (상대 경로 가능)
Returns:
str: 성공/실패 메시지
"""
try:
folder_path = validate_path(folder_name)
if not folder_path.exists():
return f"❌ 폴더가 존재하지 않습니다: {folder_name}"
if not folder_path.is_dir():
return f"❌ 파일입니다. 폴더가 아닙니다: {folder_name}"
# 폴더가 비어있는지 확인
if any(folder_path.iterdir()):
return f"❌ 폴더가 비어있지 않습니다: {folder_name}"
folder_path.rmdir()
return f"✅ 폴더가 성공적으로 삭제되었습니다: {folder_name}"
except ValueError as e:
return f"❌ 경로 오류: {str(e)}"
except PermissixxxxonError:
return f"❌ 권한 부족: {folder_name} 폴더를 삭제할 수 없습니다."
except Exception as e:
return f"❌ 폴더 삭제 실패: {str(e)}"
@mcp.tool()
def list_folders(path: str = "") -> List[str]:
"""
지정된 경로의 폴더 목록을 반환합니다.
Args:
path (str): 검색할 경로 (기본값: 루트)
Returns:
List[str]: 폴더명 리스트
"""
try:
ensure_base_path()
search_path = validate_path(path) if path else BASE_PATH
if not search_path.exists():
return [f"❌ 경로가 존재하지 않습니다: {path}"]
if not search_path.is_dir():
return [f"❌ 디렉토리가 아닙니다: {path}"]
folders = []
for item in search_path.iterdir():
if item.is_dir():
folders.append(item.name)
folders.sort()
return folders if folders else ["📁 폴더가 없습니다."]
except ValueError as e:
return [f"❌ 경로 오류: {str(e)}"]
except PermissixxxxonError:
return [f"❌ 권한 부족: {path} 폴더에 접근할 수 없습니다."]
except Exception as e:
return [f"❌ 폴더 목록 조회 실패: {str(e)}"]
@mcp.tool()
def write_file(file_path: str, content: str) -> str:
"""
새 파일을 생성하고 내용을 작성합니다.
Args:
file_path (str): 파일 경로 (상대 경로)
content (str): 파일에 작성할 내용
Returns:
str: 성공/실패 메시지
"""
try:
ensure_base_path()
full_path = validate_path(file_path)
# 상위 디렉토리가 없으면 생성
full_path.parent.mkdir(parents=True, exist_ok=True)
with open(full_path, 'w', encoding='utf-8') as f:
f.write(content)
return f"✅ 파일이 성공적으로 생성되었습니다: {file_path} ({len(content)}자)"
except ValueError as e:
return f"❌ 경로 오류: {str(e)}"
except PermissixxxxonError:
return f"❌ 권한 부족: {file_path} 파일을 생성할 수 없습니다."
except Exception as e:
return f"❌ 파일 생성 실패: {str(e)}"
@mcp.tool()
def read_file(file_path: str) -> str:
"""
파일 내용을 읽어 반환합니다.
Args:
file_path (str): 읽을 파일 경로 (상대 경로)
Returns:
str: 파일 내용 또는 오류 메시지
"""
try:
full_path = validate_path(file_path)
if not full_path.exists():
return f"❌ 파일이 존재하지 않습니다: {file_path}"
if not full_path.is_file():
return f"❌ 디렉토리입니다. 파일이 아닙니다: {file_path}"
with open(full_path, 'r', encoding='utf-8') as f:
content = f.read()
return content if content else "📄 파일이 비어있습니다."
except ValueError as e:
return f"❌ 경로 오류: {str(e)}"
except PermissixxxxonError:
return f"❌ 권한 부족: {file_path} 파일을 읽을 수 없습니다."
except UnicodeDecodeError:
return f"❌ 인코딩 오류: {file_path} 파일을 UTF-8로 읽을 수 없습니다."
except Exception as e:
return f"❌ 파일 읽기 실패: {str(e)}"
@mcp.tool()
def append_to_file(file_path: str, content: str) -> str:
"""
기존 파일에 내용을 추가합니다.
Args:
file_path (str): 파일 경로 (상대 경로)
content (str): 추가할 내용
Returns:
str: 성공/실패 메시지
"""
try:
full_path = validate_path(file_path)
if not full_path.exists():
return f"❌ 파일이 존재하지 않습니다: {file_path}"
if not full_path.is_file():
return f"❌ 디렉토리입니다. 파일이 아닙니다: {file_path}"
with open(full_path, 'a', encoding='utf-8') as f:
f.write(content)
return f"✅ 파일에 내용이 성공적으로 추가되었습니다: {file_path} (+{len(content)}자)"
except ValueError as e:
return f"❌ 경로 오류: {str(e)}"
except PermissixxxxonError:
return f"❌ 권한 부족: {file_path} 파일에 내용을 추가할 수 없습니다."
except Exception as e:
return f"❌ 파일 내용 추가 실패: {str(e)}"
@mcp.tool()
def list_files(path: str = "") -> List[str]:
"""
지정된 경로의 파일 목록을 반환합니다.
Args:
path (str): 검색할 경로 (기본값: 루트)
Returns:
List[str]: 파일명 리스트
"""
try:
ensure_base_path()
search_path = validate_path(path) if path else BASE_PATH
if not search_path.exists():
return [f"❌ 경로가 존재하지 않습니다: {path}"]
if not search_path.is_dir():
return [f"❌ 디렉토리가 아닙니다: {path}"]
files = []
for item in search_path.iterdir():
if item.is_file():
# 파일 크기 정보 포함
size = item.stat().st_size
if size < 1024:
size_str = f"{size}B"
elif size < 1024 * 1024:
size_str = f"{size/1024:.1f}KB"
else:
size_str = f"{size/(1024*1024):.1f}MB"
files.append(f"{item.name} ({size_str})")
files.sort()
return files if files else ["📄 파일이 없습니다."]
except ValueError as e:
return [f"❌ 경로 오류: {str(e)}"]
except PermissixxxxonError:
return [f"❌ 권한 부족: {path} 폴더에 접근할 수 없습니다."]
except Exception as e:
return [f"❌ 파일 목록 조회 실패: {str(e)}"]
if __name__ == "__main__":
print("🚀 FastMCP 파일 관리 서버 시작...")
print(f"📁 작업 경로: {BASE_PATH}")
mcp.run()
