返回市场
MCP编辑文件行

MCP编辑文件行

作者:oakenai30 星标更新:2024-12-19

项目介绍

编辑文件行的MCP服务器

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

功能

主编辑工具

edit_file_lines

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

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

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

// 带有属性的基本组件
const Button = ({ color = "blue", size = "md" }) => {
  return <button className={`btn-${color} size-${size}`}>Click me</button>;
};

// 带有多个属性和嵌套结构的组件
export const Card = ({
  title,
  subtitle = "默认副标题",
  theme = "light",
  size = "lg",
}) => {
  const cardClass = `card-${theme} size-${size}`;
  
  return (
    <div className={cardClass}>
      <h2>{title}</h2>
      <p>{subtitle}</p>
    </div>
  );
};

// 常量和配置
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 @@
 // 基本组件与属性
-const Button = ({ color = "blue", size = "md" }) => {
+const Button = ({ color = "primary", size = "md" }) => {
   return Click me;
 };
 
 // 带有多个属性和嵌套结构的组件

状态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 = \"新默认值\",\n  theme = \"现代\",\n  size = \"响应式\"\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 @@
 // 带有多个属性和嵌套结构的组件
 export const Card = ({
   title,
-  subtitle = "默认副标题",
-  theme = "light",
-  size = "lg",
+  subtitle = "新默认值",
+  theme = "现代",
+  size = "响应式"
 }) => {
   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   =   \"默认副标题\""  // 处理额外的空格
  }],
  "dryRun": true
}

输出:

Index: src/components/App.tsx
===================================================================
--- src/components/App.tsx        original
+++ src/components/App.tsx        modified
@@ -5,9 +5,9 @@
 // 带有多个属性和嵌套结构的组件
 export const Card = ({
   title,
-  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 @@
 // 基本组件与属性
-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 @@
 // 基本组件与属性
-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
}

输出:

第2行:
  1: // 基本组件与属性
> 2: const Button = ({ color = "primary", size = "md" }) => {
  3:   return <button className={`btn-${color} size-${size}`}>Click me</button>;

注意,状态ID在短时间内会过期以保证安全性。尝试使用已过期或无效的状态ID会导致错误:

{
  "stateId": "invalid123"
}

输出:

错误:无效或已过期的状态ID

get_file_lines

检查文件中的特定行,可选地带有上下文行。此工具在进行编辑前验证行内容时非常有用。

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

输出:

第1行:
> 1: // 基本组件与属性
  2: const Button = ({ color = "blue", size = "md" }) => {

第2行:
  1: // 基本组件与属性
> 2: const Button = ({ color = "blue", size = "md" }) => {
  3:   return Click me;

第3行:
  2: const Button = ({ color = "blue", size = "md" }) => {
> 3:   return Click me;
  4: };

search_file

搜索文件中的文本模式或正则表达式,以找到特定的行号及其周围的上下文。此工具特别适用于使用edit_file_lines定位要编辑的确切行。

特性:

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

参数:

{
  path: string;          // 要搜索的文件路径
  pattern: string;       // 搜索模式(文本或正则表达式)
  type?: "text" | "regex"; // 搜索类型(默认:"text")
  caseSensitive?: boolean; // 大小写敏感搜索(默认:false)
  contextLines?: number;   // 上下文行数(默认:2,最大:1
  maxMatches?: number;     // 最大返回匹配数(默认:100)
  wholeWord?: boolean;     // 仅匹配整词(默认:false)
  multiline?: boolean;     // 启用多行正则表达式模式(默认:false)
}

示例用例:

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

输出:

在0.9毫秒内找到6个匹配项:
文件大小:0.7KB

匹配1:第2行,第1列
----------------------------------------
     1 | // 基本组件与属性
>    2 | const Button = ({ color = "blue", size = "md" }) => {
     3 |   return <button className={`btn-${color} size-${size}`}>Click me</button>;
     4 | };

匹配2:第7行,第8列
----------------------------------------
     5 | 
     6 | // 带有多个属性和嵌套结构的组件
>    7 | export const Card = ({
     8 |   title,
     9 |   subtitle = "默认副标题",

匹配3:第13行,第3列
----------------------------------------
    11 |   size = "lg",
    12 | }) => {
>   13 |   const cardClass = `card-${theme} size-${size}`;
    14 |   
    15 |   return (

匹配4:第23行,第4列
----------------------------------------
    21 | };
    22 | 
>   23 | // 常量和配置
    24 | const THEME = {
    25 |   light: { bg: "#ffffff", text: "#000000" },

匹配5:第24行,第1列
----------------------------------------
    22 | 
    23 | // 常量和配置
>   24 | const THEME = {
    25 |   light: { bg: "#ffffff", text: "#000000" },
    26 |   dark: { bg: "#000000", text: "#ffffff" },

匹配6:第29行,第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
}

输出:

在0.7毫秒内找到2个匹配项:
文件大小:0.7KB

匹配1:第1行,第25列
----------------------------------------
>    1 | // 基本组件与属性
     2 | const Button = ({ color = "blue", size = "md" }) => {

匹配2:第6行,第28列
----------------------------------------
     5 | 
>    6 | // 带有多个属性和嵌套结构的组件
     7 | export const Card = ({
  1. 查找JSX组件:
{
  "path": "src/components/App.tsx",
  "pattern": "<[A-Z]\\w+\\s",
  "type": "regex",
  "contextLines": 1
}

输出:

在0.6毫秒内找到2个匹配项:
文件大小:0.7KB

匹配1:第3行,第10列
----------------------------------------
     2 | const Button = ({ color = "blue", size = "md" }) => {
>    3 |   return <button className={`btn-${color} size-${size}`}>Click me</button>;
     4 | };

匹配2:第16行,第5列
----------------------------------------
    15 |   return (
>   16 |     <div className={cardClass}>
    17 |       <h2>{title}</h2>

常见工作流:

  1. 查找然后编辑:
// 首先,查找该行
{
  "path": "src/config.ts",
  "pattern": "API_URL",
  "wholeWord": true
}

// 然后,在edit_file_lines中使用返回的行号
{
  "p": "src/config.ts",
  "e": [{
    "startLine": 23,  // 来自搜索结果的行号
    "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