手写 MCP Server 控制文件系统:50 行代码让 AI 学会读写文件 上周发了篇手写 MCP Server 连数据库的文章有个读者留言说“能不能也写篇怎么让 AI 读写文件的”我当时愣了一下——好像确实网上聊 MCP 的大多都在讲数据库、API、浏览器自动化很少有人提最基础的“读写文件”这件事。但我真去试了之后发现文件系统控制反而是 MCP 最有实用价值的场景之一。不是因为它多复杂——代码量可能比数据库那个还少——而是因为你每天都在跟文件打交道找一份好久没打开的笔记、批量重命名一堆下载文件、把散落在各个文件夹的素材汇总到一起。这些事情 AI 本来做不了因为它看不见你的硬盘。但现在能了。MCP 协议本质上就是个“桥”——它让 AI 通过一套标准接口调用你本地的工具。文件系统操作是这套接口里最直观的一种读文件、写文件、搜文件跟你在终端里做的事情一模一样。代码大概长这样。server.py — 不到 50 行的 MCP 文件服务器import os from pathlib import Path from mcp.server import Server, stdio server Server(filesystem-server) server.tool() async def read_file(path: str) - str: path Path(path).resolve() if not path.exists(): return f文件不存在: {path} return path.read_text(encodingutf-8) server.tool() async def write_file(path: str, content: str): path Path(path).resolve() path.parent.mkdir(parentsTrue, exist_okTrue) path.write_text(content, encodingutf-8) return f已写入 {len(content)} 字符到 {path} server.tool() async def search_files(pattern: str, root: str .): root Path(root).resolve() results list(root.rglob(pattern)) if not results: return 没找到匹配的文件 return \n.join(str(f) for f in results[:50]) server.tool() async def get_file_info(path: str) - str: path Path(path).resolve() if not path.exists(): return 文件不存在 stat path.stat() return f大小: {stat.st_size} bytes\n修改时间: {stat.st_mtime} if __name__ __main__: server.run(stdio())看到没四个工具函数加起来不到 50 行。你甚至可以去掉get_file_info核心就三个。配置 Claude Desktop 连接写好 server.py 之后在 Claude Desktop 的配置文件里加上一行{ mcpServers: { filesystem: { command: python, args: [/path/to/server.py] } } }重启 Claude Desktop你就能在工具列表里看到这四个函数了。这里踩了个坑——路径安全一开始我没加Path(path).resolve()结果 Claude 问我能不能读/etc/passwd。我当时汗都下来了——不是因为我写了个有漏洞的代码而是因为 Claude 真的会试探边界。resolve()的作用是把相对路径转成绝对路径但真正重要的是后面还要加一层校验。我后面加了个白名单目录只允许操作某个目录下的文件ALLOWED_DIR Path(/home/user/allowed).resolve() def safe_path(path: str) - Path: p Path(path).resolve() if not str(p).startswith(str(ALLOWED_DIR)): raise ValueError(f不允许访问: {path}) return p这个问题其实挺微妙的。MCP 本身不做权限控制它只是一个通道。你让 AI 能调用什么工具、能访问什么范围完全取决于你写的 server。开太多权限等于把家门钥匙交给了陌生人。我的建议是让 MCP Server 的访问范围越小越好比如只开放一个~/Documents/projects/目录不要给整盘权限。实际用起来的体验配好之后我试了几个场景让 Claude “帮我找到上周写的那个关于 MCP 的笔记”——它会先search_files(*MCP*)找到几个文件然后read_file一个个看内容最后告诉我哪个是。让它“把下载文件夹里的截图按日期重命名”——它会search_files(*.png)拿到列表然后写一段 Python 脚本用 write_file 写到临时文件然后让我确认后再跑。这个组合拳特别好用AI 做策略和代码用户做最终确认。让我意外的是写文件的场景居然最常用。有时候我想写一段多步骤的操作指南、或者整理笔记直接在对话里跟 Claude 说了它给我写进文件我打开确认就行。比起在编辑器里一个字一个字敲效率高很多。值得注意的几点MCP 的 stdio 模式是走标准输入输出通信的所以写文件这种操作不会有明显的延迟感。但由于 Claude Desktop 目前只支持单线程串行调用如果你同时调用了search_files和read_file它们是排队执行的。大目录搜索时比如**/*.logClaude 会等搜索完再读体验上会有停顿。另外就是文件编码问题。write_text默认用的是系统编码。我在 Windows 上写过中文内容的文件读回来乱码了一回——后来在参数里加了encodingutf-8就好了。上面的代码已经修了这个问题但如果你用的是 Python 3.6 以下版本记得确认编码参数被正确传递。其实这东西真正有意思的地方不是技术本身而是它改变了你跟文件打交道的方式。以前要找文件你得自己打开终端用find、用grep、翻 Finder/资源管理器。现在你跟 Claude 说一句自然语言它在后台帮你把这些苦力活干了。这50行代码我觉得最值钱的是那个search_files函数。它让 AI 第一次能看见你的“个人数据宇宙”。