FastMCP 文本编辑器服务器
一个基于Python的文本编辑器服务器,使用FastMCP构建,提供文件操作的工具。该服务器通过遵循多步骤流程的标准API,实现对文本文件的读取、编辑和管理。
MCP 服务配置
复制以下 JSON 到 OPClaw 或其他 MCP 客户端的配置文件中即可使用
{
"mcpServers": {
"text-editor": {
"args": [
"/home/daniel/pp/editor-mcp/src/text_editor/server.py"
],
"command": "/home/daniel/pp/venvs/editor-mcp/bin/python",
"env": {
"ENABLE_JS_SYNTAX_CHECK": "0",
"FAIL_ON_JS_SYNTAX_ERROR": "0",
"FAIL_ON_PYTHON_SYNTAX_ERROR": "1",
"MAX_SELECT_LINES": "100",
"PROTECTED_PATHS": "*.env,.env*,config*.json,*secret*,/etc/passwd,/home/user/.ssh/id_rsa"
}
}
}
}
服务介绍
编辑器 MCP
一个基于 FastMCP 构建的 Python 文本编辑服务器,提供了强大的文件操作工具。该服务器通过标准化 API 以独特的多步骤方法支持读取、编辑和管理文本文件,显著提高了 LLM 和 AI 助手的代码编辑准确性和可靠性。
功能
- 文件选择:使用绝对路径设置要处理的文件
- 读取操作:
- 使用
skim读取带有行号的整个文件 - 使用
read读取特定行范围,并在前面加上行号 - 使用
find_line在文件中查找特定文本 - 使用
find_function查找并提取 Python 和 JavaScript/JSX 文件中的函数定义
- 使用
- 编辑操作:
- 带有差异预览的两步编辑过程
- 通过 ID 验证选择并覆盖文本
- 清晰的编辑工作流,包括选择 → 覆盖 → 确认/取消模式
- 对 Python (.py) 和 JavaScript/React (.js, .jsx) 文件进行语法检查
- 创建包含内容的新文件
- 文件管理:
- 正确初始化创建新文件
- 从文件系统中删除文件
- 使用
listdir列出目录内容
- 测试支持:
- 使用
run_tests运行 Python 测试 - 设置 Python 路径以正确解析模块
- 使用
- 安全特性:
- 内容 ID 验证以防止冲突
- 行数限制以防止资源耗尽
- 语法检查以维护代码完整性
- 受保护的路径以限制对敏感文件的访问
安全风险
编辑器 MCP 包含一些强大的功能,但也带来了一些安全考虑:
- 越狱风险:当读取嵌入了有害指令的文件时,编辑器 MCP 可能会被越狱。正在编辑的文件中的恶意内容可能包含操纵 AI 助手的指令。
- 任意代码执行:如果启用了测试运行功能,可能会通过被篡改的测试文件或恶意 Python 代码导致任意代码执行的风险。
- 数据泄露:如果没有正确配置路径保护,访问文件系统操作可能会暴露敏感信息。
为了缓解这些风险:
- 使用
PROTECTED_PATHS环境变量来限制对敏感文件和目录的访问。 - 在生产环境中禁用测试运行功能,除非绝对必要。
- 在打开文件之前仔细审查,特别是来自不受信任来源的文件。
- 考虑在权限受限的沙箱环境中运行编辑器。
对 LLM 的关键优势
这个文本编辑器的独特设计解决了通常影响 LLM 代码编辑的关键问题:
-
防止上下文丢失 - 传统方法通常会导致LLM在几次编辑后失去对代码库的整体概览。此实现通过多步骤过程保持上下文。
-
避免资源密集型重写 - LLM在困惑时通常默认替换整个文件,这既昂贵又低效且速度慢。此编辑器强制执行选择性编辑。
-
提供视觉反馈 - 差异预览系统允许LLM在提交更改之前实际查看和验证这些更改,从而大大减少了错误。
-
强制语法检查 - 自动验证Python和JavaScript/React的语法确保不会提交损坏的代码。
-
改进编辑推理 - 多步骤方法为LLM提供了在步骤之间进行推理的时间,减少了随意生成令牌的情况。
资源管理
编辑器实施了多项保护措施以确保系统稳定性和防止资源耗尽:
- 最大编辑行数:默认情况下,编辑器对任何单次编辑操作限制为50行。
安装
此MCP是在Claude Desktop上开发和测试的。您可以在任何平台上下载Claude Desktop。
对于Linux上的Claude Desktop,您可以使用一个非官方安装脚本(使用官方文件),推荐仓库:
https://github.com/emsi/claude-desktop/tree/main
安装好Claude Desktop后,请按照以下说明安装此特定MCP:
使用UVX轻松安装(推荐)
安装Editor MCP最简单的方法是使用提供的安装脚本:
# Clone the repository
git clone https://github.com/danielpodrazka/editor-mcp.git
cd editor-mcp
# Run the installation script
chmod +x install.sh
./install.sh
此脚本将:
- 检查是否已安装UVX,如果需要则进行安装
- 在开发模式下安装Editor MCP
- 将
editor-mcp命令添加到您的PATH中
手动安装
使用UVX
# Install directly from GitHub
uvx install git+https://github.com/danielpodrazka/mcp-text-editor.git
# Or install from a local clone
git clone https://github.com/danielpodrazka/mcp-text-editor.git
cd mcp-text-editor
uvx install -e .
使用传统的pip
pip install git+https://github.com/danielpodrazka/mcp-text-editor.git
# Or from a local clone
git clone https://github.com/danielpodrazka/mcp-text-editor.git
cd mcp-text-editor
pip install -e .
使用需求文件(旧版)
从锁定文件安装:
uv pip install -r uv.lock
生成锁定的需求文件:
uv pip compile requirements.in -o uv.lock
使用
启动服务器
安装后,可以使用以下任一方法启动Editor MCP服务器:
# Using the installed script
editor-mcp
# Or using the Python module
python -m text_editor.server
MCP配置
您可以将Editor MCP添加到您的MCP配置文件中:
{
"mcpServers": {
"text-editor": {
"command": "editor-mcp",
"env": {
"MAX_SELECT_LINES": "100",
"ENABLE_JS_SYNTAX_CHECK": "0",
"FAIL_ON_PYTHON_SYNTAX_ERROR": "1",
"FAIL_ON_JS_SYNTAX_ERROR": "0",
"PROTECTED_PATHS": "*.env,.env*,config*.json,*secret*,/etc/passwd,/home/user/.ssh/id_rsa"
}
}
}
}
环境变量配置
Editor MCP支持多个环境变量来自定义其行为:
-
MAX_SELECT_LINES: "100" - 单次操作中可编辑的最大行数(默认为50)
-
ENABLE_JS_SYNTAX_CHECK: "0" - 启用/禁用JavaScript和JSX语法检查(默认为"1" - 启用)
-
FAIL_ON_PYTHON_SYNTAX_ERROR: "1" - 当启用时,Python语法错误将自动取消覆盖操作(默认为启用)
-
FAIL_ON_JS_SYNTAX_ERROR: "0" - 当启用时,JavaScript/JSX语法错误将自动取消覆盖操作(默认为禁用)
-
PROTECTED_PATHS: 以逗号分隔的文件模式或路径列表,这些路径不能被访问,支持通配符(例如,".env,.env,/etc/passwd")
从源代码构建时的示例MCP配置
{
"mcpServers": {
"text-editor": {
"command": "/home/daniel/pp/venvs/editor-mcp/bin/python",
"args": ["/home/daniel/pp/editor-mcp/src/text_editor/server.py"],
"env": {
"MAX_SELECT_LINES": "100",
"ENABLE_JS_SYNTAX_CHECK": "0",
"FAIL_ON_PYTHON_SYNTAX_ERROR": "1",
"FAIL_ON_JS_SYNTAX_ERROR": "0",
"PROTECTED_PATHS": "*.env,.env*,config*.json,*secret*,/etc/passwd,/home/user/.ssh/id_rsa"
}
}
}
}
可用工具
编辑器MCP提供了13种强大的工具,用于文件操作、编辑和测试:
1. set_file
设置要操作的当前文件。
参数:
filepath(str): 文件的绝对路径
返回:
- 包含文件路径的确认消息
2. skim
从当前文件读取全文。每行前面加上其行号。
返回:
- 包含带有行号的行、总行数以及最大编辑行数设置的字典
示例输出:
{
"lines": [
[1, "def hello():"],
[2, " print(\"Hello, world!\")"],
[3, ""],
[4, "hello()"]
],
"total_lines": 4,
"max_select_lines": 50
}
3. read
从当前文件中读取从起始行到结束行的文本。
参数:
start(int): 起始行号(基于1的索引)end(int): 结束行号(基于1的索引)
返回:
- 包含带行号的行以及起始和结束行信息的字典
示例输出:
{
"lines": [
[1, "def hello():"],
[2, " print(\"Hello, world!\")"],
[3, ""],
[4, "hello()"]
],
"start_line": 1,
"end_line": 4
}
4. select
从当前文件中选择一个行范围,用于后续的覆盖操作。
参数:
start(int): 起始行号(基于1的索引)end(int): 结束行号(基于1的索引)
返回:
- 包含选定行、行范围以及验证ID的字典
注意:
- 此工具会根据max_select_lines验证选择
- 选择详情会被存储,供覆盖工具使用
- 在调用覆盖工具之前必须使用此工具
5. overwrite
准备用新文本覆盖当前文件中的某一行范围。
参数:
new_lines(list): 覆盖选定范围的新行列表
返回:
- 显示建议更改的差异预览
注意:
- 这是两步过程的第一步:
- 首先调用overwrite()生成差异预览
- 然后调用confirm()应用更改或调用cancel()放弃待处理的更改
- 此工具允许用新内容替换之前选定的行
- 新行的数量可以与原始选择不同
- 对于Python文件(.py扩展名),在写入前会进行语法检查
- 对于JavaScript/React文件(.js, .jsx扩展名),语法检查是可选的,可以通过
ENABLE_JS_SYNTAX_CHECK环境变量禁用
6. confirm
应用来自覆盖操作的待处理更改。
返回:
- 包含状态和消息的操作结果
注意:
- 这是编辑过程第二步中的两个可能操作之一
- 成功应用更改后,选区将被移除
7. cancel
放弃覆盖操作中待处理的更改。
返回:
- 包含状态和消息的操作结果
注意:
- 这是编辑过程第二步中的两个可能操作之一
- 取消更改时,选区保持不变
8. delete_file
删除当前设置的文件。
返回:
- 包含状态和消息的操作结果
9. new_file
创建一个新文件。
参数:
absolute_file_path(str): 新文件的路径
返回:
- 包含状态和内容ID(如果适用)的操作结果
注意:
- 如果当前文件存在且不为空,此工具将失败
10. find_line
在当前文件中查找与提供的文本匹配的行。
参数:
search_text(str): 要在文件中搜索的文本
返回:
- 包含匹配行及其行号和总匹配数的字典
示例输出:
{
"status": "success",
"matches": [
[2, " print(\"Hello, world!\")"]
],
"total_matches": 1
}
注意:
- 如果未设置文件路径,则返回错误
- 在每一行内搜索完全匹配的文本
- ID可用于后续编辑操作
11. find_function
在当前的Python或JavaScript/JSX文件中查找函数或方法定义。
参数:
function_name(str): 要查找的函数或方法的名称
返回:
- 包含函数行及其行号、起始行和结束行的字典
示例输出:
{
"status": "success",
"lines": [
[10, "def hello():"],
[11, " print(\"Hello, world!\")"],
[12, " return True"]
],
"start_line": 10,
"end_line": 12
}
注意:
- 对于Python文件,此工具使用Python的AST和tokenize模块来准确识别包括装饰器和文档字符串在内的函数边界
- 对于JavaScript/JSX文件,此工具采用以下方法:
- 主要方法:当可用时使用Babel AST解析(需要Node.js和Babel包)
- 备用方法:当Babel不可用时,使用正则表达式模式匹配函数声明
- 支持多种JavaScript函数类型,包括标准函数、异步函数、箭头函数和React钩子
- 如果未设置文件路径或找不到函数,则返回错误
12. listdir
列出目录的内容。
参数:
dirpath(str): 要列出的目录的路径
返回:
- 包含文件名列表和查询路径的字典
13. run_tests 和 set_python_path
用于使用pytest运行Python测试并配置Python环境的工具。
- 设置为 "0", "false", 或 "no" 以禁用 JavaScript 语法检查
- 如果您没有安装 Babel 及相关依赖项,这将非常有用
FAIL_ON_PYTHON_SYNTAX_ERROR: 控制 Python 语法错误是否自动取消覆盖操作(默认:1)- 启用时,Python 文件中的语法错误将导致覆盖操作被自动取消
- 行将保持选中状态,以便您可以修复错误并重试
FAIL_ON_JS_SYNTAX_ERROR: 控制 JavaScript/JSX 语法错误是否自动取消覆盖操作(默认:0)- 启用时,JavaScript/JSX 文件中的语法错误将导致覆盖操作被自动取消
- 行将保持选中状态,以便您可以修复错误并重试
DUCKDB_USAGE_STATS: 控制是否在 DuckDB 数据库中收集使用统计信息(默认:0)- 设置为 "1", "true", 或 "yes" 以启用工具使用统计信息的收集
- 启用时,记录每次工具调用的信息,包括时间戳和参数
STATS_DB_PATH: 存储统计信息的 DuckDB 数据库的路径(默认:"text_editor_stats.duckdb")- 仅当
DUCKDB_USAGE_STATS启用时使用
- 仅当
PROTECTED_PATHS: 逗号分隔的文件模式或绝对路径列表,这些路径将被拒绝访问- 示例:
*.env,.env*,config*.json,*secret*,/etc/passwd,/home/user/credentials.txt - 支持精确的文件路径和灵活的通配符模式:
*.env- 匹配以 .env 结尾的文件,如.env,dev.env,prod.env.env*- 匹配以 .env 开头的文件,如.env,.env.local,.env.production*secret*- 匹配名称中包含 'secret' 的任何文件
- 提供保护,防止意外暴露敏感配置文件和凭据
- 行将保持选中状态,以便您可以修复错误并重试
- 示例:
开发
前提条件
编辑器-mcp 需要:
- Python 3.7+
- FastMCP 包
- black(用于 Python 代码格式检查)
- Babel(如果处理这些文件,则用于 JavaScript/JSX 语法检查)
安装开发依赖项:
# Using pip
pip install pytest pytest-asyncio pytest-cov
# Using uv
uv pip install pytest pytest-asyncio pytest-cov
对于 JavaScript/JSX 语法验证,您需要 Node.js 和 Babel。文本编辑器使用 npx babel 来检查 JS/JSX 语法,在编辑这些文件类型时:
# Required for JavaScript/JSX syntax checking
npm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react
# You can also install these globally if you prefer
# npm install -g @babel/core @babel/cli @babel/preset-env @babel/preset-react
编辑器需要:
@babel/core和@babel/cli- 用于语法检查的核心 Babel 包@babel/preset-env- 用于标准 JavaScript (.js) 文件@babel/preset-react- 用于 React JSX (.jsx) 文件
运行测试
# Run tests
pytest -v
# Run tests with coverage
pytest -v --cov=text_editor
测试结构
测试套件涵盖:
-
set_file 工具
- 设置有效文件
- 设置不存在的文件
-
read 工具
- 文件状态验证
- 读取整个文件
- 读取特定行范围
- 处理空文件等边缘情况
- 无效范围处理
-
select 工具
- 行范围验证
- 针对
max_select_lines的选择验证 - 为后续操作存储选择内容
-
overwrite 工具
- 使用 ID 验证选定内容
- 内容替换验证
- Python 和 JavaScript/React 文件的语法检查
- 生成更改的差异预览
-
confirm 和 cancel 工具
- 应用或取消待定更改
- 两步验证过程
-
delete_file 工具
- 文件删除验证
-
new_file 工具
- 文件创建验证
- 处理已存在的文件
-
find_line 工具
- 在文件中查找文本匹配项
- 处理特定搜索词
- 处理不存在的文件时的错误处理
- 处理没有匹配项的情况
- 处理已存在的文件
工作原理
多步骤编辑方法
与传统的代码编辑方法不同,LLM 仅通过搜索要编辑的行并进行替换(通常在多次编辑后导致混淆),此编辑器实现了一个结构化的多步骤工作流程,极大地提高了编辑准确性:
- set_file - 首先,LLM 设置它想要编辑的文件
- skim - LLM 读取整个文件以获得完整的概览
- read - LLM 检查与任务相关的特定部分,显示带有行号的行以便更好地理解上下文
- select - 当准备编辑时,LLM 选择特定的行(限制为可配置的数量,默认为 50 行)
- overwrite - LLM 提出替换内容,生成类似 git diff 的预览,显示将要更改的内容
- confirm/cancel - 在审查预览后,LLM 可以应用或丢弃更改
这种结构化的工作流程迫使 LLM 仔细考虑每个编辑,并防止常见的错误,如意外覆盖整个文件。通过在提交更改之前看到预览,LLM 可以验证其编辑是正确的。
ID 验证系统
服务器使用 FastMCP 通过一个定义良好的 API 暴露文本编辑功能。ID 验证系统通过验证在读取和修改操作之间内容未发生变化来确保数据完整性。
ID 机制使用 SHA-256 生成文件内容或选定行范围的唯一标识符。对于特定行的操作,ID 包括一个前缀,指示行范围(例如,“L10-15-[hash]”)。这有助于确保编辑被应用于预期的内容。
实现细节
主 TextEditorServer 类:
- 使用名为 "text-editor" 的 FastMCP 实例进行初始化
- 从环境变量中设置可配置的
max_select_lines限制(默认值:50) - 将当前文件路径作为状态维护
- 通过 FastMCP 注册十三个主要工具:
set_file: 验证并设置当前文件路径skim: 读取整个文件的内容,返回行号到行文本的字典read: 从指定的行范围读取行,返回行内容的结构化字典select: 选择行以进行后续覆盖操作overwrite: 接受新行列表,并为更改内容准备差异预览confirm: 应用来自覆盖操作的待处理更改cancel: 放弃来自覆盖操作的待处理更改delete_file: 删除当前文件new_file: 创建新文件find_line: 查找包含特定文本的行find_function: 在 Python 和 JavaScript/JSX 文件中查找函数或方法定义listdir: 列出目录的内容run_tests和set_python_path: 运行 Python 测试的工具
服务器默认使用 FastMCP 的 stdio 传输运行,这使得它易于与各种客户端集成。
为获得最佳结果的系统提示
为了与 AI 助手合作时获得最佳效果,建议使用系统提示(见 system_prompt.md),该提示有助于指导 AI 进行可管理且安全的编辑。
这个系统提示帮助 AI 助手:
- 进行增量更改 - 将编辑分解成更小的部分
- 保持代码完整性 - 进行保持代码功能性的更改
- 在资源限制内工作 - 避免可能使系统过载的操作
- 遵循验证工作流程 - 在编辑后进行最终错误检查
通过在与 AI 助手合作时结合此系统提示,您将获得更可靠的编辑行为,并避免自动化代码编辑中的常见陷阱。

使用统计
当启用时,文本编辑器 MCP 可以收集使用统计数据,提供有关如何使用编辑工具的见解:
- 数据收集:当启用了
DUCKDB_USAGE_STATS时,统计数据会在 DuckDB 数据库中收集 - 跟踪信息:记录工具名称、参数、时间戳、当前文件路径、工具响应以及请求/客户端 ID
- 存储位置:数据存储在由
STATS_DB_PATH指定的 DuckDB 文件中 - 隐私:所有内容都存储在您的机器上本地
收集的统计数据可以帮助理解使用模式,识别常见的工作流程,并针对最频繁的操作优化编辑器。
您可以使用任何 DuckDB 客户端通过标准 SQL 查询数据库来分析使用模式。
故障排除
如果您遇到问题:
- 检查文件权限
- 确认文件路径是绝对路径
- 确保环境使用的是 Python 3.7+
灵感来源
受到一个类似项目https://github.com/tumf/mcp-text-editor的启发,起初我对其进行了 fork,但后来决定从头开始重写整个代码库,因此只保留了大致的想法。