MCP-WebSearch-SearXNG

Permite que seu modelo (ou agente autônomo) navegue na web, execute pesquisas em vários mecanismos ao mesmo tempo e exiba imagens diretamente no seu front-end.

Documentação

WebSearch SearXNG + Servidor MCP

Um mecanismo de metapesquisa SearXNG auto-hospedado emparelhado com o servidor MCP mcp-searxng, construído para LLMs, agentes e aplicações que usam ferramentas. Permite que seu modelo (ou agente autônomo) navegue na web, execute buscas em vários mecanismos ao mesmo tempo e exiba imagens diretamente no seu front end. Tudo roda inteiramente na sua própria máquina via Docker, acessado pelo seu navegador, e fala MCP sobre transporte HTTP Streamable, então se conecta a qualquer cliente compatível com MCP (Claude Desktop, Cline, Open WebUI, LM Studio, estruturas de agentes personalizadas, etc.). Aprimorado com busca de imagens/vídeos/categorias, paginação por deslocamento e redimensionamento inteligente de imagens base64 para modelos com capacidade de visão. Ambos os serviços permanecem na sua rede local, então nada sai da sua máquina a menos que você peça. Sem anúncios, sem telemetria, sem rastreadores de terceiros, sem contas — o frontend do SearXNG é privado por design e os patches MCP não adicionam nenhum phone-home próprio.

SearXNG web frontend at localhost:8888
Frontend do SearXNG — a interface de metapesquisa que respeita a privacidade em localhost:8888. O mesmo backend que o servidor MCP consulta internamente.
LLM autonomously calling searxng_web_search and web_url_read
Cadeia de ferramentas autônoma — o modelo dispara várias chamadas searxng_web_search em paralelo e depois encadeia em web_url_read para extrair o texto completo do artigo.
Article continuation extracted via web_url_read
Extração de texto limpa — conteúdo de artigos longos extraído por web_url_read, com elementos desnecessários removidos, pronto para o modelo resumir.



Synthesized AI news briefing with inline image
Imagem inline em briefing de notícias — imagem buscada e redimensionada pelo pipeline sharp do web_url_read. Sem CDN externo, servida como bloco de imagem MCP base64.
Multi-query meme search
Busca paralela com múltiplas consultas — consultas separadas por | distribuem várias chamadas searxng_web_search de uma vez, chegando ao meme "It's Gonna Be May".
Multiple inline meme images returned by web_url_read
Blocos de imagem nativos — múltiplas imagens retornadas inline. O parâmetro detail (low/medium/high) controla a qualidade do redimensionamento versus o custo de tokens.

Instalação

Nota rápida sobre privacidade antes de começar. Esta pilha roda inteiramente na sua máquina e respeita a privacidade por design (sem telemetria, sem contas, sem rastreadores de terceiros), mas os padrões são ajustados para "simplesmente funcionar", não para máxima privacidade. Antes de expor além do seu próprio computador, para sua LAN, internet ou qualquer outra pessoa, leia ADVANCED.md

Pré-requisitos

  • Docker e Docker Compose devem estar instalados (Node.js não é necessário no host: o servidor MCP roda dentro da sua imagem Docker)

Passo 1: Clonar o Repositório

git clone https://github.com/hypersniper05/MCP-WebSearch-SearXNG.git
cd MCP-WebSearch-SearXNG

Isso fornece o docker-compose.yml, o settings.yml do SearXNG, os patches MCP e o Dockerfile personalizado já organizados — então o próximo passo é direto para a configuração.

Prefere configurar tudo manualmente em vez de clonar? Veja Construindo do zero (sem clonar) em ADVANCED.md.

Passo 2: Configurar as Configurações do SearXNG

O searxng/config/settings.yml incluído já está pré-configurado para esta pilha — saída JSON habilitada, limitador de taxa desativado, um conjunto selecionado de mecanismos que respondem a instâncias auto-hospedadas e longos tempos de suspensão de mecanismos para que um mecanismo bloqueado não seja tentado novamente a cada consulta. Ele contém apenas substituições: o SearXNG mescla isso sobre as configurações padrão dentro da imagem (fixada). A única coisa que você precisa definir é a chave secreta.

