Skip to main content
Glama

Notion MCP Server

by funcion90
main.py8.62 kB
import os import asyncio import uvicorn import sys import logging import importlib import pkgutil from pathlib import Path from fastmcp import FastMCP def get_logger(): log_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'logs') os.makedirs(log_dir, exist_ok=True) log_file = os.path.join(log_dir, 'info.log') logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(levelname)s: %(message)s', handlers=[ logging.FileHandler(log_file, encoding="utf-8"), logging.StreamHandler() ] ) return logging.getLogger("MCP") class MCPServer(FastMCP): def __init__(self, specific_tools=None): super().__init__(name="MCP Server") self.logger = get_logger() self.logger.info("MCP Server 시작") self.specific_tools = specific_tools if specific_tools: self.logger.info(f"지정된 도구들만 로드: {', '.join(specific_tools)}") self.register_api() def register_api(self): """tools 디렉토리의 Python 파일을 로드하고 등록""" tools_dir = Path(__file__).parent / "tools" package_name = "tools" if not tools_dir.exists(): self.logger.error("tools 디렉토리가 존재하지 않습니다.") return # 로드할 도구 파일들 결정 if self.specific_tools: # 지정된 도구들만 로드 python_files = [] for tool_name in self.specific_tools: tool_file = tools_dir / f"{tool_name}.py" if tool_file.exists(): python_files.append(tool_file) else: self.logger.error(f"지정된 도구 파일을 찾을 수 없습니다: {tool_name}.py") self.logger.info(f"지정된 {len(python_files)}개의 도구 파일을 로드합니다.") else: # 모든 .py 파일 로드 python_files = [f for f in tools_dir.glob("*.py") if f.name != "__init__.py"] self.logger.info(f"{len(python_files)}개의 도구 파일을 발견했습니다.") if not python_files: self.logger.warning("로드할 도구 파일이 없습니다.") return loaded_tools = [] failed_tools = [] for tool_file in python_files: tool_name = tool_file.stem try: # 모듈 동적 로드 module = importlib.import_module(f"{package_name}.{tool_name}") # register 함수가 있는지 확인 if hasattr(module, "register"): module.register(self) loaded_tools.append(tool_name) self.logger.info(f"[OK] {tool_name} 도구가 성공적으로 로드되었습니다.") else: self.logger.warning(f"{tool_name} 모듈에 register 함수가 없습니다.") failed_tools.append(f"{tool_name} (register 함수 없음)") except Exception as e: error_msg = f"{tool_name} 로드 실패: {str(e)}" self.logger.error(f"[ERROR] {error_msg}") failed_tools.append(f"{tool_name} (로드 실패: {str(e)})") # 로딩 결과 요약 self.logger.info(f"도구 로딩 완료: 성공 {len(loaded_tools)}개, 실패 {len(failed_tools)}개") if loaded_tools: self.logger.info(f"로드된 도구들: {', '.join(loaded_tools)}") if failed_tools: self.logger.warning(f"실패한 도구들: {', '.join(failed_tools)}") def get_available_tools(self): """현재 등록된 도구들의 목록을 반환""" tools_dir = Path(__file__).parent / "tools" available_tools = [] if not tools_dir.exists(): return available_tools python_files = [f for f in tools_dir.glob("*.py") if f.name != "__init__.py"] for tool_file in python_files: tool_name = tool_file.stem try: module = importlib.import_module(f"tools.{tool_name}") if hasattr(module, "register"): available_tools.append(tool_name) except Exception: pass # 로드 실패한 도구는 무시 return available_tools def check_tools_availability(): """사용 가능한 도구들을 확인하고 표시""" tools_dir = Path(__file__).parent / "tools" available_tools = [] if not tools_dir.exists(): print("[ERROR] tools 디렉토리가 존재하지 않습니다.") return [] # .py 파일들만 필터링 python_files = [f for f in tools_dir.glob("*.py") if f.name != "__init__.py"] if not python_files: print("[ERROR] tools 디렉토리에 Python 파일이 없습니다.") return [] print("사용 가능한 도구들:") for tool_file in python_files: tool_name = tool_file.stem available_tools.append(tool_name) print(f" [OK] {tool_name}.py") return available_tools def check_specific_tool(tool_name): """특정 도구가 사용 가능한지 확인""" tools_dir = Path(__file__).parent / "tools" tool_file = tools_dir / f"{tool_name}.py" if tool_file.exists(): print(f"[OK] {tool_name} 도구가 사용 가능합니다.") return True else: print(f"[ERROR] {tool_name} 도구를 찾을 수 없습니다.") return False async def run_mcp_server(specific_tools=None): """MCP 서버 실행""" print("MCP 서버를 시작합니다...") if specific_tools: print(f"지정된 도구들만 로드합니다: {', '.join(specific_tools)}") # 지정된 도구들이 존재하는지 확인 available_tools = check_tools_availability() missing_tools = [tool for tool in specific_tools if tool not in available_tools] if missing_tools: print(f"[ERROR] 다음 도구들을 찾을 수 없습니다: {', '.join(missing_tools)}") print("사용 가능한 도구들:") for tool in available_tools: print(f" [OK] {tool}") return print(f"[OK] 모든 지정된 도구들이 존재합니다: {', '.join(specific_tools)}") else: print("모든 사용 가능한 도구들을 로드합니다.") available_tools = check_tools_availability() app = MCPServer(specific_tools=specific_tools) await app.run_async(transport=os.getenv("TRANSPORT", "stdio")) async def check_server_tools(): """서버에서 실제로 로드된 도구들을 확인""" try: app = MCPServer() available_tools = app.get_available_tools() if available_tools: print("서버에서 로드된 도구들:") for tool in available_tools: print(f" [OK] {tool}") else: print("[ERROR] 서버에서 로드된 도구가 없습니다.") except Exception as e: print(f"[ERROR] 서버 도구 확인 중 오류 발생: {e}") async def main(): # 명령행 인수 처리 if len(sys.argv) > 1: command = sys.argv[1] if command == "check-tools": check_tools_availability() return elif command == "check-tool" and len(sys.argv) > 2: check_specific_tool(sys.argv[2]) return elif command == "check-server-tools": await check_server_tools() return elif command == "help": print("사용법:") print(" python main.py # MCP 서버 실행 (모든 도구)") print(" python main.py check-tools # 사용 가능한 도구 목록 확인") print(" python main.py check-tool notion # 특정 도구 확인") print(" python main.py check-server-tools # 서버에서 로드된 도구 확인") print(" python main.py help # 도움말 표시") return else: # 첫 번째 인수가 명령어가 아니라면 도구 이름으로 간주 specific_tools = sys.argv[1:] await run_mcp_server(specific_tools) return await run_mcp_server() if __name__ == "__main__": asyncio.run(main())

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/funcion90/Mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server