S3 Documentation MCP Server

Um servidor leve do Model Context Protocol (MCP) que traz capacidades de RAG (Geração Aumentada por Recuperação) para seu LLM sobre documentação Markdown armazenada no S3.

Documentação

S3 Documentation MCP Server

CI codecov Build and Push Docker Image Docker Hub

Um servidor leve Model Context Protocol (MCP) que traz capacidades de RAG (Geração Aumentada por Recuperação) para seu LLM sobre documentação Markdown armazenada no S3.

Feito para simplicidade:

  • 🪶 Stack Leve: Sem dependências pesadas ou serviços em nuvem
  • 🏠 Embeddings Flexíveis: Escolha entre Ollama (local, gratuito) ou OpenAI (nuvem, alta precisão)
  • 💾 Armazenamento Baseado em Arquivos: Índices vetoriais armazenados como arquivos simples (HNSWLib)
  • 🔌 Compatível com S3: Funciona com qualquer armazenamento compatível com S3 (AWS, MinIO, Scaleway, Cloudflare R2...)

[!IMPORTANT]
🚧 Este projeto está em desenvolvimento. APIs e comportamentos podem mudar a qualquer momento, e a compatibilidade retroativa não é garantida. Não é adequado para produção.

Requisitos

  • Provedor de Embeddings (escolha um):
    • Ollama (recomendado para uso local/offline) com o modelo nomic-embed-text
    • Chave de API OpenAI (para embeddings baseados em nuvem)
  • Node.js >= 18 (se executar a partir do código-fonte) OU Docker (recomendado)
  • Armazenamento compatível com S3 (AWS S3, MinIO, Scaleway, Cloudflare R2, etc.)

Casos de Uso

  • 📚 Documentação de Produto: Deixe Claude/Cursor/etc responder a partir da sua documentação
  • 🏢 Wiki Interna: Busca de conhecimento empresarial com IA
  • 📖 Documentação de API: Ajude desenvolvedores a encontrar informações de API
  • 🎓 Conteúdo Educacional: Construa tutores de IA com materiais de curso

Início Rápido

Com Docker (Recomendado)

# 1. Prerequisites
# Install Ollama from https://ollama.ai
ollama pull nomic-embed-text

# 2. Configure
cp env.example .env  # Add your S3 credentials

# 3. Run
docker run -d \
  --name s3-doc-mcp \
  -p 3000:3000 \
  --env-file .env \
  -e OLLAMA_BASE_URL=http://host.docker.internal:11434 \
  -v $(pwd)/data:/app/data \
  yoanbernabeu/s3-doc-mcp:latest

Ou use Docker Compose (Build Local):

docker compose up -d

A partir do Código-Fonte

# 1. Prerequisites
# Install Ollama from https://ollama.ai
ollama pull nomic-embed-text

# 2. Install & Run
npm install
cp env.example .env  # Configure your S3 credentials
npm run build && npm start

# 3. For local development
npm run dev

Seu servidor MCP agora está rodando em http://localhost:3000

Conecte-se a Clientes MCP

Depois que seu servidor estiver rodando, você precisa configurar seu cliente MCP para se conectar a ele.

Cursor

Edite seu arquivo ~/.cursor/mcp.json e adicione:

{
  "mcpServers": {
    "doc": {
        "type": "streamable-http",
        "url": "http://127.0.0.1:3000/mcp",
        "note": "S3 Documentation RAG Server"
    }
  }
}

Claude Desktop

Edite seu arquivo de configuração do Claude Desktop:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "doc": {
        "type": "streamable-http",
        "url": "http://127.0.0.1:3000/mcp",
        "note": "S3 Documentation RAG Server"
    }
  }
}

Reinicie seu cliente MCP e você deverá ver:

  • 3 Ferramentas MCP: search_documentation, refresh_index, get_full_document
  • Recursos MCP: Lista completa de arquivos de documentação indexados com acesso direto

