19 out 2026 · mcp, ia, agentes · 6 min
Servidores MCP prontos para conectar no seu agente
Conectei um servidor MCP de arquivos a um processo meu e ele respondeu com uma lista de 14 ferramentas. O de memória respondeu com 9. Nenhum dos dois ocupou o sistema: npx baixou os pacotes num cache e os executou como processo filho falando JSON-RPC pelo stdin.
O que talvez você já saiba: um servidor MCP é um programa. Não é daemon, não é serviço, não tem porta. O agente escreve uma linha de JSON no stdin dele, o processo escreve uma linha de JSON de volta no stdout. O resto é SDK, e o SDK é opcional.
os dois servidores que eu usaria
O repositório modelcontextprotocol/servers guarda as implementações de referência mantidas pelo grupo que define o protocolo. O README avisa que são exemplos para estudar, não peças prontas para produção. Duas servem para uso real:
O de arquivos é o mais útil dos dois. Recebe no comando os diretórios que pode tocar e nada fora deles. Ele expõe read_text_file, write_file, edit_file, search_files, directory_tree, get_file_info, move_file e outras, 14 ao todo. As Ferramentas de escrita vêm anotadas como destrutivas, o que permite ao cliente pedir confirmação.
O de memória guarda o que o agente aprende num grafo de entidades, relações e observações, num arquivo JSONL. São 9 ferramentas: create_entities, create_relations, add_observations, search_nodes, open_nodes, read_graph e três de apagar. O ponto dele é a persistência entre conversas.
a configuração, comentada
Dois servidores na mesma configuração. O que muda entre eles é o comando e o que vem no env.
{
"mcpServers": {
"arquivos": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/[email protected]",
"/caminho/que/o/agente/pode/ler"
]
},
"memoria": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/[email protected]"],
"env": {
"MEMORY_FILE_PATH": "/home/voce/.local/share/agente/memoria.jsonl"
}
}
}
}
O @2.0.0 no fim do pacote não é decoração. Sem ele vem a versão mais nova a cada instalação, e uma atualização quebra o agente sem você ter tocado em nada.
O caminho em MEMORY_FILE_PATH importa mais do que parece. Sem essa variável o servidor grava em ~/.npm/_npx/<hash>/node_modules/.../dist/memory.jsonl, dentro do cache do npm. Funciona até o cache ser limpo ou o hash mudar, e aí o grafo inteiro some. Foi o que aconteceu no meu primeiro teste: o arquivo estava a quatro níveis de pasta dentro do cache.
o artefato
Um script bash que fala o protocolo direto, para você ver o que o agente vê antes de ligar o agente. Sem SDK, sem Python, sem cliente.
#!/usr/bin/env bash
# mcp-call.sh - fala com um servidor MCP por stdio, sem SDK e sem agente.
#
# O protocolo e JSON-RPC 2.0, uma linha por mensagem, no stdin e no stdout do
# processo. Isso e tudo. Nao precisa de Python nem de cliente.
#
# Uso:
# ./mcp-call.sh imprime o protocolo
# ./mcp-call.sh -- <comando>... lista as ferramentas
# ./mcp-call.sh --tool NOME [--args JSON] -- <comando>... chama uma
#
# O "--" separa o comando do servidor das opcoes. Sem ele nao da para
# distinguir "npx -y pacote /caminho" de uma ferramenta chamada "-y", e
# qualquer heuristica erra. Por isso o nome da ferramenta vem em --tool, e
# nao em posicao fixa.
#
# Detalhe que economiza uma hora de depuracao: o servidor sai quando o stdin
# fecha. Sem o sleep depois da ultima linha, ele le as tres mensagens e morre
# antes de responder a terceira. O pipe precisa ficar aberto.
set -uo pipefail
PROTOCOLO='2025-06-18'
ESPERA="${MCP_ESPERA:-20}"
FERRAMENTA=""
ARGS='{}'
mostrar_protocolo() {
cat <<'FIM'
Servidor MCP = processo que fala JSON-RPC 2.0, uma linha por mensagem.
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{...}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
Chamar uma ferramenta:
{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"list_directory","arguments":{"path":"/tmp"}}}
Ordem obrigatoria: initialize, notifications/initialized, so depois tools/list
ou tools/call. E o servidor encerra quando o stdin fecha.
FIM
}
case "${1:-}" in
""|"-h"|"--help") mostrar_protocolo; exit 0 ;;
esac
# Opcoes antes do "--".
while [ $# -gt 0 ]; do
case "$1" in
--tool) FERRAMENTA="${2:-}"; shift 2 ;;
--args) ARGS="${2:-{\}}"; shift 2 ;;
--) shift; break ;;
*) break ;;
esac
done
if [ $# -eq 0 ]; then
echo "faltou o comando do servidor depois do --" >&2
exit 2
fi
INIT="{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"$PROTOCOLO\",\"capabilities\":{},\"clientInfo\":{\"name\":\"mcp-call\",\"version\":\"0\"}}}"
PRONTO='{"jsonrpc":"2.0","method":"notifications/initialized"}'
if [ -n "$FERRAMENTA" ]; then
PEDIDO="{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"$FERRAMENTA\",\"arguments\":$ARGS}}"
else
PEDIDO='{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
fi
# O { ...; sleep; } segura o stdin aberto depois da ultima linha.
SAIDA="$({ printf '%s\n%s\n%s\n' "$INIT" "$PRONTO" "$PEDIDO"; sleep "$ESPERA"; } \
| timeout 120 "$@" 2>/dev/null)"
if [ -z "$FERRAMENTA" ]; then
if printf '%s' "$SAIDA" | grep -q '"result":{"tools"'; then
printf '%s\n' "$SAIDA" | grep '"result":{"tools"' \
| jq -r '.result.tools[] | " " + .name' | sort
printf 'total de ferramentas: '
printf '%s\n' "$SAIDA" | grep '"result":{"tools"' | jq -r '.result.tools | length' | head -1
else
echo "nenhuma resposta de tools/list. O comando do servidor falhou ou"
echo "exige outra versao de node. Teste o comando sozinho antes."
fi
else
printf '%s\n' "$SAIDA" | grep '"id":2' | jq -r '.result.content[]?.text // .error.message'
fi
o que eu medi
Rodei os dois servidores pelo script, com node v22.23.3, em 19 de outubro de 2026.
O de arquivos devolveu as 14 ferramentas, incluindo list_directory e write_file. A chamada de teste em list_directory voltou [FILE] init.jsonl, o único arquivo do diretório que eu tinha passado. O de memória devolveu 9 ferramentas, e o create_entities gravou uma entidade que o read_graph leu de volta inteira.
Tamanho dos pacotes: 94.972 bytes descompactados o de arquivos e 57.615 o de memória, 16 MB em disco cada um com as dependências. Licença MIT, os dois. O de arquivos pediu node 24 ou mais e rodou em node 22 com um aviso, sem quebrar.
como verificar
chmod +x mcp-call.sh
./mcp-call.sh -- npx -y @modelcontextprotocol/[email protected]
A saída lista as 9 ferramentas e fecha com o total. Para chamar uma:
./mcp-call.sh --tool read_graph --args '{}' -- npx -y @modelcontextprotocol/[email protected]
O jq está no meio do caminho: ele é quem lê a resposta. Sem ele você vê a linha de JSON inteira, o que também serve.
se der errado
O servidor responde o initialize e morre. É o caso mais comum, e é o stdin fechando. Pipe que termina logo depois da última mensagem mata o processo antes da resposta, porque o servidor lê até o fim do arquivo e encerra. O script segura o pipe com um sleep depois da última linha.
Aviso de EBADENGINE na saída. O pacote do servidor de arquivos pede node 24 ou mais e eu testei em node 22. Ele funcionou, mas em máquina restrita pode não funcionar. A correção é subir o node.
A lista de ferramentas vem vazia. Quase sempre é jq ausente ou o servidor falhando antes do handshake. Rode o comando sozinho e veja se aparece a linha de identificação.
escolher entre os dois
| Servidor | Ferramentas | Guarda estado onde | Serve para |
|---|---|---|---|
| filesystem 2.0.0 | 14 | nada, só lê e escreve | dar acesso a arquivos com limite de diretório |
| memory 2.0.0 | 9 | JSONL, com MEMORY_FILE_PATH |
lembrar entre conversas |
| fetch 2.0.0 | 1 | nada | buscar uma URL e converter para markdown |
| sequentialthinking | variável | nada | raciocínio passo a passo, mais uso de token |
Os dois primeiros cobrem o que a maioria dos agentes precisa. Um agente com shell já tem filesystem, o que faz do servidor de arquivos mais um limite do que uma capacidade nova, como discutido na postagem sobre rodar contêiner sem root. Para estado em arquivo com consulta, a busca semântica com sqlite-vec resolve o mesmo problema de um jeito mais fácil de auditar.
perguntas que aparecem sempre
Preciso instalar alguma coisa? Não, se usar npx. O pacote é baixado num cache e executado como processo filho. Instalar globalmente funciona, e aí você perde o controle de qual versão está rodando.
Servidor MCP abre porta? Não no transporte por stdio, que é o caso dos dois servidores aqui. Existem servidores remotos, que sim escutam socket, mas aí entra autenticação e TLS no meio.
Posso escrever meu próprio? Sim, e é bem menos trabalho do que parece: o agente precisa de uma linha de JSON com método e parâmetros. Os servidores de referência servem de exemplo do envelope.
Dá para ligar mais de um ao mesmo tempo? Pode. O modelcontextprotocol trata cada servidor como um bloco independente, e o cliente decide quando chamar cada um.
Versão ou latest? Versão, sempre. Os dois pacotes-publicados dentro do mesmo dia na semana em que escrevi isto, e uma mudança de nome de ferramenta entre versões quebraria o agente sem aviso.
fontes
Lista de servidores e o aviso sobre serem implementações de referência: github.com/modelcontextprotocol/servers, conferido em 19 de outubro de 2026. Versão, licença e ferramentas: server-filesystem 2.0.0 e server-memory 2.0.0. O conceito de ferramenta, recurso e prompt está em understanding mcp servers, do time do protocolo.