Skip to main content
Glama
isabelasdantas

wiki-mcp-server

README.md
# wiki-mcp-server

Servidor **MCP (Model Context Protocol)** serverless na AWS que conecta o **Claude** a uma wiki interna escrita em Markdown.
Os colaboradores entram com o SSO da empresa e fazem perguntas no Claude (web, desktop, mobile ou Slack). O Claude busca e lê as páginas da wiki para responder, citando a fonte.

> **Sem RAG e sem banco vetorial.** A wiki cabe inteira em memória, a busca é lexical e quem interpreta o conteúdo é o próprio modelo. Isso deixa o sistema mais simples, mais barato e mais fácil de auditar.

## Arquitetura

```mermaid
flowchart LR
    subgraph CICD["CI/CD"]
        A[Autores<br/>git push + PR] --> R[(Repositório<br/>da wiki)]
        R -->|merge na main| P[Pipeline<br/>tar.gz → S3]
    end

    subgraph AWS["Conta AWS"]
        P --> S3[(S3 privado<br/>versionado)]
        WAF[WAF + ALB<br/>allowlist de IPs<br/>HTTPS] --> L[Lambda<br/>servidor MCP]
        L -->|carrega e indexa<br/>em memória| S3
        L --> CW[CloudWatch<br/>logs e buscas sem resultado]
    end

    subgraph Anthropic
        C[Claude<br/>conector personalizado]
    end

    U[Colaboradores] --> C
    C -->|MCP via HTTPS<br/>+ Bearer token| WAF
    U -.->|login OAuth<br/>uma vez| IdP[Provedor de identidade<br/>Entra ID / Okta / Cognito]
    C -.-> IdP
```

### Fluxo de uma pergunta
1. O colaborador pergunta algo no Claude.
2. O Claude chama o servidor MCP por HTTPS, enviando o token OAuth do usuário.
3. O **WAF** só deixa passar os IPs de saída da Anthropic. O **ALB** termina o TLS.
4. A **Lambda** valida o JWT (assinatura, emissor, audience, expiração e, opcionalmente, o grupo do usuário) e executa a ferramenta pedida.
5. Cada busca vai para o **CloudWatch** com a quantidade de resultados. As buscas sem resultado mostram onde falta documentação.

### Ferramentas expostas ao Claude

| Ferramenta    | O que faz                                                    |
|---------------|--------------------------------------------------------------|
| `list_pages`  | Lista caminho e título das páginas (filtro por pasta opcional) |
| `search_wiki` | Busca por palavras-chave, sem diferenciar acentos, e retorna os trechos mais relevantes |
| `read_page`   | Retorna o Markdown completo de uma página                    |

## Decisões de design

| Decisão | Por quê |
|---|---|
| **Busca lexical em vez de RAG** | Para algumas centenas de páginas, embeddings acrescentam custo, latência e mais uma peça para manter. O modelo já reformula a busca e lê as páginas certas. |
| **Lambda stateless** | O MCP via *Streamable HTTP* aceita servidores sem sessão: cada POST é independente. Sai barato em uso esporádico e não tem servidor para administrar. |
| **Wiki empacotada em `tar.gz`** | Um único objeto no S3 = um download por cold start. O ETag diz quando recarregar e o cache fica em memória entre invocações. |
| **WAF + JWT** | Duas camadas: na rede, só o Claude alcança o endpoint; na aplicação, só usuários autenticados no IdP e do grupo certo. |
| **Metadados OAuth (RFC 9728)** | O endpoint `/.well-known/oauth-protected-resource` permite que o Claude descubra sozinho qual IdP emite os tokens. |

## Estrutura

```
src/wiki_mcp/
  handler.py   # entrada HTTP (evento do ALB), rotas e resposta 401 com o desafio OAuth
  mcp.py       # JSON-RPC do MCP: initialize, tools/list, tools/call
  wiki.py      # carga, índice em memória, busca e leitura
  auth.py      # validação do JWT via JWKS do IdP
  storage.py   # download do tar.gz do S3 com cache por ETag
  local.py     # servidor local para desenvolvimento
infra/template.yaml       # AWS SAM: S3, Lambda, ALB, WAF, logs
pipeline/buildspec.yml    # CodeBuild: empacota a wiki e publica no S3
wiki/                     # conteúdo de exemplo (empresa fictícia)
tests/                    # pytest
```

## Rodando localmente

```bash
python -m venv .venv
source .venv/bin/activate        # Windows: .venv\Scripts\activate
pip install -r requirements-dev.txt
pytest -q

cd src && python -m wiki_mcp.local --wiki ../wiki --port 8000
```

Teste com o [MCP Inspector](https://github.com/modelcontextprotocol/inspector): rode `npx @modelcontextprotocol/inspector`, escolha *Streamable HTTP* e use a URL `http://localhost:8000/mcp`.

## Deploy na AWS

```bash
sam build -t infra/template.yaml
sam deploy --guided
```

Depois do deploy:
1. Aponte o domínio para o `LoadBalancerDns` (saída do stack).
2. Configure a pipeline (CodePipeline + CodeBuild com `pipeline/buildspec.yml`, ou GitHub Actions) para publicar `wiki.tar.gz` no bucket a cada merge.
3. Registre um aplicativo OAuth no IdP e, no Claude, adicione um **conector personalizado** com a URL `McpEndpoint`.

## Sobre o projeto

Projeto pessoal para explorar como dar a um assistente de IA acesso seguro à base de conhecimento de uma empresa, cobrindo arquitetura serverless na AWS, protocolo MCP, autenticação OAuth/OIDC e infraestrutura como código. O conteúdo da wiki é fictício.

**Desenvolvido com IA:** a arquitetura, o código e os testes foram feitos em pair programming com o Claude (Claude Code), da discussão do desenho à implementação.

## Licença

MIT