文本编辑服务器

一个基于Python和FastMCP构建的文本编辑服务器,提供文件操作、编辑和管理功能,特别优化了LLM和AI助手的代码编辑准确性和可靠性。

  • by danielpodrazka
  • Python
  • 本地部署
  • 14 星标
  • 更新于
在 GitHub 查看 danielpodrazka/editor-mcp

使用说明

编辑器MCP

基于Python的文本编辑器服务器,使用FastMCP构建,为文件操作提供了强大的工具。该服务器能够通过标准化的API读取、编辑和管理文本文件,并采用独特的多步骤方法,显著提高LLM和AI助手的代码编辑准确性和可靠性。

特性

  • 文件选择:使用绝对路径设置要使用的文件
  • 读取操作:
    • 使用以下命令读取带有行号的整个文件 skim
    • 使用以下命令读取带有前缀行号的特定行范围 read
    • 使用以下命令在文件中查找特定文本 find_line
    • 使用以下命令在Python和JavaScript/JSX文件中查找和提取函数定义 find_function
  • 编辑操作:
    • 带有差异预览的两步编辑过程
    • 使用ID验证选择并覆盖文本
    • 使用select清理编辑工作流程→ 覆盖→ 确认/取消模式
    • Python(.py)和JavaScript/RReact(.js、.jsx)文件的语法检查
    • 创建包含内容的新文件
  • 文件管理:
    • 使用正确的初始化创建新文件
    • 从文件系统中删除文件
    • 列出目录内容 listdir
  • 测试支持:
    • 使用以下命令运行Python测试 run_tests
    • 设置Python路径以实现正确的模块解析
  • 安全功能:
    • 内容ID验证以防止冲突
    • 行数限制以防止资源耗尽
    • 语法检查以维护代码完整性
    • 限制访问敏感文件的受保护路径

危险分子

编辑器mcp包括一些强大的功能,这些功能都有一定的安全考虑:

  • 越狱风险:当读取其中嵌入了有害指令的文件时,编辑器mcp可能会被越狱。正在编辑的文件中的恶意内容可能包含操纵AI助手的指令。
  • 任意代码执行:如果启用了运行测试,则存在通过操纵测试文件或恶意Python代码执行任意代码的风险。
  • 数据暴露:如果未配置适当的路径保护,则访问文件系统操作可能会暴露敏感信息。

为了降低这些风险:

  1. 使用 PROTECTED_PATHS 环境变量,用于限制对敏感文件和目录的访问。
  2. 除非绝对必要,否则禁用生产环境中的测试运行功能。
  3. 在打开文件之前,请仔细检查文件,特别是如果它们来自不受信任的来源。
  4. 考虑在权限有限的沙盒环境中运行编辑器。

LLM的主要优势

此文本编辑器的独特设计解决了通常影响LLM代码编辑的关键问题:

  • 防止上下文丢失 -传统方法通常会导致LLM在几次编辑后失去对代码库的概述。此实现通过多步骤过程维护上下文。

  • 避免资源密集型重写 -LLM通常在混淆时默认替换整个文件,这成本高、速度慢、效率低。此编辑器强制执行选择性编辑。

  • 提供视觉反馈 -diff预览系统允许LLM在提交更改之前实际查看和验证更改,从而大大减少错误。

  • 强制语法检查 -Python和JavaScript/RReact的自动验证可确保不会提交损坏的代码。

  • 改进编辑推理 -多步骤方法为LLM提供了在步骤之间进行推理的时间,减少了随意的代币生产。

资源管理

编辑器实施了多种保护措施,以确保系统稳定性并防止资源耗尽:

  • 最大编辑行数:默认情况下,编辑器对任何单个编辑操作强制执行50行限制

安装

该MCP是用Claude Desktop开发和测试的。您可以在任何平台上下载Claude Desktop。 对于Linux上的Claude Desktop,您可以使用非官方的安装脚本(使用官方文件),推荐的存储库: https://github.com/emsi/claude-desktop/tree/main

