code-editor
面向多客户端并发、安全沙箱、编码感知的代码编辑 MCP 服务器。
路径访问更新:所有参数必须是绝对路径。除
read_files外,其余文件/目录工具仍校验是否落在允许目录列表内。CODE_EDIT_ROOT只是安全标记,不做访问边界或相对路径解析;访问新目录请用config_ops(action="set_root", path="...")加入允许列表。
安装与运行
# 安装(pip 或 uv 均可,包名 code-editor-mcp)
pip install code-editor-mcp # 或 uv pip install code-editor-mcp
# 更新最新版
pip install -U code-editor-mcp
# 直接启动 CLI 入口
code-editor
# 若从源码运行
uv sync
uv run python server.py
关键环境变量:
CODE_EDIT_ROOT:安全标记(默认启动时的 CWD),不做访问边界,也不参与相对路径解析。CODE_EDIT_ALLOWED_ROOTS_FILE:允许目录持久化 JSON,默认tools/.code_edit_roots.json。CODE_EDIT_ALLOWED_DIRECTORIES:逗号分隔允许目录列表(兼容旧的CODE_EDIT_ALLOWED_ROOTS)。
环境变量一览:
| 变量 | 作用 | 默认值 |
|---|---|---|
CODE_EDIT_ROOT |
安全标记(非访问边界,不做路径解析) | 当前工作目录 |
CODE_EDIT_ALLOWED_ROOTS_FILE |
允许目录持久化文件 | tools/.code_edit_roots.json |
CODE_EDIT_ALLOWED_DIRECTORIES (兼容 CODE_EDIT_ALLOWED_ROOTS) |
额外允许目录(逗号分隔) | 空 |
CODE_EDIT_FILE_READ_LINE_LIMIT |
(legacy)内部 read_file 默认行数上限;read_files v2 使用 page_line_count/max_lines_per_snippet 控制输出 |
1000 |
CODE_EDIT_FILE_WRITE_LINE_LIMIT |
file_ops 写入行数警戒 |
50 |
设计要点
- 允许目录列表:默认允许用户主目录;路径需落在允许目录内,否则拒绝。
config_ops(action="set_root")仅将目录加入允许列表并更新安全标记,不做路径拼接。 - 持久允许目录:
config_ops(action="set_root")成功后写入 JSON,可跨会话复用。 - 乐观锁:写/删类支持秒或纳秒级
expected_mtime,10ms 容忍;写入走原子写避免部分落盘。 - 默认忽略:
.git、__pycache__、node_modules、.DS_Store、.env*、.venv、*.log、*.pem;ignore_patterns传空字符串/空列表可关闭默认忽略。 - 编码感知:
read_filesv2 默认逐文件auto检测/复用编码(基于最新 mtime 刷新的元信息缓存);如自动结果乱码,可在每个 request 里显式传encoding覆盖。 - 安全删除:禁止删除当前根/其祖先/关键系统目录。
MCP 工具(code-editor)
文件系统工具
| 名称 | 工具 | 功能 | 主要参数/说明 | 常见误用 |
|---|---|---|---|---|
config_ops |
config_ops(action, path=None) |
允许目录管理 + 元信息 | action=set_root/list_roots/get_info;path 仅 set_root/get_info 需要 |
拼错 action;误以为 list_roots 需要 path |
read_files |
read_files(requests, default_encoding="auto", page_line_count=400, max_snippets=64, max_total_chars=200000, max_chars_per_snippet=50000, max_lines_per_snippet=2000, parallelism=4) |
LLM 友好读取:多文件/同文件多片段 + 分页 | requests 为 list[dict]:支持 mode=range/tail/all;行号 1-based;可用 cursor 继续分页;返回结构化 results[],每项含 content(纯内容)、start_line/end_line、core_*、encoding、sha256_utf8、可选 next_cursor;encoding 支持 auto/utf-8/gbk/gb2312/gb18030;仅此工具允许读取任意绝对路径,不受允许目录白名单限制 |
继续传旧的 file_paths;把 start_line 当 0-based;一次请求太多片段触发 max_total_chars;对图片用 range/tail |
dir_ops |
`dir_ops(action, dir_path, depth=2, format="tree" | "flat", ignore_patterns=None, max_items=1000, expected_mtime=None, confirm_token=None, allow_nonempty=None, approval_token=None)` | 统一目录操作 | action=create/list/delete;绝对路径;list: tree 返回字符串列表、flat 返回字典列表;ignore_patterns 为 None 用默认忽略,空字符串/空列表关闭默认忽略;flat 下 max_items 限制返回条数;delete: 必须提供 expected_mtime、confirm_token、allow_nonempty,confirm_token=delete:<normalized_abs_path>(Path.resolve + os.path.normcase);高风险删除会返回结构化 needs_approval 并要求 approval_token 二次提交 |
file_ops |
file_ops(action, file_path=None, content=None, source_path=None, destination_path=None, expected_mtime=None, encoding="utf-8", approval_token=None) |
综合文件操作:write/append/copy/move/delete | 所有路径必须绝对且在允许目录内;write 覆盖、append 追加;write/append 需 file_path+content;copy/move 需 source_path+destination_path;delete 需 file_path;encoding 仅写入使用;expected_mtime:写/删校验目标文件,拷贝/移动校验源文件;删除返回结构化结果 | action 不支持或参数缺失;copy 目标已存在;delete 目标是目录 |
convert_file_encoding |
convert_file_encoding(file_paths, source_encoding, target_encoding, error_handling="strict", mismatch_policy="warn-skip") |
批量转码并覆盖写回 | 绝对路径列表;utf-8/gbk/gb2312/gb18030;错误处理 strict/replace/ignore;编码检测( charset-normalizer ),策略 fail-fast / warn-skip(默认) / force;结果返回 detectedEncoding/Confidence/mismatch;内置别名兼容 utf8/utf_8/utf-8-sig/ascii/cp936/gb-2312/gb-18030 | 相对路径;二进制文件;未在白名单 |
dir_ops 参数要点(避免误调用)
create:仅dir_path必须;其余参数会被忽略。list:format仅支持tree/flat;max_items必须为正整数或 None。delete:必须同时提供expected_mtime、confirm_token、allow_nonempty(显式 True/False)。- 删除行为统一移动到回收站,不支持永久删除。
- 命中高风险规则时会返回
status=needs_approval,响应内包含approval_token与llm_instruction。 - 盘符根目录(如
C:\/D:\/E:\)会被永久阻断并返回status=blocked_critical。 confirm_token生成规则(严格匹配):
from pathlib import Path
import os
normalized = os.path.normcase(str(Path(dir_path).resolve()))
confirm_token = f"delete:{normalized}"
代码精准编辑工具
| 名称 | 工具 | 功能 | 主要参数/说明 | 常见误用 |
|---|---|---|---|---|
edit_blocks |
edit_blocks(edits, error_policy="fail-fast", encoding="auto") |
单编辑/批量编辑:搜索替换 | edits 支持 dict(单编辑,支持大文件)或 list[dict](批量,支持同文件多处与多文件);每个 edit 必须有 file_path(注意不是 path);支持 encoding="auto" 自动检测;批量模式支持 error_policy: fail-fast/continue/rollback |
把 read_files 的 path 当成 file_path;传了不支持的编码;批量模式传空列表;大文件用批量模式(应改为单编辑 dict) |
edit_blocks 返回格式(v0.3.0+)
edit_blocks 返回结构化数据,包含修改位置信息便于验证:
# edit_blocks(单编辑)返回示例
{
"status": "success",
"message": "Applied 2 edit(s) to /path/file.py (lines 10-12, 20-25)",
"file_path": "/path/file.py",
"replacements": 2,
"locations": [
{"start_line": 10, "end_line": 12, "start_col": 5, "end_col": 20},
{"start_line": 20, "end_line": 25, "start_col": 1, "end_col": 15}
]
}
# edit_blocks(批量)返回示例
{
"status": "success", # success/partial/error
"message": "Completed 3/3 edits",
"total_edits": 3,
"successful_edits": 3,
"failed_edits": 0,
"results": [
{"status": "success", "file_path": "...", "replacements": 1, "locations": [...], "message": "..."},
{"status": "success", "file_path": "...", "replacements": 1, "locations": [...], "message": "..."},
{"status": "success", "file_path": "...", "replacements": 1, "locations": [...], "message": "..."}
]
}
使用示例
- 查看并新增允许目录:
config_ops(action="list_roots")→ 若未包含目标,调用config_ops(action="set_root", path="/data/project")。 - 带锁写入:
info = config_ops(action="get_info", path="/abs/path/src/app.py")→file_ops(action="write", file_path="/abs/path/src/app.py", content=content, expected_mtime=info["modified"])。 - 精确替换(单编辑):
edit_blocks(edits={"file_path":"/abs/path/src/app.py","old_string":"old","new_string":"new","expected_replacements":1,"expected_mtime":info["modified"]})。 - 单文件片段读取(range,行号 1-based):
read_files([
{"path": "/abs/path/src/app.py", "mode": "range", "start_line": 10, "line_count": 60}
])
- 同文件多片段 + 跨文件(一次拿齐,减少多次调用):
read_files([
{"path": "/abs/path/src/app.py", "mode": "range", "start_line": 1, "line_count": 80, "id": "app_head"},
{"path": "/abs/path/src/app.py", "mode": "range", "start_line": 200, "line_count": 80, "id": "app_mid"},
{"path": "/abs/path/README.md", "mode": "range", "start_line": 1, "line_count": 120, "id": "readme"},
], max_total_chars=200000, parallelism=4)
- 分页读取整文件(all + cursor):
resp1 = read_files([{"path": "/abs/path/src/app.py", "mode": "all"}], page_line_count=400)
cursor = resp1["results"][0].get("next_cursor")
resp2 = read_files([{"cursor": cursor}], page_line_count=400) # 继续下一页
- 批量编辑(同文件多处修改):
edit_blocks(edits=[
{"file_path": "/abs/app.py", "old_string": "foo", "new_string": "bar"},
{"file_path": "/abs/app.py", "old_string": "hello", "new_string": "world"},
], error_policy="rollback")
- 批量编辑(多文件):
edit_blocks(edits=[
{"file_path": "/abs/a.py", "old_string": "v1", "new_string": "v2"},
{"file_path": "/abs/b.py", "old_string": "v1", "new_string": "v2"},
], error_policy="continue")
- 批量转码:
convert_file_encoding(["/abs/a.txt", "/abs/b.txt"], "gb2312", "utf-8", error_handling="replace", mismatch_policy="warn-skip")。 - 列目录(扁平):
dir_ops(action="list", dir_path="/abs/path", format="flat", ignore_patterns=[".git", "node_modules"])。 - 删除目录(显式确认,统一进回收站):
info = config_ops(action="get_info", path="/abs/path")→normalized = os.path.normcase(str(Path("/abs/path").resolve()))→token = f"delete:{normalized}"→dir_ops(action="delete", dir_path="/abs/path", expected_mtime=info["modified"], confirm_token=token, allow_nonempty=True)。 - 高风险删除二次审批:首次调用 delete 可能返回
status=needs_approval+approval.approval_token,拿到用户明确同意后,带上approval_token再次调用同一 delete。
MCP 客户端快速配置示例
{
"mcpServers": {
"code-editor": {
"command": "code-editor",
"env": {
"CODE_EDIT_ROOT": "."
}
}
}
}
[mcp_servers.code-editor]
command = "code-editor"
# 将工作目录指向当前项目,使 CODE_EDIT_ROOT 默认跟随启动时的 CWD
cwd = "."
startup_timeout_sec = 120
安全/行为提示
- 路径验证:除
read_files外,其他操作要求绝对路径且落在允许目录列表内;read_files仅要求绝对路径;CODE_EDIT_ROOT仅为安全标记。 - 删除防护:删除只允许移动到回收站;任何失败都会直接拒绝(不会降级为永久删除)。
- 盘符根目录阻断:
C:\、D:\、E:\(及其他文件系统根目录)会被永久阻断,并返回极高风险警告。 - 二次审批:仅“重要目录 + 大规模删除”触发;返回会强制提示模型先询问用户并等待批准。
- 允许目录管理:如需访问新路径,先
config_ops(action="set_root")加入白名单;不在白名单的绝对路径会被拒绝。
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
code_editor_mcp-0.2.5.tar.gz
(37.0 kB
view details)
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file code_editor_mcp-0.2.5.tar.gz.
File metadata
- Download URL: code_editor_mcp-0.2.5.tar.gz
- Upload date:
- Size: 37.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7b6c2c2b80a1da48e29a2b8b5c2eef6c17cf7df17bd5a6f90fd137bcdb1e0133
|
|
| MD5 |
822fed04c21c4f804331a81868784372
|
|
| BLAKE2b-256 |
aca8584176a30eaaa82ff1f4f43f2266de4546a2e306533be93d01964f7f1a3c
|
File details
Details for the file code_editor_mcp-0.2.5-py3-none-any.whl.
File metadata
- Download URL: code_editor_mcp-0.2.5-py3-none-any.whl
- Upload date:
- Size: 41.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ed1f8f81bda824f9025bce65a1e8af767d479866e4546f787500e02b46ce8f44
|
|
| MD5 |
fd5a48e2de9f41723ca5bdb10a61e5d8
|
|
| BLAKE2b-256 |
8f66308d9d1e25d491cbe2f533df878e3c33e5e26d6565c6d26400291d8175ed
|