Skip to main content
Glama
sirius-cc-wu

Markdown Notes MCP Server

by sirius-cc-wu
main.py3.49 kB
import os from fastmcp import FastMCP from config import settings mcp = FastMCP(name="MarkdownNotes") def _get_safe_path(user_path: str) -> str: """ Resolves a user-provided path against the base path and ensures it's safe. Raises: PermissionError: If the path is outside the base path. FileNotFoundError: If the path doesn't exist. """ base_path = os.path.realpath(settings.notes_dir) # Prevent user_path from being an absolute path if os.path.isabs(user_path): raise PermissionError("Error: Absolute paths are not allowed.") target_path = os.path.realpath(os.path.join(base_path, user_path)) if not target_path.startswith(base_path): raise PermissionError("Error: Access to paths outside of the notes directory is not allowed.") if not os.path.exists(target_path): raise FileNotFoundError(f"Error: Path \'{user_path}\' not found.") return target_path @mcp.tool def list_notes(path: str = "", recursive: bool = False) -> dict: """ Lists notes in a given directory relative to the base path. The base path can be set using the 'NOTES_DIR' environment variable, otherwise it defaults to the current working directory. """ try: safe_path = _get_safe_path(path) if recursive: file_list = [] for root, _, files in os.walk(safe_path): for file in files: full_path = os.path.join(root, file) relative_path = os.path.relpath(full_path, safe_path) file_list.append(relative_path) return {"status": "success", "data": file_list} else: return {"status": "success", "data": os.listdir(safe_path)} except (PermissionError, FileNotFoundError) as e: return {"status": "error", "error": str(e)} @mcp.tool def read_note(file_path: str) -> dict: """ Reads the content of a note file relative to the base path. The base path can be set using the 'NOTES_DIR' environment variable, otherwise it defaults to the current working directory. """ try: safe_path = _get_safe_path(file_path) if os.path.isdir(safe_path): return {"status": "error", "error": f"Error: \'{file_path}\' is a directory, not a file."} with open(safe_path, "r") as f: return {"status": "success", "data": f.read()} except (PermissionError, FileNotFoundError) as e: return {"status": "error", "error": str(e)} @mcp.tool def search_notes(keyword: str, recursive: bool = False) -> dict: """ Searches for a keyword in all markdown files in the notes directory. """ list_response = list_notes(recursive=recursive) if list_response["status"] == "error": return list_response results = [] for file_path in list_response["data"]: if file_path.endswith(".md"): read_response = read_note(file_path) if read_response["status"] == "success": for i, line in enumerate(read_response["data"].splitlines()): if keyword.lower() in line.lower(): results.append({ "file_path": file_path, "line_number": i + 1, "snippet": line.strip() }) return {"status": "success", "data": results} if __name__ == "__main__": mcp.run(transport="http", port=8080)

Latest Blog Posts

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/sirius-cc-wu/mcp-md-notes'

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