Skip to main content
Glama
Desearch-ai

Desearch MCP Server

Official

Desearch MCP Server

npm version GitHub stars

If Desearch is useful, a star helps others find it.

Remote: https://mcp.desearch.ai/mcp with header Authorization: Bearer <DESEARCH_API_KEY>.

Local: npx -y desearch-mcp-server with env DESEARCH_API_KEY.

Get a key.

Find Desearch on

Related MCP server: grok-mcp-server

Demo

Prompt: Search the web for latest news on AI.

web-search takes query (required) and start (optional pagination offset: 0, 10, 20, ...).

{
    "name": "web-search",
    "arguments": {
        "query": "latest news on AI"
    }
}

Example output:

{
    "data": [
        {
            "title": "Example result",
            "link": "https://example.com/page",
            "snippet": "Short preview text."
        }
    ]
}

The tool returns that JSON as pretty-printed text: { "content": [{ "type": "text", "text": "<json above>" }] }.

AI search, X search and web search for AI agents, plus page extraction, X data tools, and People Search (find people and creators on X, YouTube, LinkedIn, and TikTok). Bring your own Desearch API key.

Tools

The Desearch MCP server includes the following tools.

Lookup tools, including search and fetch, set readOnlyHint: true, destructiveHint: false, and openWorldHint: true. people-search starts a paid job billed to the user's Desearch balance, so readOnlyHint is false and destructiveHint is true. people-search-control can cancel a search, so readOnlyHint is false and destructiveHint is true. openWorldHint is true on every tool because the call reaches a live external source.

  • AI Search (ai-search): Performs AI Twitter and web searches with relevant links and summary. tools uses short source ids (web, twitter, arxiv, wikipedia, hackernews, reddit). Older labels such as Web Search, ArXiv Search, Wikipedia Search, Hacker News Search, and Reddit Search are still accepted and sent as the short id. youtube is not accepted. Default is ["web", "twitter"].

  • X Search (x-search): Tweet search on X. Arguments: query (required), count (optional, default 20). Sort stays Top. Optional filters: user, start_date, end_date (YYYY-MM-DD), lang, verified, blue_verified, is_quote, is_video, is_image, min_retweets, min_replies, min_likes.

  • Search (search): Web search that returns { results: [{ id, title, url }] }. Argument: query (required). id is the result URL.

  • Fetch Page (fetch): Read a public page as text. Argument: id (required, an http or https URL from search).

  • Web Search (web-search): SERP-style web search. Arguments: query (required), start (optional pagination offset).

  • Web Links Search (web-links-search): Web link search. Arguments: prompt (required), tools (optional, only web, default ["web"]; Web Search is accepted and rewritten to web), count (optional, 10–200). The links/web API rejects other sources, so they are not in the enum.

  • Extract (extract): Read a public URL as text or HTML. Preferred over crawl. Arguments: url (required), format (optional, html or text), js (optional), wait (optional milliseconds).

  • Web Crawl (web-crawl): Same arguments as extract, on the legacy /web/crawl route. The SDK marks webCrawl deprecated in favor of extract; this tool stays so that route remains reachable. Prefer extract for new integrations.

  • X Links Search (x-links-search): AI search for X post links. Arguments: prompt (required), count (optional, 10–200).

  • X Posts By URLs (x-posts-by-urls): Full posts for a list of URLs. Argument: urls (required).

  • X Post By ID (x-post-by-id): One post by ID. Argument: id (required).

  • X Posts By User (x-posts-by-user): Posts by a user. Arguments: user (required), query (optional), count (optional, 1–100).

  • X Post Retweeters (x-post-retweeters): Users who retweeted a post. Arguments: id (required), cursor (optional).

  • X User Posts (x-user-posts): A user's timeline. Arguments: username (required), cursor (optional).

  • X User Replies (x-user-replies): Posts and replies by a user. Arguments: user (required), count (optional, 1–100), query (optional).

  • X Post Replies (x-post-replies): Replies to a post. Arguments: post_id (required), count (optional, 1–100), query (optional).

  • X Trends (x-trends): Trending topics for a location. Arguments: woeid (required), count (optional, 30–100).

  • People Search (people-search): Start a paid job billed to the user's Desearch balance: a search for people who match a plain-language description. Arguments: platform (required: x, youtube, linkedin, or tiktok), query (required, 3–1000 characters), count (optional, 5–200, API default 25), min_score (optional, 0–100), exclude (optional handles), metadata (optional labels, below), idempotency_key (optional), and that platform's filters (below). Returns the task_id, status, and reserved_cost_usd.

  • People Search Status (people-search-status): A task's status, progress, and cost, plus a page of the people found so far. Arguments: task_id (required), cursor (optional, next_cursor from the previous call), limit (optional, 1–100, default 25), include_people (optional, default true). Free.

  • Control People Search (people-search-control): Pause, resume, or cancel a task. Arguments: task_id (required), action (required: pause, resume, or cancel). Free.

  • List People Search Tasks (people-search-tasks): Your searches, newest first. Arguments: platform (optional), status (optional list, for example ["running", "paused"]), limit (optional, 1–100), cursor (optional), metadata (optional, up to 3 labels a task must have, for example {"campaign": "q4-outbound"}). Free.

  • List People Found (people-profiles): Everyone your searches found on one platform, one entry per person, with the search that found them. Arguments: platform (required), q (optional text in name, handle, bio, or location), sort (optional: score, recent, or audience), limit (optional, 1–200, default 25), cursor (optional), and the filters has (channels every person must have: email, website, x, linkedin, instagram, youtube, tiktok), min_audience, max_audience, min_score, location, verified. Free.

