# Intent signals MCP tools

> Tool descriptions and complete input schemas for intent operations.

Source: https://docs.graph8.com/developers/mcp-reference/intent/

Use this reference to find a tool and its inputs. [Connect an MCP client](https://docs.graph8.com/developers/mcp/) before calling tools. Tool visibility depends on discovery and permissions.

For actions that send messages, spend credits, delete data, or start execution, review the intended records and confirm the action before proceeding. Obtain IDs from a prior result; do not invent them. A registered tool does not guarantee that its supporting service is available in every organization.

## g8_intent_add_keywords

> Bulk-add plain compete-tracking keyword phrases (web-UI parity). The MCP twin of the Buyer Intent &gt; Keywords bulk-add screen: saves each phrase as a plain keyword row (stored lowercased). Keywords that already exist for this org + signal_type are reported as skipped, not duplicated. For signal_type "intent" each NEW keyword seeds its URL set in the background - URLs and resolved contacts appear later, not in this response. Use g8_intent_update_keyword_filters afterwards to set per-keyword search filters (e.g. a hybrid semantic blend). Args: keywords: 1-50 keyword phrases (each max 500 chars). signal_type: "intent" (default), "jobs", or "job_changes".

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keywords` | Yes | array | See the schema below for constraints and defaults. |
| `signal_type` | No | string | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keywords": {
      "items": {
        "type": "string"
      },
      "title": "Keywords",
      "type": "array"
    },
    "signal_type": {
      "default": "intent",
      "title": "Signal Type",
      "type": "string"
    }
  },
  "required": [
    "keywords"
  ],
  "title": "g8_intent_add_keywordsArguments",
  "type": "object"
}
```

</details>

## g8_intent_create_from_domain

> Compete-tracking keyword create from a competitor domain. Pulls on-domain pages, resolves contacts, and saves a keyword row with both URLs and pre-resolved contacts. Strict off-domain guard: only &lt;domain&gt; and *.&lt;domain&gt; are saved. Returns the new keyword_id plus counts (pages_seeded, contacts_seeded, companies_seeded, off_domain_rejected). CONFIRM STEP: a call without confirm=true saves NOTHING. It returns status "confirmation_required" with the preview (counts + sample_pages + sample_contacts, keyword_id null). Show the user that preview, then call again with confirm=true to create the keyword, which the daily resolver keeps processing. Args: domain: Competitor domain, bare (no scheme), e.g. "cognism.com". page_limit: Max pages to seed (default 200, 1-500). contact_limit: Max contacts to pre-resolve (default 200, 1-500). dry_run: True = preview only, even with confirm=true. False (explicit) = create in one call without the confirm step (kept for existing scripted callers). confirm: True = create the keyword (after showing the preview).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `domain` | Yes | string | See the schema below for constraints and defaults. |
| `page_limit` | No | integer | See the schema below for constraints and defaults. |
| `contact_limit` | No | integer | See the schema below for constraints and defaults. |
| `dry_run` | No | boolean / null | See the schema below for constraints and defaults. |
| `confirm` | No | boolean | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "domain": {
      "title": "Domain",
      "type": "string"
    },
    "page_limit": {
      "default": 200,
      "title": "Page Limit",
      "type": "integer"
    },
    "contact_limit": {
      "default": 200,
      "title": "Contact Limit",
      "type": "integer"
    },
    "dry_run": {
      "anyOf": [
        {
          "type": "boolean"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Dry Run"
    },
    "confirm": {
      "default": false,
      "title": "Confirm",
      "type": "boolean"
    }
  },
  "required": [
    "domain"
  ],
  "title": "g8_intent_create_from_domainArguments",
  "type": "object"
}
```

</details>

## g8_intent_delete_keyword

> Soft-delete a compete-tracking keyword row. Unknown or already deleted ids return "not found". Args: keyword_id: UUID of the keyword row (from g8_intent_list_keywords).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_id` | Yes | string | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_id": {
      "title": "Keyword Id",
      "type": "string"
    }
  },
  "required": [
    "keyword_id"
  ],
  "title": "g8_intent_delete_keywordArguments",
  "type": "object"
}
```

</details>

## g8_intent_domain_search

> Find every indexed page on a competitor's domain (and subdomains). Returns the apex domain and every subdomain (www, blog, help, etc.) - not news articles that merely mention the competitor. Args: domain: Competitor root domain, bare (no scheme/path), e.g. "cognism.com". limit: Max pages (default 200, max 500).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `domain` | Yes | string | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "domain": {
      "title": "Domain",
      "type": "string"
    },
    "limit": {
      "default": 200,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "domain"
  ],
  "title": "g8_intent_domain_searchArguments",
  "type": "object"
}
```

</details>

## g8_intent_keyword_companies

