# ai.spideriq/leads (npm · @spideriq/mcp-leads)

SpiderIQ Leads: lead-gen MCP (jobs, campaigns, IDAP, Maps, People, Verify, company intel, spiderPR)

- Trust score: 60/100 (medium)
- Change this week: +41
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `@spideriq/mcp-leads`: 60/100 (this document), [markdown](https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads.md), [page](https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads)

## Channel facts

- Registry: `npm`
- Package: `@spideriq/mcp-leads`
- Version: `1.9.0`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 87/100
  - No malware found by supply-chain analysis.
  - Only part of the dependency tree could be resolved (100 of 104), so this covers what we could see, not the whole tree.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (100 of 104), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 19/100
  - Repository check failed: the declared repository URL returned HTTP 404.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 7 days ago).
  - Security-disclosure policy not yet verified: we couldn't inspect the source repository.
- **Schema Quality & AI Usability**: 57/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 9196 tokens (~180/item across 51 items; 51 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 99/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 98% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add ai-spideriq-leads -- npx -y @spideriq/mcp-leads
```

### Codex

```bash
codex mcp add ai-spideriq-leads -- npx -y @spideriq/mcp-leads
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ai-spideriq-leads": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "@spideriq/mcp-leads"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ai-spideriq-leads --command npx --arg -y --arg @spideriq/mcp-leads
```

### Hermes

```yaml
mcp_servers:
  ai-spideriq-leads:
    command: "npx"
    args: ["-y", "@spideriq/mcp-leads"]
```

### Other

```json
{
  "mcpServers": {
    "ai-spideriq-leads": {
      "command": "npx",
      "args": [
        "-y",
        "@spideriq/mcp-leads"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-02 (score 60, +47)

- [security regression] Provenance: unverified → fail
- [security improvement] Install scripts: unverified → pass
- [security improvement] Known CVEs: unverified → partial
- [security improvement] Malware scan: unverified → pass
- [functional regression] Tool coverage: 100 → unverified
- [functional improvement] License: unverified → pass
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Stability: unverified → 0.23
- [functional improvement] Schema quality: unverified → good
- [functional improvement] Dependency health: unverified → partial
- [functional] Licence: MIT

### 2026-08-01 (score 13, +13)

- [functional improvement] Tool coverage: unverified → 100

### 2026-07-31 (score 0, −19)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-27 (score 19)

First indexed and scored.

## MCP tools (51)

### `request_access` (~157 tokens)

Request access to SpiderIQ API. This sends an approval email to the admin.
After calling this, use check_access_status to poll for approval.
Once approved, the token is automatically saved for subsequent API calls.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `email` (string, required): Admin email address (the person who will approve access)
- `project` (string): Project name (shown in approval email)
- `recover_as` (string): Recover an existing agent by its OPVS address (username). Only takes effect when NO PAT is stored — a held PAT always rotates the SAME account.
- `scopes` (array): Requested permission scopes (default: jobs:submit, jobs:read)

### `check_access_status` (~152 tokens)

Check the status of a PAT access request.
Returns 'pending', 'active', 'denied', 'expired', or 'revoked' (matches the
backend PATRequestStatus enum). Once status==='active', the token is saved to
\~/.spideriq/credentials.json automatically. Multi-brand approvals save one
entry per workspace under client_id, with the first aliased as 'default' so
existing tools (upload_local_file, etc.) keep working without --workspace.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `poll_token` (string, required): Poll token from request_access
- `request_id` (string, required): Request ID from request_access

### `get_auth_status` (~33 tokens)

Check if you are authenticated and get current user info.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `logout` (~25 tokens)

Remove stored authentication credentials.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `list_workspaces` (~19 tokens)

List all configured workspaces and their authentication status.

### `health_check` (~51 tokens)

Check if the SpiderIQ API is healthy and responsive.

Input parameters:

- `api_url` (string): API URL (default: https://spideriq.ai)
- `workspace` (string): Workspace name (default: default)

### `get_queue_stats` (~48 tokens)

Get statistics about job queues (pending jobs, consumers, etc.).

Input parameters:

- `format` (string): Response format (default: json)
- `workspace` (string): Workspace name (default: default)

### `get_api_info` (~33 tokens)

Get information about the SpiderIQ API and your connection.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `submit_job` (~254 tokens)

Submit a new scraping job to SpiderIQ.

Available job types:
\- spiderSite: Scrape website content and extract contact info
\- spiderMaps: Search Google Maps for businesses
\- spiderMapsEnrich: Enrich Google Maps place with details
\- spiderVerify: Verify email addresses
\- spiderPeople: Find people information
\- spiderPhone: Extract phone-related data
\- spiderFacebookPage: Scrape Facebook pages
\- spiderPublicInstagram: Scrape public Instagram profiles
\- spiderPublicLinkedin: Scrape public LinkedIn profiles
\- spiderLanding: Capture landing page screenshots
\- spiderVideo: Generate video content
\- spiderMail: Send emails
\- spiderCompanyData: Research company information
\- spiderVayapin: VayaPin export
\- spiderSocial: Social Media Enrichment — recover a missing email/phone/website/socials for one business from its social handles

Each job type requires different payload fields. See API documentation for details.

Input parameters:

- `format` (string): Response format (default: json)
- `payload` (object, required): Job payload (varies by job type)
- `type` (string, required): Job type to submit
- `workspace` (string): Workspace name (default: default)

### `get_job_status` (~55 tokens)

Get the current status of a job.

Input parameters:

- `format` (string): Response format (default: json)
- `job_id` (string, required): Job ID to check
- `workspace` (string): Workspace name (default: default)

### `get_job_results` (~57 tokens)

Get the results of a completed job.

Input parameters:

- `format` (string): Response format (default: json)
- `job_id` (string, required): Job ID to get results for
- `workspace` (string): Workspace name (default: default)

### `list_jobs` (~93 tokens)

List your submitted jobs with optional filtering.

Input parameters:

- `format` (string): Response format (default: json)
- `page` (number): Page number (default: 1)
- `per_page` (number): Results per page (default: 20)
- `status` (string): Filter by status
- `type` (string): Filter by job type
- `workspace` (string): Workspace name (default: default)

### `cancel_job` (~40 tokens)

Cancel a pending or queued job.

Input parameters:

- `job_id` (string, required): Job ID to cancel
- `workspace` (string): Workspace name (default: default)

### `scrape_website` (~128 tokens)

Scrape a website to extract contact information, social links, and content.
This is a convenience wrapper for submit_job with type=spiderSite.

Input parameters:

- `extract_emails` (boolean): Extract email addresses (default: true)
- `extract_phones` (boolean): Extract phone numbers (default: true)
- `extract_social` (boolean): Extract social media links (default: true)
- `max_pages` (number): Maximum pages to crawl (default: 10)
- `url` (string, required): Website URL to scrape
- `workspace` (string): Workspace name (default: default)

### `search_google_maps` (~79 tokens)

Search Google Maps for businesses.
This is a convenience wrapper for submit_job with type=spiderMaps.

Input parameters:

- `max_results` (number): Maximum results to return (default: 20)
- `search_query` (string, required): Search query (e.g., "restaurants in New York")
- `workspace` (string): Workspace name (default: default)

### `verify_emails` (~57 tokens)

Verify email addresses for deliverability.
This is a convenience wrapper for submit_job with type=spiderVerify.

Input parameters:

- `emails` (array, required): List of email addresses to verify
- `workspace` (string): Workspace name (default: default)

### `create_video` (~234 tokens)

Stitch AI-generated video scenes into a final video with transitions and music.
Supports portrait (9:16) and landscape (16:9), fade transitions, background music, and SpiderMedia upload.
This is a convenience wrapper for submit_job with type=spiderVideo.

Input parameters:

- `aspect_ratio` (string): Aspect ratio (default: 9:16 portrait)
- `music_url` (string): Background music URL (mp3, wav)
- `music_volume` (number): Music volume 0-1 (default: 0.3)
- `preprocess` (boolean): Auto-fix invalid formats with FFmpeg (default: false)
- `project_name` (string, required): Output filename without extension
- `scenes` (array, required): Video scenes to stitch (1-50)
- `test` (boolean): Route to test queue (default: false)
- `transition_frames` (number): Fade transition in frames (default: 15 = 0.5s at 30fps)
- `upload` (boolean): Upload result to SpiderMedia (default: false)
- `workspace` (string): Workspace name (default: default)

### `search_people` (~314 tokens)

Search for people on LinkedIn — profile lookup, search, research, or company employee extraction.

Modes:
\- profile: Get a single LinkedIn profile by URL
\- search: Search people by natural language query (e.g., "CTO fintech Israel")
\- research: Deep research on a LinkedIn profile
\- company: Extract employees from a LinkedIn company page

This is a convenience wrapper for submit_job with type=spiderPeople.

Input parameters:

- `company_url` (string): LinkedIn company URL (required for company mode)
- `icp_description` (string): Ideal Customer Profile for lead scoring
- `linkedin_url` (string): LinkedIn profile URL (required for profile/research modes)
- `max_employees` (number): Max employees to extract 1-2000 (default: 100)
- `mode` (string, required): Operation mode
- `person_name` (string): Person name (optional, extracted from LinkedIn if not provided)
- `product_description` (string): Your product description for lead scoring
- `profile_mode` (string): Employee detail level: short ($4/1K), full ($8/1K), full_email ($12/1K)
- `search_limit` (number): Max profiles in search 1-50 (default: 10)
- `search_query` (string): Natural language search query (required for search mode)
- `test` (boolean): Route to test queue (default: false)
- `workspace` (string): Workspace name (default: default)

### `capture_landing_page` (~223 tokens)

Capture a landing page — screenshots, HTML bundle, and AI-extracted marketing content.
Useful for competitive analysis, ad tracking, and archiving landing pages.
This is a convenience wrapper for submit_job with type=spiderLanding.

Input parameters:

- `ad_id` (string): Facebook Ad ID for correlation with ad library data
- `capture_full_page` (boolean): Capture full-page screenshot (default: true)
- `capture_html_bundle` (boolean): Download self-contained HTML (default: true)
- `capture_screenshot` (boolean): Capture above-fold screenshot (default: true)
- `dismiss_popups` (boolean): Dismiss cookie/popup banners via AI (default: true)
- `extract_content` (boolean): AI-extract marketing content (default: true)
- `test` (boolean): Route to test queue (default: false)
- `timeout_seconds` (number): Max capture time 10-300 seconds (default: 60)
- `url` (string, required): Landing page URL to capture
- `workspace` (string): Workspace name (default: default)

### `get_company_data` (~296 tokens)

Look up company data from public registries (US SEC EDGAR, UK Companies House, EU VIES VAT).

Modes:
\- search: Search by company name (e.g., "Apple Inc" in US)
\- lookup: Look up by registry ID (e.g., CIK "0000320193" in US)
\- vat: Validate EU VAT number (e.g., "GB123456789")

This is a convenience wrapper for submit_job with type=spiderCompanyData.

Input parameters:

- `country` (string): Country code ISO 3166-1 alpha-2 (US, GB, EU, etc.)
- `financials_mode` (string): Financials extraction method (UK only, default: auto)
- `identifier` (string): Registry-specific company ID — CIK (US), Company Number (UK)
- `include_financials` (boolean): Extract financial data from filings (UK only)
- `limit` (number): Max results 1-100 (default: 10, search mode only)
- `mode` (string): Operation mode (default: search)
- `name` (string): Company name to search for (required for search mode)
- `test` (boolean): Route to test queue (default: false)
- `vat_number` (string): EU VAT number with country prefix (e.g., "GB123456789")
- `workspace` (string): Workspace name (default: default)

### `submit_vayapin` (~322 tokens)

Create a VayaPin business profile from enriched data.
Requires business basics (name, country, coordinates) and website content (markdown URL or direct content).
This is a convenience wrapper for submit_job with type=spiderVayapin.

Input parameters:

- `business_address` (string): Full business address
- `business_name` (string, required): Business name for the VayaPin profile
- `business_phone` (string): Business phone number
- `country_code` (string, required): 2-letter ISO country code (e.g., "DK", "US", "DE")
- `domain` (string): Website domain (e.g., "example.com")
- `emails_verified` (array): Verified emails from SpiderVerify [{email, status, source}]
- `facebook` (string): Facebook page URL
- `gmaps_link` (string): Google Maps URL
- `instagram` (string): Instagram profile URL
- `latitude` (number, required): Latitude from Google Maps
- `linkedin` (string): LinkedIn page URL
- `logo` (string): Logo image URL
- `longitude` (number, required): Longitude from Google Maps
- `markdown_compendium` (string): Direct markdown content (alternative to markdown_url)
- `markdown_url` (string): URL to crawled website markdown file (from SpiderSite/SpiderMedia)
- `original_website` (string): Original website URL
- `test` (boolean): Route to test queue (default: false)
- `twitter` (string): Twitter/X profile URL
- `workspace` (string): Workspace name (default: default)

### `submit_social_enrichment` (~521 tokens)

Recover a missing email / phone / real website / social links for ONE business from its public social handles (Social Media Enrichment).

Given the business's known social handles (Facebook preferred, then Instagram) and optionally a single social-only website (linktr.ee / facebook / instagram URL), the job recovers whatever contact info it can and folds it in additively (never overwrites what you passed). If the business already has a usable email, the job self-skips (`has_email`) — recovery is only spent where it's needed.

Requires the account's **Social Media Enrichment** plan to be enabled (entitlement-gated). Provide at least one social handle or a social-only website, or the job self-skips (`no_social_handle`).

This is a convenience wrapper for submit_job with type=spiderSocial. Poll get_job_results for the recovered {email, phone, website, socials} — or the typed skip reason.

Input parameters:

- `business_name` (string): Business name (context only).
- `campaign_id` (string): Campaign context — scopes the per-campaign usage cap. Usually omitted for standalone submissions.
- `country_code` (string): ISO-2 country code, e.g. "US", "DE" (context only).
- `email` (string): An email already known for the business. If present, the job self-skips (has_email).
- `facebook` (string): Facebook page URL or handle (preferred source).
- `format` (string): Response format (default: json).
- `instagram` (string): Instagram profile URL or handle.
- `linkedin` (string): LinkedIn page URL or handle.
- `phone` (string): A phone already known for the business (folded, never overwritten).
- `place_id` (string): Stable business identifier (Google place_id). Used as the exactly-once recovery key.
- `social_media` (object): Alternative to the individual handle fields: a map of {platform: url|handle}, e.g. {"facebook": "https://facebook.com/acme", "instagram": "acme"}. Merged with any individual handle fields above.
- `test` (boolean): Route to the test queue (default: false).
- `tiktok` (string): TikTok profile URL or handle.
- `twitter` (string): Twitter/X profile URL or handle.
- `website` (string): A single social-only website (linktr.ee / facebook / instagram URL), if known.
- `workspace` (string): Workspace name (default: default).

### `pr_submit` (~324 tokens)

Submit a press release to the wire for distribution (SpiderPR).

You author the release (title + body, plus optional summary/category/tags/contact); the job is dispatched to the SpiderPR wire worker, which renders it to wire-ready HTML, submits it to the provider, and polls until it is published. This is a convenience wrapper for submit_job with type=spiderPR.

Poll get_job_results (or pr_get_result) for the {provider_order_id, status, published_url, wire_report_url}. Status flows queued → submitted → published (or failed).

Input parameters:

- `body` (string, required): Full body of the release, plain text or HTML (required, max 50000 chars).
- `category` (string): Release category/topic (e.g. 'Technology', 'Finance').
- `contact` (object): Media/press contact carried on the release (all fields optional).
- `format` (string): Response format (default: json).
- `priority` (number): Job priority 0 (lowest) to 10 (highest). Default 5.
- `scheduled_release_at` (string): Requested wire release time (ISO 8601). Omit for ASAP.
- `summary` (string): Short summary / subheadline of the release.
- `tags` (array): Keyword tags for the release (max 25).
- `test` (boolean): Route to the test queue (default: false).
- `title` (string, required): Headline of the press release (required, max 300 chars).
- `workspace` (string): Workspace name (default: default).

### `pr_get_result` (~93 tokens)

Get the SpiderPR wire-distribution result for a job — provider order id, distribution status (queued|submitted|published|failed), published URL, and wire report URL. Convenience wrapper for get_job_results.

Input parameters:

- `format` (string): Response format (default: json).
- `job_id` (string, required): SpiderPR job ID to get results for.
- `workspace` (string): Workspace name (default: default).

### `create_campaign` (~578 tokens)

Create a new multi-location scraping campaign.

Campaigns orchestrate Google Maps searches across multiple locations with optional website scraping and email verification. The backend automatically selects the appropriate WindMill workflow:

\- Maps + Site + Verify: Full pipeline (default)
\- Maps + Site: Skip email verification
\- Maps only: Quick business search without site scraping

Provide a search query, country code, and optionally a workflow config to control which steps run.

SMARTLEAD EXPORT (push leads to an outreach campaign automatically): set workflow.smartlead = { enabled: true, connection_id, remote_campaign_id }. When enabled, the campaign's VERIFIED leads are pushed into that SmartLead campaign automatically when the run finishes (no separate push step). You MUST discover the two ids first: call list_outreach_connections (→ connection_id) then list_outreach_campaigns(connection_id) (→ remote_campaign_id). Those two tools live in the SpiderMail slice / kitchen-sink @spideriq/mcp. field_map is optional (backend defaults already map location + VayaPin pin_name). Only leads with a verified email are exported; set only_with_vayapin_seo:true to restrict to businesses that got a VayaPin SEO pin.

SCOPING US ZIP CAMPAIGNS ("state = country"): the US is too large to scrape whole. To run a US ZIP campaign, scope it to ONE STATE: set filter = { mode: "regions", admin_regions: ["Texas"], include_postcodes: true }. Discover valid state names with list_regions(country_code="US") (or list_countries, which lists the 50 states as country-equivalent units). One state runs every ZIP in it as its own Maps search — list_regions returns each state's postcode_count so you can size it first. Scoping a postcode (ZIP) run to all of the US — or omitting the state — is rejected by the API (422, >10K location cap). Pick exactly one state per campaign.

Input parameters:

- `country_code` (string, required): 2-letter ISO country code (e.g., "US", "DE", "IL")
- `filter` (object): Location filter configuration. For a US ZIP campaign, scope to ONE state: { mode: "regions", admin_regions: ["Texas"], include_postcodes: true }.
- `max_results` (number): Max results per location (1-500, default: 100)
- `name` (string): Campaign name (auto-generated if not provided)
- `search_query` (string, required): What to search for (e.g., "restaurants", "dentists", "plumbers")
- `test` (boolean): Route to test queue (default: false)
- `workflow` (object): Workflow configuration to control which pipeline steps run
- `workspace` (string): Workspace name (default: default)

### `list_campaigns` (~100 tokens)

List your campaigns with optional status filtering.

Input parameters:

- `country_code` (string): Filter by country code
- `format` (string): Response format (default: json)
- `page` (number): Page number (default: 1)
- `page_size` (number): Results per page (1-100, default: 20)
- `status` (string): Filter by campaign status
- `workspace` (string): Workspace name (default: default)

### `get_campaign_status` (~95 tokens)

Get detailed status and progress of a campaign.

Returns:
\- Campaign configuration (query, country, workflow settings)
\- Progress: completed/failed/pending locations and percentage
\- Total businesses found
\- Which WindMill workflow is being used

Input parameters:

- `campaign_id` (string, required): Campaign ID to check
- `format` (string): Response format (default: json)
- `workspace` (string): Workspace name (default: default)

### `stop_campaign` (~46 tokens)

Stop an active campaign. Can be resumed later with continue_campaign.

Input parameters:

- `campaign_id` (string, required): Campaign ID to stop
- `workspace` (string): Workspace name (default: default)

### `continue_campaign` (~40 tokens)

Resume a stopped or paused campaign.

Input parameters:

- `campaign_id` (string, required): Campaign ID to resume
- `workspace` (string): Workspace name (default: default)

### `update_campaign` (~123 tokens)

Update a campaign's configuration. Workflow config changes are merged with existing settings.

Use this to change the search query, max results, or toggle workflow steps (site scraping, email verification) on an active campaign.

Input parameters:

- `campaign_id` (string, required): Campaign ID to update
- `max_results` (number): New max results per location
- `name` (string): New campaign name
- `search_query` (string): New search query
- `workflow` (object): Updated workflow configuration (merged with existing)
- `workspace` (string): Workspace name (default: default)

### `retry_campaign_location` (~157 tokens)

Retry one location in a campaign (re-dispatches worker jobs).

Use the location's `id` from list_campaign_jobs (campaign_locations.id), NOT the job_id.

\- retry_mode "full": re-run the whole workflow from SpiderMaps
\- retry_mode "site": keep Maps results, re-run SpiderSite + SpiderVerify
\- retry_mode "verify": keep Site results, re-run SpiderVerify only

Max 3 retries per location.

Input parameters:

- `campaign_id` (string, required): Campaign ID
- `location_id` (number, required): campaign_locations.id (the `id` from list_campaign_jobs)
- `retry_mode` (string): Retry depth (default: full)
- `workspace` (string): Workspace name (default: default)

### `retry_failed_locations` (~98 tokens)

Retry every failed location in a campaign (up to max_locations, default 10).

Locations that already hit the 3-retry cap are skipped, not errored. Useful after a campaign finishes with some failed locations.

Input parameters:

- `campaign_id` (string, required): Campaign ID
- `max_locations` (number): Max locations to retry, 1-50 (default: 10)
- `workspace` (string): Workspace name (default: default)

### `delete_campaign` (~82 tokens)

Delete a campaign and all of its data. Irreversible.

The campaign must be STOPPED first — this fails with a 409 if it still has active jobs. Call stop_campaign, wait for in-flight jobs to settle, then delete.

Input parameters:

- `campaign_id` (string, required): Campaign ID to delete
- `workspace` (string): Workspace name (default: default)

### `list_countries` (~88 tokens)

List available countries (with location counts) you can target with a campaign. To target the US by ZIP, pick a STATE instead (the US is too large to scrape whole) — use list_regions(country_code="US"), or list_selectable_units which returns the 50 US states as country-equivalent units alongside real countries.

Input parameters:

- `workspace` (string): Workspace name (default: default)

### `list_regions` (~122 tokens)

List the admin regions (US states / provinces) of a country, each with its city_count and postcode_count. This is how you discover valid state names for a US ZIP campaign: pick ONE state, then create_campaign with filter { mode: "regions", admin_regions: [state], include_postcodes: true }. A state's postcode_count is roughly how many Maps searches the ZIP run fans out into.

Input parameters:

- `country_code` (string, required): 2-letter ISO country code, e.g. "US".
- `workspace` (string): Workspace name (default: default)

### `list_selectable_units` (~166 tokens)

List selectable geo units for a typeahead picker — countries plus, by default, the 50 US states as top-level "country-equivalent" units (so you target "Florida" the same way as "Germany"). Each unit has unit_id ("DE" or "US:Florida"), label, and kind ("country"|"state"). With states_as_units=true (default), "all of US" is intentionally NOT selectable (a US ZIP campaign must scope to one state). Set states_as_units=false to get plain countries (US as a whole) for non-ZIP use.

Input parameters:

- `states_as_units` (boolean): When true (default), replace the US with its 50 states as top-level units.
- `workspace` (string): Workspace name (default: default)

### `idap_fetch_resource` (~223 tokens)

Fetch a single resource from the client's normalized data store.

Returns the resource data with active flags and optional related resources. Use field projection (`fields`) to reduce token usage. Use `include` to fetch related data in one call (e.g., a business + its emails and phones).

Resource types: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media.

Example ref format: idap://businesses/550e8400-e29b-41d4-a716-446655440000

Input parameters:

- `fields` (string): Comma-separated fields to return (projection). E.g., "name,domain,email"
- `include` (string): Comma-separated related types to include. E.g., "emails,phones" for businesses
- `resource_id` (string, required): UUID of the resource
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `workspace` (string): Workspace name (default: default)

### `idap_list_resources` (~311 tokens)

List resources from the client's normalized data with filtering and cursor-based pagination.

Supports incremental sync via `since` parameter — only returns resources modified after that timestamp. Use `flags` to filter (e.g., "qualified" for flagged-only, or "-rejected" to exclude rejected).

Returns items array, cursor for next page, and has_more boolean.

Input parameters:

- `campaign_id` (string): Filter by campaign ID
- `cursor` (string): Pagination cursor from previous response
- `fields` (string): Comma-separated fields to return
- `flags` (string): Filter by flags. "qualified" = must have flag. "-rejected" = exclude flag
- `include` (string): Comma-separated related types to include
- `limit` (number): Max results per page (1-500, default: 100)
- `order` (string): Sort order (default: desc)
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `since` (string): ISO 8601 datetime — only resources modified after this time
- `sort` (string): Sort column (e.g., created_at, name)
- `source` (string): Filter by source worker (e.g., spiderMaps, spiderSite)
- `until` (string): ISO 8601 datetime — only resources modified before this time
- `workspace` (string): Workspace name (default: default)

### `idap_write_flags` (~253 tokens)

Add or remove flags on a resource.

Flags are bidirectional metadata for lead qualification, workflow control, and agent coordination.

Common flags: qualified, priority, rejected, do_not_contact, duplicate, reviewed, needs_enrichment.

Behavioral flags:
\- "rejected" → excluded from default list responses
\- "do_not_contact" → respected by outreach workers
\- "duplicate" → triggers FuzzIQ merge

Flags are idempotent (adding an existing flag is a no-op). Removes are soft-deletes (history preserved).

Input parameters:

- `add` (array): Flags to add (e.g., ["qualified", "priority"])
- `flagged_by` (string): Who is flagging (e.g., "agent:claude-code", "user:martin")
- `reason` (string): Reason for flagging
- `remove` (array): Flags to remove (e.g., ["needs_enrichment"])
- `resource_id` (string, required): UUID of the resource to flag
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `workspace` (string): Workspace name (default: default)

### `idap_batch_fetch` (~144 tokens)

Batch fetch up to 100 resources by their idap:// refs.

Accepts an array of ref strings (e.g., "idap://businesses/uuid1", "idap://emails/uuid2"). Returns results keyed by ref, plus errors for missing/invalid refs.

Efficient for board views or CRM sync — one call instead of N individual fetches.

Input parameters:

- `fields` (string): Comma-separated fields to return
- `include` (string): Comma-separated related types to include
- `refs` (array, required): Array of idap:// ref strings (max 100)
- `workspace` (string): Workspace name (default: default)

### `idap_search` (~176 tokens)

Full-text search within a resource type.

Uses PostgreSQL tsvector for relevance-ranked results. Search fields vary by type:
\- businesses: name, address, category
\- domains: domain, title
\- contacts: name, email, title
\- emails: address
\- phones: phone_number

Returns the same format as idap_list_resources.

Input parameters:

- `fields` (string): Comma-separated fields to return
- `flags` (string): Filter by flags
- `limit` (number): Max results (1-500, default: 20)
- `q` (string, required): Search query string
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `workspace` (string): Workspace name (default: default)

### `idap_stats` (~105 tokens)

Get aggregate statistics for a resource type.

Returns total count, flag distribution (how many resources have each flag), source breakdown (which workers generated the data), and last-24h activity counts.

Useful for dashboards, health checks, and understanding data coverage.

Input parameters:

- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `workspace` (string): Workspace name (default: default)

### `idap_resolve_resource` (~644 tokens)

Resolve a single resource by external identifier instead of UUID.

Use this when you have an external identifier (Google place_id, domain, email, VAT, LEI, etc.) and need the canonical IDAP record without first listing or searching.

Accepted (resource_type, identifier) pairs — server enforces this allowlist:
\- businesses        → place_id, domain
                      pin_name, pin_data_set_id, account_id, pin_subscription_id  (Wave D.1 — joined via pins.business_id)
\- domains           → domain
\- emails            → email
\- contacts          → email, linkedin, twitter
\- linkedin_profiles → url
\- company_registry  → vat, registration_number, lei, tax_id, source_id
\- pins              → pin_name, pin_data_set_id, account_id, pin_subscription_id  (IDAP PR 2)

Wave D.1 (2026-05-24): the 4 VayaPin pin keys now also resolve a `businesses` row directly — the service joins through `pins.business_id` so you can look up a business by any of the pin identifiers without first resolving the pin and then the business.

Exactly ONE identifier must be supplied — supplying two or zero returns a 400 envelope. Supplying an identifier that isn't valid for the resource_type returns a 400 envelope listing the allowed keys.

Returns 404 if no row matches in the client's tenant scope. Added by IDAP PR 1 (2026-05-19); pins resource added by PR 2 (2026-05-24); businesses-by-pin-key joined lookup added by Wave D.1 (2026-05-24).

Input parameters:

- `account_id` (string): VayaPin account UUID (pins)
- `domain` (string): Domain name (businesses, domains)
- `email` (string): Email address (emails, contacts)
- `fields` (string): Comma-separated field projection
- `include` (string): Comma-separated related types to include
- `lei` (string): Legal Entity Identifier (company_registry)
- `linkedin` (string): LinkedIn profile URL on a contact
- `pin_data_set_id` (string): VayaPin data set UUID (pins)
- `pin_name` (string): VayaPin PIN name e.g. "BB:TAPAS" (pins)
- `pin_subscription_id` (string): VayaPin subscription UUID (pins)
- `place_id` (string): Google Place ID (businesses)
- `registration_number` (string): National registration number (company_registry)
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `source_id` (string): Registry source id (company_registry, dev/admin only)
- `tax_id` (string): National tax id (company_registry)
- `twitter` (string): Twitter profile URL on a contact
- `url` (string): LinkedIn URL (linkedin_profiles)
- `vat` (string): VAT number (company_registry)
- `workspace` (string): Workspace name (default: default)

### `idap_media` (~160 tokens)

Get the URL for an IDAP media resource (screenshot, photo, document).

Returns a URL to the media proxy endpoint — does not return binary data. The URL supports:
\- ?thumb=true — 400px thumbnail
\- ?download=true — Content-Disposition: attachment
\- Conditional requests (If-None-Match, If-Modified-Since → 304)

Use the URL in markdown, HTML, or pass it to other tools.

Input parameters:

- `download` (boolean): Return download URL with Content-Disposition header (default: false)
- `media_id` (string, required): UUID of the media resource
- `thumb` (boolean): Return 400px thumbnail URL (default: false)
- `workspace` (string): Workspace name (default: default)

### `idap_find_duplicates` (~379 tokens)

Find duplicate resources sharing a common external key. Used in dedupe workflows before calling the (future) delete endpoint.

Returns clusters where two or more resources share the same value for a whitelisted key. Each cluster has `count >= 2` (single-occurrence values are filtered out server-side).

Whitelisted `key` values per `resource_type` (Wave D.1, 2026-05-24):

\- businesses → google_place_id, domain, phone_e164  (direct columns on businesses)
               vat, registration_number, lei, tax_id  (joined via company_registry.business_id)

Other resource types are not yet supported (returns 400 with the list of currently-supported types).

Response shape:
\```
{
  "resource_type": "businesses",
  "key": "google_place_id",
  "clusters": [
    { "key_value": "ChIJ...", "count": 3, "resource_ids": ["uuid", "uuid", "uuid"] },
    ...
  ],
  "total_clusters": N
}
\```

Default `limit` = 100; max = 500. Clusters are ordered by count DESC, then key_value ASC.

Use this BEFORE the (forthcoming) DELETE endpoint to confirm which duplicates to remove.

Input parameters:

- `key` (string, required): Clustering key. For businesses (Wave D.1): google_place_id, domain, phone_e164 (direct columns) or vat, registration_number, lei, tax_id (joined via company_registry).
- `limit` (integer): Maximum clusters to return (1..500). Default 100.
- `resource_type` (string, required): IDAP resource type: businesses, domains, contacts, emails, phones, company_registry, linkedin_profiles, media, pins
- `workspace` (string): Workspace name (default: default)

### `idap_delete_business` (~724 tokens)

🔴 DESTRUCTIVE — delete a business + cascade across per-tenant tables. IRREVERSIBLE.

Hard-deletes the business row in norm_cli_<client>.businesses AND cascades to linked tables (pins, business_contacts, business_registry, company_registry, contacts, phones, domains, linkedin_profiles). Transactional — all-or-nothing. Audit row written to public.idap_deletions_audit in the same transaction.

WHEN TO USE:
\- Surfacing a duplicate via idap_resolve_resource + manual review, then cleaning up the duplicate.
\- Tenant cleanup of stale/incorrect business records.
\- Cascading removal of contact/email/phone associations for a business.

RECOMMENDED FLOW:
1\. Resolve target with idap_resolve_resource (e.g. {resource_type: 'businesses', domain: 'example.com'}) → get the canonical business_id (UUID).
2\. (Optional) idap_find_duplicates (D.1) to confirm this isn't unique-data destruction.
3\. Call idap_delete_business with the resolved UUID + a short audit reason.

⚠️ DOES NOT TOUCH cs.vayapin.com.
VayaPin pin pages are permanent per VayaPin §10. Response includes vayapin_pins_remain_external (boolean) + vayapin_pin_data_set_ids_orphaned (array). Tell the user about any remaining external URLs.

⚠️ DOES NOT CASCADE THE 'emails' TABLE.
emails is a tenant-wide canonical store (UNIQUE on the email column) shared across businesses via business_contacts (M:N). Only the link row is removed; the email's verification metadata stays. Other businesses still reference the same email.

WHAT AUTO-CASCADES (Postgres ON DELETE CASCADE):
booking_flows, services — surfaced in response.auto_cascaded {table: count}.

WHAT BLOCKS THE DELETE (returns 409 Conflict, never partial):
bookings rows referencing this business or its contacts via ON DELETE NO ACTION FK. Response.detail.blocking_booking_ids lists up to 50 blocking IDs. Caller must re-point or delete those bookings before retrying.

AUTH:
Tenant-owner only — caller's client_id IS the tenant scope. No super-admin override in V1. Second DELETE on t…

Input parameters:

- `business_id` (string, required): UUID of the business to delete. Resolve alternate keys via idap_resolve_resource first.
- `reason` (string): Optional free-text reason recorded in the audit log (max 500 chars). e.g. "duplicate of <other_uuid>".
- `workspace` (string): Workspace name (default: default)

### `lead_search` (~215 tokens)

Find leads for a search query in a location. Full pipeline: Google Maps → website crawl → email verification → VayaPin profile. Returns job_id to poll for results via get_job_results.

Input parameters:

- `country_code` (string): ISO 2-letter country code (default: "US")
- `lang` (string): Language code for results (default: "en")
- `location` (string): Location to search in (e.g. "Berlin", "Boston, MA"). If omitted, include location in search_query.
- `max_results` (number): Max businesses to find (default: 20, max: 500)
- `search_query` (string, required): What to search for (e.g. "restaurants", "plumbers", "software companies")
- `test` (boolean): Route to test queue
- `workflow` (object): Pipeline config: { spidersite: { enabled, mode }, spiderverify: { enabled }, vayapin: { enabled } }. Defaults to full pipeline.
- `workspace` (string)

### `company_intel_research` (~275 tokens)

Research a single company through the full intelligence pipeline: Perplexity discovery → website crawl → company registry → email verification → people/LinkedIn. Returns job_id to poll for results.

Input parameters:

- `city` (string): City/location hint (helps discovery)
- `company_name` (string, required): Company name to research (required)
- `config` (object): Advanced pipeline config — toggle steps: { discovery: { enabled }, site: { enabled, mode, max_pages }, company_data: { enabled }, verify: { enabled }, people: { enabled } }
- `country_code` (string): ISO 2-letter country code (e.g. "US", "DE")
- `domain` (string): Known domain — skips Perplexity discovery step
- `linkedin_url` (string): Known LinkedIn company URL
- `max_employees` (number): Max employees to extract per company (1-2000, default 20)
- `profile_mode` (string): Employee detail level: 'short' = name+title+location ($4/1K), 'full' = +skills/education/experience ($8/1K), 'full_email' = +email discovery ($12/1K). Default: short
- `test` (boolean): Route to test queue
- `workspace` (string)

### `company_intel_batch` (~150 tokens)

Research multiple companies in batch (max 50). Same pipeline as single but processes all companies in parallel. Returns job_id to poll.

Input parameters:

- `companies` (array, required): Array of companies to research. Each: { company_name (required), city?, country_code?, domain?, linkedin_url? }
- `config` (object): Advanced pipeline config applied to all companies
- `max_employees` (number): Max employees per company (1-2000, default 20)
- `profile_mode` (string): Employee detail level for all companies: 'short', 'full', 'full_email'. Default: short
- `test` (boolean): Route to test queue
- `workspace` (string)

### `subscribe_events` (~99 tokens)

Subscribe to real-time job events (SSE). Opens a short-lived connection and returns a buffer of recent events. Event types: job.queued, job.started, job.completed, job.failed, connected.

Input parameters:

- `duration_seconds` (number): How long to listen for events (default: 5, max: 30)
- `max_events` (number): Max events to collect before returning (default: 50)
- `workspace` (string)

### `get_event_status` (~35 tokens)

Get event stream status — service health, active subscriptions, and whether your client is currently connected.

Input parameters:

- `workspace` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads#diagnostics

## Score history

- 2026-08-03: 60
- 2026-08-02: 60
- 2026-08-01: 13
- 2026-07-31: 0
- 2026-07-30: 19
- 2026-07-28: 19
- 2026-07-27: 19

## Links

- npm package: https://www.npmjs.com/package/@spideriq/mcp-leads
- Socket report: https://socket.dev/npm/package/@spideriq/mcp-leads
- Changelog RSS feed: https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads/changelog.json
- HTML version of this page: https://verifymcp.io/servers/ai-spideriq-leads/spideriq-mcp-leads
