HasData DuckDuckGo MCP Server
Búsqueda de DuckDuckGo como JSON con resultados orgánicos clasificados, anuncios en su propio array y 37 regiones.
Documentación
Servidor MCP de DuckDuckGo
Un servidor de Protocolo de Contexto de Modelo (MCP) alojado que brinda a Claude, Cursor, Windsurf y cualquier otro cliente MCP resultados de búsqueda de DuckDuckGo como JSON estructurado. Resultados orgánicos clasificados con posiciones, anuncios en su propio arreglo, la respuesta de IA propia de DuckDuckGo y 37 regiones para segmentar. Diseñado para volumen y para análisis, sin navegador local ni cadena de respaldo que configurar.
https://mcp.hasdata.com/api/mcp?apis=duckduckgo
Contenido
- Lo que necesitas
- Inicio rápido
- Ejemplos de indicaciones
- Herramientas
- Errores y rutas de fallo
- Precios, plan gratuito y límites
- Selección de herramientas
- Cómo se compara
- Preguntas frecuentes
- Enlaces de HasData
- Desarrollo
- Contribuciones
- Licencia
Lo que necesitas
Un cliente MCP que hable HTTP transmisible con encabezados personalizados. Una clave de API de HasData desde el panel, gratuita de crear. Nada más. Este es un servidor remoto, por lo que la ruta más simple es una URL y un encabezado, sin paquete de navegador que agregar ni proceso local que mantener. Un cliente solo-stdio puede usar el lanzador @hasdata/duckduckgo-mcp (npm) o hasdata-duckduckgo-mcp (PyPI) en su lugar.
Inicio rápido
La URL del servidor es la misma para cada cliente. Lo ejecutamos de forma práctica en Claude Code y Claude Desktop. Los otros bloques siguen el formato documentado de cada cliente para un servidor remoto.
| Campo | Valor |
|---|---|
| URL | https://mcp.hasdata.com/api/mcp?apis=duckduckgo |
| Transporte | HTTP, transmisible |
| Encabezado de autenticación | x-api-key: HASDATA_API_KEY |
Los clientes con soporte OAuth pueden agregar la misma URL como conector e iniciar sesión sin poner una clave en un archivo de configuración.
Claude Code
claude mcp add --transport http duckduckgo "https://mcp.hasdata.com/api/mcp?apis=duckduckgo" \
--header "x-api-key: HASDATA_API_KEY"
Claude Desktop
Configuración, luego Conectores, luego Agregar conector personalizado, luego pega https://mcp.hasdata.com/api/mcp?apis=duckduckgo e inicia sesión.
Para la ruta de archivo de configuración, Claude Desktop carga solo servidores locales (stdio), por lo que llega a un servidor remoto a través de un lanzador stdio. El paquete @hasdata/duckduckgo-mcp es ese lanzador, y lee la clave del entorno. Agrega esto a claude_desktop_config.json:
{
"mcpServers": {
"duckduckgo": {
"command": "npx",
"args": ["-y", "@hasdata/duckduckgo-mcp"],
"env": { "HASDATA_API_KEY": "YOUR_KEY" }
}
}
}
¿Python en lugar de Node? Cambia el lanzador por el paquete de PyPI, que uvx ejecuta sin instalación manual:
{
"mcpServers": {
"duckduckgo": {
"command": "uvx",
"args": ["hasdata-duckduckgo-mcp"],
"env": { "HASDATA_API_KEY": "YOUR_KEY" }
}
}
}
Cursor
~/.cursor/mcp.json para cada proyecto, o .cursor/mcp.json para uno solo:
{
"mcpServers": {
"duckduckgo": {
"url": "https://mcp.hasdata.com/api/mcp?apis=duckduckgo",
"headers": { "x-api-key": "HASDATA_API_KEY" }
}
}
}
Windsurf
~/.codeium/windsurf/mcp_config.json. Windsurf llama al campo serverUrl, no url:
{
"mcpServers": {
"duckduckgo": {
"serverUrl": "https://mcp.hasdata.com/api/mcp?apis=duckduckgo",
"headers": { "x-api-key": "HASDATA_API_KEY" }
}
}
}
Cline
{
"mcpServers": {
"duckduckgo": {
"url": "https://mcp.hasdata.com/api/mcp?apis=duckduckgo",
"type": "streamableHttp",
"headers": { "x-api-key": "HASDATA_API_KEY" },
"disabled": false
}
}
}
VS Code
.vscode/mcp.json en el espacio de trabajo:
{
"servers": {
"duckduckgo": {
"type": "http",
"url": "https://mcp.hasdata.com/api/mcp?apis=duckduckgo",
"headers": { "x-api-key": "HASDATA_API_KEY" }
}
}
}
Codex CLI
~/.codex/config.toml:
[mcp_servers.duckduckgo]
url = "https://mcp.hasdata.com/api/mcp?apis=duckduckgo"
[mcp_servers.duckduckgo.headers]
"x-api-key" = "HASDATA_API_KEY"
Gemini CLI
~/.gemini/settings.json:
{
"mcpServers": {
"duckduckgo": {
"httpUrl": "https://mcp.hasdata.com/api/mcp?apis=duckduckgo",
"headers": { "x-api-key": "HASDATA_API_KEY" }
}
}
}
Ejemplos de indicaciones
Indicaciones, no código. Pega una y el agente llama a la herramienta por sí mismo. Cada una está anotada con las llamadas que requiere, porque en MCP el modelo decide cuántas llamadas hacer y cada llamada exitosa cuesta 10 créditos.
Busca en DuckDuckGo "model context protocol" y dame los diez mejores resultados con sus posiciones y dominios.
Una llamada, 10 créditos.
Ejecuta la consulta "vpn review" en la región alemana y nuevamente en la región de EE. UU., luego dime qué dominios aparecen en una y no en la otra.
Dos llamadas, 20 créditos. La región es un parámetro. La misma consulta en dos mercados son dos llamadas.
Busca "best crm software" y lista solo las colocaciones pagadas, con el dominio del anunciante para cada una.
Una llamada, 10 créditos. Los anuncios llegan en su propio arreglo y no necesitan heurísticas de filtrado.
Toma la consulta "model context protocol" y recorre las primeras tres páginas, luego dime qué dominios tienen más de una posición.
Tres llamadas, 30 créditos. Cada página después de la primera es una llamada nueva con el cursor, y elimina q de los argumentos una vez que tengas uno.
Busca "who invented the transistor" y muéstrame la respuesta de IA propia de DuckDuckGo junto a los resultados orgánicos en los que se basó.
Una llamada, 10 créditos.
Dos de esos son la razón por la que existe este servidor. La segmentación por región es un parámetro de primera clase en 37 mercados. Comparar una consulta entre países es un bucle y no una configuración de proxy. Y las colocaciones pagadas vuelven por separado de las orgánicas, lo que evita que el seguimiento de clasificación dependa de adivinar qué resultado era un anuncio.
Paginación cuesta una llamada cada vez. Una indicación que recorre diez páginas son diez llamadas y 100 créditos.
Herramientas
Una herramienta. Las muestras a continuación están recortadas de llamadas reales, y los resultados en ellas cambian a medida que cambia la web. Léelas como formas.
Las muestras son la carga útil, no la respuesta completa. Un resultado tools/call lleva un bloque de texto, y ese texto es en sí mismo JSON que contiene url, status, text y json, con los datos extraídos bajo json. Desde una respuesta JSON-RPC cruda, la ruta es result.content[0].text, analizada, luego .json. Un cliente de chat lo desenvuelve por ti y el código que habla directamente con el endpoint no lo hace.
Obtener resultados de búsqueda de DuckDuckGo
hasdata_duckduckgo_serp_getSearchResults
Obtiene una página de resultados de DuckDuckGo y la devuelve analizada.
| Parámetro | Tipo | Notas |
|---|---|---|
q | string | El término de búsqueda. Ya sea q o nextPageToken tiene que estar presente |
nextPageToken | string | Cursor de pagination.nextPageToken en la respuesta anterior. Gana si envías ambos, y el q que enviaste junto a él se ignora sin advertencia |
kl | string | Región como <country>-<language>, 37 valores desde us-en y de-de hasta jp-jp y wt-wt para sin región |
cc | string | País de dos letras, 36 valores. Una alternativa a kl cuando se combina con setLang |
setLang | string | Idioma de interfaz y resultados, 33 valores |
safeSearch | string | off, moderate o strict |
deviceType | string | desktop, mobile o tablet |
Envía ya sea
qonextPageToken. Enviar ninguno devuelve 422 nombrando ambos campos, porque el requisito es condicional y el esquema no puede expresarlo como una lista obligatoria simple. Enviar ambos tampoco es un error, el cursor gana y la consulta no va a ninguna parte, por lo que un agente que mantieneqen los argumentos mientras pagina lee silenciosamente el conjunto de resultados incorrecto.
positioncuenta dentro de la página de la que proviene, no en todo el conjunto de resultados. La página dos vuelve con posiciones comenzando en 1 nuevamente, y el tamaño de página tampoco es fijo, por lo que páginas de 10, 15 y 14 resultados aparecen todas. La clasificación absoluta es por lo tanto el número de resultados orgánicos que ya has recopilado másposition, no nada que puedas derivar del número de página. Construye un conjunto de datos de clasificación sin eso y cada página contribuye con su propio número uno.
Devuelve organicResults, ads, searchAssist y pagination. Las entradas orgánicas llevan position, title, link, displayedLink, source y snippet, más una fecha, enlaces de sitio y metadatos de video donde DuckDuckGo los muestra. searchAssist contiene la respuesta de IA propia de DuckDuckGo para la consulta.
adsysearchAssistestán ausentes cuando la página no tiene ninguno, así que prueba la clave antes de leerla.organicResultstambién puede estar ausente, así que léelo con un valor predeterminado en lugar de tratar su presencia como dada. Una consulta sin coincidencias reales aún vuelve como una página completa de entradas vagamente relacionadas, que no es como suele verse "nada encontrado".
{
"organicResults": [
{
"position": 1,
"title": "What is the Model Context Protocol (MCP)?",
"link": "https://modelcontextprotocol.io/docs/getting-started/intro",
"displayedLink": "modelcontextprotocol.io › docs › getting-started › intro",
"source": "modelcontextprotocol.io",
"snippet": "MCP is an open-source standard for connecting AI applications to external systems."
}
],
"ads": [
{ "position": 1, "title": "Make Agents Accountable", "link": "https://www.gravitee.io/platform/ai-agent-management" }
],
"searchAssist": {
"answer": "Model Context Protocol (MCP) is an open standard from Anthropic that lets LLMs connect to external tools, systems, and data sources using a shared interface."
},
"pagination": { "nextPageToken": "eyJ1cmwiOiJodHRwczovL2xpbmtzLmR1Y2tkdWNrZ28uY29t…" }
}
Errores y rutas de fallo
Tu cliente casi nunca ve un código de error HTTP de una llamada de herramienta. La capa MCP responde 200 y pone el fallo dentro del resultado, con isError establecido en true y la razón como texto. El agente lee un mensaje donde podrías esperar una línea de estado.
Una clave incorrecta surge como salida de herramienta, no como una conexión fallida. Listar herramientas acepta cualquier clave no vacía, por lo que el cliente completa su protocolo de enlace y muestra verde. La primera llamada de herramienta luego vuelve con isError: true y el texto HasData API error: 401 Unauthorized. Vigila esa cadena, porque nada antes en el flujo informa el problema.
Una clave faltante es el único error HTTP real. La autorización se ejecuta antes de cualquier herramienta, y la conexión misma falla con 401.
Un argumento que rompe el esquema se rechaza antes de convertirse en una búsqueda. El servidor responde con isError: true y el texto MCP error -32602: Input validation error, nombrando el campo. Nada se obtiene y nada se cobra.
Ni q ni nextPageToken devuelve 422 con un arreglo errors nombrando ambos campos y la regla requiredIfNotExists que los une.
Una consulta sin nada detrás aún devuelve resultados. DuckDuckGo decide la relevancia, por lo que una cadena sin sentido vuelve como una página normal de diez entradas vagamente relacionadas con ads y searchAssist ausentes. Nada la marca como un fallo, lo que importa si estás construyendo una alerta sobre "sin cobertura para esta marca".
Los resultados que llevan datos también llevan un requestMetadata.id que vale la pena citar en soporte.
Precios, plan gratuito y límites
Cada llamada cuesta 10 créditos. El número de resultados no cambia el precio. Una página completa cuesta lo mismo que una página con una entrada.
La prueba gratuita es 1,000 créditos durante 30 días sin tarjeta, que son 100 búsquedas. Después de eso, una cuenta activa sigue recibiendo 100 créditos recargados cada día cuando su saldo baja de 100, por lo que un agente de bajo volumen funciona en el plan gratuito indefinidamente.
Los planes pagados comienzan en $49 al mes por 200,000 créditos, que son 20,000 búsquedas. El precio unitario baja con el volumen, desde $2.45 por 1,000 búsquedas en el plan de entrada hasta $0.99 en Business, $0.83 en Growth y $0.75 en los planes de alto volumen más grandes. Los números actuales viven en la página de precios.
Tu plan también establece la concurrencia. La prueba gratuita permite 1 solicitud a la vez, Startup 15, Business 30, Growth 50, y los planes de alto volumen van de 200 a 1,500. Maneja el caso de desbordamiento de manera defensiva en cualquier cosa desatendida, porque un agente que se expande alcanzará el techo antes que tú.
Una solicitud que vuelve no-200 no se factura. Una llamada exitosa que no encuentra nada sigue siendo una llamada.
Selección de herramientas
El parámetro de consulta apis decide qué herramientas ve tu agente. Menos herramientas significa menos contexto gastado en definiciones de herramientas, y menos oportunidades para que el modelo alcance la incorrecta.
?apis=duckduckgo the one tool in this repo
?apis=duckduckgo,google_serp add Google search
?apis=duckduckgo,bing_serp,google_serp three engines side by side
El parámetro toma nombres de proveedores como duckduckgo y nombres de API individuales como google_maps_search. Los nombres mal escritos se ignoran. Si cada nombre es incorrecto, la solicitud falla con 400, y el cuerpo lista tanto lo que no reconoció como cada valor válido. Elimina el parámetro y el mismo endpoint expone las 57 herramientas de HasData.
Tres motores en un solo agente es la razón habitual para ampliar la lista aquí, porque comparar la misma consulta en DuckDuckGo, Google y Bing es una sola instrucción una vez que los tres están expuestos.
Cómo se compara
La alternativa realista es un servidor autoalojado. Los populares son paquetes de Python que ejecutas localmente, llegan a DuckDuckGo desde tu propia máquina y le entregan al modelo un bloque de texto formateado. Eso funciona bien para un asistente de investigación que responde una pregunta a la vez. Deja de funcionar cuando necesitas volumen y una forma estable.
| Servidor autoalojado | Este servidor | |
|---|---|---|
| Lo que devuelve una búsqueda | Una cadena de texto formateada creada para que el modelo la lea | JSON con position, title, link, displayedLink, source, snippet, fechas y enlaces de sitio |
| Ubicaciones pagadas | Eliminadas junto con el resto del ruido | Conservadas en un array ads separado |
| Paginación | Un límite de max_results en una sola página | Cursor en cada respuesta |
| Regiones | Un código region | 37 códigos de región, o país e idioma configurados por separado |
| SafeSearch | Fijado al iniciar el servidor, deliberadamente no invocable por el agente | Por llamada |
| Quién obtiene la página | Tu máquina, a través de httpx, con un backend curl_cffi opcional y una alternativa a configurar | Nosotros |
| Rendimiento | Autolimitado a 30 búsquedas por minuto | Concurrencia del plan, desde 1 en la prueba hasta 1.500 |
| Lo que ejecutas | Un entorno de Python, un extra opcional y ajustes de contenedor o proxy cuando no está en localhost | Una URL y una cabecera |
| Extracción de contenido de página | Una herramienta fetch_content | No se ofrece |
| Coste | Gratis | 10 créditos por llamada |
Dos filas cargan con la mayor parte de la decisión. Un bloque de texto es la salida correcta para una respuesta de chat y la incorrecta para un conjunto de datos de ranking, porque reconstruir position a partir de prosa es trabajo que no deberías estar haciendo. Y que la obtención sea nuestra significa que la cuestión del backend desaparece, junto con elegir entre httpx y un cliente que imita al navegador, instalar el extra del que depende la alternativa y leer un rastreo de pila cuando un cliente HTTP simple deja de recibir una página.
Todo lo demás en esa lista es un verdadero intercambio. Un servidor autoalojado es gratuito, no necesita cuenta, mantiene tus consultas en tu propia máquina y obtiene contenido de página, algo que este servidor no hace. Si ejecutas un puñado de búsquedas al día dentro de un asistente, es la mejor opción. Este es para el caso en el que el número de búsquedas, el número de regiones o la forma de la salida empiezan a importar.
Frente a la propia API de DuckDuckGo. api.duckduckgo.com es la API de Instant Answer, y devuelve un resumen enciclopédico cuando existe en lugar de una página de resultados. No hay un endpoint oficial que te entregue resultados web clasificados, por eso cada opción aquí analiza la página.
Lo que este servidor no hace. Sin obtención de páginas ni extracción de contenido, sin verticales de imágenes o noticias, sin autocompletado. Devuelve la página de resultados, analizada.
Preguntas frecuentes
¿Existe un servidor MCP oficial de DuckDuckGo?
No. DuckDuckGo no publica ningún servidor MCP. Cada opción está construida por otra persona. La mayoría son proyectos de código abierto que se ejecutan localmente, y este es un servidor alojado mantenido por HasData.
¿Qué es un servidor MCP de DuckDuckGo?
Un servidor que expone la búsqueda de DuckDuckGo como una herramienta que un cliente de IA puede invocar. El cliente envía una llamada de herramienta a través del Model Context Protocol, el servidor ejecuta la búsqueda y devuelve JSON estructurado, y el modelo trabaja con el resultado y nunca ve una página de HTML.
¿Necesito una cuenta de DuckDuckGo o una clave de API?
No. La única credencial es tu clave de HasData. DuckDuckGo no tiene un programa de desarrolladores al que registrarse, y la API de Instant Answer que sí publica no devuelve resultados de búsqueda.
¿Necesito alojar o ejecutar algo?
No. Este es un servidor MCP remoto en HTTP transmisible. Nada que instalar, sin entorno de Python, sin paquete de navegador, sin proceso que reiniciar.
¿Los datos son en vivo o en caché?
En vivo. Cada llamada obtiene la página de resultados en el momento de la solicitud y lleva su propio requestMetadata.id. Dos llamadas idénticas son dos obtenciones separadas y no una reproducción de una copia almacenada.
¿Puedo comparar la misma consulta entre regiones?
Sí, y esa es la razón principal para usar un parámetro en lugar de un proxy. kl acepta 37 códigos de región, y cc con setLang separa país e idioma cuando necesitas distinguirlos. Cada región es su propia llamada.
¿Qué ocurre cuando DuckDuckGo cambia su diseño?
Nada por tu parte. Nosotros seguimos los cambios y mantenemos estable el esquema de respuesta, así que los nombres y tipos de campos permanecen. Un bloque sin nada que informar está ausente de la respuesta, así que lee ads y searchAssist con un valor predeterminado.
¿Puedo usar esto junto con otras APIs de HasData?
Sí. El parámetro apis acepta una lista, y ?apis=duckduckgo,google_serp,bing_serp le da a tu agente tres motores de búsqueda a la vez.
¿Puedo iniciar sesión con OAuth en lugar de pegar una clave?
Sí, en clientes que lo admitan. Claude Desktop y Cursor pueden añadir el endpoint como conector e iniciar sesión. Los agentes y scripts no supervisados usan la cabecera x-api-key.
Cumplimiento y datos personales
HasData accede únicamente a datos disponibles públicamente. Los términos de una plataforma pueden restringir el acceso automatizado, y tú eres responsable de tu propio cumplimiento. Cuando los datos que recopilas incluyan información personal, asegúrate de tener una base legal para ello según el GDPR, la CCPA o las normas equivalentes en tu jurisdicción.
Enlaces de HasData
| Página de producto y constructor de solicitudes | DuckDuckGo SERP API |
| Documentación del servidor | MCP server docs |
| Las 57 herramientas en un solo servidor | HasData/hasdata-mcp |
| Tutoriales para clientes | MCP clients and integrations |
| Los otros motores de búsqueda que analizamos | Google, Bing and 53 more APIs |
| Planes y costes de créditos | Plans and credit costs |
| Claves y uso | HasData dashboard |
| Lanzador de Node en npm | @hasdata/duckduckgo-mcp |
| Lanzador de Python en PyPI | hasdata-duckduckgo-mcp |
Desarrollo
Este repositorio es configuración y documentación para un servidor remoto. No hay paso de compilación ni nada que contenerizar.
Las pruebas en test/ verifican el contrato de la herramienta, la parte que puede romperse sin un commit aquí. Comprueban que ?apis=duckduckgo devuelve exactamente una herramienta, que su nombre no ha cambiado, que los parámetros que documenta este README siguen existiendo con las enumeraciones que cita, y que la clave en uso es realmente aceptada. Esa última comprobación ejecuta una búsqueda real y cuesta 10 créditos, que es el precio de un canario que puede fallar por la razón correcta.
# macOS and Linux
HASDATA_API_KEY=your_key_here npm test
# Windows PowerShell
$env:HASDATA_API_KEY="your_key_here"; npm test
La misma suite se ejecuta en CI en cada push y una vez a la semana en un horario, porque la lista de herramientas ascendente puede cambiar sin que nadie toque este repositorio. Un fallo significa que la lista de herramientas se movió, la clave dejó de funcionar o el endpoint era inalcanzable, y el mensaje de la aserción indica cuál.
Contribuciones
Las correcciones a la tabla de parámetros y a la muestra de respuesta son la contribución más útil, porque esas son las partes que se desvían. Incluye la llamada que hiciste y la respuesta que obtuviste. Las solicitudes de extracción desde bifurcaciones ejecutan la suite sin clave, y las comprobaciones en vivo se omiten en lugar de ponerse en rojo.
Licencia
MIT. Ver LICENSE.