> Companies resolved against a keyword's URL set. Aggregates contacts by company_domain so you see which orgs are poking around the competitor, not just individuals. One row per company (`total` counts the same companies), strongest first: `signal_count` is its number of visits, `signal_strength` the same strong / light rule as the People rows, and `topics_of_interest` up to 3 other keywords it also lit up for. Placeholder employers ("self-employed", "freelance") are not listed. `company_id` is this org's CRM record id (null when not in the CRM); `global_company_id` is the exact global COMPANY_ID. An unknown keyword_id returns "not found".

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_id` | Yes | string | See the schema below for constraints and defaults. |
| `page` | No | integer | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_id": {
      "title": "Keyword Id",
      "type": "string"
    },
    "page": {
      "default": 1,
      "title": "Page",
      "type": "integer"
    },
    "limit": {
      "default": 100,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "keyword_id"
  ],
  "title": "g8_intent_keyword_companiesArguments",
  "type": "object"
}
```

</details>

## g8_intent_keyword_contacts

> People resolved against a keyword's URL set. Each row includes full contact identity (name, job title, LinkedIn, work email) plus the company they're tied to (null when unknown). IDs: CONTACT_ID / COMPANY_ID are graph8's global keys (too large for JSON numbers, so they can appear rounded); use `company_id` / `contact_id` (this org's CRM record ids, null when the company or person is not in the CRM) with the company and contact tools, and `global_company_id` / `global_contact_id` for the exact global key. `mode_counts.signals_only` is the signal-contact total; the ICP modes stay 0 unless the keyword has a buying committee. An unknown keyword_id returns "not found".

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_id` | Yes | string | See the schema below for constraints and defaults. |
| `page` | No | integer | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_id": {
      "title": "Keyword Id",
      "type": "string"
    },
    "page": {
      "default": 1,
      "title": "Page",
      "type": "integer"
    },
    "limit": {
      "default": 100,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "keyword_id"
  ],
  "title": "g8_intent_keyword_contactsArguments",
  "type": "object"
}
```

</details>

## g8_intent_keyword_urls

> URLs linked to a compete-tracking keyword. Args: keyword_id: UUID from g8_intent_list_keywords. page: Page (default 1). limit: Per page (default 100, max 500).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_id` | Yes | string | See the schema below for constraints and defaults. |
| `page` | No | integer | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_id": {
      "title": "Keyword Id",
      "type": "string"
    },
    "page": {
      "default": 1,
      "title": "Page",
      "type": "integer"
    },
    "limit": {
      "default": 100,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "keyword_id"
  ],
  "title": "g8_intent_keyword_urlsArguments",
  "type": "object"
}
```

</details>

## g8_intent_keywords_create_from_search

