Edit File Lines MCP Server
Faça edições precisas baseadas em linhas em arquivos de texto dentro de diretórios permitidos.
Documentação
Servidor MCP de Edição de Linhas de Arquivos
Um servidor MCP baseado em TypeScript que fornece ferramentas para fazer edições precisas baseadas em linhas em arquivos de texto dentro de diretórios permitidos.
Recursos
Ferramenta Principal de Edição
edit_file_lines
Faça edições baseadas em linhas em um arquivo usando correspondência de padrões de string ou regex. Cada edição pode:
- Substituir linhas inteiras
- Substituir correspondências de texto específicas preservando a formatação da linha
- Usar padrões regex para correspondências complexas
- Lidar com múltiplas linhas e múltiplas edições
- Visualizar alterações com o modo de execução simulada
Arquivo de exemplo (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,
};
Exemplos de Casos de Uso
- Substituição Simples de String
{
"p": "src/components/App.tsx",
"e": [{
"startLine": 2,
"endLine": 2,
"content": "primary",
"strMatch": "blue"
}],
"dryRun": true
}
Saída:
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 do Estado: fcbf740a Use este ID com approve_edit para aplicar as alterações.
- Conteúdo Multilinha com Estrutura Preservada
{
"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
}
Saída:
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 do Estado: f2ce973f Use este ID com approve_edit para aplicar as alterações.
- Modificação Complexa de Estrutura 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
}
Saída:
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 do Estado: f1f1d27b Use este ID com approve_edit para aplicar as alterações.
- Atualização de Configuração com Preservação de Espaços em Branco
{
"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
}
Saída:
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 do Estado: 20e93c34 Use este ID com approve_edit para aplicar as alterações.
- Correspondência Flexível de Espaços em Branco
{
"p": "src/components/App.tsx",
"e": [{
"startLine": 9,
"endLine": 9,
"content": "description",
"strMatch": "subtitle = \"Default subtitle\"" // Extra spaces are handled
}],
"dryRun": true
}
Saída:
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}`;
Ferramentas Adicionais
approve_edit
Aplique alterações de uma execução simulada anterior de edit_file_lines. Esta ferramenta fornece um processo de edição em duas etapas para segurança. Aqui está um exemplo de fluxo de trabalho:
- Primeiro, faça uma edição de execução simulada:
{
"p": "src/components/App.tsx",
"e": [{
"startLine": 2,
"endLine": 2,
"content": "primary",
"strMatch": "blue"
}],
"dryRun": true
}
Saída:
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 do Estado: fcbf740a Use este ID com approve_edit para aplicar as alterações.
- Em seguida, aprove as alterações usando o ID do estado:
{
"stateId": "fcbf740a"
}
Saída:
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>;
};
- Verifique as alterações:
{
"path": "src/components/App.tsx",
"lineNumbers": [2],
"context": 1
}
Saída:
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>;
Observe que os IDs de estado expiram após um curto período por segurança. Tentar usar um ID de estado expirado ou inválido resultará em um erro:
{
"stateId": "invalid123"
}
Saída:
Error: Invalid or expired state ID
get_file_lines
Inspecione linhas específicas em um arquivo com linhas de contexto opcionais. Esta ferramenta é útil para verificar o conteúdo das linhas antes de fazer edições.
{
"path": "src/components/App.tsx",
"lineNumbers": [1, 2, 3],
"context": 1
}
Saída:
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
Pesquise em um arquivo por padrões de texto ou expressões regulares para encontrar números de linha específicos e seu contexto ao redor. Esta ferramenta é particularmente útil para localizar as linhas exatas que você deseja editar com edit_file_lines.
Recursos:
- Pesquisa de texto simples com sensibilidade a maiúsculas/minúsculas opcional
- Suporte a expressões regulares
- Correspondência de palavras inteiras
- Linhas de contexto configuráveis
- Retorna números de linha, conteúdo e contexto ao redor com números de linha
Argumentos:
{
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)
}
Exemplos de casos de uso:
- Pesquisa de texto simples:
{
"path": "src/components/App.tsx",
"pattern": "const",
"contextLines": 2
}
Saída:
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,
- Pesquisa de palavra inteira com sensibilidade a maiúsculas/minúsculas:
{
"path": "src/components/App.tsx",
"pattern": "props",
"caseSensitive": true,
"wholeWord": true,
"contextLines": 1
}
Saída:
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 = ({
- Encontrando componentes JSX:
{
"path": "src/components/App.tsx",
"pattern": "<[A-Z]\\w+\\s",
"type": "regex",
"contextLines": 1
}
Saída:
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>
Fluxos de trabalho comuns:
- Encontrar e depois editar:
// 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';"
}]
}
- Encontrar todos os usos:
{
"path": "src/components/App.tsx",
"pattern": "\\buseMemo\\b",
"type": "regex",
"contextLines": 2,
"maxMatches": 50
}
- Encontrar padrões específicos de props:
{
"path": "src/components/App.tsx",
"pattern": "className=['\"]([^'\"]+)['\"]",
"type": "regex",
"contextLines": 1
}
Notas Importantes
-
Tratamento de Espaços em Branco
- A ferramenta lida inteligentemente com espaços em branco em correspondências de string e regex
- A indentação original é preservada nas substituições
- Múltiplos espaços entre tokens são normalizados para correspondência
-
Correspondência de Padrões
- Correspondências de string (
strMatch) são normalizadas quanto a espaços em branco - Padrões regex (
regexMatch) suportam look-ahead e look-behind - Não é possível usar ambos
strMatcheregexMatchna mesma edição - Padrões regex sobrepostos são detectados e prevenidos
- Correspondências de string (
-
Melhores Práticas
- Sempre use a execução simulada primeiro para verificar alterações
- Revise a saída de diff antes de aprovar alterações
- Mantenha as operações de edição focadas e atômicas
- Use a correspondência de padrões apropriada para o seu caso de uso
Desenvolvimento
Instale as dependências:
npm install
Compile o servidor:
npm run build
Para desenvolvimento com recompilação automática:
npm run watch
Testes
Execute a suíte de testes:
npm run test
Utilitários de teste adicionais:
Script de Ferramentas de Teste
Teste as ferramentas MCP diretamente contra arquivos de exemplo:
npm run test:tools
Este script:
- Redefine os fixtures de teste para um estado conhecido
- Conecta-se ao servidor MCP
- Testa cada ferramenta em sequência:
get_file_linesedit_file_lines(execução simulada)approve_edit
- Mostra a saída de cada operação
- Verifica se as alterações foram aplicadas corretamente
Script de Redefinição de Fixtures
Redefina os fixtures de teste para seu estado original:
npm run reset:fixtures
Use este script para:
- Redefinir arquivos de teste para um estado conhecido antes de testar
- Limpar após testes com falha
- Garantir um ambiente de teste consistente
- Criar diretórios de fixtures ausentes
Uso
O servidor requer um ou mais diretórios permitidos a serem especificados ao iniciar:
node build/index.js <allowed-directory> [additional-directories...]
Todas as operações de arquivo serão restritas a esses diretórios por segurança.
Variáveis de Ambiente
MCP_EDIT_STATE_TTL: Tempo de vida em milissegundos para estados de edição (padrão: 60000). Os estados de edição expirarão após essa duração e deverão ser recriados.
Instalação
Para usar com o Claude Desktop, adicione a configuração do servidor:
No MacOS: ~/Library/Application Support/Claude/claude_desktop_config.json
No 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)
}
}
}
}
Tratamento de Erros
A ferramenta fornece mensagens de erro claras para problemas comuns:
- Correspondência Não Encontrada
Error: No string match found for "oldValue" on line 5
- Regex Inválido
Error: Invalid regex pattern "([": Unterminated group
- Múltiplas Edições na Mesma Linha
Error: Line 5 is affected by multiple edits
Considerações de Segurança
- Todas as operações de arquivo são restritas a diretórios explicitamente permitidos
- Links simbólicos são validados para evitar escapar dos diretórios permitidos
- A navegação para diretórios pai é prevenida
- A normalização de caminhos é realizada para verificações de segurança consistentes
- Números de linha e posições de caracteres inválidos são rejeitados
- A normalização de finais de linha garante comportamento consistente entre plataformas
- Os estados de edição expiram após 60 segundos por segurança
- As aprovações de edição exigem correspondência exata do caminho do arquivo e das edições
Depuração
Use o script de Ferramentas de Teste para testar as ferramentas MCP diretamente contra arquivos de exemplo. O Inspetor MCP pode ajudar, mas atualmente não suporta entrada de valores que não sejam strings.