The full SDK method → endpoint → MCP tool map is in docs/API_MCP_PARITY.md. Every public desearch-js 1.5 method is a tool. latestTweets was removed from the SDK (GET /twitter/latest in 1.0.1) and is not exposed. People Search is not in desearch-js 1.5; its tools call the /desearch/people/* routes directly, and the parity doc lists them too.

People Search finds X profiles, YouTube creators, LinkedIn members, or TikTok creators who match a plain-language description. Each person comes back with a fit score, one line on why they matched, their audience (followers, or subscribers on YouTube), location, and the public contacts and links the search found.

A search is a background task:

  1. people-search starts a paid job billed to the user's Desearch balance and returns a task_id at once. It is the only billed People Search call. It reserves count people at the platform's per-person price (reserved_cost_usd). When the search ends you pay only for the people it delivered (a per-search minimum applies when it finds anyone; a search that finds no one is free), and the rest of the reservation is returned. Send the same idempotency_key to retry a call without starting, or paying for, a second search.

  2. The search usually runs for 1 to 5 minutes. people-search-status returns its status, progress, cost, and the people found so far. People arrive while it runs: pass next_cursor back as cursor to get only the new ones. When done is true and has_more is false, you have everyone it found.

  3. people-search-control pauses, resumes, or cancels it. A cancelled search bills only the people it already delivered.

People found stay readable for 30 days after a search ends. people-profiles lists them per platform across all your searches, with filters such as has: ["email"].

Search filters depend on the platform. A filter that does not apply is rejected before the billed call.

Platform

Filters

x

min_followers, max_followers, verified_only, countries, keywords, exclude_keywords

youtube

min_subscribers, max_subscribers, countries, require_contact, keywords, exclude_keywords

linkedin

min_followers, max_followers, countries, keywords, exclude_keywords

tiktok

min_followers, max_followers, require_contact, keywords, exclude_keywords

require_contact keeps only creators with a public email (on TikTok, in the bio). keywords and exclude_keywords take up to 20 words each.

metadata labels a search with your own keys, for example {"campaign": "q4-outbound", "workspace_id": "ws_42"}. A search takes up to 10 keys; keys are 1–40 characters of a-z, 0-9, _, . or -, and values are strings of up to 200 characters. A bad label is rejected before the billed call. The labels come back as metadata on the task, and people-search-tasks with metadata: {"campaign": "q4-outbound"} lists only the searches that carry them (up to 3 pairs, exact match). The search itself does not use them.

Prompt: find 10 TikTok skincare creators with a public email.

{
    "name": "people-search",
    "arguments": {
        "platform": "tiktok",
        "query": "Skincare creators who review skincare products",
        "count": 10,
        "require_contact": true
    }
}

Example output:

{
    "task_id": "3f1c2b9e-8d4a-4c1e-9b7a-2e5f6a7b8c9d",
    "platform": "tiktok",
    "status": "queued",
    "done": false,
    "query": "Skincare creators who review skincare products",
    "count": 10,
    "result_count": 0,
    "reserved_cost_usd": 0.5,
    "created_at": "2026-10-17T10:00:00Z",
    "cost_usd": 0.5,
    "currency": "USD",
    "next": "Searches usually take 1 to 5 minutes. Poll people-search-status with this task_id every 15 to 30 seconds; people appear while it runs."
}

Then poll with {"task_id": "3f1c2b9e-8d4a-4c1e-9b7a-2e5f6a7b8c9d"} on people-search-status:

{
    "task_id": "3f1c2b9e-8d4a-4c1e-9b7a-2e5f6a7b8c9d",
    "platform": "tiktok",
    "status": "running",
    "stage": "processing",
    "done": false,
    "query": "Skincare creators who review skincare products",
    "count": 10,
    "result_count": 4,
    "progress": { "round": 1, "candidates_processed": 40, "qualified": 4 },
    "reserved_cost_usd": 0.5,
    "created_at": "2026-10-17T10:00:00Z",
    "people": [
        {
            "id": "tiktok:example_creator",
            "platform": "tiktok",
            "handle": "example_creator",
            "name": "Example Creator",
            "url": "https://www.tiktok.com/@example_creator",
            "audience": 48200,
            "location": "United States",
            "score": 88,
            "why": "Reviews sunscreens and moisturizers every week.",
            "contacts": [{ "type": "email", "value": "creator@example.com" }],
            "links": [{ "type": "instagram", "url": "https://instagram.com/example_creator" }],
            "evidence_url": "https://www.tiktok.com/@example_creator/video/1"
        }
    ],
    "next_cursor": "4",
    "has_more": false,
    "next": "Still searching. Wait 15 to 30 seconds, then call people-search-status again with cursor \"4\" to get only the people found since this call."
}

The output above is shortened to one person. CSV and JSON Lines downloads (/export routes) are not MCP tools; call the API directly for a file.

When the search has ended, the task also says why and how complete it is, and each person says what their own profile confirms (0.3.2 and later):

{
    "status": "completed",
    "done": true,
    "completion_reason": "cost_limit",
    "coverage_limited": true,
    "warnings": [
        { "code": "partial_enrichment", "platform": "linkedin", "attempted": 20, "failed": 7, "by_reason": { "not_found": 7 } }
    ],
    "people": [
        {
            "handle": "example_engineer",
            "score": 74,
            "fully_verified": false,
            "unverified_criteria": ["Profile fit: Software Engineer based in Georgia (unknown)"],
            "enrichment": "failed",
            "enrichment_error": "not_found"
        }
    ],
    "next": "Finished early: a budget stopped it (cost_limit) before it found 10 people, so more people may match. You have every person it found."
}
  • completion_reason is one of count_reached, rounds_exhausted, no_candidates, zero_qualified, candidate_budget, cost_limit, time_limit, cancelled, or failed. It is left out while the search runs.

  • coverage_limited appears (as true) only when a budget stopped the search before it found count people. The status is still completed.

  • warnings lists what made part of the search less reliable. partial_enrichment: failed of attempted profiles could not be read after search, so those people were scored on the search hit and show enrichment: "failed" with enrichment_error.

  • fully_verified is true when every criterion is confirmed by the person's own profile or posts. unverified_criteria lists up to five that are not: (unknown), (not met), or a disqualifier that (applies). Both are information only: the person still qualified. Results scored before 2026-10-20 have neither.

Prerequisites 📋

Installation 🛠️

NPM Installation

The package name is desearch-mcp-server. The current version is on npm. See CHANGELOG.md for release notes. The stdio entry is the desearch-mcp-server bin (build/index.js), which requires DESEARCH_API_KEY.

npm install -g desearch-mcp-server

Or run it without a global install:

npx -y desearch-mcp-server

Cursor or Claude can start that bin directly:

{
    "mcpServers": {
        "desearch": {
            "command": "npx",
            "args": ["-y", "desearch-mcp-server"],
            "env": {
                "DESEARCH_API_KEY": "your-api-key"
            }
        }
    }
}

command: "desearch-mcp-server" (no args) is the same entry after the global install above.

Gemini CLI

Install the extension from this repository. Gemini CLI asks for your Desearch API key (stored as a sensitive setting) and connects to the hosted server https://mcp.desearch.ai/mcp:

gemini extensions install https://github.com/Desearch-ai/mcp-desearch

To change the key later, run gemini extensions config desearch. AI agents such as Cline can follow llms-install.md to set up the server.

Using Smithery

To install the Desearch MCP server for Claude Desktop automatically via Smithery:

npx -y @smithery/cli install desearch/desearch --client claude

Or for Cursor IDE:

npx -y @smithery/cli install desearch/desearch --client cursor

Windsurf

Windsurf's Cascade agent reads MCP servers from mcp_config.json under the mcpServers key. Open it from the Cascade panel: click the ... (Actions) menu, then Open MCP config file. Windsurf builds use ~/.codeium/windsurf/mcp_config.json (on Windows, %USERPROFILE%\.codeium\windsurf\mcp_config.json). Newer builds may open ~/.config/devin/mcp_config.json instead (Windows: %APPDATA%\devin\mcp_config.json); edit whichever file that action opens.

Hosted server (no local install). Remote servers use serverUrl with headers:

{
    "mcpServers": {
        "desearch": {
            "serverUrl": "https://mcp.desearch.ai/mcp",
            "headers": {
                "Authorization": "Bearer your-api-key"
            }
        }
    }
}

To keep the key out of the file, Windsurf can interpolate an environment variable: "Authorization": "Bearer ${env:DESEARCH_API_KEY}".

Local stdio alternative:

{
    "mcpServers": {
        "desearch": {
            "command": "npx",
            "args": ["-y", "desearch-mcp-server"],
            "env": {
                "DESEARCH_API_KEY": "your-api-key"
            }
        }
    }
}

Save the file, then refresh the MCP servers list in Cascade.

Zed

Zed calls MCP servers context servers. Open your settings file with the zed: open settings file action (or use Settings → AI → MCP Servers → Add Server) and add a context_servers entry.

Hosted server:

{
    "context_servers": {
        "desearch": {
            "url": "https://mcp.desearch.ai/mcp",
            "headers": {
                "Authorization": "Bearer your-api-key"
            }
        }
    }
}

Local stdio alternative:

{
    "context_servers": {
        "desearch": {
            "command": "npx",
            "args": ["-y", "desearch-mcp-server"],
            "env": {
                "DESEARCH_API_KEY": "your-api-key"
            }
        }
    }
}

The server is ready when the dot next to desearch in Settings → AI → MCP Servers turns green ("Server is active").

Configuration ⚙️

1. Configure Cursor IDE to run the Desearch MCP server

Open Cursor IDE, access command palette Cmd+Shift+P or Ctrl+Shift+P, and search for Open MCP Settings. Click on Add new global MCP server to open the mcp.json file.

2. Add the Desearch server configuration:

{
    "mcpServers": {
        "desearch": {
            "command": "desearch-mcp-server",
            "env": {
                "DESEARCH_API_KEY": "your-api-key"
            }
        }
    }
}

Replace your-api-key with your actual Desearch API key from console.desearch.ai/api-keys.

3. Restart Cursor IDE

For the changes to take effect:

  1. Completely quit Cursor IDE

  2. Start Cursor IDE again

1. Configure Claude Desktop to run the Desearch MCP server

Open the Claude Desktop app and enable Developer Mode from the top-left menu bar.

Once enabled, open Settings (also from the top-left menu bar) and navigate to the Developer Option, where you'll find the Edit Config button. Clicking it will open the claude_desktop_config.json file, allowing you to make the necessary edits.

OR (if you want to open claude_desktop_config.json from terminal)

For macOS:

  1. Open your Claude Desktop config:

code ~/Library/Application\ Support/Claude/claude_desktop_config.json

For Windows:

  1. Open your Claude Desktop configuration:

code %APPDATA%\Claude\claude_desktop_config.json

2. Add the Desearch server configuration:

{
    "mcpServers": {
        "desearch": {
            "command": "desearch-mcp-server",
            "env": {
                "DESEARCH_API_KEY": "your-api-key"
            }
        }
    }
}

Replace your-api-key with your actual Desearch API key from console.desearch.ai/api-keys.

3. Restart Claude Desktop

For the changes to take effect:

  1. Completely quit Claude Desktop

  2. Start Claude Desktop again

  3. You can verify the server by checking status in Settings > Developer > desearch

Remote Streamable HTTP

The same server can run over MCP Streamable HTTP for a remote client. Local stdio (desearch-mcp-server, Smithery) is unchanged and still reads DESEARCH_API_KEY from the environment.

Remote requests do not use that environment variable. Discovery does not need a key: initialize, notifications/initialized, ping, tools/list, prompts/list, resources/list, and resources/templates/list return 200 so a marketplace scanner can read the tool list. tools/call and every other method still require the caller's own Desearch API key, the same key from console.desearch.ai/api-keys:

  • Authorization: Bearer <DESEARCH_API_KEY> (preferred)

  • x-api-key: <DESEARCH_API_KEY> (also accepted)

  • Authorization: Bearer <oauth access token> after the OAuth sign-in below

A bare Authorization: <DESEARCH_API_KEY> value is also accepted. The key is not read from the query string. There is no shared server secret. A protected call without a valid key or access token returns 401 with a WWW-Authenticate header pointing at /.well-known/oauth-protected-resource/mcp. The hosted process forwards the per-request Desearch API key to the Desearch API only when a call needs it. An OAuth access token is opaque: the server looks up the key stored for that token and does not put the raw key in the token.

The MCP endpoint is POST /mcp. Responses are JSON (stateless Streamable HTTP). GET and DELETE on /mcp return 405 because the server does not keep a session or push server-to-client messages. GET /, GET /health, and GET /api/health are unauthenticated health checks.

Hosted endpoint

The public Streamable HTTP endpoint is https://mcp.desearch.ai/mcp. Listing the tools does not need a key. Send your Desearch API key on each tools/call using Authorization: Bearer <DESEARCH_API_KEY> (preferred). The x-api-key header is also accepted. Use the key from console.desearch.ai/api-keys. The server does not read a key from the query string. Remote requests do not use a process-level DESEARCH_API_KEY.

Cursor, or any remote MCP client:

{
    "mcpServers": {
        "desearch": {
            "url": "https://mcp.desearch.ai/mcp",
            "headers": {
                "Authorization": "Bearer your-api-key"
            }
        }
    }
}

OAuth sign-in

Clients that follow the MCP authorization spec (2025-06-18) can sign in instead of sending a key on every request. Discovery documents:

  • GET /.well-known/oauth-protected-resource

  • GET /.well-known/oauth-protected-resource/mcp

  • GET /.well-known/oauth-authorization-server

  • GET /.well-known/openid-configuration (same authorization server document)

POST /register is dynamic client registration. GET /authorize is the Desearch page where the user pastes an API key. POST /token exchanges the authorization code and rotates refresh tokens. PKCE S256 is required. Public clients use token_endpoint_auth_method none.

Allowed callback URLs:

  • https://claude.ai/api/mcp/auth_callback

  • https://claude.com/api/mcp/auth_callback

  • https://chatgpt.com/connector_platform_oauth_redirect

  • https://chatgpt.com/connector/oauth/{callback_id}

  • Loopback http://localhost, http://127.0.0.1, and http://[::1] on any port (host and path must match the registered callback)

The connector URL is https://mcp.desearch.ai/mcp. On the sign-in page, paste a key from console.desearch.ai/api-keys. Leave a client id blank when the client can register itself.

Environment variables for the host:

Variable

Required

Purpose

OAUTH_ISSUER

Production

Canonical origin with no trailing slash, for example https://mcp.desearch.ai. Required when NODE_ENV=production or VERCEL is set. The process refuses OAuth and bearer challenges if it is unset. The issuer is never taken from X-Forwarded-Host. Locally, the request URL is used.

OAUTH_RESOURCE

No

Canonical MCP URL. Default is {OAUTH_ISSUER}/mcp. Access tokens are rejected when their stored audience does not match this resource.

OAUTH_STORE

Production

memory (local default) or redis. Production (NODE_ENV=production or VERCEL) refuses to start unless this is redis.

REDIS_URL

When OAUTH_STORE=redis

Redis connection string (redis:// or rediss://).

OAUTH_ENCRYPTION_KEY

When OAUTH_STORE=redis

32-byte key, base64 or hex. Generate with openssl rand -base64 32. Encrypts stored API keys.

OAUTH_ACCESS_TTL_SEC

No

Access token lifetime. Default 3600. Range 60 to 86400.

OAUTH_REFRESH_TTL_SEC

No

Refresh token lifetime. Default 30 days. Range 300 to 90 days.

OAUTH_CODE_TTL_SEC

No

Authorization code lifetime. Default 300. Range 30 to 600.

OAUTH_CLIENT_TTL_SEC

No

Dynamic client lifetime. Default 90 days. Range 3600 to 5 years.

OAUTH_REGISTER_RATE_LIMIT

No

Registration attempts per IP per window. Default 10. Range 1 to 10000.

OAUTH_REGISTER_RATE_WINDOW_SEC

No

Registration rate-limit window in seconds. Default 3600 (1 hour). Range 1 to 86400.

OAUTH_AUTHORIZE_RATE_LIMIT

No

Sign-in key checks per IP per window. Default 20. Range 1 to 10000.

OAUTH_AUTHORIZE_RATE_WINDOW_SEC

No

Sign-in key-check window in seconds. Default 600 (10 minutes). Range 1 to 86400.

DESEARCH_API_BASE

No

Key check host. Default https://api.desearch.ai.

OAUTH_REQUIRE_AUTH_ON_INITIALIZE

No

Set to true to require a key or access token on initialize. Default is off, so keyless initialize stays public. tools/list stays public either way.

The key check calls GET /twitter/trends?woeid=1&count=1. A real key is authenticated and then rejected as invalid input (HTTP 422), so the check does not run a full trends query. Only 422 counts as a valid key. 401 and 403 reject the key. Any other status, including a 2xx, is a verification error and is not treated as valid.

POST /register allows 10 requests an hour per IP. The sign-in key check allows 20 requests every 10 minutes per IP. A request past the limit returns 429 with Retry-After. On Vercel the address is the first X-Forwarded-For hop. The sign-in page uses Referrer-Policy: same-origin and posts response_type=code with the other authorize fields. The form accepts a same-origin Origin or Referer, and accepts Sec-Fetch-Site: same-origin when Origin is missing or null. It rejects Sec-Fetch-Site cross-site and same-site, a foreign Origin, and a POST that has no origin signal.

Use with Claude (custom connector)

Desearch is not in the Claude Connectors Directory yet. You can add the hosted server as a custom connector with your Desearch API key, or with OAuth sign-in.

Sources: Custom remote MCP connectors and connector authentication. Request-header authentication is a beta feature in Claude.

Claude.ai / Claude Desktop (organization admin)

  1. Open Organization settings > Connectors.

  2. Select Add, then Custom. If asked for the connector type, choose Web.

  3. Server URL: https://mcp.desearch.ai/mcp

  4. Sign-in option: No sign-in.

  5. Under Request headers, add Authorization with Bearer <DESEARCH_API_KEY> as the value, replacing <DESEARCH_API_KEY> with your Desearch API key.

  6. Select Add.

The header value is stored once and shared by everyone in the organization who uses the connector.

OAuth alternative: choose sign-in instead of a request header, leave the OAuth client id empty so the client can register itself, and paste a Desearch API key on the Desearch page. The callback URL for hosted Claude apps is https://claude.ai/api/mcp/auth_callback. Claude Code uses a loopback callback, which this server accepts on any port.

Claude Code

claude mcp add --transport http desearch https://mcp.desearch.ai/mcp \
  --header "Authorization: Bearer your-api-key"

Run locally

npm install
npm run build
npm run start:http

This listens on 0.0.0.0:3000 (PORT and HOST override that). MCP_TRANSPORT=http is the same as --http.

curl -sS http://127.0.0.1:3000/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'Authorization: Bearer your-api-key' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.1"}}}'

Cursor (or any remote MCP client):

{
    "mcpServers": {
        "desearch": {
            "url": "http://127.0.0.1:3000/mcp",
            "headers": {
                "Authorization": "Bearer your-api-key"
            }
        }
    }
}

The image default is stdio MCP (node build/index.js). Registries such as Glama start the container and speak MCP on stdin/stdout, so the image does not pass --http unless you override it. Stdio requires DESEARCH_API_KEY. Smithery does not use this image command; smithery.yaml starts node build/index.js and injects DESEARCH_API_KEY itself.

Streamable HTTP is an override. Replace the command with --http, or set MCP_TRANSPORT=http and keep the default command. The image still exposes port 3000 for that mode.

docker build -t desearch-mcp .
# stdio (image default)
docker run --rm -e DESEARCH_API_KEY=your-api-key -i desearch-mcp
# Streamable HTTP
docker run --rm -p 3000:3000 desearch-mcp node build/index.js --http
# same HTTP mode via env, without replacing the command
docker run --rm -e MCP_TRANSPORT=http -p 3000:3000 desearch-mcp

Deploy on Vercel

Vercel fits the MCP handler because each JSON-RPC call is one response. vercel.json builds the project, serves POST /mcp, and sets the function duration to 60 seconds. The same file rewrites the public OAuth paths to /api/*. The server accepts those rewritten paths and the public paths, and the metadata documents still advertise the public paths. Hobby plans cap function duration lower than that, so AI Search tool calls need a plan that allows at least 60 seconds. initialize and tools/list are short either way.

OAuth codes and tokens need shared storage. On Vercel set OAUTH_STORE=redis, REDIS_URL, OAUTH_ENCRYPTION_KEY, and OAUTH_ISSUER=https://mcp.desearch.ai. The server refuses OAuth when OAUTH_ISSUER is unset or OAUTH_STORE is not redis, because Vercel sets VERCEL on every function. OAUTH_REQUIRE_AUTH_ON_INITIALIZE=true is optional. Leave it unset unless a client treats public initialize as a reason to skip sign-in.

No server-side Desearch API key is required in the Vercel project. After deploy, the endpoint is:

https://<project>.vercel.app/mcp

https://mcp.desearch.ai/mcp is the public hostname. This repo does not create DNS records. Clients send Authorization: Bearer <DESEARCH_API_KEY> (preferred). The x-api-key header is also accepted.

The same node build/index.js --http process is the fallback if you would rather run a long-lived Node host instead of Vercel. The Docker image defaults to stdio; pass --http or set MCP_TRANSPORT=http to serve Streamable HTTP from it.

Troubleshooting 🔧

Common Issues

  1. Server Not Found

    • Check Claude or Cursor Desktop configuration syntax

    • Ensure Node.js is installed

  2. API Key Issues

    • Confirm your DESEARCH_API_KEY is valid

    • Check the DESEARCH_API_KEY is correctly set in the Cursor or Claude Desktop config

    • Verify that there are no spaces around the API key

    • For the remote HTTP server, send Authorization: Bearer <DESEARCH_API_KEY> (preferred); x-api-key is also accepted. A hosted DESEARCH_API_KEY environment variable is not used for those requests.

  3. Connection Issues

    • Restart Claude Desktop or Cursor IDE completely

    • Check Claude Desktop logs:

    # macOS
    tail -n 50 -f ~/Library/Logs/Claude/mcp*.log
    
    # Windows
    type "%APPDATA%\Claude\logs\mcp*.log"

Available Tools

22 tools
extractExtract Page ContentA
Read-only
Inspect

Extract a public URL and return its content as plain text or HTML using Desearch. Preferred over web-crawl for new integrations. API docs: https://www.desearch.ai/docs/api-reference/get-web-extract

NameRequiredDescriptionDefault
jsNoRender JavaScript before reading the page.
urlYesPublic URL to read, example: 'https://desearch.ai'
waitNoPost-load wait in milliseconds when JavaScript rendering is enabled.
formatNoContent format to return: 'html' or 'text'.

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=true, destructiveHint=false), so the description does not need to restate them. It adds that the URL must be public and that output is plain text or HTML, but it does not discuss authentication, rate limits, or JavaScript-rendering behavior beyond what is in the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two tightly written sentences plus a documentation link. The core action is front-loaded, and every sentence adds either capability, routing guidance, or reference material without repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does a good job of stating the return content type. The input schema fully covers parameters and annotations cover safety, so the definition is complete enough for correct invocation, though it could say more about JavaScript-rendering expectations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters are already documented in the input schema. The description reinforces the URL and output-format semantics but does not add new meaning for js or wait, making the baseline 3 appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource ("Extract a public URL") and specifies the return content ("plain text or HTML"). It also distinguishes the tool from the sibling web-crawl by explicitly recommending itself for new integrations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It names the alternative web-crawl and gives a clear condition for choosing this tool: preferred for new integrations. It does not state explicit exclusions or when-not-to-use conditions, so it falls short of the highest level but still provides useful routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fetchFetch PageA
Read-only
Inspect

Read a public page as text. Pass a URL returned by search.

NameRequiredDescriptionDefault
idYesURL of the page to read.

Output Schema

NameRequiredDescription
idYes
urlYes
textYes
titleYes
metadataNo

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds that only *public* pages can be read and that output is text, which is genuine extra context, but it says nothing about auth requirements, rate limits, or failure behavior on non-public URLs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short, front-loaded sentences with zero filler. The action and its scope come first, the input sourcing second.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with an output schema, annotations covering safety, and 100% schema coverage, nothing essential is missing. The description supplies the action, scope, and input provenance the agent needs to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With one parameter at 100% schema coverage, the baseline is 3; the description goes slightly beyond the schema by specifying the URL's provenance ('returned by search'), which tells the agent how to source the value rather than just its type.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Read a public page as text'), which is clearly distinguishable from mutation siblings. It does not, however, differentiate itself from likely-overlapping siblings like extract or web-crawl, so it stops short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Pass a URL returned by search' gives a precondition for the input, implying this tool follows a search step. But there is no when-to-use/when-not guidance versus the many search and extraction siblings, leaving the choice largely to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

people-profilesList People FoundA
Read-only
Inspect

Everyone your People Searches found on one platform, one entry per person: their best-scoring result and the search that found them (found_by). Free; it does not run a new search. Search by name, handle, bio, or location with q, filter by contact channels (has), audience, fit score, location, or verification, and sort by score, recent, or audience. People from searches that ended more than 30 days ago are left out.

NameRequiredDescriptionDefault
qNoText in the name, handle, bio, or location, example: 'skincare'.
hasNoChannels every person must have, example: ['email', 'instagram']. 'email' is a public email; the others are a link of that type.
sortNo'score' (API default), 'recent', or 'audience'.
limitNoPeople per page (1-200, default 25).
cursorNonext_cursor from the previous page.
locationNoText in the location, example: 'united states'.
platformYesPlatform: 'x', 'youtube', 'linkedin', or 'tiktok'.
verifiedNoOnly verified accounts. Only X and TikTok people carry a verified flag.
min_scoreNoMinimum fit score (0-100).
max_audienceNoMaximum followers (subscribers on YouTube).
min_audienceNoMinimum followers (subscribers on YouTube).

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only/open-world/non-destructive. The description adds genuinely new behavior: the call is free, it does not trigger a new search, and results expire after 30 days. It also discloses the shape of each entry (best-scoring result plus found_by), which annotations do not.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core semantics and cost/retention facts. The middle sentence is a dense enumeration of filters that largely restates the schema, which slightly dilutes an otherwise tight structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter read tool with no output schema, the description covers return shape, filtering, sorting, and a retention boundary. Pagination behavior (cursor/limit) is left entirely to the schema, which is acceptable but the only remaining gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so baseline is 3. The description paraphrases the filter surface (q, has, sort, location, verification, audience, fit score) but adds no syntax, format, or precedence detail beyond the schema, and omits limit/cursor handling.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb+resource ('List People Found') and immediately scopes it: results from prior People Searches on one platform, one entry per person. It distinguishes itself from the search-running sibling by stating 'it does not run a new search'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly frames when this is used (retrieve existing results) and when it is not ('does not run a new search'), which routes the agent to people-search. The retention caveat ('searches that ended more than 30 days ago are left out') further conditions use, though no sibling is named directly.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

people-search-controlControl People SearchA
DestructiveIdempotent
Inspect

Pause, resume, or cancel a People Search task. Free. pause: a queued search pauses at once; a running one finishes its current batch first (status pausing, then paused). A search paused for more than 7 days is cancelled. resume: continues a paused search where it stopped, with no new charge. cancel: stops the search for good; you pay only for the people it already delivered and the rest of the reservation is returned. People found so far stay readable for 30 days.

NameRequiredDescriptionDefault
actionYes'pause', 'resume', or 'cancel'. cancel cannot be undone.
task_idYestask_id returned by people-search, example: '3f1c2b9e-8d4a-4c1e-9b7a-2e5f6a7b8c9d'

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare destructiveHint=true, idempotentHint=true, and readOnlyHint=false, but the description adds substantial context beyond them: pause timing (queued pauses at once, running finishes its batch, status pausing then paused), a 7-day auto-cancel rule, resume with no new charge, cancel billing/refund semantics, and 30-day result retention. These are exactly the operational traits an agent needs and none are derivable from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and cost ('Pause, resume, or cancel a People Search task. Free.') then dedicates one tight clause group per action. Every sentence carries distinct information about behavior, billing, or retention; nothing is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With only two well-documented parameters, no output schema, and annotations already covering the safety profile, the description supplies the remaining operational detail (timing, billing, retention, irreversibility of cancel). Nothing an agent needs to call this correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes further by explaining the effect of each enum value (what pause/resume/cancel actually do to the task), which meaningfully enriches the bare enum list. It does not add format details for task_id beyond the schema's UUID example, hence not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States specific verbs (pause, resume, cancel) on a specific resource (a People Search task), so the agent knows exactly what the tool does. It is clearly distinct from siblings like people-search-status and people-search-tasks, which read rather than mutate task state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Each action is given a clear behavioral condition (queued vs running, paused-where-it-stopped, stops-for-good), which tells the agent when each applies. However, it never routes the agent against alternatives such as people-search-status or people-search-tasks for read-only inspection, so the guidance stops short of explicit when-not/alternative statements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

people-search-statusGet People Search StatusA
Read-only
Inspect

Status, progress, and cost of one People Search task, plus a page of the people found so far: name, handle, url, platform, audience, location, fit score, why they matched, contacts, and links. Free. People arrive while the search runs: pass the returned next_cursor as cursor on the next call to get only the people found since then. When done is true and has_more is false you have everyone the search found. An ended task has completion_reason (why it stopped), coverage_limited: true when a budget stopped it before count (more people may match), and warnings such as partial_enrichment (some profiles could not be read, so those people were scored on the search hit; they show enrichment: failed). Each person has fully_verified (every criterion confirmed by their own profile or posts) and unverified_criteria (criteria that are unknown or not met, or a disqualifier that applies). These are information only: the person still qualified.

NameRequiredDescriptionDefault
limitNoPeople per page (1-100, default 25).
cursorNonext_cursor from the previous people-search-status call. Omit to start from the first person.
task_idYestask_id returned by people-search, example: '3f1c2b9e-8d4a-4c1e-9b7a-2e5f6a7b8c9d'
include_peopleNoSet false to read only the status, progress, and cost.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, non-destructive, openWorld), and the description adds substantially more: cost ('Free'), the pagination/cursor semantics, what completion_reason means, the coverage_limited warning when a budget truncated results, partial_enrichment with the failed enrichment marker, and the meaning of fully_verified/unverified_criteria (informational only, not disqualifying). That is real behavioral context an agent cannot get from the annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is front-loaded with what the tool returns and efficiently packs cost, pagination, completion, warnings, and per-person fields into one dense paragraph. It is long and unsegmented (no line breaks or bullets), which slightly hurts scannability, but nearly every clause carries information an agent needs to interpret the response.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description bears full responsibility for return-value semantics and it discharges that thoroughly: page contents, per-person fields, pagination lifecycle, completion state, budget-truncation warning, enrichment failure, and verification flags. Nothing material is missing for correct invocation or interpretation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3, but the description adds genuine meaning beyond the schema: it explains the cursor-chaining contract (feed the returned next_cursor back as cursor) and that the page contains people found 'since then', which is not stated in the schema's cursor description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: it returns the status, progress, and cost of ONE People Search task, plus a page of the people found. Scoping to a single task implicitly separates it from people-search-tasks (list) and people-search (start), and the cursor-based polling contract further distinguishes it from any sibling that only kicks off or cancels a search.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear operating context: 'Free', call it while the search runs, pass the returned next_cursor as cursor to get only newly found people, and the termination condition (done true + has_more false). It stops short of naming an alternative tool or an exclusion (e.g., when to prefer people-search-control for canceling), so it is clear context without explicit routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

people-search-tasksList People Search TasksA
Read-only
Inspect

Your People Search tasks, newest first, with status, counts, cost, why each ended search stopped (completion_reason, coverage_limited), and the metadata labels set on people-search. Free. Use it to find a task_id (filter by metadata to find the searches of one campaign), or to see which searches are still queued, running, or paused: a new search is refused while too many are active.

NameRequiredDescriptionDefault
limitNoTasks per page (1-100, API default 20).
cursorNonext_cursor from the previous page. Keep the same metadata filter when you page.
statusNoOnly tasks in these statuses, example: ['running', 'paused'].
metadataNoOnly tasks whose metadata has all of these key/value pairs (exact match, up to 3), example: {"campaign": "q4-outbound"}.
platformNoOnly tasks on this platform: 'x', 'youtube', 'linkedin', or 'tiktok'.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, non-destructive, open-world. The description adds context annotations cannot carry: the call is free, results are newest-first, and terminal searches expose a stop reason (completion_reason, coverage_limited). It does not discuss pagination limits or rate behavior beyond the free note, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads identity and ordering before the return-field list and the usage sentence; every clause carries information. The dense parenthetical field enumeration is justified because there is no output schema, though it makes the sentence long.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description steps in to name the returned fields (status, counts, cost, completion_reason, coverage_limited, metadata labels), and the schema fully covers the five filters and pagination. Coverage is strong; only the exact shape of counts/cost is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description goes further by explaining the intent behind the metadata filter — using it to isolate one campaign's searches — which is more than the schema's mechanical 'exact match, up to 3' wording. It does not touch limit, cursor, or platform.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('People Search tasks'), scoped to the caller ('Your') and ordered ('newest first'), and enumerates what each task carries. It is clearly distinguishable from siblings like people-search-status or people-search-control.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives two concrete use cases: retrieving a task_id (with the metadata-filter trick for one campaign's searches) and inspecting queued/running/paused work. It also explains why that second case matters — new searches are refused while too many are active. No explicit alternatives or when-not-to-use, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

web-crawlCrawl Web Page (Legacy)A
Read-only
Inspect

Crawl a public URL and return its content as plain text or HTML on the legacy Desearch /web/crawl route. The SDK marks webCrawl deprecated in favor of extract; this tool stays for parity with that route. Prefer extract for new integrations. API docs: https://www.desearch.ai/docs/guide/apis/extract-api

NameRequiredDescriptionDefault
jsNoRender JavaScript before reading the page.
urlYesPublic URL to read, example: 'https://desearch.ai'
waitNoPost-load wait in milliseconds when JavaScript rendering is enabled.
formatNoContent format to return: 'html' or 'text'.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds useful legacy-route and deprecation context beyond annotations, but does not detail runtime behaviors like rate limits or JS-rendering caveats that a crawl tool might have.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and legacy context, then deprecation guidance, then the docs link. It is slightly redundant between the deprecation sentence and the 'Prefer extract' sentence, but every sentence closely relates to correct tool selection.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a fully documented schema, safety annotations, and no output schema, the description supplies the key missing context: deprecation status and the preferred alternative. It is nearly complete, lacking only optional operational caveats for a legacy web-crawling route.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents url, js, wait, and format with examples and enums. The description only mentions the return format generally, adding no parameter-level meaning beyond what the schema provides. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb (Crawl), resource (public URL), and output (plain text or HTML) and explicitly names the sibling alternative (extract). An agent can distinguish this legacy tool from extract and other search/fetch tools without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says the SDK marks webCrawl deprecated in favor of extract and advises 'Prefer extract for new integrations,' while noting this tool exists for legacy route parity. This gives clear when-to-use and when-not-to-use guidance with a named alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-post-by-idGet X Post by IDB
Read-only
Inspect

Fetch a single X (Twitter) post by its ID.

NameRequiredDescriptionDefault
idYesThe unique ID of the post, example: '1234567890'

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds nothing beyond that: no auth requirements, no rate-limit note, no behavior for missing/invalid IDs or protected posts.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One front-loaded sentence with zero filler; the resource and lookup key come first. Nothing is wasted and nothing is buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read tool with no output schema and full annotation coverage, the definition is essentially sufficient to invoke correctly. It could go further on error/missing-post behavior, but nothing essential is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single 'id' parameter is documented with an example in the schema itself. The description adds no format or constraint detail beyond what the schema already provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch a single X post') plus the lookup key ('by its ID'), which implicitly separates it from x-posts-by-urls and x-posts-by-user. It never names a sibling or explicit boundary, so it falls short of the 5 tier.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance at all. With a crowded sibling set (x-posts-by-urls, x-posts-by-user, x-search, x-post-replies), the description should say when ID lookup is preferable, but it leaves the agent to infer everything.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-post-repliesGet X Post RepliesB
Read-only
Inspect

Fetch replies to an X (Twitter) post, with an optional keyword query.

NameRequiredDescriptionDefault
countNoNumber of posts to retrieve (1-100).
queryNoAdvanced search query to filter replies.
post_idYesThe ID of the post to fetch replies for.

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety and reach profile is covered. The description adds essentially nothing beyond that: no pagination behavior, no ordering, no rate-limit or result-cap context, and no note that count caps at 100.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler. The core action leads and the optional modifier trails it. Nothing can be trimmed without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with no output schema and full schema coverage, the description is barely sufficient. It leaves open the practical questions an agent faces: how many replies come back by default, whether results are paginated or ordered, and how the keyword query interacts with the fetched set.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents post_id, count (1-100), and the advanced query string. The description only restates the query parameter and adds no format, syntax, or default value detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Fetch replies to an X (Twitter) post.' That is unambiguous on its own. However, it does not distinguish this tool from close siblings such as x-user-replies (replies authored by a user) or x-search, so an agent must infer the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance, no prerequisites, and no mention of alternatives. The phrase 'with an optional keyword query' hints at filtering but never says when keyword filtering is preferable to a plain fetch or to using x-search for reply discovery.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-post-retweetersList X Post RetweetersA
Read-only
Inspect

List users who retweeted an X (Twitter) post. Pass cursor to page through more users.

NameRequiredDescriptionDefault
idYesThe ID of the post to get retweeters for.
cursorNoCursor for pagination from a previous response.

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds the pagination/cursor behavior, but says nothing about auth requirements, rate limits, or result completeness for a public X endpoint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, zero filler, and the core action is front-loaded ahead of the paging hint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

A simple two-parameter read tool; annotations carry the safety profile and the schema documents both params. There is no output schema, so the return shape is not explained, but nothing essential for a correct call is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters are fully documented in the schema, so the baseline is 3. The description restates cursor's purpose (paging) without adding syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'List users who retweeted an X (Twitter) post.' The resource is precise enough to separate it from siblings like x-post-replies or x-posts-by-user, though no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Pass cursor to page through more users' gives operational guidance for the pagination parameter, but there is no statement of when to use this tool versus the other X-post tools (e.g., replies, by-id). Usage is implied by the resource name rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-posts-by-urlsGet X Posts by URLsB
Read-only
Inspect

Fetch full X (Twitter) posts for a list of post URLs.

NameRequiredDescriptionDefault
urlsYesPost URLs to fetch, example: ['https://x.com/user/status/123']

TDQS

B3.1/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds essentially nothing beyond that — no batch size limits, rate-limit notes, behavior on invalid or deleted URLs, or partial-failure handling, which matter for a batch fetch against an open-world source.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the verb and resource come first. Nothing in the sentence is redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple one-parameter read tool with full schema coverage and safety annotations, the description is minimally sufficient. It is missing the operational context that would make a batch external fetch fully usable, such as batch limits or per-URL failure behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is only one parameter, so the schema carries the semantics (array of URL strings, minItems 1, with an example). The description only restates 'a list of post URLs' without adding format constraints or limits, so baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a clear verb ('Fetch') and resource ('full X (Twitter) posts') scoped to a list of post URLs, which is specific enough to understand the operation. However, it does not distinguish itself from the closely related sibling x-post-by-id, which an agent might reasonably choose for the same intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this bulk-by-URL tool versus x-post-by-id, x-user-posts, or x-search. The description also omits any prerequisites or conditions such as URL validity requirements or what happens with mixed/broken URLs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-posts-by-userSearch X Posts by UserB
Read-only
Inspect

Search X (Twitter) posts by a specific user, with an optional keyword query.

NameRequiredDescriptionDefault
userYesUser to search for, example: 'elonmusk'
countNoNumber of posts to retrieve (1-100).
queryNoAdvanced search query to filter this user's posts.

TDQS

B3.2/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered. The description adds nothing behavioral beyond that — no mention of rate limits, pagination, result ordering, or what an empty result means — making it essentially redundant with the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single tight sentence with no filler, and the core action is front-loaded. It is arguably too terse for a tool with a confusable sibling, but there is no wasted language.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 3-parameter read tool with full schema coverage and annotations, the description is minimally sufficient to call the tool correctly. It falls short on sibling disambiguation (x-user-posts) and any behavioral context about result volume or ordering.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters (user, count, query) are documented in the schema itself. The description restates the optional keyword query but adds no syntax, format, or default details beyond the schema, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (search X posts) scoped to a user, plus an optional keyword filter. It is clear what the tool does, but it offers no differentiation from the very similar sibling x-user-posts, which an agent could easily confuse it with.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'with an optional keyword query' implies one usage pattern (keyword-filtered user timelines), but there is no explicit when-to-use guidance, no prerequisites, and no naming of alternatives such as x-search or x-user-posts.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-user-postsGet X User TimelineC
Read-only
Inspect

Retrieve a user's X (Twitter) timeline posts by username. Pass cursor to page through more posts.

NameRequiredDescriptionDefault
cursorNoCursor for pagination from a previous response.
usernameYesUsername to fetch posts for, example: 'elonmusk'

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false, so the safety profile is covered without the description. The description adds nothing beyond that — no notes on rate limits, auth requirements, result ordering, or timeline scope (e.g., replies/retweets included) — so its behavioral contribution is minimal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the core action and free of filler. The second sentence is somewhat redundant with the schema's cursor description, so it doesn't fully earn its place, but overall sizing is appropriate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter read tool with full schema coverage and a complete read-only annotation set, the description is adequate. It omits what the returned post objects contain (no output schema exists) and, more importantly, how this differs from the sibling x-posts-by-user.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (username, cursor) are already documented in the schema, giving a baseline of 3. The description's cursor note restates pagination behavior rather than adding format or semantics beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Retrieve a user's X (Twitter) timeline posts by username'), which is clearer than a bare name restatement. However, it offers no differentiation from the near-identical sibling x-posts-by-user (or x-search/x-user-replies), leaving the agent unable to tell which to pick without opening schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use or when-not-to-use guidance and no named alternative. The only operational note, 'Pass cursor to page through more posts,' is parameter mechanics rather than selection guidance, so the agent gets no help choosing between this and x-posts-by-user.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x-user-repliesGet X User RepliesB
Read-only
Inspect

Fetch posts and replies by an X (Twitter) user, with an optional keyword query.

NameRequiredDescriptionDefault
userYesUsername of the user to search for, example: 'elonmusk'
countNoNumber of posts to retrieve (1-100).
queryNoAdvanced search query to filter this user's posts and replies.

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds the useful behavioral detail that both posts and replies are returned, but says nothing about pagination, rate limits, or result ordering.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the primary action and the optional qualifier are both stated immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only, 3-parameter tool with no output schema this is minimally adequate, but it leaves the overlap with x-user-posts and x-post-replies unresolved and gives no hint about result volume or pagination behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented. The description only restates the optional keyword query, adding no format, syntax, or default semantics beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Fetch) and resource (posts and replies by an X user), so the agent knows the operation. However, it does not differentiate itself from close siblings like x-user-posts, x-post-replies, or x-search, and the phrase 'posts and replies' blurs the boundary with x-user-posts.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance is given. The mention of an 'optional keyword query' implies a filtered-search use case, but the description never says when to prefer this tool over x-user-posts, x-post-replies, or x-search.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv0.3.3
    • Addedfetch
    • Addedpeople-profiles
    • Addedpeople-search
    • Addedpeople-search-control
    • Addedpeople-search-status
    • Addedpeople-search-tasks
    • Addedsearch
    • Changedx-search9 fields changed
      • removedInput schema / properties / min_likes / $ref
        Removed value: -"#/properties/min_retweets"
      • addedInput schema / properties / min_likes / minimum
        Added value: +0
      • addedInput schema / properties / min_likes / type
        Added value: +"integer"
      • removedInput schema / properties / min_replies / $ref
        Removed value: -"#/properties/min_retweets"
      • addedInput schema / properties / min_replies / minimum
        Added value: +0
      • addedInput schema / properties / min_replies / type
        Added value: +"integer"
      • removedInput schema / properties / min_retweets / anyOf
        Removed value: -[
        -  {
        -    "minimum": 0,
        -    "type": "integer"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]
      • addedInput schema / properties / min_retweets / minimum
        Added value: +0
      • addedInput schema / properties / min_retweets / type
        Added value: +"integer"
  2. 1 tool updatev0.1.4
    • Changedai-search2 fields changed
      • changedInput schema / properties / tools / description
        Previous value: -"Source ids sent to POST /desearch/ai/search. Use short ids such as 'web' and 'twitter'. Legacy labels such as 'Web Search' are accepted and rewritten to those ids. Example: ['web', 'twitter']."New value: +"Source ids sent to POST /desearch/ai/search. Short ids: 'web', 'twitter', 'arxiv', 'wikipedia', 'hackernews', 'reddit'. Legacy labels such as 'Web Search', 'ArXiv Search', 'Wikipedia Search', 'Hacker News Search', and 'Reddit Search' are rewritten to those ids. Example: ['web', 'twitter']."
      • changedInput schema / properties / tools / items / enum
        Previous value: -[
        -  "web",
        -  "twitter",
        -  "arxiv",
        -  "wikipedia",
        -  "youtube",
        -  "hackernews",
        -  "reddit"
        -]New value: +[
        +  "web",
        +  "twitter",
        +  "arxiv",
        +  "wikipedia",
        +  "hackernews",
        +  "reddit"
        +]
  3. 1 tool updatev0.1.3
    • Changedai-search1 field changed
      • changedInput schema / properties / model / description
        Previous value: -"Model to use for the search, example: 'NOVA', Nova is 10s model, Orbit is 30s model"New value: +"Model to use for the search: NOVA (default) or ORBIT."
  4. 15 tool updatesv0.1.2
    • First observedai-search
    • First observedextract
    • First observedweb-crawl
    • First observedweb-links-search
    • First observedweb-search
    • First observedx-links-search
    • First observedx-post-by-id
    • First observedx-post-replies
    • First observedx-post-retweeters
    • First observedx-posts-by-urls
    • First observedx-posts-by-user
    • First observedx-search
    • First observedx-trends
    • First observedx-user-posts
    • First observedx-user-replies

TDQS

B3.1/5.0

Scored across 22 tools

Disambiguation2/5

The set contains many overlapping search and fetch tools: search, web-search, web-links-search, ai-search, x-search, x-links-search, fetch, extract, and web-crawl. Descriptions distinguish some cases, but an agent can easily choose the wrong web-search or page-reading tool.

Naming Consistency3/5

All names use kebab-case, which is good, but the patterns are mixed: x-post-by-id, x-posts-by-urls, x-user-posts, web-search, and bare search/fetch/extract do not follow one consistent prefix or verb_noun convention. Readable but not predictable.

Tool Count3/5

22 tools is heavy for this scope, largely because multiple search and extraction variants duplicate coverage. The People Search job lifecycle tools are justified, but the overall count feels over-expanded.

Completeness4/5

Coverage is broad across web search, X/Twitter posts, extraction, and the People Search lifecycle including status, control, tasks, and profiles. Minor gaps remain, such as no direct X user-profile lookup, but core workflows are covered.

Maintenance

ActivityActive
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables searching X (formerly Twitter) using xAI's Responses API with support for filtering by handles, date ranges, and media understanding, returning structured results with citations.
    1
    3 npm
    1
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables real-time search of X.com (Twitter) posts, users, threads, and trends via xAI's Grok API, directly from Claude.
    5
    47 PyPI
    3
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables real-time search of X (Twitter) posts, user timelines, and trends using either xAI's Responses API or the official X API v2.
    4
    -