Edit File Lines MCP Server

local-only server

The server can only run on the client’s local machine because it depends on local resources.

Integrations

  • Offers tools specifically designed for editing TypeScript files with specialized pattern matching and regex support for handling TypeScript syntax, components, and configurations.

编辑文件行 MCP 服务器

基于 TypeScript 的 MCP 服务器,提供对允许目录内的文本文件进行精确的基于行的编辑的工具。

特征

主要编辑工具

edit_file_lines

使用字符串或正则表达式模式匹配对文件进行基于行的编辑。每次编辑可以:

  • 替换整行
  • 替换特定的文本匹配,同时保留行格式
  • 使用正则表达式模式进行复杂匹配
  • 处理多行和多个编辑
  • 使用试运行模式预览更改

示例文件( src/components/App.tsx ):

// Basic component with props const Button = ({ color = "blue", size = "md" }) => { return <button className={`btn-${color} size-${size}`}>Click me</button>; }; // Component with multiple props and nested structure export const Card = ({ title, subtitle = "Default subtitle", theme = "light", size = "lg", }) => { const cardClass = `card-${theme} size-${size}`; return ( <div className={cardClass}> <h2>{title}</h2> <p>{subtitle}</p> </div> ); }; // Constants and configurations const THEME = { light: { bg: "#ffffff", text: "#000000" }, dark: { bg: "#000000", text: "#ffffff" }, }; const CONFIG = { apiUrl: "https://api.example.com", timeout: 5000, retries: 3, };