安装完Claude Desktop后,请按照以下说明安装此特定的MCP:

UVX易于安装(推荐)

安装编辑器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

此脚本将:

  1. 检查是否安装了UVX,必要时进行安装
  2. 在开发模式下安装编辑器MCP
  3. 制作 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配置

您可以将编辑器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"
       }
     }
  }
}

环境变量配置

编辑器MCP支持多个环境变量来自定义其行为:

  • MAX_SELECT_LINES:“100”-一次操作中可以编辑的最大行数(默认值为50)

  • ENABLE_jssyntax_CHECK:“0”-启用/禁用JavaScript和JSX语法检查(默认值为“1”-启用)

  • FAIL_ON_PYTHON_SYNTAX_ERROR:“1”-启用时,Python语法错误将自动取消覆盖操作(默认启用)

  • FAIL_ON_JS_SYNTAX_ERROR:“0”-启用后,JavaScript/JSX语法错误将自动取消覆盖操作(默认为禁用)

  • 保护路径:逗号分隔的无法访问的文件模式或路径列表,支持通配符(例如,“.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"
        }
     }
  }
}

可用工具

Editor 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):覆盖所选范围的新行列表

退货:

  • 显示拟议更改的差异预览

备注:

  • 这是两步过程的第一步:
    1. 首先调用oversite()来生成diff预览
    2. 然后调用confirm()来应用或cancel()来丢弃挂起的更改
  • 此工具允许用新内容替换以前选择的行
  • 新行的数量可能与原始选择不同
  • 对于Python文件(扩展名为.py),在写入之前会执行语法检查
  • 对于JavaScript/RReact文件(.js、.jsx扩展名),语法检查是可选的,可以通过 ENABLE_JS_SYNTAX_CHECK 环境变量

6. confirm

应用覆盖操作中的挂起更改。

退货:

  • 带有状态和消息的操作结果

备注:

  • 这是编辑过程第二步中的两个可能操作之一
  • 成功应用更改后,选择将被删除

7. cancel

放弃覆盖操作中的待定更改。

退货:

  • 带有状态和消息的操作结果

备注:

  • 这是编辑过程第二步中的两个可能操作之一
  • 取消更改时,选择保持不变

8. delete_file

删除当前设置的文件。

退货:

  • 带有状态和消息的操作结果

9. new_file

创建一个新文件,并自动将其设置为后续操作的当前文件。

参数:

  • filepath (str):新文件的路径

退货:

  • 带有状态、消息和选择信息的操作结果
  • 第一行会自动选择进行编辑

行为:

  • 如果父目录不存在,则自动创建父目录
  • 将新创建的文件设置为当前工作文件
  • 第一行已预先选定,可立即编辑

受保护文件注释:

  • 与某些模式匹配的文件(如 *.env)可以正常创建
  • 但是,一旦移动到另一个文件,这些受保护的文件就无法重新打开
  • 这允许对敏感配置文件进行“一次写入,后保护”的工作流程
  • 示例:您可以创建 config.env,用示例配置填充它,但以后无法重新打开它

备注:

  • 如果当前文件存在且不为空,则此工具将失败

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):要查找的函数或方法的名称

退货:

  • 包含函数行及其行号、start_line和end_line的字典

输出示例:

