Skip to main content
Glama
oakenai

Edit File Lines MCP Server

by oakenai

MCP 서버 파일 줄 편집

허용된 디렉터리 내에서 텍스트 파일에 대한 정확한 줄 기반 편집을 위한 도구를 제공하는 TypeScript 기반 MCP 서버입니다.

특징

주요 편집 도구

edit_file_lines

문자열 또는 정규식 패턴 매칭을 사용하여 파일을 줄 단위로 편집할 수 있습니다. 각 편집은 다음을 수행할 수 있습니다.

  • 전체 줄 바꾸기

  • 줄 서식을 유지하면서 특정 텍스트 일치 항목 바꾸기

  • 복잡한 일치에 정규식 패턴 사용

  • 여러 줄과 여러 편집을 처리합니다

  • 드라이런 모드로 변경 사항 미리 보기

예제 파일( src/components/App.tsx ):

지엑스피1

예시 사용 사례

  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 의 이전 연습 실행에서 변경 사항을 적용합니다. 이 도구는 안전을 위해 2단계 편집 프로세스를 제공합니다. 다음은 워크플로 예시입니다.

  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 )은 미리 보기와 뒤돌아보기를 지원합니다.

    • 동일한 편집에서 strMatch 와 regexMatch 모두 사용할 수 없습니다.

    • 중복되는 정규식 패턴이 감지되어 방지됩니다.

  3. 모범 사례

    • 변경 사항을 확인하려면 항상 먼저 연습을 실행하세요.

    • 변경 사항을 승인하기 전에 diff 출력을 검토하세요.

    • 편집 작업을 집중적이고 원자적으로 유지하세요

    • 사용 사례에 적합한 패턴 매칭을 사용하세요

Related MCP server: mcp-editor

개발

종속성 설치:

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 : 편집 상태의 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 검사기가 도움이 될 수도 있지만, 현재 문자열 값이 아닌 입력은 처리할 수 없습니다.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    A TypeScript MCP server port of Anthropic's filesystem editing tools, allowing file manipulation via client-approved operations without automated writes to prevent system harm.
    5
    9
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    A lightweight MCP server that provides 40 tools for TypeScript/JavaScript refactoring and code intelligence, directly mapping to TypeScript's tsserver protocol commands for accurate structural changes and workspace analysis.
    40
    29 npm
    3
    MIT