示例用例

  1. 简单字符串替换
{ "p": "src/components/App.tsx", "e": [{ "startLine": 2, "endLine": 2, "content": "primary", "strMatch": "blue" }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -1,6 +1,6 @@ // Basic component with props -const Button = ({ color = "blue", size = "md" }) => { +const Button = ({ color = "primary", size = "md" }) => { return Click me; }; // Component with multiple props and nested structure

状态 ID:fcbf740a 使用此 ID 和 approve_edit 来应用更改。

  1. 保留结构的多行内容
{ "p": "src/components/App.tsx", "e": [{ "startLine": 16, "endLine": 19, "content": " <div className={cardClass}>\n <h2 className=\"title\">{title}</h2>\n <p className=\"subtitle\">{subtitle}</p>\n </div>", "regexMatch": "<div[^>]*>[\\s\\S]*?</div>" }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -13,10 +13,10 @@ const cardClass = `card-${theme} size-${size}`; return ( <div className={cardClass}> - <h2>{title}</h2> - <p>{subtitle}</p> + <h2 className="title">{title}</h2> + <p className="subtitle">{subtitle}</p> </div> ); };

状态 ID:f2ce973f 使用此 ID 和 approve_edit 来应用更改。

  1. 复杂的 JSX 结构修改
{ "p": "src/components/App.tsx", "e": [{ "startLine": 7, "endLine": 12, "content": "export const Card = ({\n title,\n subtitle = \"New default\",\n theme = \"modern\",\n size = \"responsive\"\n}) => {", "regexMatch": "export const Card[\\s\\S]*?\\) => \\{" }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -5,11 +5,11 @@ // Component with multiple props and nested structure export const Card = ({ title, - subtitle = "Default subtitle", - theme = "light", - size = "lg", + subtitle = "New default", + theme = "modern", + size = "responsive" }) => { const cardClass = `card-${theme} size-${size}`; return (

状态 ID:f1f1d27b 使用此 ID 和 approve_edit 来应用更改。

  1. 保留空白的配置更新
{ "p": "src/components/App.tsx", "e": [{ "startLine": 29, "endLine": 32, "content": "const CONFIG = {\n baseUrl: \"https://api.newexample.com\",\n timeout: 10000,\n maxRetries: 5", "regexMatch": "const CONFIG[\\s\\S]*?retries: \\d+" }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -26,8 +26,8 @@ dark: { bg: "#000000", text: "#ffffff" }, }; const CONFIG = { - apiUrl: "https://api.example.com", - timeout: 5000, - retries: 3, + baseUrl: "https://api.newexample.com", + timeout: 10000, + maxRetries: 5 };

状态 ID:20e93c34 使用此 ID 和 approve_edit 来应用更改。

  1. 灵活的空白匹配
{ "p": "src/components/App.tsx", "e": [{ "startLine": 9, "endLine": 9, "content": "description", "strMatch": "subtitle = \"Default subtitle\"" // Extra spaces are handled }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -5,9 +5,9 @@ // Component with multiple props and nested structure export const Card = ({ title, - subtitle = "Default subtitle", + description theme = "light", size = "lg", }) => { const cardClass = `card-${theme} size-${size}`;

其他工具

approve_edit

应用上一次edit_file_lines试运行中的更改。此工具提供了两步编辑流程以确保安全。以下是示例工作流程:

  1. 首先,进行一次试运行编辑:
{ "p": "src/components/App.tsx", "e": [{ "startLine": 2, "endLine": 2, "content": "primary", "strMatch": "blue" }], "dryRun": true }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -1,6 +1,6 @@ // Basic component with props -const Button = ({ color = "blue", size = "md" }) => { +const Button = ({ color = "primary", size = "md" }) => { return <button className={`btn-${color} size-${size}`}>Click me</button>; };

状态 ID:fcbf740a 使用此 ID 和 approve_edit 来应用更改。

  1. 然后,使用状态 ID 批准更改:
{ "stateId": "fcbf740a" }

输出:

Index: src/components/App.tsx =================================================================== --- src/components/App.tsx original +++ src/components/App.tsx modified @@ -1,6 +1,6 @@ // Basic component with props -const Button = ({ color = "blue", size = "md" }) => { +const Button = ({ color = "primary", size = "md" }) => { return <button className={`btn-${color} size-${size}`}>Click me</button>; };
  1. 验证更改:
{ "path": "src/components/App.tsx", "lineNumbers": [2], "context": 1 }

输出:

Line 2: 1: // Basic component with props > 2: const Button = ({ color = "primary", size = "md" }) => { 3: return <button className={`btn-${color} size-${size}`}>Click me</button>;

请注意,出于安全考虑,州 ID 会在短时间内过期。尝试使用过期或无效的州 ID 将导致错误:

{ "stateId": "invalid123" }

输出:

Error: Invalid or expired state ID

get_file_lines

使用可选的上下文行检查文件中的特定行。此工具可用于在编辑前验证行内容。

{ "path": "src/components/App.tsx", "lineNumbers": [1, 2, 3], "context": 1 }

输出:

Line 1: > 1: // Basic component with props 2: const Button = ({ color = "blue", size = "md" }) => { Line 2: 1: // Basic component with props > 2: const Button = ({ color = "blue", size = "md" }) => { 3: return Click me; Line 3: 2: const Button = ({ color = "blue", size = "md" }) => { > 3: return Click me; 4: };

search_file

在文件中搜索文本模式或正则表达式,以查找特定的行号及其上下文。此工具对于使用edit_file_lines定位要编辑的行尤其有用。

特征:

  • 带有可选区分大小写的简单文本搜索
  • 正则表达式支持
  • 全词匹配
  • 可配置的上下文行
  • 返回行号、内容以及带有行号的周围上下文

参数:

{ path: string; // Path to the file to search pattern: string; // Search pattern (text or regex) type?: "text" | "regex"; // Type of search (default: "text") caseSensitive?: boolean; // Case-sensitive search (default: false) contextLines?: number; // Number of context lines (default: 2, max: 10) maxMatches?: number; // Maximum matches to return (default: 100) wholeWord?: boolean; // Match whole words only (default: false) multiline?: boolean; // Enable multiline regex mode (default: false) }

示例用例:

  1. 简单文本搜索:
{ "path": "src/components/App.tsx", "pattern": "const", "contextLines": 2 }

输出:

Found 6 matches in 0.9ms: File size: 0.7KB Match 1: Line 2, Column 1 ---------------------------------------- 1 | // Basic component with props > 2 | const Button = ({ color = "blue", size = "md" }) => { 3 | return <button className={`btn-${color} size-${size}`}>Click me</button>; 4 | }; Match 2: Line 7, Column 8 ---------------------------------------- 5 | 6 | // Component with multiple props and nested structure > 7 | export const Card = ({ 8 | title, 9 | subtitle = "Default subtitle", Match 3: Line 13, Column 3 ---------------------------------------- 11 | size = "lg", 12 | }) => { > 13 | const cardClass = `card-${theme} size-${size}`; 14 | 15 | return ( Match 4: Line 23, Column 4 ---------------------------------------- 21 | }; 22 | > 23 | // Constants and configurations 24 | const THEME = { 25 | light: { bg: "#ffffff", text: "#000000" }, Match 5: Line 24, Column 1 ---------------------------------------- 22 | 23 | // Constants and configurations > 24 | const THEME = { 25 | light: { bg: "#ffffff", text: "#000000" }, 26 | dark: { bg: "#000000", text: "#ffffff" }, Match 6: Line 29, Column 1 ---------------------------------------- 27 | }; 28 | > 29 | const CONFIG = { 30 | apiUrl: "https://api.example.com", 31 | timeout: 5000,
  1. 区分大小写的全词搜索:
{ "path": "src/components/App.tsx", "pattern": "props", "caseSensitive": true, "wholeWord": true, "contextLines": 1 }

输出:

Found 2 matches in 0.7ms: File size: 0.7KB Match 1: Line 1, Column 25 ---------------------------------------- > 1 | // Basic component with props 2 | const Button = ({ color = "blue", size = "md" }) => { Match 2: Line 6, Column 28 ---------------------------------------- 5 | > 6 | // Component with multiple props and nested structure 7 | export const Card = ({
  1. 查找 JSX 组件:
{ "path": "src/components/App.tsx", "pattern": "<[A-Z]\\w+\\s", "type": "regex", "contextLines": 1 }

输出:

Found 2 matches in 0.6ms: File size: 0.7KB Match 1: Line 3, Column 10 ---------------------------------------- 2 | const Button = ({ color = "blue", size = "md" }) => { > 3 | return <button className={`btn-${color} size-${size}`}>Click me</button>; 4 | }; Match 2: Line 16, Column 5 ---------------------------------------- 15 | return ( > 16 | <div className={cardClass}> 17 | <h2>{title}</h2>

常见工作流程:

  1. 查找然后编辑:
// First, search for the line { "path": "src/config.ts", "pattern": "API_URL", "wholeWord": true } // Then use the returned line number in edit_file_lines { "p": "src/config.ts", "e": [{ "startLine": 23, // Line number from search result "endLine": 23, "content": "export const API_URL = 'https://new-api.example.com';" }] }
  1. 查找所有用法:
{ "path": "src/components/App.tsx", "pattern": "\\buseMemo\\b", "type": "regex", "contextLines": 2, "maxMatches": 50 }
  1. 查找特定的道具图案:
{ "path": "src/components/App.tsx", "pattern": "className=['\"]([^'\"]+)['\"]", "type": "regex", "contextLines": 1 }

重要提示

  1. 空格处理
    • 该工具可以智能地处理字符串和正则表达式匹配中的空格
    • 替换时保留原始缩进
    • 标记之间的多个空格被规范化以便匹配
  2. 模式匹配
    • 字符串匹配( strMatch )是空白规范化的
    • 正则表达式模式( regexMatch )支持前瞻和后瞻
    • 不能在同一编辑中同时使用strMatchregexMatch
    • 检测并阻止重叠的正则表达式模式
  3. 最佳实践
    • 始终先使用试运行来验证更改
    • 在批准更改之前检查差异输出
    • 保持编辑操作的集中性和原子性
    • 针对您的用例使用适当的模式匹配

发展

安装依赖项:

npm install

构建服务器:

npm run build

对于使用自动重建的开发:

npm run watch

测试

运行测试套件:

npm run test

附加测试实用程序:

测试工具脚本

直接针对示例文件测试 MCP 工具:

npm run test:tools

此脚本:

  • 将测试装置重置为已知状态
  • 连接到 MCP 服务器
  • 按顺序测试每个工具:
    • get_file_lines
    • edit_file_lines (试运行)
    • approve_edit
  • 显示每个操作的输出
  • 验证更改是否正确应用

重置赛程脚本

将测试装置重置为原始状态:

npm run reset:fixtures

使用此脚本可以:

  • 在测试之前将测试文件重置为已知状态
  • 测试失败后清理
  • 确保一致的测试环境
  • 创建缺失的夹具目录

用法

服务器启动时需要指定一个或多个允许的目录:

node build/index.js <allowed-directory> [additional-directories...]

为了安全起见,所有文件操作都将限制在这些目录中。

环境变量

  • MCP_EDIT_STATE_TTL :编辑状态的生存时间(毫秒)(默认值:60000)。编辑状态在此持续时间后将过期,必须重新创建。

安装

要与 Claude Desktop 一起使用,请添加服务器配置:

在 MacOS 上: ~/Library/Application Support/Claude/claude_desktop_config.json在 Windows 上: %APPDATA%/Claude/claude_desktop_config.json

{ "mcpServers": { "edit-file-lines": { "command": "node", "args": [ "/path/to/edit-file-lines/build/index.js", "<allowed-directory>" ], "env": { "MCP_EDIT_STATE_TTL": "300000" // Optional: Set custom TTL (in milliseconds) } } } }

错误处理

该工具针对常见问题提供了清晰的错误消息:

  1. 未找到匹配项
Error: No string match found for "oldValue" on line 5
  1. 无效的正则表达式
Error: Invalid regex pattern "([": Unterminated group
  1. 同一行上的多个编辑
Error: Line 5 is affected by multiple edits

安全注意事项

  • 所有文件操作都限制在明确允许的目录中
  • 验证符号链接以防止转义允许的目录
  • 阻止父目录遍历
  • 执行路径规范化以进行一致的安全检查
  • 无效的行号和字符位置将被拒绝
  • 行尾规范化确保跨平台行为一致
  • 出于安全考虑,编辑状态将在 60 秒后过期
  • 编辑批准需要文件路径和编辑完全匹配

调试

使用测试工具脚本直接针对示例文件测试 MCP 工具。MCP检查器可能会有所帮助,但目前不支持处理非字符串值的输入。

-
security - not tested
A
license - permissive license
-
quality - not tested

基于 TypeScript 的 MCP 服务器,提供对允许目录内的文本文件进行精确的基于行的编辑的工具。

  1. Features
    1. Main Editing Tool
    2. Example Use Cases
    3. Additional Tools
    4. Important Notes
  2. Development
    1. Testing
  3. Usage
    1. Environment Variables
  4. Installation
    1. Error Handling
    2. Security Considerations
    3. Debugging
ID: 2apib1zht1