{
  "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
    • 支持精确的文件路径和灵活的glob模式,在任何位置都可以使用通配符:
      • *.env -匹配以.env结尾的文件,如 .env, dev.env, prod.env
      • .env* -匹配以.env开头的文件,如 .env, .env.local, .env.production
      • *secret* -匹配名称中包含“secret”的任何文件
    • 提供保护,防止意外暴露敏感的配置文件和凭据
    • 这些行将保持选中状态,以便您修复错误并重试

发展

先决条件

编辑器mcp要求:

  • Python 3.7+
  • FastMCP封装
  • 黑色(用于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

测试结构

测试套件包括:

  1. set_file工具

    • 设置有效文件
    • 设置不存在的文件
  2. 读取工具

    • 文件状态验证
    • 读取整个文件
    • 读取特定行范围
    • 空白文件等边缘情况
    • 范围处理无效
  3. 选择工具

    • 线路范围验证
    • 根据max_select_lines进行选择验证
    • 后续操作的选择存储
  4. 覆盖工具

    • 使用ID验证所选内容
    • 内容替换验证
    • Python和JavaScript/RReact文件的语法检查
    • 为更改生成差异预览
  5. 确认和取消工具

    • 应用或取消待处理的更改
    • 两步验证过程
  6. delete_file工具

    • 文件删除验证
  7. new_file工具

    • 文件创建验证
    • 处理现有文件
  8. find_line工具

    • 在文件中查找文本匹配项
    • 处理特定搜索词
    • 对不存在的文件进行错误处理
    • 处理没有匹配的案件
    • 处理现有文件

原理

多步编辑方法

与传统的代码编辑方法不同,LLM只是搜索要编辑的行并进行替换(通常在多次编辑后会导致混淆),这款编辑器实现了一个结构化的多步骤工作流程,大大提高了编辑准确性:

  1. set_file -首先,LLM设置要编辑的文件
  2. 撇去 -LLM读取整个文件以获得完整的概述
  3. 读 -LLM检查与任务相关的特定部分,并在数字旁边显示线条以获得更好的上下文
  4. 选择 -当准备好编辑时,LLM会选择特定的行(限于可配置的数量,默认值为50)
  5. 覆盖 -LLM建议替换内容,从而产生一个git diff风格的预览,准确显示将要更改的内容
  6. 确认/取消 -查看预览后,LLM可以应用或放弃更改

这种结构化的工作流程迫使LLM仔细思考每次编辑,并防止意外覆盖整个文件等常见错误。通过在提交更改之前查看更改的预览,LLM可以验证其编辑是否正确。

身份验证系统

服务器使用FastMCP通过定义良好的API公开文本编辑功能。ID验证系统通过验证内容在读取和修改操作之间没有变化来确保数据完整性。

ID机制使用SHA-256来生成文件内容或所选行范围的唯一标识符。对于特定于行的操作,ID包括一个指示行范围的前缀(例如,“L10-15-[hash]”)。这有助于确保编辑被应用于预期的内容。

实现细节

主要 TextEditorServer 类别:

  1. 使用名为“文本编辑器”的FastMCP实例进行初始化
  2. 设置可配置 max_select_lines 环境变量的限制(默认值:50)
  3. 将当前文件路径保持为状态
  4. 通过FastMCP注册13个主要工具:
    • 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助手:

  1. 进行增量更改 -将编辑分解为更小的部分
  2. 维护代码完整性 -进行更改以保持代码的功能
  3. 在资源限制范围内工作 -避免可能使系统不堪重负的操作
  4. 遵循验证工作流程 -编辑后进行最终错误检查

通过在使用AI助手时结合此系统提示,您将获得更可靠的编辑行为,并避免自动代码编辑中的常见陷阱。

使用统计

启用后,文本编辑器MCP可以收集使用统计数据,提供有关编辑工具使用情况的见解:

  • 数据收集:统计数据在以下情况下收集在DuckDB数据库中 DUCKDB_USAGE_STATS 已启用
  • 跟踪信息:记录工具名称、参数、时间戳、当前文件路径、工具响应和请求/客户端ID
  • 存储位置:数据存储在由指定的DuckDB文件中 STATS_DB_PATH
  • 隐私:所有内容都存储在您的机器上

收集的统计数据可以帮助了解使用模式,确定常见的工作流程,并针对最频繁的操作优化编辑器。

您可以通过任何DuckDB客户端使用标准SQL查询数据库,以分析使用模式。

故障排除

如果您遇到问题:

  1. 检查文件权限
  2. 验证文件路径是否为绝对路径
  3. 确保环境使用Python 3.7+

灵感

受到类似项目的启发:https://github.com/tumf/mcp-text-editor,起初我分叉了,但我决定从头开始重写整个代码库,所以只有总体思路保持不变。