💡 Dica: Se estiver usando Docker, certifique-se de que o mapeamento de portas corresponde à sua configuração (padrão é 3000:3000)

Recursos

  • 🔌 S3 Universal: AWS S3, MinIO, Scaleway, DigitalOcean Spaces, Cloudflare R2, Wasabi...
  • 🧠 Embeddings Flexíveis:
    • Ollama (nomic-embed-text) - Local, gratuito, funciona offline
    • OpenAI (text-embedding-3-small, text-embedding-3-large) - Baseado em nuvem, alta precisão, multilíngue
  • 🔄 Sincronização Inteligente: Atualizações incrementais via comparação de ETag + sincronização completa automática quando o armazenamento vetorial está vazio
  • ⚡ Busca Rápida: Índice vetorial HNSWLib com similaridade de cosseno
  • 🔐 Autenticação Opcional: Autenticação por chave de API para implantações seguras
  • 🛠️ 3 Ferramentas MCP: search_documentation, refresh_index e get_full_document
  • 📚 Recursos MCP: Suporte nativo para descobrir e ler arquivos indexados via API padrão de Recursos MCP

Como Funciona

O servidor segue um pipeline simples:

  1. S3Loader: Escaneia seu bucket S3 em busca de arquivos .md, baixa seu conteúdo e rastreia ETags para detecção de alterações
  2. SyncService: Detecta arquivos novos, modificados ou excluídos e realiza sincronização incremental (sem reprocessamento desnecessário)
  3. VectorStore:
    • Divide documentos em chunks (1000 caracteres por padrão)
    • Gera embeddings usando seu provedor escolhido:
      • Ollama: nomic-embed-text (local, gratuito)
      • OpenAI: text-embedding-3-small ou text-embedding-3-large (nuvem, alta precisão)
    • Indexa vetores usando HNSWLib para busca rápida por similaridade
  4. Servidor MCP: Expõe tanto Ferramentas quanto Recursos via HTTP:
    • Ferramentas: search_documentation, refresh_index, get_full_document para busca semântica e ações
    • Recursos: resources/list, resources/read para descoberta de arquivos e acesso direto

O que é HNSWLib?

HNSWLib (Hierarchical Navigable Small World) é uma biblioteca leve de busca vetorial em memória, perfeita para este caso de uso:

  • ⚡ Rápido: Busca aproximada do vizinho mais próximo em milissegundos
  • 💾 Simples: Armazena índices como arquivos locais (sem necessidade de banco de dados)
  • 🪶 Eficiente: Baixo uso de memória, ideal para documentação pessoal/de pequenas equipes
  • 🎯 Preciso: Alta recuperação com similaridade de cosseno para busca semântica

É o ponto ideal entre simplicidade e desempenho para aplicações RAG.

Configuração

Copie env.example para .env e configure suas variáveis de ambiente:

cp env.example .env

Variáveis Essenciais

# S3 Configuration
S3_BUCKET_NAME=your-bucket-name           # Your S3 bucket name
S3_ACCESS_KEY_ID=your-access-key          # S3 access key
S3_SECRET_ACCESS_KEY=your-secret-key      # S3 secret key
S3_REGION=us-east-1                       # S3 region
S3_ENDPOINT=                              # Optional: for non-AWS S3 (MinIO, Scaleway, etc.)

# Embeddings Provider (choose one)
EMBEDDING_PROVIDER=ollama                 # ollama (default) or openai

# Option 1: Ollama (Local)
OLLAMA_BASE_URL=http://localhost:11434    # Ollama API endpoint
OLLAMA_EMBEDDING_MODEL=nomic-embed-text   # Ollama embedding model

# Option 2: OpenAI (Cloud) - Only if EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=                           # Your OpenAI API key
OPENAI_EMBEDDING_MODEL=text-embedding-3-small  # or text-embedding-3-large

Consulte env.example para todas as opções disponíveis e documentação detalhada (parâmetros RAG, modo de sincronização, tamanho do chunk, etc.).

Provedores de Embeddings

