
Executando o assistente WUIC em um LLM local: Ollama, um servidor MCP e um VS Code agentivo gratuito
Nosso chatbot RAG in-product tem duas partes. A primeira é recuperação — híbrido BM25 + bge-m3 + um reranker ajustado, rodando localmente como .NET/ONNX nativo, sem superfície de API para ninguém. A segunda é geração — transformando os pedaços recuperados em uma resposta, ou em uma mudança de metadados proposta. Essa segunda parte se comunicava com uma API na nuvem com cobrança por token.
Este post é sobre substituir essa segunda parte por um modelo local, e sobre um efeito colateral que acabou sendo mais útil do que o objetivo original: o mesmo conhecimento WUIC, exposto ao VS Code, lhe dá um assistente de codificação livre e autônomo que realmente conhece o framework — sem chave de API, sem custo por token. Esse efeito colateral mais tarde se tornou um produto próprio — veja a atualização no final.
É também um post honesto. Um LLM local não é "grátis" no sentido que as pessoas geralmente entendem. Você troca dinheiro e ganhos de privacidade por perdas de qualidade e latência. A última seção é a conta.
O que realmente mudou
A parte de recuperação não mudou — já era local. Apenas o cérebro mudou.
ANTES recuperação (local ONNX) → API Claude ($ por token, round-trip na nuvem)
DEPOIS recuperação (local ONNX) → Ollama / qwen2.5 ($0, em uma caixa GPU na LAN)
Os dois não são da mesma classe de modelo, e fingir o contrário seria desonesto — mais sobre isso abaixo. Mas a fiação é limpa, porque o motor já falava um dialeto compatível com OpenAI. Apontá-lo para um servidor local é configuração, não cirurgia:
rag-llm-provider = ollama # formato de fio compatível com OpenAI
rag-llm-base-url = http://<gpu-host>:11434/v1 # endpoint OpenAI do Ollama
rag-llm-api-key = ollama # dummy, não vazio
rag-llm-default-chat-model = qwen2.5-coder:32b
A topologia
Três caixas. Sua máquina executa o backend WUIC e a recuperação local. Uma segunda máquina com GPU executa o Ollama (pode ser a mesma máquina se tiver VRAM). O VS Code se comunica com ambas através de uma pequena ponte.
Sua máquina Caixa GPU (mesma LAN)
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ Backend WUIC :5000 │ │ Ollama :11434 │
│ ├─ Recuperação RAG (ONNX) │ │ qwen2.5-coder:32b │
│ │ BM25 + bge-m3 + rerank │ ───► │ geração + chamada de ferramenta │
│ └─ /api/Rag/Query /Rag/Chat│ └──────────────────────────────┘
└──────────────────────────────┘
▲
│ stdio MCP (servidor "wuic-rag")
│
┌──────────────────────────────┐
│ VS Code │
│ Assistente WUIC ───────► │ chat autônomo: editar arquivos, executar comandos
│ (cérebro = mesmo Ollama) │ conhecimento = WUIC RAG via o servidor MCP
└──────────────────────────────┘
A seta do backend para o Ollama é o novo passo de geração do chatbot RAG. A seta do VS Code de volta para o backend é a nova parte: um servidor MCP que permite que qualquer editor autônomo consulte a mesma recuperação WUIC.
A ponte: um pequeno servidor MCP
MCP (Modelo Contexto Protocolo) é o padrão aberto para fornecer a um cliente LLM ferramentas. Cline, Continue, Cursor e Claude Code todos falam isso. Então, em vez de construir uma extensão personalizada para o VS Code na época, lançamos um pequeno servidor MCP stdio que envolve a API REST que o backend já expõe:
Você (no editor): "onde o login do cookie é tratado?"
│
▼
O agente (modelo local) decide chamar uma ferramenta
│ tools/call wuic_codebase_search
▼
wuic-rag-mcp.mjs ──POST /api/Rag/Query──► motor RAG ──► top-8 pedaços (arquivo:linha + trecho)
│
▼
O agente lê os pedaços, responde com citações reais — ou começa a editar
Ele foi lançado com duas ferramentas: wuic_codebase_search (recuperação — caminhos de arquivos e trechos) e wuic_ask (uma resposta RAG completa gerada pelo modelo local). É sem dependências — o http embutido do Node, sem npm install, roda em qualquer Node ≥ 14.18 — e sem estado: cada chamada apenas faz proxy para o backend. Isso importa para distribuição: ele é enviado dentro de cada aplicativo WUIC e é conectado automaticamente na primeira execução, então um desenvolvedor final recebe um .mcp.json já apontando para ele.
O ponto de design crucial dessa primeira iteração: o servidor MCP não é o agente. Ele adiciona conhecimento, não autonomia. A edição, a execução de comandos, o loop de planejar/agir pertenciam ao editor host; reutilizar um suporte de código aberto maduro foi o objetivo principal. (Essa é a parte que mudou — veja a atualização.)
O único problema difícil: chamada de ferramenta
A recuperação apenas funcionou no primeiro dia. A falha interessante foi o caminho de ação — a capacidade do chatbot de emitir uma chamada de ferramenta estruturada (por exemplo, "adicionar uma regra de estilo de linha com esta condição JS") em vez de prosa.
Modelos na nuvem retornam chamadas de ferramentas em um campo estruturado. Nossa pilha de serviço local, por baixo, muitas vezes não o fazia: ela colocava a chamada da ferramenta no conteúdo da mensagem como texto bruto, em formatos inconsistentes — às vezes JSON válido sem o envelope, às vezes um literal de objeto JavaScript com aspas simples e key=value em vez de key: value. O modelo sabia o que fazer; a fiação deixou isso cair no chão.
A solução foi um parser tolerante do nosso lado: detectar um nome de ferramenta conhecido no conteúdo, capturar o bloco {...} seguinte e normalizar esse literal parecido com JS em JSON — ciente de aspas, para que corpos de callback incorporados com suas próprias chaves e aspas sobrevivam. Uma mudança contida levou o roteamento de inutilizável a bom. A lição é geral: com modelos locais, reserve orçamento para as peculiaridades do serviço, não apenas para o modelo. Os pesos são capazes; o adaptador ao redor deles é onde o trabalho está.
Resultados medidos — sem arredondar
Fizemos benchmark contra nosso verdadeiro conjunto de roteamento de ferramentas (89 variantes de prompt, 3 repetições cada, em uma GPU de 24 GB):
| Modelo | Taxa de passagem de roteamento | Latência / chamada | Notas |
|---|---|---|---|
| qwen2.5-coder:32b | ~91% | ~8 s | melhor fidelidade de esquema + geração de código/JS |
| gpt-oss:20b | menor | ~2.6 s | muito mais rápido, mais fraco em esquemas de ferramentas complexos |
As falhas residuais, quando investigamos, eram na maioria não o modelo: algumas eram comportamentos genuinamente corretos do único-tur
A transição para modelos locais pode reduzir custos e aumentar a privacidade para empresas brasileiras. A implementação de um servidor MCP facilita a integração de assistentes de IA em ambientes de desenvolvimento, promovendo eficiência. Isso pode impactar positivamente a forma como as empresas desenvolvem e gerenciam suas aplicações.

