>_ josetilabs.com
← blog

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.

json
{
  "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.

bash
#!/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.

Diagrama mostrando o agente enviando JSON-RPC por stdin para um processo servidor MCP, que responde com a lista de ferramentas pelo stdout, sem porta de rede
O caminho inteiro: uma linha de JSON entra pelo stdin, outra sai pelo stdout, e nenhuma porta é aberta.

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

bash
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:

bash
./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.

Leia também

// Por e-mail

Os textos publicados aqui também vão por e-mail. O envio ainda não começou: quem deixar o endereço agora entra na primeira lista.

Guardo só o seu e-mail, a data e o registro desta autorização. Sem cookies, sem rastreador e nada compartilhado com terceiros. Detalhes na política de privacidade.