# seo_research

> SEO data.

URL: https://mcp-docs.opennomos.com/docs/tools/research/seo_research

> SEO data. action=serp: Google organic results for keyword, returned directly (~8s, $0.002). action=keyword_suggestions: keyword results with search_volume, cpc, competition, difficulty and intent (~3s, ~$0.013). action=keyword_difficulty: difficulty for keywords (~3s, ~$0.012).>
> location_code takes a country name ('United States', 'China', 'Hong Kong') or a numeric code, default US; language_code defaults to 'en'. depth controls SERP depth; limit controls keyword suggestions.

| Field | Value |
| --- | --- |
| Pack | SEO & AI visibility (`seo`) |
| Estimated cost per call | ~$0.013 (upstream cost; see the description for per-action figures) |
| Monthly pack limit | $3 of upstream cost (not shown to users) |
| Project | optional (`project` or `X-OpenNomos-Project`); only attaches the project id to the result |

## Parameters

| Parameter | Required | Type | Description |
| --- | --- | --- | --- |
| `project` | no | `string` | Project slug or id. Omit to use the credential or workspace default. |
| `action` | yes | `"serp"` \| `"keyword_suggestions"` \| `"keyword_difficulty"` | serp = Google organic results; keyword_suggestions = related keywords with volume/cpc/difficulty; keyword_difficulty = difficulty for given keywords. |
| `keyword` | no | `string` | Seed keyword, e.g. 'ai crm'. Used by serp and keyword_suggestions (and as a single keyword for keyword_difficulty). |
| `keywords` | no | `string[]` | keyword_difficulty only: keywords to score, e.g. ['ai crm', 'sales copilot']. |
| `location_code` | no | `integer (≥ 1) \| string` | Where to search from: a country name (e.g. "United States", "China", "Hong Kong", "Japan"), a 2-letter country code ("US", "CN"), or a numeric DataForSEO location code (e.g. 2840). Default United States. |
| `language_code` | no | `string` | Search language code, e.g. 'en', 'de', 'ja'. Default 'en'. |
| `depth` | no | `integer (≥ 1, ≤ 100)` | serp only: how many results to ask for. Default 10. |
| `limit` | no | `integer (≥ 1, ≤ 100)` | keyword_suggestions only: max keywords to return. Default 20. |

## Example call

```json
{
  "action": "keyword_suggestions",
  "keyword": "ai crm",
  "location_code": "United States",
  "limit": 20
}
```

REST: `POST https://service.opennomos.com/v1/tools/seo_research` with that JSON as the body. MCP: `tools/call` with `name: "seo_research"` and that JSON as `arguments`.

## Example result

Values are illustrative; the shape comes from the service code.

```json
{
  "results": [
    {
      "keyword": "ai crm software",
      "search_volume": 5400,
      "cpc": 12.4,
      "competition": 0.61,
      "difficulty": 38,
      "intent": "commercial"
    },
    "…"
  ]
}
```

## Notes

- Three actions: `serp` (Google organic results, about 8 s and $0.002), `keyword_suggestions` (about 3 s, about $0.013) and `keyword_difficulty` (about 3 s, about $0.012).
- `location_code` accepts a country name ("United States", "China", "Hong Kong"), a two-letter country code ("US", "CN") or a numeric DataForSEO code. An unknown name returns an error that lists examples.
- For `serp`, only organic results are returned, and `note` explains when fewer than `depth` came back.
- The exact field names inside each keyword row come from the provider and are not normalised.

## Errors

Upstream trouble is reported **inside a normal result** as `error`, `reason` and `action` (and `tool` / `retry_after_seconds` when they apply). For `search_signals` this appears per source. See [Errors](https://mcp-docs.opennomos.com/docs/reference/errors.md).

This tool is in the **SEO & AI visibility** pack. If the pack is not enabled the call fails with `pack_required` (HTTP 403); if the pack's monthly upstream cost limit is used up it fails with `soft_limit` (HTTP 429). Both carry `action: "give_up_and_tell_user"` and the console URL.
