mcp-local-erp
Enables local file reading and writing for your project via Claude Desktop, with tools to read, write, and list files in a specified root path.
README
mcp-local-erp
Servidor MCP local de leitura e escrita de arquivos de um projeto, para
uso com o Claude Desktop. Cada projeto (ex: erp-distribuidora,
erp-consultorio, erp-confeccao...) recebe sua própria cópia desta pasta,
com um config.yaml próprio. Isso permite que vários projetos rodem em
paralelo, cada um aparecendo com um nome distinto dentro do Claude Desktop.
Toda escrita de arquivo passa por um harness de controle de mudanças: nenhuma alteração acontece sem um plano prévio (feature + arquivos envolvidos) aprovado explicitamente. Veja a seção Harness de controle de mudanças abaixo.
Estrutura
mcp-local-erp/
├── config.yaml # nome do projeto e raiz de arquivos que o servidor enxerga
├── server.py # define as ferramentas (read_file, write_file, list_dir, harness)
├── change_control.py # implementação do harness: planos, aprovação, log de auditoria
├── start.py # registra este servidor no Claude Desktop
├── pyproject.toml # dependências (fastmcp, pyyaml, psutil)
├── mcp_audit.jsonl # log append-only de todo evento do harness (versionado no Git)
├── mcp_state.json # planos pendentes/aprovados (transitório — não versionado)
└── README.md
mcp_state.json e mcp_audit.jsonl ficam sempre dentro desta pasta
(mcp-local-erp/), nunca dentro do projeto que o servidor gerencia — mesmo
quando root_path aponta para fora dela. Veja o porquê em
Arquivos gerados pelo harness.
Instalação (primeira vez na máquina)
1. Python
Verifique se já está instalado:
python --version
Se não retornar nada, instale a versão 3.11 ou superior:
| Sistema | Comando |
|---|---|
| Windows | winget install Python.Python.3.12 |
| macOS | brew install python@3.12 |
| Linux | sudo apt install python3 python3-venv |
2. uv (gerenciador de dependências)
| Sistema | Comando |
|---|---|
| Windows (PowerShell) | powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" |
| macOS / Linux | curl -LsSf https://astral.sh/uv/install.sh | sh |
Feche e reabra o terminal depois de instalar, para o uv entrar no PATH.
3. Dependências do projeto
Dentro da pasta mcp-local-erp:
cd C:\project-claude\mcp-local
uv sync
Isso cria um .venv local e instala tudo conforme o pyproject.toml.
Configuração
Edite o config.yaml antes de registrar:
project_name: mcp-local-erp # nome único — é o que aparece no Claude Desktop
environment: dev # dev | prod — identifica o ambiente na auditoria
root_path: ../ # pasta raiz do projeto que este servidor pode ler/escrever
allowed_extensions: # extensões que write_file tem permissão de gravar
- .py
- .tsx
- .ts
- .json
- .yaml
- .md
blocked_dirs: # diretórios nunca acessíveis, nem para leitura
- node_modules
- .git
- .venv
mcp-local-erp é o nome padrão de fábrica do pacote. Ao colocar esta pasta
dentro de um projeto específico (erp-distribuidora, erp-consultorio,
erp-confeccao...), troque project_name para um nome único por projeto —
é o que diferencia os servidores quando mais de um estiver rodando ao mesmo
tempo no Claude Desktop.
root_path define o escopo de read_file / list_dir / write_file — ou
seja, o projeto que este servidor enxerga e pode alterar. Isso é
propositalmente diferente de onde o harness guarda seu próprio estado (ver
seção seguinte).
Registro no Claude Desktop
Passo 1 — Feche o Claude Desktop por completo
Isso é obrigatório, não opcional. O Claude Desktop mantém o
claude_desktop_config.json em memória enquanto está aberto; se ele
continuar rodando durante o registro, pode sobrescrever o arquivo com o
estado antigo ao ser fechado depois — apagando a entrada nova sem aviso.
No Windows:
- Clique com o botão direito no ícone do Claude na bandeja do sistema → Sair / Quit.
- Confirme que não sobrou processo algum:
Se não retornar nada, está encerrado.Get-Process Claude -ErrorAction SilentlyContinue
Passo 2 — Rode o script de registro
uv run start.py
O script:
- detecta automaticamente onde este Windows guarda o
claude_desktop_config.json— cobre tanto instalação via Microsoft Store (MSIX) (%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\) quanto a instalação tradicional (%APPDATA%\Claude\). Isso importa: editar o arquivo errado é a causa mais comum de "registrei mas não apareceu"; - limpa processos órfãos de
server.pydeste projeto — instâncias presas de sessões anteriores cujo processo pai (o Claude Desktop) já fechou. Só encerra processo com pai morto; nunca mexe em processo com o Claude Desktop ainda rodando; - lê o
project_namedoconfig.yamle, se a entrada ainda não existir, adiciona automaticamente (com backup do arquivo original antes de qualquer alteração); se já existir, apenas avisa e não altera nada; - em qualquer um dos dois casos, relê o arquivo no final e mostra a lista de servidores registrados, como conferência.
Se mcp-local-erp (ou o nome que você definiu) não aparecer nessa lista
final, não abra o Claude Desktop ainda — confirme antes se o processo
estava mesmo encerrado no Passo 1.
Passo 3 — Abra o Claude Desktop
O novo servidor MCP aparece na lista de ferramentas conectadas com o nome
definido em project_name.
Harness de controle de mudanças
Nenhuma escrita acontece "direto". Toda alteração de arquivo passa obrigatoriamente por um plano prévio, revisado por você, antes de o conteúdo ser gravado. Isso dá rastreabilidade clara do propósito de cada mudança e impede que várias alterações aconteçam sem revisão.
O processo, passo a passo
┌──────────────────────────┐
│ 1. propose_change │ Claude declara: feature, descrição do
│ (Claude chama) │ propósito, e a lista exata de paths que
│ │ serão criados/alterados.
└────────────┬──────────────┘
│ grava plano com status "pending"
│ em mcp_state.json (dentro de mcp-local-erp/)
▼
┌──────────────────────────┐
│ 2. revisão humana │ Você lê o plano exibido na conversa:
│ (você decide) │ feature, arquivos, propósito.
└────────────┬──────────────┘
│
┌───────┴────────┐
│ │
aprovado rejeitado
│ │
▼ ▼
┌───────────────┐ ┌───────────────────┐
│ 3. approve_ │ │ reject_change │
│ change │ │ (Claude chama) │
│ (Claude chama) │ │ plano vira │
│ plano vira │ │ "rejected" — fim │
│ "approved" │ └───────────────────┘
└───────┬────────┘
▼
┌────────────────────────────────────┐
│ 4. write_file(rel_path, content, │
│ plan_id, feature, description) │
│ │
│ Antes de gravar, verifica: │
│ - rel_path é um arquivo interno │
│ reservado do harness? recusa │
│ - plan_id existe? │
│ - status == "approved"? │
│ - rel_path está na lista de │
│ files do plano? │
│ │
│ Se qualquer checagem falhar │
│ → recusa com erro, nada é gravado. │
│ │
│ Se tudo OK: │
│ - injeta comentário de │
│ rastreabilidade no topo do │
│ arquivo (feature, plano, data) │
│ - grava o arquivo (dentro de │
│ ROOT, o projeto gerenciado) │
│ - registra o evento em │
│ mcp_audit.jsonl (dentro de │
│ mcp-local-erp/) │
└────────────────────────────────────┘
Ferramentas do harness
| Ferramenta MCP | Quando usar | Efeito |
|---|---|---|
propose_change(feature, description, files) |
Antes de qualquer alteração | Cria plano pending, devolve plan_id |
approve_change(plan_id) |
Depois que você aprovar na conversa | Plano vira approved |
reject_change(plan_id) |
Se você recusar o plano proposto | Plano vira rejected |
list_pending_changes(status) |
Para conferir o que está pendente/aprovado/rejeitado | Lista os planos filtrados por status |
write_file(rel_path, content, plan_id, feature, description) |
Só depois do plano aprovado | Grava o arquivo com comentário de rastreabilidade; recusa se o plano não cobrir rel_path |
read_file(rel_path) |
A qualquer momento | Leitura livre, sem exigir plano (não altera nada) |
list_dir(rel_path) |
A qualquer momento | Leitura livre da árvore de arquivos |
Arquivos gerados pelo harness
mcp_state.json— os planos e seus status (pending/approved/rejected) e quais escritas cada plano já cobriu. Não é versionado (está no.gitignore): é estado de trabalho, não histórico.mcp_audit.jsonl— log append-only, uma linha JSON por evento (propose,approve,reject,write), com timestamp. Este arquivo é versionado — é o seu histórico auditável de quem pediu e aprovou o quê, mesmo depois de o plano ter saído domcp_state.json.
Os dois arquivos vivem sempre em HARNESS_ROOT
(Path(__file__).parent em server.py, ou seja, a própria pasta
mcp-local-erp/) — não em ROOT (root_path do config.yaml, que é
o projeto gerenciado, ex: erp-distribuidora/). Essa separação é
intencional: ROOT muda de projeto para projeto e pode até apontar para
fora desta pasta, mas o bookkeeping do harness precisa ficar contido e
previsível, sempre no mesmo lugar, independente de onde root_path aponte.
Por isso também write_file recusa qualquer tentativa de gravar em um
arquivo chamado mcp_state.json ou mcp_audit.jsonl — mesmo com plano
aprovado — para que o próprio fluxo de aprovação não possa corromper seu
próprio estado.
Exemplo de recusa (proteção funcionando)
Se o Claude tentar escrever em um arquivo fora do escopo aprovado:
ValueError: Arquivo 'app/models/pagamento.py' não está no escopo
declarado do plano 'a1b2c3d4' (['server.py', 'change_control.py']).
Proponha um novo plano cobrindo este arquivo.
Isso é o comportamento esperado: qualquer expansão de escopo exige um novo plano — e uma nova aprovação sua.
Reaproveitando em projetos futuros
Esta pasta é autocontida — nada nela depende de algo externo. Para usar em um novo projeto:
- Copie a pasta
mcp-local-erpinteira para dentro do repositório. - Ajuste
project_nameeroot_pathnoconfig.yaml. - Repita os passos de Registro no Claude Desktop acima.
Não é um pacote instalável (não vai pro PyPI, não é importado por outro código) — é um servidor autônomo, então não precisa de nenhum ajuste de packaging além do que já está pronto aqui.
Troubleshooting
Erro Failed to build mcp-local mencionando hatchling ou
only-include: o pyproject.toml já vem corrigido com
[tool.uv] package = false, que avisa o uv para instalar dependências e
rodar os scripts sem tentar empacotar nada. Se aparecer de novo, confirme
que seu pyproject.toml tem esse bloco e não tem uma seção
[build-system].
A entrada some do claude_desktop_config.json depois de reiniciar o
Claude Desktop: o app estava aberto durante o registro. Siga o Passo 1
da seção de Registro à risca antes de rodar start.py de novo.
A entrada nunca aparece na tela "Servidores MCP locais", mesmo o
terminal confirmando o registro: o script pode ter escrito no arquivo
tradicional (%APPDATA%\Claude\) enquanto sua instalação do Claude
Desktop é via Microsoft Store (MSIX), que lê de
%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\. A versão
atual do start.py já detecta isso automaticamente e imprime qual
caminho encontrou — confira a linha "Config detectado" no início da
saída para confirmar qual arquivo está sendo usado.
spawn uv ENOENT nos logs do Claude Desktop: o app não achou o
executável do uv no seu próprio PATH (que pode ser mais restrito que o
do terminal). O start.py já resolve o caminho absoluto do uv
automaticamente; se o aviso aparecer na tela, rode where uv e confirme
o caminho manualmente no claude_desktop_config.json.
write_file recusa com "Plano não encontrado" ou "não aprovado": o
harness está funcionando como esperado — chame propose_change (e,
depois da sua aprovação, approve_change) antes de tentar escrever.
write_file recusa dizendo que o arquivo é "interno do harness":
também esperado — mcp_state.json e mcp_audit.jsonl nunca podem ser
alvo de write_file, mesmo com plano aprovado; são gerenciados só pelas
funções internas de change_control.py.
Observação importante
Rodar python server.py diretamente no terminal não faz nada visível
— o servidor fica esperando mensagens no stdin. Quem inicia o processo de
fato é o Claude Desktop, usando o comando registrado pelo start.py. Use
o start.py apenas para garantir o registro; o "start" do servidor em si
acontece automaticamente quando o Claude Desktop abre.
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.