Quer mudar quais mecanismos estão habilitados, o tempo limite de solicitação ou qualquer outro padrão do SearXNG? Veja Modificando as configurações padrão em ADVANCED.md.

Definir o secret_key (ou usar a variável de ambiente)

O SearXNG iniciará sem uma chave, então para uma instância pessoal somente localhost você pode voltar a isso mais tarde. Mas se você vincular a 0.0.0.0, expor isso à sua LAN ou compartilhar com qualquer pessoa, defina uma chave real — caso contrário, qualquer pessoa pode forjar o HMAC que o endpoint /image_proxy do SearXNG verifica e usar sua instância como um proxy de imagem aberto.

Defina em um arquivo .env ao lado de docker-compose.yml:

SEARXNG_SECRET=<paste your generated 64-char hex string here>

docker-compose.yml sempre passa SEARXNG_SECRET para o contêiner, e o SearXNG permite que essa variável substitua settings.yml mesmo quando vazia. Portanto, o espaço reservado secret_key: "CHANGE_ME_BEFORE_RUNNING" em settings.yml nunca é usado, e editá-lo não tem efeito — sem um valor .env, a instância roda com uma chave vazia. Use .env (está no gitignore, então a chave nunca chega ao repositório).

Gere uma chave com qualquer ferramenta que você tiver instalada:

