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
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues