{"id":50386428,"url":"https://github.com/opastorello/correios-rastreamento","last_synced_at":"2026-05-30T15:01:01.059Z","repository":{"id":344330014,"uuid":"1181413035","full_name":"opastorello/correios-rastreamento","owner":"opastorello","description":"MCP server para rastreamento de objetos dos Correios com solver de CAPTCHA próprio (CRNN 99.6%)","archived":false,"fork":false,"pushed_at":"2026-04-23T17:03:54.000Z","size":8687,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-04-23T19:05:23.244Z","etag":null,"topics":["captcha","correios","fastapi","fastmcp","mcp","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/opastorello.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-14T05:23:50.000Z","updated_at":"2026-04-23T17:03:58.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/opastorello/correios-rastreamento","commit_stats":null,"previous_names":["opastorello/correios-rastreamento-mcp","opastorello/correios-rastreamento"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/opastorello/correios-rastreamento","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcorreios-rastreamento","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcorreios-rastreamento/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcorreios-rastreamento/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcorreios-rastreamento/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/opastorello","download_url":"https://codeload.github.com/opastorello/correios-rastreamento/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/opastorello%2Fcorreios-rastreamento/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33696683,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["captcha","correios","fastapi","fastmcp","mcp","python"],"created_at":"2026-05-30T15:01:00.153Z","updated_at":"2026-05-30T15:01:01.048Z","avatar_url":"https://github.com/opastorello.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 📦 Correios Rastreamento\n\n\u003e Rastreie encomendas dos Correios com histórico completo de eventos, resolução automática de CAPTCHA via rede neural treinada localmente.\n\nExpõe as mesmas operações como **MCP tools** (para agentes AI) e **REST API** (para integrações diretas), com interface web incluída.\n\n---\n\n## 💡 O que este projeto faz\n\n| | |\n|--|--|\n| 📦 | Rastreia qualquer objeto pelos Correios pelo código (ex: AA000000000BR) |\n| 🚀 | Consulta até 20 objetos em paralelo com um único CAPTCHA |\n| 🤖 | Integra com qualquer agente AI via protocolo MCP |\n| 📋 | Mantém histórico de rastreamentos no servidor |\n\nO rastreamento é feito via scraping do site oficial dos Correios. A resolução de CAPTCHA é feita por uma **CRNN (Convolutional Recurrent Neural Network)** treinada especificamente para isso, atingindo **99.62% de acurácia** sem depender de nenhum serviço externo.\n\n---\n\n## 🤖 MCP Tools\n\n| Tool | Descrição |\n| ---- | --------- |\n| `rastrear_objeto` | Rastreia um objeto pelo código (ex: AA000000000BR) |\n| `rastrear_multiplos` | Rastreia até 20 objetos de uma vez com um único CAPTCHA |\n\n---\n\n## 🌐 REST API\n\n| Método | Rota | Rate limit | Descrição |\n| ------ | ---- | ---------- | --------- |\n| `GET`  | `/` | — | Interface web |\n| `POST` | `/rastreamento/objeto` | 20/min por IP | Rastreia um objeto |\n| `POST` | `/rastreamento/multiplos` | 10/min por IP | Rastreia até 20 objetos em paralelo |\n| `GET`  | `/history/` | — | Lista o histórico de rastreamentos |\n| `POST` | `/history/save` | — | Salva ou atualiza uma entrada no histórico |\n| `DELETE` | `/history/` | — | Limpa todo o histórico |\n| `DELETE` | `/history/{codigo}` | — | Remove a entrada de um código específico |\n| `GET`  | `/health` | — | Health check — retorna `{\"status\": \"ok\"}` |\n\nDocumentação interativa: `http://localhost:8000/docs` (disponível apenas em `ENV=development`).\n\n### 📂 Histórico de rastreamentos\n\nO histórico é **global e compartilhado** — todas as consultas feitas pela interface web, pela REST API ou via MCP gravam no mesmo arquivo de histórico do servidor.\n\n- **Interface web:** rastreamentos bem-sucedidos são salvos automaticamente no histórico.\n- **REST API / MCP:** toda consulta bem-sucedida pode ser registrada chamando `POST /history/save` com os dados do objeto.\n\n---\n\n## 🏗️ Arquitetura\n\nFastAPI com FastMCP 3.0 montado em `/mcp` (streamable-http). A camada `services/` não tem dependência de framework — a mesma lógica é consumida pelos routers REST e pelo MCP server.\n\n```\napp/\n├── main.py             # FastAPI — routers + mcp.http_app() em /mcp + rate limiter\n├── config.py           # Lê todas as variáveis de ambiente com defaults\n├── mcp_server.py       # FastMCP(\"correios-rastreamento\") — 2 tools\n├── auth.py             # TokenMiddleware — autenticação via API_TOKEN + controle prod/dev\n├── services/\n│   └── correios.py     # Scraping: curl_cffi + CAPTCHA solver + JSON parsing\n├── routers/\n│   ├── rastreamento.py # POST /rastreamento/objeto, /rastreamento/multiplos\n│   ├── history.py      # GET/POST/DELETE /history/ — histórico de rastreamentos\n│   └── ui.py           # GET / — interface web\n└── captcha/\n    ├── model.py        # Arquitetura CRNN (CNN + BiLSTM + CTC Loss)\n    ├── predictor.py    # Inferência: carrega captcha_model.pt e prediz\n    ├── dataset.py      # CaptchaDataset com data augmentation\n    ├── train.py        # Loop de treino com early stopping + AMP + registry\n    ├── collector.py    # Coleta amostras rotuladas direto dos Correios\n    ├── evaluate.py     # Avalia acurácia contra amostras salvas\n    └── registry.py     # Versionamento de modelos\n```\n\n**Regras de camada:**\n- `services/` — zero imports de FastAPI ou FastMCP\n- `routers/` e `mcp_server.py` — importam apenas de `services/`\n- I/O bloqueante em `services/correios.py` é sempre executado via `run_in_threadpool`\n\n---\n\n## ⚙️ Configuração\n\nTodas as opções são lidas de variáveis de ambiente ou do arquivo `.env` na raiz do projeto.\n\n### Referência completa de variáveis\n\n| Variável | Padrão | Descrição |\n| -------- | ------ | --------- |\n| `API_TOKEN` | *(vazio — sem auth)* | Token Bearer. Se vazio, todos os endpoints ficam abertos |\n| `ENV` | `development` | `development` ou `production` — controla quais rotas ficam abertas sem token |\n| `RATE_LIMIT_OBJETO` | `20/minute` | Rate limit de `/rastreamento/objeto` por IP |\n| `RATE_LIMIT_MULTIPLOS` | `10/minute` | Rate limit de `/rastreamento/multiplos` por IP |\n| `HISTORY_RETENTION_DAYS` | `90` | Dias de retenção do histórico. `0` = sem limite |\n| `APP_TIMEZONE` | `America/Sao_Paulo` | Timezone para timestamps do histórico |\n\n### 🔒 Rotas abertas por ambiente\n\n| Rota | `development` | `production` |\n| ---- | :-----------: | :----------: |\n| `/` | ✅ aberta | ✅ aberta |\n| `/health` | ✅ aberta | ✅ aberta |\n| `/docs` | ✅ aberta | 🔒 token |\n| `/redoc` | ✅ aberta | 🔒 token |\n| `/openapi.json` | ✅ aberta | 🔒 token |\n| `/mcp` | 🔒 token | 🔒 token |\n| demais | 🔒 token | 🔒 token |\n\n\u003e Se `API_TOKEN` estiver vazio, o middleware ignora autenticação em qualquer ambiente.\n\n---\n\n## 🔐 Autenticação\n\nCom `API_TOKEN` configurado, todas as requisições protegidas precisam enviar:\n\n```\nAuthorization: Bearer meu-token-secreto\n```\n\n**REST:**\n\n```bash\ncurl -X POST http://localhost:8000/rastreamento/objeto \\\n  -H \"Authorization: Bearer meu-token-secreto\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"codigo\": \"AA000000000BR\"}'\n```\n\n**Claude Desktop / Claude Code (`claude_desktop_config.json`):**\n\n```json\n{\n  \"mcpServers\": {\n    \"correios-rastreamento\": {\n      \"command\": \"npx\",\n      \"args\": [\"mcp-remote\", \"http://localhost:8000/mcp\", \"--allow-http\"],\n      \"env\": {\n        \"MCP_REMOTE_HEADER_AUTHORIZATION\": \"Bearer meu-token-secreto\"\n      }\n    }\n  }\n}\n```\n\nA interface web (`/`) exibe um **gate de autenticação** quando `API_TOKEN` está definido — o token é validado contra o servidor e salvo no navegador.\n\n---\n\n## 🚀 Instalação\n\n### Docker (recomendado)\n\n```bash\ngit clone https://github.com/opastorello/correios-rastreamento.git\ncd correios-rastreamento\ncp .env.example .env   # edite se quiser definir API_TOKEN\ndocker compose up --build -d\n```\n\n### Local\n\n```bash\npip install -r requirements.txt\ncp .env.example .env\nuvicorn app.main:app --host 0.0.0.0 --port 8000 --reload\n```\n\nApós iniciar:\n- Interface web: `http://localhost:8000/`\n- REST docs: `http://localhost:8000/docs` *(apenas em `ENV=development`)*\n- MCP endpoint: `http://localhost:8000/mcp`\n\n---\n\n## 📋 Exemplos de uso\n\n### Rastrear um objeto\n\n```bash\ncurl -X POST http://localhost:8000/rastreamento/objeto \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"codigo\": \"AA000000000BR\"}'\n```\n\n```json\n{\n  \"codObjeto\": \"AA000000000BR\",\n  \"tipoPostal\": { \"descricao\": \"SEDEX\" },\n  \"situacao\": \"E\",\n  \"dtPrevista\": \"01/01/2026\",\n  \"eventos\": [\n    {\n      \"descricaoWeb\": \"ENTREGUE\",\n      \"dtHrCriado\": { \"date\": \"2026-01-01 10:00:00.000000\" },\n      \"unidade\": { \"endereco\": { \"cidade\": \"SAO PAULO\", \"uf\": \"SP\" } }\n    }\n  ]\n}\n```\n\n### Rastrear múltiplos objetos\n\n```bash\ncurl -X POST http://localhost:8000/rastreamento/multiplos \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"codigos\": [\"AA000000000BR\", \"AA000000001BR\"]}'\n```\n\n---\n\n## 🧠 Modelo de CAPTCHA\n\n### Arquitetura CRNN\n\n```\nInput (1×80×215 grayscale)\n    → Conv2D ×4 + BatchNorm + ReLU + MaxPool   (extração de features visuais)\n    → BiLSTM ×2 (128 hidden, bidirectional)    (modelagem de sequência)\n    → Linear → CTC Loss                         (decode sem segmentação)\nOutput: string [0-9a-z] (CHARSET: 36 chars)\n```\n\n### Histórico de treino\n\n| Rodada | Amostras | Rotulador | val_acc |\n| ------ | -------- | --------- | :-----: |\n| 1 | 55.033 | ddddocr (bootstrap) | 99.57% |\n| 2 | 55.000 | Modelo R1 (83.6% acerto) | **99.61%** |\n| 3 (fine-tuning) | 20.000 | Modelo R2 (~99%) | 99.63% |\n| 4 (fine-tuning) | 100.000 | Modelo R3 (~99%) | **99.62%** |\n\nResultado v6 sobre 100k amostras: **99.97% por sequência** | **99.99% por caractere**\n\nErros residuais são confusões visuais: `n↔h`, `e↔c`, `r↔p`, `v↔y`.\n\n### Fluxo de scraping\n\n**Objeto único:**\n1. GET `index.php` — session cookie\n2. GET `securimage_show.php` — imagem CAPTCHA\n3. Resolve com CRNN local (99.62% acurácia)\n4. GET `resultado.php?objeto={code}\u0026captcha={text}\u0026mqs=S` — JSON com eventos\n5. Retry até 4× em caso de CAPTCHA inválido\n\n**Múltiplos objetos (até 20):**\n- Mesmos passos 1–3, mas usa `rastroMulti.php?objeto={cod1cod2...}\u0026captcha={text}`\n- **1 CAPTCHA para até 20 objetos** (códigos concatenados)\n\n---\n\n## Treinar o modelo\n\n**1. Coletar amostras**\n\n```bash\npython -m app.captcha.collector --probe AA000000000BR --target 20000 --workers 8\n```\n\n**2. Treinar do zero**\n\n```bash\npython -m app.captcha.train --epochs 80 --batch 128 --lr 1e-3\n```\n\n**3. Fine-tuning a partir de checkpoint**\n\n```bash\npython -m app.captcha.train --epochs 60 --batch 128 --lr 1e-4 --checkpoint app/captcha/captcha_model.pt\n```\n\nO melhor modelo (menor `val_loss`) é salvo em `app/captcha/captcha_model.pt`. Para consultar o histórico de versões:\n\n```bash\npython -m app.captcha.registry\n```\n\n---\n\n## 🗺️ Roadmap\n\nIdeias e melhorias planejadas para versões futuras.\n\n### Escalabilidade\n- **Cache de resultados** — objetos já consultados recentemente retornam resultado armazenado sem nova requisição aos Correios. Reduz latência e carga no servidor.\n- **Worker distribuído** — arquitetura de fila para distribuir consultas em múltiplos IPs e reduzir risco de throttling.\n\n### Multi-usuário\n- **Histórico isolado por token** — cada integração (web, API, MCP) mantém seu próprio registro separado em vez do histórico global compartilhado atual.\n- **Quota de consultas por token** — limite diário/mensal de rastreamentos configurável independentemente do rate limit por IP.\n\n### Cobertura\n- **Notificação de atualização** — webhook ou push notification quando um objeto muda de status desde a última consulta.\n\n---\n\n## ⚖️ Responsabilidade de Uso\n\nEste projeto consulta exclusivamente o sistema público dos **Correios** — os mesmos dados acessíveis por qualquer pessoa pelo site oficial, sem login ou cadastro.\n\n**Usos adequados:**\n- Acompanhamento pessoal de encomendas\n- Integração com agentes AI para automação de processos legítimos\n- Monitoramento de entregas em sistemas próprios\n\n**O projeto não se destina a:**\n- Varredura em massa sem finalidade específica\n- Qualquer uso que sobrecarregue desnecessariamente a infraestrutura dos Correios\n- Qualquer uso que viole os termos de serviço ou a legislação brasileira vigente\n\nO código é aberto e auditável. A responsabilidade pelo uso é inteiramente do operador que implanta e utiliza o serviço. Rate limiting está configurado por padrão para desincentivar abuso.\n\n---\n\n## 📦 Dependências principais\n\n| Pacote | Uso |\n| ------ | --- |\n| [FastMCP](https://github.com/jlowin/fastmcp) | Framework MCP server |\n| [FastAPI](https://github.com/fastapi/fastapi) | REST API |\n| [slowapi](https://github.com/laurentS/slowapi) | Rate limiting por IP |\n| [curl-cffi](https://github.com/yifeikong/curl-cffi) | HTTP com impersonação TLS Chrome |\n| [PyTorch](https://github.com/pytorch/pytorch) | Rede neural CRNN para CAPTCHA |\n| [torchvision](https://github.com/pytorch/vision) | Transforms e augmentation de imagem |\n| [Pillow](https://github.com/python-pillow/Pillow) | Processamento de imagem |\n| [python-dotenv](https://github.com/theskumar/python-dotenv) | Carregamento de variáveis do `.env` |\n\n---\n\n## 📄 Licença\n\n[MIT](LICENSE) © 2026 Nícolas Pastorello\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopastorello%2Fcorreios-rastreamento","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopastorello%2Fcorreios-rastreamento","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopastorello%2Fcorreios-rastreamento/lists"}