# PowerShell (Windows PowerShell 5.1 and PowerShell 7 — built in)
$b = New-Object byte[] 32; [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($b); -join ($b | ForEach-Object { $_.ToString('x2') })
# Node.js (if you have it)
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

# Docker (works anywhere this stack does)
docker run --rm alpine sh -c "apk add --no-cache openssl > /dev/null && openssl rand -hex 32"

# Git Bash / Linux / macOS
openssl rand -hex 32

# Python
python -c "import secrets; print(secrets.token_hex(32))"

Para o restante das compensações de privacidade/endurecimento (exposição LAN, autenticação MCP, roteamento Tor), veja ADVANCED.md.

Passo 3: Construir e Iniciar Tudo

docker compose build
docker compose up -d

Passo 4: Verificar Serviços

Verificação de saúde:

curl -s http://localhost:3001/health

Esperado: {"status":"healthy","server":"ihor-sokoliuk/mcp-searxng","version":"2.4.0-enhanced","transport":"http"}

Busca de teste:

curl -s "http://localhost:8888/search?q=test&format=json" | head -c 200

Passo 5 (somente se acessar de outra máquina): Abrir os vínculos para sua LAN / Tailscale

Por padrão, o docker-compose.yml incluído vincula o SearXNG a 127.0.0.1 (somente esta máquina) e o servidor MCP a 0.0.0.0 (já acessível da sua LAN / tailnet Tailscale). Ambos vêm de .env: SEARXNG_BIND (padrão 127.0.0.1) e MCP_BIND (padrão 0.0.0.0).

Diagnóstico rápido para identificar isso:

docker compose ps

Observe a coluna PORTS. Se você vir:

O que você vêO que significa
0.0.0.0:8888->8080/tcpAcessível de qualquer lugar na rede ✓
127.0.0.1:8888->8080/tcpSomente localhost — o exato sintoma que faz o acesso externo "expirar"

Se uma linha mostrar 127.0.0.1: e você precisar que seja acessível fora do host, defina o vínculo em .env (ao lado de docker-compose.yml). Não edite docker-compose.yml em si: .env está no gitignore, então git pull nunca conflita com sua escolha.

SEARXNG_BIND=0.0.0.0   # default 127.0.0.1
MCP_BIND=0.0.0.0       # already the default; 127.0.0.1 keeps the MCP endpoint on this machine

Em seguida, recrie os contêineres (mudanças de porta não se aplicam em um simples restart):

docker compose down
docker compose up -d
docker compose ps

As linhas alteradas agora devem mostrar 0.0.0.0:....

Se docker compose ps já mostra 0.0.0.0 e o acesso externo ainda falha, é o firewall do sistema operacional. No Windows, permita as portas de um PowerShell administrativo:

New-NetFirewallRule -DisplayName "MCP SearXNG (8888)" -Direction Inbound -Protocol TCP -LocalPort 8888 -Action Allow
New-NetFirewallRule -DisplayName "MCP Server (3001)"   -Direction Inbound -Protocol TCP -LocalPort 3001 -Action Allow

Clientes MCP baseados em navegador (qualquer coisa que envie um cabeçalho Origin, como uma interface web ou o MCP Inspector) são recusados com HTTP 403, a menos que sua origem esteja listada. Adicione as origens exatas, com esquema e porta, a .env, por exemplo, MCP_ALLOWED_ORIGINS=http://localhost:3001,http://100.x.y.z:3001. A lista substitui o padrão localhost, então inclua-os também se precisar. Clientes que não enviam Origin (Claude Code, clientes SDK, LM Studio, curl) não são afetados.

Nota de segurança: 0.0.0.0 expõe um serviço a qualquer pessoa que possa alcançar sua máquina nessa porta, e o servidor MCP está vinculado a 0.0.0.0 por padrão (defina MCP_BIND=127.0.0.1 em .env para mantê-lo local). O servidor MCP não tem autenticação por padrão. O upstream pode exigir um token bearer estático em seu modo endurecido, ou tokens de acesso OAuth; se você for além de uma rede doméstica/Tailscale confiável, leia ADVANCED.md → Nível 2.

Resumo de Endpoints

ServiçoURLPropósito
Interface SearXNGhttp://localhost:8888Interface de busca web
API SearXNGhttp://localhost:8888/searchAPI de busca JSON
Servidor MCPhttp://localhost:3001/mcpMCP Streamable HTTP
Saúde MCPhttp://localhost:3001/healthEndpoint de verificação de saúde

Precisa de TLS para um cliente somente HTTPS? O caminho mais limpo é Tailscale Serve se ambas as extremidades estiverem em uma tailnet (certificado real confiável pela Let's Encrypt, zero configuração por cliente), ou um proxy reverso como Caddy / nginx com seu próprio certificado caso contrário. Qualquer um é adicionado na frente do endpoint MCP HTTP existente sem nenhuma alteração nesta pilha.

Ferramentas MCP

1. searxng_web_search

Busca web com suporte a categoria, paginação e filtragem. Retorna JSON estruturado: results (título, url, descrição, data de publicação, fonte engines, score), suggestions, corrections, answers, infoboxes, unresponsive_engines, engine_coverage (answered mecanismos e failed_count) e pagination.

Separe consultas com | para executar várias buscas em uma única chamada ("CFM LEAP engine | A320neo sharklet") — até 10, duas por vez.

ParâmetroTipoDescrição
querystringConsulta de busca (obrigatório). Operadores: "exact phrase", site:, filetype:, +required -excluded, OR
categoriesstringgeneral (padrão), images, videos, news, science, music, files (torrents), it (sites de desenvolvedores/TI), social media; separados por vírgula para vários
max_resultsnúmeroResultados por chamada, 1-50 (padrão: 20 gerais/notícias, 10 imagens/vídeos)
offsetnúmeroPular N resultados para paginação (ex.: 10 para resultados 11-20)
pagenonúmeroNúmero da página do SearXNG (um novo lote dos mecanismos)
time_rangestringday, week, month, year
languagestringCódigo de idioma (ex.: en, fr); all = sem filtro (padrão)
safesearchnúmero0 (nenhum, padrão), 1 (moderado), 2 (estrito)
enginesstringNomes de mecanismos separados por vírgula para usar em vez dos mecanismos da categoria (ex.: bing,yahoo)
min_scorenúmeroDescarta resultados abaixo desta pontuação de relevância (0.0-1.0)

Argumentos opcionais podem ser null ou ""; eles são tratados como não definidos.

2. web_url_read

Lê páginas web (como markdown), PDFs (até 16 MB) e imagens. URLs de imagens são detectadas automaticamente e retornadas como blocos de imagem base64 redimensionados.

ParâmetroTipoDescrição
urlstringURL para ler (obrigatório)
detailstringNível de redimensionamento de imagem: low (448px, ~256 tokens), medium (768px, ~756 tokens, padrão), high (1280px, ~2048 tokens)
startCharnumberDeslocamento de caractere para paginação de texto
maxLengthnumberMáximo de caracteres a retornar
sectionstringExtrair conteúdo sob um título
paragraphRangestringIntervalo de parágrafos (ex.: 1-5)
readHeadingsbooleanRetornar apenas títulos

web_url_read recusa endereços privados — localhost, LAN (RFC1918), Tailscale (100.64.0.0/10), link-local e nomes de host Docker — na primeira solicitação e em cada redirecionamento. Defina MCP_HTTP_ALLOW_PRIVATE_URLS=true no serviço mcp-searxng somente se quiser que ele leia serviços internos.

3. searxng_instance_info e searxng_search_suggestions

Do upstream. searxng_instance_info lista as categorias e mecanismos da instância. searxng_search_suggestions não retorna sugestões de consulta aqui, porque o autocompletar está desativado no settings.yml (a interface web, caso contrário, enviaria cada tecla pressionada a um serviço de sugestão de terceiros). Ele apenas completa os prefixos !bang do SearXNG, ex.: !bi → !bing.

Fluxo de Pesquisa de Imagens

  1. searxng_web_search({query: "sunset", categories: "images"}) -> retorna URLs de imagens + metadados
  2. Escolha uma imagem -> web_url_read({url: "https://example.com/sunset.jpg", detail: "medium"}) -> retorna imagem base64 redimensionada
  3. Para ver mais resultados -> searxng_web_search({query: "sunset", categories: "images", offset: 10}) -> resultados 11-20

Imagens SVG são renderizadas como PNG. Imagens acima de 100 megapixels são recusadas, e no máximo dois redimensionamentos raster e duas renderizações SVG são executados por vez (imagens JPEG/PNG/GIF/WebP pequenas que não precisam de redimensionamento passam direto).

Arquivos de Patch Personalizados

O servidor MCP é o upstream mcp-searxng 2.4.0 com alguns arquivos montados somente leitura sobre sua pasta dist/. Todos os outros arquivos upstream (incluindo sua segurança de URL, segurança HTTP e leitura de PDF) são executados sem modificação.

ArquivoPropósito
Dockerfileisokoliuk/mcp-searxng:2.4.0 upstream + sharp (redimensionamento de imagem) + fontes DejaVu (texto em SVGs)
index.jsArquivo upstream com pequenas edições marcadas como // ENHANCED: — roteia pesquisas e leituras de imagem para os módulos abaixo
version.jsRelata 2.4.0-enhanced
enhanced-search.jsSaída JSON estruturada, `
image-reader.jsBusca de imagens (com a proteção SSRF do upstream), redimensionamento sharp com os 3 presets de detalhe, renderização SVG em um processo filho com limite de memória e tempo

Atualizando o SearXNG

O SearXNG está fixado em uma tag datada em docker-compose.yml (atualmente 2026.9.23-3cd69d30e). settings.yml contém apenas substituições sobre as configurações padrão dentro da imagem, então uma nova imagem pode silenciosamente habilitar, desabilitar ou remover mecanismos — por isso as atualizações são um aumento deliberado de tag em vez de um pull de :latest.

# 1. Edit docker-compose.yml: set the new tag from https://hub.docker.com/r/searxng/searxng/tags
docker compose up -d searxng                               # pulls the tag, recreates the container
docker compose logs searxng --tail 100                     # look for "can't register engine" (unknown settings keys are mostly ignored silently)
curl.exe -s http://localhost:8888/config > config-new.json # compare categories/engines with the old version
curl.exe -s http://localhost:8888/stats/errors             # after a few searches: which engines fail

Compare também a lista plugins: em settings.yml com o /usr/local/searxng/searx/settings.yml da própria imagem: a sobreposição substitui a lista completa de plugins, então um novo plugin upstream não é carregado até que você o adicione. O SearXNG não publica releases no GitHub; a parte após a data em uma tag é um hash de commit, então revise as alterações entre as duas tags em https://github.com/searxng/searxng/compare/3cd69d30e...<new-hash>. Para reverter, defina a tag antiga novamente.

Um meio-termo razoável para se manter atualizado: agende um trabalho semanal que verifique no Docker Hub se há uma tag mais recente e o reporte, mas não a aplique.

Atualizando o servidor MCP

mcp-searxng é construído localmente a partir de mcp-searxng-patches/Dockerfile, que está fixado em isokoliuk/mcp-searxng:2.4.0. Após puxar este repositório em outra máquina, ou após alterar o Dockerfile:

docker compose build mcp-searxng
docker compose up -d --force-recreate mcp-searxng
curl -s http://localhost:3001/health        # version must be 2.4.0-enhanced

--force-recreate não é opcional. Um docker compose up -d simples reconstrói a imagem, mas deixa o contêiner existente em execução na imagem antiga, então a atualização silenciosamente não faz nada. Confirme que o contêiner está na imagem recém-construída — esses dois IDs devem corresponder:

docker inspect mcp-searxng --format '{{.Image}}' && docker images --no-trunc --format '{{.ID}}' mcp-searxng-enhanced:latest

Para mover para uma versão upstream mais recente: aumente a tag FROM, copie os novos dist/index.js e dist/version.js da imagem (docker run --rm --entrypoint cat isokoliuk/mcp-searxng:<tag> /app/dist/index.js), reaplique as edições // ENHANCED: e reconstrua. enhanced-search.js e image-reader.js importam módulos upstream, então verifique-os quanto a exports renomeados.

Testado Com

  • Qwen3.6 35B A3B — executa tanto searxng_web_search (incluindo multi-consulta e filtros de categoria) quanto web_url_read (modos texto + imagem) de forma confiável. Seleção de ferramentas, inferência de parâmetros e interpretação de resultados funcionam bem com este modelo.

Notas

  • O servidor MCP usa transporte HTTP Streamable (não stdio ou somente SSE)
  • O SearXNG se conecta internamente via nome de host Docker searxng:8080
  • Nenhuma chave de API externa necessária. As consultas vão do seu IP para os mecanismos de busca; um mecanismo, findborg, é um proxy sem chave de terceiros do índice do Brave (desative-o em settings.yml se não quiser isso).
  • Os patches personalizados são licenciados sob MIT e não adicionam telemetria. Seu único acesso a processos/arquivos: image-reader.js inicia seu renderizador SVG através de /bin/sh -c 'ulimit -v … && exec node …' (com um ambiente vazio) e escreve o /proc/<pid>/oom_score_adj desse filho
  • Mecanismos de busca (web geral): Bing, Yahoo, DuckDuckGo (via seu endpoint web), Google (via um endpoint Custom Search sem chave), Yandex, Keenable, Swisscows, mwmbl e findborg, além de infoboxes da Wikipedia. Normalmente 6-8 deles respondem a cada consulta, e resultados que vários mecanismos concordam são classificados primeiro.
  • Se os resultados parecerem escassos, verifique seu IP de saída primeiro. Brave (HTTP 429), o endpoint html do DuckDuckGo, Google web, Qwant web/imagens e GMX (CAPTCHA), e Yep (HTTP 403) rejeitam instâncias auto-hospedadas em endereços compartilhados ou sinalizados — saídas de VPN, CGNAT e faixas de datacenter são as causas comuns. Eles falham na primeira consulta de um contêiner frio, então não é um problema de limite de taxa que você pode ajustar, e eles estão desabilitados na configuração enviada. Startpage também está desligado: seu desafio de prova de trabalho fica mais difícil para seu IP após uma consulta. (Qwant News e Qwant Videos ainda respondem e permanecem habilitados.) Verifique o que o SearXNG relata:
    curl -s "http://localhost:8888/search?q=test&format=json" | jq .unresponsive_engines
    curl -s http://localhost:8888/stats/errors
    
    Opções, aproximadamente em ordem de esforço: pesquise de um IP residencial sem VPN, coloque as solicitações de saída atrás de proxies (outgoing.proxies em searxng/config/settings.yml), ou forneça uma chave de API para um mecanismo que venda uma (braveapi). Habilitar mais mecanismos bloqueados não ajuda.
  • Algumas falhas são normais e autolimitadas: Swisscows recusa algumas consultas com HTTP 450 ("Unavailable For Legal Reasons"), Yahoo recusa rajadas de consultas por um curto período, e o endpoint Custom Search do Google responde "unusual traffic from your network" quando seu IP de saída está sinalizado, às vezes na primeira consulta. O SearXNG suspende o mecanismo (15 minutos para o Google) e os outros carregam a pesquisa.