O servidor suporta dois provedores de embeddings:

🏠 Ollama (Local) - Padrão

Vantagens:

  • ✅ Gratuito: Sem custos de API, uso ilimitado
  • ✅ Privado: Todos os dados permanecem na sua máquina
  • ✅ Offline: Funciona sem conexão com a internet
  • ✅ Rápido: Chamadas diretas à API local

Desvantagens:

  • ⚠️ Requer instalação do Ollama e download do modelo
  • ⚠️ Usa recursos locais de CPU/GPU

Configuração:

# Install Ollama from https://ollama.ai
ollama pull nomic-embed-text

# Configure
EMBEDDING_PROVIDER=ollama
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_EMBEDDING_MODEL=nomic-embed-text

☁️ OpenAI (Nuvem)

Vantagens:

  • ✅ Alta Precisão: Embeddings de última geração
  • ✅ Multilíngue: Excelente suporte para 20+ idiomas
  • ✅ Sem Recursos Locais: Executa inteiramente na nuvem
  • ✅ Menor Latência: Respostas rápidas da API

Desvantagens:

  • ⚠️ Requer chave de API e créditos
  • ⚠️ Dados enviados aos servidores da OpenAI
  • ⚠️ Custo por token (muito acessível: ~$0,00002/1K tokens para text-embedding-3-small)

Configuração:

# Get an API key from https://platform.openai.com/api-keys

# Configure
EMBEDDING_PROVIDER=openai
OPENAI_API_KEY=sk-...your-key...
OPENAI_EMBEDDING_MODEL=text-embedding-3-small  # or text-embedding-3-large

Comparação de Modelos:

ModeloDimensõesDesempenhoCustoMelhor Para
text-embedding-3-small1536AltoBaixoUso geral, sensível a custo
text-embedding-3-large3072Mais altoMédioPrecisão máxima, multilíngue

💡 Dica: Comece com text-embedding-3-small para a maioria dos casos de uso. Só mude para text-embedding-3-large se precisar da melhor precisão absoluta ou trabalhar extensivamente com conteúdo não-inglês.

Comportamento de Fallback:

Se você definir EMBEDDING_PROVIDER=openai mas não fornecer um OPENAI_API_KEY válido, o servidor fará fallback automaticamente para Ollama (se configurado). Isso garante que o servidor sempre possa iniciar, mesmo com configuração incompleta.

Modos de Sincronização

O servidor suporta três modos de sincronização via SYNC_MODE:

  • startup (padrão): Sincroniza na inicialização do servidor

    • ✅ Detecção automática: Se o armazenamento vetorial estiver vazio, executa automaticamente uma sincronização completa
    • ✅ Caso contrário, executa uma sincronização incremental (apenas arquivos alterados)
    • ✅ Sem necessidade de refresh_index manual após reiniciar!
  • periodic: Sincroniza em intervalos regulares (SYNC_INTERVAL_MINUTES)

    • Executa sincronizações incrementais automaticamente
  • manual: Sem sincronização automática

    • Você deve chamar a ferramenta refresh_index manualmente

💡 Nota: O servidor detecta automaticamente quando o armazenamento vetorial está vazio (por exemplo, após excluir a pasta ./data/ ou na primeira execução) e aciona uma sincronização completa. Você não precisa mais executar refresh_index manualmente após cada reinicialização!

🔐 Segurança e Autenticação

Autenticação por Chave de API (Opcional)

Por padrão, o servidor roda em modo de acesso aberto para facilitar o desenvolvimento local. Para implantações compartilhadas ou remotas, você pode habilitar a autenticação por chave de API:

# Enable authentication
ENABLE_AUTH=true

# Set your API key
MCP_API_KEY=your-secret-key-here

Quando a autenticação está habilitada:

  • ✅ Todos os endpoints (exceto /health) exigem uma chave de API válida
  • ✅ A chave de API pode ser fornecida via:
    • Cabeçalho Authorization (recomendado): Authorization: Bearer your-secret-key
    • Parâmetro de consulta: ?api_key=your-secret-key
  • ✅ Chaves inválidas ou ausentes retornam HTTP 401 Não Autorizado

Exemplos de Uso:

# With Authorization header (recommended)
curl -H "Authorization: Bearer your-secret-key" http://localhost:3000/mcp

# With query parameter
curl "http://localhost:3000/mcp?api_key=your-secret-key"

Configuração do Cliente MCP com Chave de API:

{
  "mcpServers": {
    "doc": {
      "type": "streamable-http",
      "url": "http://127.0.0.1:3000/mcp",
      "headers": {
        "Authorization": "Bearer your-secret-key"
      },
      "note": "S3 Documentation RAG Server with authentication"
    }
  }
}

💡 Boas Práticas:

  • Mantenha a autenticação desabilitada para desenvolvimento local
  • Habilite para redes compartilhadas ou implantações remotas
  • Use chaves fortes e geradas aleatoriamente (por exemplo, openssl rand -hex 32)
  • O endpoint /health está sempre acessível sem autenticação para monitoramento

Ferramentas MCP

search_documentation

{
  "query": "How to configure S3?",
  "max_results": 4
}

Retorna chunks de documentos relevantes com pontuações de similaridade e fontes.

refresh_index

{
  "force": false  // default: incremental sync (recommended)
}

Sincroniza o índice de documentação com o S3, detectando arquivos novos, modificados ou excluídos.

Parâmetros:

  • force (booleano, opcional, padrão: false)
    • false: Sincronização incremental - Processa apenas alterações (rápida, eficiente) ✅
    • true: Reindexação completa - Reprocessa TODOS os arquivos (lenta, cara) ⚠️

⚠️ Importante: O parâmetro force deve ser definido como true SOMENTE quando explicitamente necessário (por exemplo, "forçar reindexação", "reconstruir tudo do zero"). A reindexação completa é cara:

  • Baixa novamente todos os arquivos do S3
  • Regenera todos os embeddings
  • Reconstrói todo o armazenamento vetorial

Para operações normais, use sempre a sincronização incremental (comportamento padrão).

get_full_document

{
  "s3_key": "docs/authentification_magique_symfony.md"
}

Recupera o conteúdo completo de um arquivo Markdown do S3 junto com metadados:

  • Chave S3 completa: O identificador S3 do documento
  • Conteúdo Markdown completo: Documento inteiro (não dividido em chunks)
  • Metadados: Tamanho em bytes, data da última modificação, ETag, contagem de chunks (se indexado)

Casos de Uso:

  • Visualizar o documento completo após encontrá-lo via search_documentation
  • Exportar documentação para uso externo
  • Entender o contexto completo em torno de um resultado de busca
  • Exibir documentos completos em integrações de terceiros

Notas Importantes:

  • Se um documento aparecer nos resultados de busca, mas get_full_document retornar "não encontrado", significa que o arquivo foi excluído do S3 após ser indexado
  • Solução: Execute refresh_index para sincronizar o índice com o estado atual do S3
  • A ferramenta fornecerá uma mensagem de erro útil indicando quando uma sincronização é necessária

Recursos MCP

Além das 3 ferramentas, o servidor implementa Recursos MCP para descoberta de arquivos e acesso direto:

  • resources/list: Lista todos os arquivos Markdown indexados com metadados (nome, URI, tamanho, chunks, última modificação)
  • resources/read: Lê o conteúdo completo de um arquivo específico pela sua URI (por exemplo, s3doc://docs/authentication.md)

Caso de uso: Quando os usuários perguntam "Quais arquivos você tem?" ou "Mostre-me o arquivo X", o LLM pode navegar e acessar arquivos diretamente sem busca semântica.

🤝 Contribuindo

Contribuições são bem-vindas! Leia nosso Guia de Contribuição para detalhes sobre como enviar pull requests, relatar problemas e contribuir com o projeto.

📝 Licença

MIT

👤 Autor

Yoan Bernabeu