> Keywords Create From Search. Uses the current organization and existing API permissions. Review the intended change and set confirm=true to execute; otherwise nothing is changed and the preview's `target` says what would be created (nothing is resolved or saved). API: POST /intent/keywords/create-from-search

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `body` | Yes | #/$defs/ApiKeywordsCreateFromSearchRequest | See the schema below for constraints and defaults. |
| `confirm` | No | boolean | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "$defs": {
    "ApiKeywordsCreateFromSearchRequest": {
      "additionalProperties": false,
      "properties": {
        "contact_limit": {
          "default": 50,
          "description": "Max contacts to pre-resolve per keyword.",
          "maximum": 100.0,
          "minimum": 1.0,
          "title": "Contact Limit",
          "type": "integer"
        },
        "keywords": {
          "description": "1-10 free-text keyword queries. Each is searched against the intent page index, contacts/companies are resolved, and a compete-tracking keyword row is saved. Duplicates within the request (case-insensitive, trimmed) are skipped, not re-saved.",
          "items": {
            "type": "string"
          },
          "maxItems": 10,
          "minItems": 1,
          "title": "Keywords",
          "type": "array"
        },
        "page_limit": {
          "default": 20,
          "description": "Max pages to seed per keyword. Deliberately smaller than create-from-domain's 200 default since this runs once per keyword.",
          "maximum": 50.0,
          "minimum": 1.0,
          "title": "Page Limit",
          "type": "integer"
        },
        "search_filters": {
          "anyOf": [
            {
              "additionalProperties": true,
              "type": "object"
            },
            {
              "type": "null"
            }
          ],
          "default": null,
          "description": "Optional intent-search filters applied to EVERY keyword in the batch (audience, page_type, commercial_score_min, etc.). Stored verbatim on each saved keyword row so the daily resolver replays them.",
          "title": "Search Filters"
        },
        "semantic_ratio": {
          "default": 0.0,
          "description": "0 = text search (default, cheapest), 1 = semantic, between = hybrid.",
          "maximum": 1.0,
          "minimum": 0.0,
          "title": "Semantic Ratio",
          "type": "number"
        }
      },
      "required": [
        "keywords"
      ],
      "title": "ApiKeywordsCreateFromSearchRequest",
      "type": "object"
    }
  },
  "properties": {
    "body": {
      "$ref": "#/$defs/ApiKeywordsCreateFromSearchRequest"
    },
    "confirm": {
      "default": false,
      "title": "Confirm",
      "type": "boolean"
    }
  },
  "required": [
    "body"
  ],
  "title": "g8_intent_keywords_create_from_searchArguments",
  "type": "object"
}
```

</details>

## g8_intent_list_keywords

> All compete-tracking keyword rows for this org. Each row carries total_resolved_contacts and total_resolved_companies so you can rank by delivered compete intelligence. Companies can exceed contacts: a company is also counted when a visit resolved only to the company (by IP), with no named person. Args: keyword_contains: Optional case-insensitive substring filter. page: Page number (default 1). limit: Rows per page (default 100, max 500).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_contains` | No | string / null | See the schema below for constraints and defaults. |
| `page` | No | integer | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_contains": {
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Keyword Contains"
    },
    "page": {
      "default": 1,
      "title": "Page",
      "type": "integer"
    },
    "limit": {
      "default": 100,
      "title": "Limit",
      "type": "integer"
    }
  },
  "title": "g8_intent_list_keywordsArguments",
  "type": "object"
}
```

</details>

## g8_intent_page_visitors

> Resolve the people who visited a specific page URL. `visitors` holds this page of resolved people and `total` is how many are in it; `total_visitors` is every distinct visitor on the URL in the lookback window. `breakdown` tallies every SCANNED visitor by tier (verified / b2b / b2c / name_only / company / anonymous) and sums to `scanned`. On a busy page the server stops early and sets `partial=true` with a `warnings` entry; page on with nextOffset. `newest_visit` is the latest visit date seen on the URL and `feed` says whether the intent feed itself is delayed (feed.degraded). Args: url: Canonical PAGE_URL (no scheme, no www), e.g. "cognism.com/pricing". limit: Max visitors (default 50, 1-500; larger values are capped). mode: "quick" (CID + UP_ID only) or "full" (all identity paths, slower). Busy pages can take 10-20 s either way.

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `url` | Yes | string | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |
| `mode` | No | string | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "url": {
      "title": "Url",
      "type": "string"
    },
    "limit": {
      "default": 50,
      "title": "Limit",
      "type": "integer"
    },
    "mode": {
      "default": "quick",
      "title": "Mode",
      "type": "string"
    }
  },
  "required": [
    "url"
  ],
  "title": "g8_intent_page_visitorsArguments",
  "type": "object"
}
```

</details>

## g8_intent_pages_contacts

> Aggregated, deduplicated resolved contacts across multiple page URLs. Useful for compete-tracking setup: pre-populate a keyword's contacts so it shows real counts immediately. Counts differ from g8_intent_pages_visitor_counts BY DEFINITION: `total` = visitors that resolve to a profiled person among the `scanned_visitors` most active of `total_visitors` distinct visitors (anonymous visitors are not contacts). See `definition`. Args: urls: Up to 200 canonical PAGE_URLs. limit: Max contacts returned (default 100, 1-500; larger values are capped). mode: "quick" or "full".

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `urls` | Yes | array | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |
| `mode` | No | string | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "urls": {
      "items": {
        "type": "string"
      },
      "title": "Urls",
      "type": "array"
    },
    "limit": {
      "default": 100,
      "title": "Limit",
      "type": "integer"
    },
    "mode": {
      "default": "quick",
      "title": "Mode",
      "type": "string"
    }
  },
  "required": [
    "urls"
  ],
  "title": "g8_intent_pages_contactsArguments",
  "type": "object"
}
```

</details>

## g8_intent_pages_visitor_counts

> Batched unique-visitor count per page URL. Useful for ranking a URL list by traffic before drilling into contacts. Every requested URL is in `counts` (0 = no visitors). These are ALL distinct visitors on the web, so they are larger than the resolved contact counts of g8_intent_pages_contacts (see `definition`). Args: urls: Up to 15,000 canonical PAGE_URLs.

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `urls` | Yes | array | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "urls": {
      "items": {
        "type": "string"
      },
      "title": "Urls",
      "type": "array"
    }
  },
  "required": [
    "urls"
  ],
  "title": "g8_intent_pages_visitor_countsArguments",
  "type": "object"
}
```

</details>

## g8_intent_search_pages

> Text / semantic / hybrid search across intent-enriched pages. Supports operator syntax: bare domain (cognism.com) -&gt; domain-mode; site:cognism.com, intitle:pricing, inurl:blog, type:blog, audience:b2b, -excluded_word. A bare-domain search matches the apex + www only; use g8_intent_domain_search for every subdomain (it can list more pages). With include_visitors=true (default) only pages with visitors are returned and each carries `visitors`. If the visitor count is slow or fails, the pages still come back (unfiltered, visitors=null) and `warnings` / `visitors_error` say why. `filtered_no_visitors` counts hits hidden for having no visitors (total_hits still counts them). Args: query: Search string (free-form text + operators). Must not be blank. limit: Max results (default 50, 1-500; larger values are capped at 500). semantic_ratio: 0.0 text-only, 1.0 semantic-only, between = hybrid (must be 0.0-1.0). filters: Optional filter dict (audience, page_type, commercial_intent_level, etc.). sort: Optional sort fields like ["commercial_score:desc"]. include_visitors: When true, enriches each hit with a visitor count.

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `query` | Yes | string | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |
| `semantic_ratio` | No | number | See the schema below for constraints and defaults. |
| `filters` | No | object / null | See the schema below for constraints and defaults. |
| `sort` | No | array / null | See the schema below for constraints and defaults. |
| `include_visitors` | No | boolean | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "query": {
      "title": "Query",
      "type": "string"
    },
    "limit": {
      "default": 50,
      "title": "Limit",
      "type": "integer"
    },
    "semantic_ratio": {
      "default": 0.0,
      "title": "Semantic Ratio",
      "type": "number"
    },
    "filters": {
      "anyOf": [
        {
          "additionalProperties": true,
          "type": "object"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Filters"
    },
    "sort": {
      "anyOf": [
        {
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        {
          "type": "null"
        }
      ],
      "default": null,
      "title": "Sort"
    },
    "include_visitors": {
      "default": true,
      "title": "Include Visitors",
      "type": "boolean"
    }
  },
  "required": [
    "query"
  ],
  "title": "g8_intent_search_pagesArguments",
  "type": "object"
}
```

</details>

## g8_intent_search_url_companies

> Companies that visited a single page URL, aggregated by company. Returns each company's audience bucket (b2b/b2c), visit_count, contacts_seen, last_seen, plus light enrichment (industry, employee_count range, logo_url). Scope: companies of contacts YOUR keywords have already resolved on this URL, so a URL none of your keywords tracks returns 0 even when its visitor count is high (see `definition`). For keyword-keyed rollups across many URLs, use g8_intent_keyword_companies instead. Args: url: Canonical page_url, no scheme/www (e.g. "cognism.com/pricing"). days: Lookback window in days (default 90, must be 1-365). limit: Max companies returned (default 200, 1-500; larger values are capped).

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `url` | Yes | string | See the schema below for constraints and defaults. |
| `days` | No | integer | See the schema below for constraints and defaults. |
| `limit` | No | integer | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "url": {
      "title": "Url",
      "type": "string"
    },
    "days": {
      "default": 90,
      "title": "Days",
      "type": "integer"
    },
    "limit": {
      "default": 200,
      "title": "Limit",
      "type": "integer"
    }
  },
  "required": [
    "url"
  ],
  "title": "g8_intent_search_url_companiesArguments",
  "type": "object"
}
```

</details>

## g8_intent_stats

> Intent index coverage stats (doc count + size) and feed freshness. Call before starting a compete-tracking program to confirm the index has meaningful coverage for the orgs / domains of interest. `feed` reports the visitor-signal feed: status ok / delayed / unknown, newest_day, lag_days and gap_days; when feed.degraded is true, tell the user intent results are out of date.

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| None | No | — | No user-supplied inputs. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {},
  "title": "g8_intent_statsArguments",
  "type": "object"
}
```

</details>

## g8_intent_update_keyword_filters

> Replace a keyword's search_filters JSON. Full replacement, not merge. Optional typed fields: audience ("b2b"\|"b2c"\|"both"); exclude_page_types (list of "news"\|"finance"\|"forum"\|"vendor_marketing"); min_commercial_intent_level (int 0-100); max_urls_per_domain (int 1-20); llm_triage (bool); exclude_domains (list of domain strings). Args: keyword_id: UUID of the keyword. search_filters: Full replacement filter dict.

### Inputs

| Input | Required | Type | Description |
|---|---|---|---|
| `keyword_id` | Yes | string | See the schema below for constraints and defaults. |
| `search_filters` | Yes | object | See the schema below for constraints and defaults. |

<details>
<summary>Complete input schema</summary>

```json
{
  "properties": {
    "keyword_id": {
      "title": "Keyword Id",
      "type": "string"
    },
    "search_filters": {
      "additionalProperties": true,
      "title": "Search Filters",
      "type": "object"
    }
  },
  "required": [
    "keyword_id",
    "search_filters"
  ],
  "title": "g8_intent_update_keyword_filtersArguments",
  "type": "object"
}
```

</details>
